List Index Fehler

Hallo ich habe mir ein kleines Script geschrieben was soweit auch reibungslos Funktioniert, denn wird bei mir die Log zu gespammt mit errors:

18.09.2020 23:08:57 Fehler Runtime error "List index out of bounds (1)" in background script D:\mairlist-scripts\test2.mls, handling message: PLAYERCONTROL_START 2204709A4CF9DD04 00 00000000 00000000 ?

Was ist da der Fehler?

Das Script kann ich auf anfrage dann zeigen ich möchte es hier nicht veröffentlichen

Ich ahne, woran es liegen könnte, muß aber zunächst fragen:

Wie stellst Du Dir das vor: Dein Skript funktioniert nicht, aber Du magst es nicht posten, damit Dir geholfen werden könnte?

const
  iMax = 5;                                        // Hier die maximale Senderanzahl einsetzen
  IP = '--';                           // <-- IP-Adresse
  PORT = '--';                                   // <-- Port
  PATH = 'C:\ProgramData\mAirList\6.3\sfk174.exe'; // <-- Pfad
  
var
  sl: TStringList;
  pi: IPlaylistItem;
  idx, c, i: integer;
  EncoderState: array[0 .. iMax] of integer;  

  

procedure PostOnAirScreen(Befehl: string);
begin
  ShellExecuteHidden (PATH, 'udpsend ' + IP + Chr(32) + PORT + Chr(32) + Chr(34) + Befehl + Chr(34) + Chr(32) + '-quiet');
  //ShellExecute (PATH, 'udpsend ' + IP + Chr(32) + PORT + Chr(32) + Chr(34) + Befehl + Chr(34));
end;

procedure PostOnAirLED(Befehl: string);
begin
  ShellExecuteHidden ('C:\Windows\System32\curl.exe', '-s -X POST -d @' + Befehl + '.xml http://admin:12345678@XX:XXXXXX/smartplug.cgi');
end;

procedure OnLoad;
begin
  // Eigentlich muss das nicht mal bei jedem Ladevorgang neu passieren aber so sind wir sicher, dass da keiner was verfummelt hat 
  // und man kann relativ komfortabel die Konfiguration anpassen ohne dass man an die eigentliche Anzeige ran muss
  PostOnAirScreen('CONF:LED2:autoflash=True'); // Diese Anzeige soll blinken, blinkede Anzeigen sehen immer wichtig aus.
  PostOnAirScreen('CONF:LED3:text=EOF'); // Auf dem Button soll EOF stehen.
  PostOnAirScreen('CONF:CONF:APPLY=TRUE'); 
  PostOnAirScreen('LED1:OFF');
  PostOnAirScreen('LED2:OFF');
  PostOnAirScreen('LED3:OFF');
  PostOnAirScreen('LED4:OFF');
  PostOnAirScreen('AIR4:OFF');
  PostOnAirScreen('AIR4:RESET');
  
end;

procedure OnEncoderInputToggle(Input: TEncoderInput; NewState: boolean);
begin
  if Input = eiMic then begin
    if NewState = true then begin
      PostOnAirScreen('AIR1:ON');
	  //PostOnAirLED('on');
	  end
    else begin
      PostOnAirScreen('AIR1:OFF');
	  //PostOnAirLED('off');
	  end
  end;
end;



procedure OnRuntimeDataChange(Key, Value: string);
begin
  if Key = 'EncoderStatus' then begin
    if Value = ('true') then begin
	  PostOnAirScreen('AIR4:OFF');
      PostOnAirScreen('AIR4:RESET');
	  end
	else begin
	  PostOnAirScreen('AIR4:ON');
	  end;
	end
  else if Key = 'GamepadStatus' then begin
    PostOnAirScreen(Value);
	end
  else if Key = 'EncoderError' then begin
    PostOnAirScreen(Value);
	end;
end;

procedure OnPlayerStart(PlaylistIndex: integer; PlayerIndex: integer; Item: IPlaylistItem);

begin
  idx := CurrentPlaylist.IndexOf(item);
  if idx = -1 then begin
    SystemLog('Das war kein Element aus unserer Playlist ...');
    exit;
  end;

  sl := TStringList.Create;
  c := 0;                                                                                                       
  while (idx < CurrentPlaylist.GetCount) and (c < 2) do begin
    pi := CurrentPlaylist.GetItem(idx);
    sl.Add(pi.GetArtist + Chr(32) + 'mit' + Chr(32) + pi.GetTitle );
    c := c + 1;
    idx := idx + 1;
  end;
  PostOnAirScreen('NOW:' + sl[0] );
  PostOnAirScreen('NEXT:' + sl[1] );
  sl.Free;
end;

procedure OnOnAir;
begin
  PostOnAirScreen('LED1:ON');
end;

procedure OnOffAir;
begin
  PostOnAirScreen('LED1:OFF');
end;

