OnPlayerStateChange – Denkfehler?

Und hier eine neue Denksportaufgabe aus mAirLists Skript-Büchlein:

Beim Ladevorgang eines Players (if NewState = psLoading) kann ich schauen, um welchen der Player es sich handelt (PlayerIndex) und entsprechende Maßnahmen ergreifen. Gut. Verschiebe ich jetzt aber ein Element zwischen Player A und Player B, dann findet im jeweils anderen Player ja auch ein Ladevorgang statt, und der PlayerIndex ist plötzlich ein völlig anderer, was meine ursprünglichen Maßnahmen konterkariert.

Welchen Denkfehler mache ich hier?! Wie kann ich meine Maßnahmen auf den gewünschten Player fokussieren?

Verwirrte Grüße

TSD

Lass’ mich bitte mal mitdenken: Ich meine mich erinnern zu können, dass du mAirList weitestgehend mauslos bedienen wolltest.

Preisfrage: Wie “verschiebst” (!) du das Element denn, wenn ohne Maus - und kannst du den Vorgang an sich nicht abfragen?

  • Beide Player sind geladen und sollen tauschen. In dem Fall käme
    PLAYLIST 1 SWAP x y
    zum tragen. Lässt sich dieses Kommando nicht abfragen?

  • Nur ein Player ist geladen und soll von A nach B wechseln. Dadurch wechselt der bislang geladene Player den Player State von Loaded auf Empty.

Hilft dir das bei der Entwirrung?

Können wir uns bitte auf die Sache fokussieren?! Von „mauslos“ war nirgendwo die Rede. Von externen Befehlen zum Wechseln auch nicht. Welchen Preis lobst Du aus? Habe ich den Sachverhalt unverständlich dargestellt? Ich bitte um dahingehende Klarstellung.

Ja, aber wenn der andere Player vorher besetzt war, wird der ursprüngliche eben nicht empty sondern gleichwohl loaded. Und nu?

Also musst du diesen Fall im Grunde einfach ignorieren, oder habe ich etwas falsch verstanden?

Dazu würde ich mir einfach in 2 Variablen Artist und Titel der beiden Player merken, die geladen wurden.
Und wenn diese nun nur vertauscht sind,

Ignorieren…

Ignorieren kann ich das leider nicht, weil das Laden der Auslöser für gewisse weitere Schritte sein soll.

Ja, und damit fängt die Misere an: Der eine Titel wird in Player 0 geladen, den vergleiche ich dann mit dem anderen in Player 1. Und welcher ist der andere? Der mit dem anderen Playerindex natürlich. Zu diesem Zweck könnten wir die komfortablerweise zur Verfügung stehenden Variablen Item und PlayerIndex heranziehen. Da aber (beinahe) gleichzeitig auch im anderen Player ein Titel geladen wird, ändert sich folglich der Playerindex, und der andere Titel ist plötzlich der eine!

Man erhält also ein wenn nicht zufälliges, so doch zumindest nicht vorhersehbares Ergebnis. Diese Erkenntnis hat mich einen Nachmittag gekostet.

Ich werde jetzt nach dem Laden ein kleines Sicherheitspäuschen einlegen und dann versuchen, die Player direkt anzusprechen bzw. auszulesen.

Ich verstehe das Problem noch nicht ganz.

OnPlayerStateChange wird immer dann aufgerufen, wenn irgendein Player seinen Zustand geändert hat. Wobei die Nummer des Players ( PlayerIndex) und seiner Playlist (PlaylistIndex) als Parameter übergeben werden, so dass du die Ereignisse bei Bedarf filtern kannst.

Die Player arbeiten (z.B. beim Laden) dabei jeder in seinem eigenen Thread, also “gleichzeitig”; es kann also durchaus sein, dass du in aufeinanderfolgenden Aufrufen von OnPlayerStateChange mal Ergeinisse von Player 0 und dann wieder von Player 1 erhälst. (Wobei OnPlayerStateChange immer nur einmal gleichzeitig aufgerufen wird.) Wenn du aber die Aufrufe für einen bestimmten Player betrachtest, sollte die Reihenfolge der Statusänderungen immer Sinn ergeben.

Wenn man jeden Player für sich betrachten kann, ist alles gut. Ich möchte aber neben dem Element des einen Players (PlayerIndex) auch etwas mit dem anderen machen (Abs(PlayerIndex - 1)). Beispiel:

var
  BlueItemLoaded: Array[0..1] of boolean;
// PlayerPriority = 0: Player A hat Vorrang,
//              … = 1: Player B hat Vorrang,
//              … = -1: keiner hat Vorrang
  PlayerPriority: integer;    
  
procedure OnLoad;
var i: integer;
begin
  PlayerPriority := -1;
  for i := 0 to 1 do
    BlueItemLoaded[i] := false;
end;

function abs(r: integer): integer;
begin
  if r < 0 then
    Result := r * -1
  else
    Result := r;
end;

procedure OnPlayerStateChange(PlaylistIndex: integer; 
  PlayerIndex: integer; OldState: TPlayerState; 
  NewState: TPlayerState; Item: IPlaylistItem);
begin
  if NewState = psLoaded then
  begin
  // WENN ITEM BLAU
    if Item.GetColor = $FF0000 then
    begin
      BlueItemLoaded[PlayerIndex] := true;
  // Player mit blauem bekommt Vorrang
      PlayerPriority := PlayerIndex;                                         
  // Wenn der andere Player auch schon ein blaues Item hat,
      if BlueItemLoaded[abs(PlayerIndex - 1)] then  
  // dann bleibt der Vorrang bei ihm. (Der erste gewinnt.)   
        PlayerPriority := abs(PlayerPriority - 1);
    end
    else
  // WENN ITEM NICHT BLAU
    begin
  // Mach was anderes
    end;
  end;
  SystemLog(IntToStr(PlayerPriority));
end;

begin
end.


  • Wenn ein blaues Element in Player 0 geladen wird, hat er Vorrang. Gut, geht.
  • Wenn ein blaues Element in Player 1 geladen wird, soll er Vorrang bekommen, aber nur, wenn der andere Player noch kein blaues Element hatte! Geht auch.
  • Wenn beide Player jeweils ein blaues Element haben, und ich verschiebe die beiden Elemente untereinander, sei es mit dem Befehl PLAYLIST 1 SWAP 1 2 oder sei es mit einem beherzten Mausschub, dann soll der Vorrang bei dem Element bleiben, das vorher schon Vorrang hatte, sprich: die Player tauschen den Vorrang.

Gerade der letzte Punkt geht so nicht, denn wenn ich das Element aus Player 0 in Player 1 schiebe, dann habe ich tatsächlich zwei Ladevorgänge, denn es wird ja auch das Element aus Player 1 nach Player 0 verschoben. Damit ändert sich aber der PlayerIndex, weil ja der andere Player seinen auch loswerden will. Das Ergebnis wird zufällig.

Nachtrag: Ich bin mal weg von den ganzen PlayerIndices und habe das ganze so gelöst, daß ich die Playerzustände jeweils direkt abfrage. Folge: Alles funktioniert, sogar sicherer, nur beim Verschieben zweier „blauen“ untereinander bekomme ich einen doppelten Trigger über psLoaded – die ursprünglich richtige PlayerPriority wird sofort wieder durch ihr Gegenteil überbügelt.

Ich habe es jetzt über eine Zeitsperre gelöst.

1 Like