Mitunter steht man vor dem Problem, eine Playlist generieren zu müssen, welche Titel (bspw. Musikclips) in zufälliger Reihenfolge abspielen soll. Dabei dürfen natürlich Titel nicht mehrfach abgespielt oder andere einfach ausgelassen werden. Es sollen also
Mein Beispiel arbeitet mit insgesamt 20 einzelnen Titeln. Das hier vorgestellte Modul ist jedoch so flexibel, daß durch die Änderung eines einzigen Wertes (siehe PRE-Commands Hauptmenü) die Anzahl der Titel (bis max. 48) individuell angepasst werden kann.
Folgende Register werden vom VM-Command-Modul verwendet und dürfen nicht anderweitig verändert werden:
GPRM0 | Hilfsregister Zahlengenerator |
GPRM1 | errechnete Zufallszahl, wird später für die Caselist verwendet |
GPRM2 | Anzahl der Titel/DVD (max. 48) |
GPRM3 | Countdown-Counter, ist dieser 0, sind alle Titel gespielt. |
GPRM4 | Flagregister für die Titel 0-15 |
GPRM5 | Flagregister für die Titel 16-31 |
GPRM6 | Flagregister für die Titel 32-47 |
GPRM7 | Hilfsregister |
GPRM8 | Hilfsregister |
Im Haupt- bzw. Auswahlmenü werden folgende PRE-Commands eingearbeitet. Fett hervorgehobene Commands
müssen evtl. angepasst werden!
UPDATE: Bitte den Code weiter unten verwenden!
Zeile | Code | Erklärung |
1 | GPRM2=20 | Anzahl der Titel/DVD - dieser Wert muss individuell angepasst werden! |
2 | GPRM3=GPRM2 | unser Countdown-Zähler. Hier wird er auf die Anz. Titel/DVD gesetzt (GPRM2) |
3 | GPRM4=0 | Flagregister Titel 0...15 |
4 | GPRM5=0 | Flagregister Titel 16...31 |
5 | GPRM6=0 | Flagregister Titel 32...47 |
6 | SetGPRMMD counter (GPRM0=0) | GPRM0 wird in den Countermode versetzt und zählt jede Sekunde um 1 hoch |
Beim Anwählen des Hautpmenüs (nach DVD-Start oder Drücken der Menü-Taste der FB) werden alle Register wieder definiert gesetzt und die Flags gelöscht. Es geht also wieder von vorn los. Eine besondere Bedeutung hat die Zeile 6: Hier wird Register GPRM0 in den Countermode versetzt und zählt jede Sekunde um Eins hoch. Diesen Wert benötigt der Zufallsgenerator als sogenannten "Seed" (Start- oder Initialisierungswert) zur Erzeugung seiner Zufallszahlenreihen. Wir machen uns also die "Verzögerung" vom Erscheinen des Menüs bis zur Nutzerreaktion zunutze, um nicht immer die gleichen Zahlenfolgen generieren zu müssen. Den internen Zufallszahlengenerator des Players lassen wir aus o.g. Gründen aussen vor...
Unser Herzstück - Das VM-Command-Modul - unser Randomizer (Code aktualisiert am 08.06.05)
Zeile | Code | Erklärung |
1 | if (GPRM3==GPRM7) LinkPGCN 2 | Counter ist abgelaufen, zurück zum Hauptmenü. Wer möchte, daß stattdessen der DVD-Player stoppt, trägt anstelle von LinkPGCN 2 einfach EXIT ein. GPRM7 ist übrigens immer Null (siehe auch weiter unten) |
2 | GPRM8=GPRM2 | Ermittlung des Offsets anhand der Titelanzahl |
3 | GPRM8%=2 | Startoffset (0: gerade Titelanzahl, 1: ungerade) |
4 | GPRM8+=1 | um 1 erhöhen |
5 | GPRM8+=GPRM1 | und letzte Zufallszahl addieren |
6 | if (GPRM7!=0) GPRM0 rnd GPRM8 | letzte Titelnummer war nicht frei, neuen Seed setzen |
7 | if (GPRM0==0) GPRM0=2046 | Hier beginnt der Part des RANDU |
8 | if (GPRM0>=2047) GPRM0=2046 | Dieser arbeitet mit bestimmten Primzahlenkombinationen, |
9 | GPRM0&=2047 | um gleichverteilte Zufallszahlen zu erzeugen. |
10 | GPRM1=GPRM0 | Dazu werden Bitmasken gesetzt, verschoben und verknüpft. |
11 | GPRM1&=17 | |
12 | if (GPRM1==1) GPRM0|=2048 | |
13 | if (GPRM1==16) GPRM0|=2048 | |
14 | GPRM0/=2 | |
15 | GPRM1=GPRM0 | Unsere zufällige Titelnummer (0...2046) |
16 | if (GPRM7!=0) GPRM1=GPRM8 | Damit sich einige Player nicht in einer Schleife festfahren, wenn das Ermitteln eines freien Titels fehlgeschlagen ist, wird einfach ein Offset zur Titelnummer addiert und das Flag später entsprechend getestet. |
17 | GPRM1%=GPRM2 | Titelnummer wird auf einen Bereich von 0... Anz. Titel - 1 begrenzt (Modulo-Bildung) |
18 | GPRM7=GPRM1 | Titelnummer in GPRM7 |
19 | GPRM8=GPRM1 | und GPRM8 merken |
20 | GPRM7/=16 | Flagregister 1, 2 oder 3? |
21 | GPRM8%=16 | "Bitschiebezähler" - welches Flag (0...7)? |
22 | if (GPRM7==2) Goto 44 | Flagregister 3 |
23 | if (GPRM7==1) Goto 34 | Flagregister 2 |
24 | GPRM7=1 | Flagregister 1, Bit 0 auf 1 setzen |
25 | if (GPRM8==0) Goto 29 | Bitschieberei beendet, weiter |
26 | GPRM7*=2 | Bit um eine Position nach links schieben, |
27 | GPRM8-=1 | "Schiebezähler" runterzählen |
28 | Goto 25 | und (evtl.) weiterschieben... |
29 | GPRM8=GPRM7 | Flag merken |
30 | GPRM7&=GPRM4 | und testen, ob bereits gesetzt |
31 | if (GPRM7!=0) Goto 2 | ja, bereits gespielt, neue Zufallszahl ermitteln |
32 | GPRM4|=GPRM8 | nein, Flag jetzt setzen |
33 | Goto 53 | und noch ein paar Commands ausführen |
34 | GPRM7=1 | das Gleiche, nur für Flagregister 2 (GPRM5) |
35 | if (GPRM8==0) Goto 39 | |
36 | GPRM7*=2 | |
37 | GPRM8-=1 | |
38 | Goto 35 | |
39 | GPRM8=GPRM7 | |
40 | GPRM7&=GPRM5 | |
41 | if (GPRM7!=0) Goto 2 | |
42 | GPRM5|=GPRM8 | |
43 | Goto 53 | |
44 | GPRM7=1 | und hier für Flagregister 3 (GPRM6) |
45 | if (GPRM8==0) Goto 49 | |
46 | GPRM7*=2 | |
47 | GPRM8-=1 | |
48 | Goto 45 | |
49 | GPRM8=GPRM7 | |
50 | GPRM7&=GPRM6 | |
51 | if (GPRM7!=0) Goto 2 | |
52 | GPRM6|=GPRM8 | |
53 | GPRM3-=1 | Counterzähler um 1 runterzählen |
54 | LinkPGCN 4 | und ab zur Caselist. In der Caselist wird GPRM1 ausgewertet. |
Die Caselist selbst ist relativ einfach zu programmieren. Wir haben eine Zufallszahl, die im Bereich von [0] (Titel 1) bis [max. Anzahl Titel minus 1] liegt (in meinem Beispiel ist die größte Zufallszahl also 19). Diese Zahl steckt in GPRM1, welches mittels der Caselist nur noch ausgewertet werden muss. Der Screenshot verdeutlicht das nochmals.
Bitte daran denken, das die Endlinks der Clips wieder auf auf den Randomizer zeigen.
Zur besseren Verständlichkeit stelle ich das komplette Projekt zum Download bereit. Achtung: Ich verwende für jeden Titel immer den gleichen Clip! Der einzige Unterschied sind die Untertitel, diese zeigen die gewählte Clipnummer an. Also Untertitel im DVD-Player einschalten!
Und hier das Projekt [678 KB, geupdatet am 08.06.2005]. Feedback ist wie immer im Forum ausdrücklich erwünscht.
Der vorliegende Code wurde zunächst mit zwei Software-Playern (Marks Trayplayer und WinDVD 4) getestet. Wie nicht anders zu erwarten, halten sich die Software-Player exakt an die Programmierung und erzeugen demzufolge auch wunderschöne Randomlisten. Es war an der Zeit, den Random-Generator auch auf Standalone-Geräten auf Tauglichkeit zu testen. Zur Verfügung standen:
Hier zeigten sich dann auch erste Probleme. Einzig der Pioneer arbeitete wie erwartet und konnte seine zufallsgenerierte Liste abspielen. Die anderen Player fuhren nach dem Abspielen des ersten Titels fest...
Als Ursache für das Festfahren vermute ich eine unvollständige bzw. ungenaue Implementierung des Instructionsets (VM-Commands) in der Firmware der Player, welche hier insbesondere die arithmetischen Instruktionen (Multiplikation, Modulobildung, bitweise Verknüpfung) betreffen und die beim "normalen" Authoring einer DVD auch nicht verwendet werden. Als Ergebnis erzeugen diese Player dann auch immer wieder die selbe Zufallszahl, so dass der Randomizer in einer Endlosschleife festhängt.
Der überarbeitete Code verhindert ein solches Festfahren, indem in eben jener Schleife noch zusätzlich ein Offset (nächster Titel) von 3 eingearbeitet wird und dieser als Startwert für den RANDU genutzt wird. Damit ist das Problem mit der Endlosschleife behoben.
Interessant ist jedoch die Beobachtung, das diese Player zwei Durchläufe benötigen, um mit der Bildung von Zufallszahlen zu beginnen. Die ersten beiden Titelnummern sind daher immer gleich (hier im Beispiel sind das die Titel 8 und 11). Wer damit nicht leben kann, kann (dieser Vorschlag stammt von taste777):
In der Playlist (hintereinander abspielen) tauchen die Dummies natürlich nicht auf. Wenn mir wieder etwas mehr Zeit zur Verfügung steht, werde ich den Randomizer um etwas "Aufwärm-Code" erweitern - z.B. zunächst mehrere Durchläufe des Randomizers, bevor mit der Titelgenerierung begonnen wird.
Als Fazit empfiehlt sich also das Testen des Randomizers auf dem eigenen Gerät, um ein ordnungsgemäßes Abspielen zumindest zu Hause sicherzustellen. An dieser Stelle auch vielen Dank an taste777, der mich auf das Problem aufmerksam gemacht hat und die entsprechenden Änderungen auf seinen Geräten getestet hat.
Im Hauptmenü ist in den Pre-Commands folgendes einzutragen:
Zeile | Code | Erklärung |
1 | GPRM2 = 20 | wie gehabt, die Anzahl der Titel (bitte ändern!) |
2 | GPRM3 = 3 | Anzahl der "Aufwärmzyklen", wer möchte, kann auch einen höheren Wert eintragen |
3 | GPRM8 = GPRM2 | Titelanzahl nach GPRM8, |
4 | GPRM8 %= 2 | auf gerade/ungerade Anzahl testen (wichtig für die Offsetbildung), |
5 | GPRM8 += 1 | um 1 erhöhen (gerade Anzahl: Offset 1, ungerade: Offset 2) |
6 | GPRM8 += GPRM1 | und den Offset zur Zufallszahl zuaddieren |
7 | GPRM0 rnd GPRM8 | |
8 | if (GPRM0 == 0) GPRM0 = 2046 | Hier beginnt der Part des RANDU |
9 | if (GPRM0 >= 2047) GPRM0 = 2046 | |
10 | GPRM0 &= 2047 | |
11 | GPRM1 = GPRM0 | |
12 | GPRM1 &= 17 | |
13 | if (GPRM1 == 1) GPRM0 |= 2048 | |
14 | if (GPRM1 == 16) GPRM0 |= 2048 | |
15 | GPRM0 /= 2 | |
16 | GPRM1 = GPRM0 | |
17 | GPRM1 %= GPRM2 | |
18 | GPRM3 -= 1 | alle Aufwärmzyklen durch? |
19 | if (GPRM3 > 0) Goto 3 | nein, weiter. |
20 | GPRM3 = GPRM2 | Initialisierung der Register wie gehabt |
21 | GPRM4 = 0 | |
22 | GPRM5 = 0 | |
23 | GPRM6 = 0 | |
24 | SetGPRMMD counter (GPRM0=0) |
Da DVDLab Pro intern die Register GPRM10 - GPRM15 nutzt, wir bereits GPRM0 - GPRM8 verwenden,
bleibt nur noch ein Register (GPRM9) übrig...
Dieses läßt sich natürlich ebenfalls als Flagregister "missbrauchen" und wir kommen dann auf
4 x 16 = 64 mögliche zufällige Titel. Wer sich den Code des Randomizers mal genauer anschaut,
wird sicherlich auch keine Probleme haben, den ergänzenden Code noch unterzubringen.
64 Titel sind dann aber wirklich als oberste Grenze anzusehen, auch im Hinblick auf die Caselist:
Diese belegt pro "Fallentscheidung" 2 VM-Commands, und mehr als 128 VM-Commands (jeweils in der
PRE- und POST-Sektion) können nicht untergebracht werden...
Gruss BJ1
[letzte Änderung: 08.06.2005]