Ein Playlist-Generator mit zufälliger Auswahl der Titel mit DVDLab (Pro)

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

Wir haben zwei Probleme:

  1. Der VM-Command-Set besitzt eine Funktion zum Ermitteln einer (Pseudo-) Zufallszahl. Jedoch ist dieses Command in vielen DVD-Playern so schlecht implementiert, daß zwar eine zufällige Zahlenreihe generiert wird, diese aber nach dem Einlegen einer DVD immer wieder die gleiche ist. Da kann man auch gleich würfeln und die Ergebnisse in einer Playlist ablegen.
    Hier muss ein eigener (softwaregesteuerter) Zufallszahlengenerator her. Wir verwenden eine sogenannte RANDU (RANDom Unit) welche - aus heutiger Sicht - in leistungsschwachen Rechnersystemen (Großrechner der 60er und 70er sowie erste PCs) verwendet wurde und gleichverteilte Zufallszahlen generiert. Ausgangspunkt für den Einsatz einer RANDU war dieser Thread im Forum von Mediachance (www.mmbforums.com). Vielen Dank an dieser Stelle an Santiago und Vapymid. Wer mehr über die RANDU und den theoretischen Hintergrund wissen will, kann sich hier umfassend informieren.


  2. Wie soll man sich merken, welcher Titel bereits gespielt worden ist? Das geht per Merkregister (GPRM), welches ja bekanntermaßen 16 Bits hat. Jedes Bit kann den Zustand 0 oder 1 haben. Weisen wir ein Bit einem Titel zu und setzen wir dieses Bit auf 1, wissen wir, daß dieser Titel bereits gespielt wurde (oder eben noch läuft). Diese Vorgehensweise nennt sich "flaggen" (Flagge oben - Titel gespielt, Flagge unten - Titel nicht gespielt), ist jedoch auf maximal 16 Titel begrenzt - was doch etwas wenig ist.
    Ich stelle hier eine Variante vor, welche maximal 48 Titel verwalten kann. Der Aufwand an Registern ist jedoch nicht unbeträchtlich, so werden insgesamt 9 (!) GPRMs "verbraten", davon allein 3 für die "Flaggen" (3 x 16 = 48).

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.

Zur Struktur der DVD:

Connection Window - für
größeres Bild bitte anklicken

Die Registerbelegung

Folgende Register werden vom VM-Command-Modul verwendet und dürfen nicht anderweitig verändert werden:

GPRM0Hilfsregister Zahlengenerator
GPRM1errechnete Zufallszahl, wird später für die Caselist verwendet
GPRM2Anzahl der Titel/DVD (max. 48)
GPRM3Countdown-Counter, ist dieser 0, sind alle Titel gespielt.
GPRM4Flagregister für die Titel 0-15
GPRM5Flagregister für die Titel 16-31
GPRM6Flagregister für die Titel 32-47
GPRM7Hilfsregister
GPRM8Hilfsregister

Jetzt wird es ernst - die VM-Commands.

Im Haupt- bzw. Auswahlmenü werden folgende PRE-Commands eingearbeitet. Fett hervorgehobene Commands müssen evtl. angepasst werden!

UPDATE: Bitte den Code weiter unten verwenden!

ZeileCodeErklärung
1GPRM2=20Anzahl der Titel/DVD - dieser Wert muss individuell angepasst werden!
2GPRM3=GPRM2unser Countdown-Zähler. Hier wird er auf die Anz. Titel/DVD gesetzt (GPRM2)
3GPRM4=0Flagregister Titel 0...15
4GPRM5=0Flagregister Titel 16...31
5GPRM6=0Flagregister Titel 32...47
6SetGPRMMD 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)

ZeileCodeErklärung
1if (GPRM3==GPRM7) LinkPGCN 2Counter 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)

2GPRM8=GPRM2Ermittlung des Offsets anhand der Titelanzahl
3GPRM8%=2Startoffset (0: gerade Titelanzahl, 1: ungerade)
4GPRM8+=1um 1 erhöhen
5GPRM8+=GPRM1und letzte Zufallszahl addieren
6if (GPRM7!=0) GPRM0 rnd GPRM8letzte Titelnummer war nicht frei, neuen Seed setzen
7if (GPRM0==0) GPRM0=2046Hier beginnt der Part des RANDU
8if (GPRM0>=2047) GPRM0=2046Dieser arbeitet mit bestimmten Primzahlenkombinationen,
9GPRM0&=2047um gleichverteilte Zufallszahlen zu erzeugen.
10GPRM1=GPRM0Dazu werden Bitmasken gesetzt, verschoben und verknüpft.
11GPRM1&=17 
12if (GPRM1==1) GPRM0|=2048 
13if (GPRM1==16) GPRM0|=2048 
14GPRM0/=2 
15GPRM1=GPRM0Unsere zufällige Titelnummer (0...2046)
16if (GPRM7!=0) GPRM1=GPRM8Damit 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.
17GPRM1%=GPRM2Titelnummer wird auf einen Bereich von 0... Anz. Titel - 1 begrenzt (Modulo-Bildung)