procedure OnPlayerEOFWarning(PlaylistIndex: integer; PlayerIndex: integer);
begin
  PostOnAirScreen('LED3:ON');
end;

//procedure OnPlayerStop(PlaylistIndex: integer; PlayerIndex: integer; Duration: TTimeValue; Item: IPlaylistItem);
procedure OnPlayerStateChange(PlaylistIndex: integer; PlayerIndex: integer; OldState: TPlayerState; NewState: TPlayerState; Item: IPlaylistItem);
begin
  PostOnAirScreen('LED3:OFF');
end;

procedure OnShutdown; // Sollte den Rechner mit den OnAirScreen herunterfahren, funktioniert bisher aber nicht.
begin
  PostOnAirScreen('CMD:SHUTDOWN');
end;


begin
end.

Danke. Der Fehler ist derselbe wie hier. Achte insbesondere auf die procedure OnPlayerStart.
 

Veraltete Grüße

TSD

Hier der Alte command:
procedure OnPlayerStart(PlaylistIndex: integer; PlayerIndex: integer; Item: IPlaylistItem);,

Hier dann jetzt der neue:
procedure OnPlayerStart(PlaylistIndex: integer; PlayerIndex: integer; Duration: TTimeValue; Item: IPlaylistItem);

Nachdem ich das gemacht habe kommt der Fehler aber immernoch

Dann ist es noch ein anderer. Bitte überprüfe alle procedures und vergleiche mit den aktuellen, die Du hier findest. Und poste mal die Fehlermeldung, die immer noch auftaucht.

Also es ist alles auf dem neusten stand und das ist die aktuelle Meldung:

20.09.2020 19:36:29 Fehler       Runtime error "List index out of bounds (1)" in background script D:\mairlist-scripts\LEDuScreen.mls, handling message: PLAYERCONTROL_START 1BC30336662B2A10 00 00000000 00000000 ?

Hier ist schonmal eine potentielle Ursache: Du gibst die ersten beiden Elemente der StringList aus, ohne zu überprüfen, wie viele Einträge sie überhaupt hat. (Wenn es kein “Next”-Element gibt, dann hat sie nur einen Eintrag - nämlich den aktuellen Titel - und das sl[1] führt dann genau zu der Fehlermeldung “List index out of bounds (1)”).

Edit: Weiterhin kann ich nur empfehlen, den gesamten Block in ein BeginRead...EndRead zu packen, denn die Scripts laufen in einem Hintergrund-Thread ab, und es kann durchaus sein, dass gleichzeitig ein anderer Thread Änderungen an der Playlist vornimmt, wenn du sie nicht sperrst. Insbesondere kann es passieren, dass der andere Thread dir genau in der Millisekunde zwischen GetCountund GetItem(idx) etwas oben aus der Liste rauslöscht, und schon passt alles nicht mehr zusammen.

Daher lieber so machen:

CurrentPlaylist.BeginRead;
try
  // hier den Rest der Befehle
finally
  CurrentPlaylist.EndRead;
end;

Falls man nicht nur lesen möchte sondern auch Änderungen vornehmen, benutzt man stattdessen BeginUpdate und EndUpdate.

1 Like

Ersetze die procedure OnPlayerStart durch folgende:

procedure OnPlayerStart(PlaylistIndex: integer; PlayerIndex: integer; 
  Duration: TTimeValue; Item: IPlaylistItem);
begin
  CurrentPlaylist.BeginRead;
  try
    idx := CurrentPlaylist.IndexOf(item);
    if idx = -1 then begin
      SystemLog('Das war kein Element aus unserer Playlist ...');
      exit;
    end;

    sl := TStringList.Create;
    c := 0;                                                                                                       
    while (idx < CurrentPlaylist.GetCount) and (c < 2) do begin
      pi := CurrentPlaylist.GetItem(idx);
      sl.Add(pi.GetArtist + Chr(32) + 'mit' + Chr(32) + pi.GetTitle );
      c := c + 1;
      idx := idx + 1;
    end;
    if CurrentPlaylist.GetCount > 0 then
      PostOnAirScreen('NOW:  ' + sl[0]);
    if CurrentPlaylist.GetCount > 1 then
      PostOnAirScreen('NEXT: ' + sl[1]);
    sl.Free;
  finally
    CurrentPlaylist.EndRead;
  end;
end;

procedure OnOnAir;
begin
  PostOnAirScreen('LED1:ON');
end;

(Ungetestet.)

1 Like

Oh, ich sehe gerade: die procedure OnOnAir ist mir da noch reingerutscht, die kann unverändert bleiben.

@manuel.sueffert: Wie ist denn der Stand der Dinge? Geht’s denn jetzt?

Rückmeldende Grüße

TSD

Also der fehler ist bis jetzt nicht mehr aufgetreten wenn ich aber es so mache wie du es zuletzt gemeint hast ist er wieder da