18GPRM7=GPRM1Titelnummer in GPRM7
19GPRM8=GPRM1und GPRM8 merken
20GPRM7/=16Flagregister 1, 2 oder 3?
21GPRM8%=16"Bitschiebezähler" - welches Flag (0...7)?
22if (GPRM7==2) Goto 44Flagregister 3
23if (GPRM7==1) Goto 34Flagregister 2

24GPRM7=1Flagregister 1, Bit 0 auf 1 setzen
25if (GPRM8==0) Goto 29Bitschieberei beendet, weiter
26GPRM7*=2Bit um eine Position nach links schieben,
27GPRM8-=1"Schiebezähler" runterzählen
28Goto 25und (evtl.) weiterschieben...
29GPRM8=GPRM7Flag merken
30GPRM7&=GPRM4und testen, ob bereits gesetzt
31if (GPRM7!=0) Goto 2ja, bereits gespielt, neue Zufallszahl ermitteln
32GPRM4|=GPRM8nein, Flag jetzt setzen
33Goto 53und noch ein paar Commands ausführen

34GPRM7=1das Gleiche, nur für Flagregister 2 (GPRM5)
35if (GPRM8==0) Goto 39 
36GPRM7*=2 
37GPRM8-=1 
38Goto 35 
39GPRM8=GPRM7 
40GPRM7&=GPRM5 
41if (GPRM7!=0) Goto 2 
42GPRM5|=GPRM8 
43Goto 53 

44GPRM7=1und hier für Flagregister 3 (GPRM6)
45if (GPRM8==0) Goto 49 
46GPRM7*=2 
47GPRM8-=1 
48Goto 45 
49GPRM8=GPRM7 
50GPRM7&=GPRM6 
51if (GPRM7!=0) Goto 2 
52GPRM6|=GPRM8 

53GPRM3-=1Counterzähler um 1 runterzählen
54LinkPGCN 4und ab zur Caselist. In der Caselist wird GPRM1 ausgewertet.

Die Caselist

Die Caselist

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.






Erste Tests

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.

Update (08.06.2005)

Da auf einigen (auch hier getesteten) Geräten die ersten zufällig generierten Titelnummern immer gleich waren, habe ich den Randomizer um einen "Warmlaufcode" erweitert. Im Prinzip erfolgen einfach ein paar Durchläufe des Zufallszahlengenerators, um diesen zu initialisieren, der Code selbst befindet sich jedoch nicht im Randomizer (dem VM-Command-Object) selbst, sondern im Haupt- bzw. Auswahlmenü. Das ist möglich, da ja die zuletzt erzeugte Zufallszahl permanent in GPRM1 gehalten wird. Außerdem wurde ein kleiner Bug behoben, welcher den Offset zum Verhindern des Festfahrens falsch berechnete. Mit dem neuen Code ist die von taste777 vorgeschlagene Vorgehensweise mit den "Schwarzdummys" somit hinfällig.

Zum Code:

Im Hauptmenü ist in den Pre-Commands folgendes einzutragen:

ZeileCodeErklärung
1GPRM2 = 20wie gehabt, die Anzahl der Titel (bitte ändern!)
2GPRM3 = 3Anzahl der "Aufwärmzyklen", wer möchte, kann auch einen höheren Wert eintragen
3GPRM8 = GPRM2Titelanzahl nach GPRM8,
4GPRM8 %= 2auf gerade/ungerade Anzahl testen (wichtig für die Offsetbildung),
5GPRM8 += 1um 1 erhöhen (gerade Anzahl: Offset 1, ungerade: Offset 2)
6GPRM8 += GPRM1und den Offset zur Zufallszahl zuaddieren
7GPRM0 rnd GPRM8

8if (GPRM0 == 0) GPRM0 = 2046Hier beginnt der Part des RANDU
9if (GPRM0 >= 2047) GPRM0 = 2046
10GPRM0 &= 2047
11GPRM1 = GPRM0
12GPRM1 &= 17
13if (GPRM1 == 1) GPRM0 |= 2048
14if (GPRM1 == 16) GPRM0 |= 2048
15GPRM0 /= 2
16GPRM1 = GPRM0
17GPRM1 %= GPRM2

18GPRM3 -= 1alle Aufwärmzyklen durch?
19if (GPRM3 > 0) Goto 3nein, weiter.

20GPRM3 = GPRM2Initialisierung der Register wie gehabt
21GPRM4 = 0
22GPRM5 = 0
23GPRM6 = 0
24SetGPRMMD counter (GPRM0=0)

Ausblick

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]