Hohe Systemlast und Freeze bei serieller Fernsteuerung [3.0.1 Build 541]

Jau klar… wie komme ich denn in PlayerControl an die Nummer des Players? Bisher werte ich wie folgt den Namen aus:

function FindPlayer(iPlayer: IPlayerControl; var playlist, player: integer): boolean; begin for playlist := 0 to PlaylistCount - 1 do for player := 0 to PlaybackControl(playlist).GetPlayerCount - 1 do if PlaybackControl(playlist).GetPlayer(player).GetCaption = iPlayer.GetCaption then begin Result := true; exit; end; Result := false; end;

Hatte ich irgendwo hier im Forum gefunden und so adaptiert, aber wirklich schön ist das nicht, der Playername muss halt dann numerisch sein…

GetIndex

Ah ok, ist das neuer?

Build 553 wirft beim Start haufenweise “Access violation at adress 00000000, Read of address 0000000”.
Halt stop, muss irgendwo an den Scripten liegen, ohne Scripte gehts… such

Ich meine, das hab ich mal irgendwann nachträglich eingeführt, ja.

Build 553 ist da, mit zwei neuen Prozeduren:

procedure OnPlayerStateChange(PlayerControl: IPlayerControl; OldState: TPlayerState; NewState: TPlayerState);
begin
end;

procedure OnCartPlayerStateChange(PlayerControl: IPlayerControl; OldState: TPlayerState; NewState: TPlayerState);
begin
end;

Bitte auf jeden Fall vorher PlayerControl auf nil überprüfen. Denn auch der Extra-PFL-Player meldet seine Statuswechsel auf diese Weise.

Leider kann es dennoch vorkommen, dass der Player mitten in deinem Code plötzlich “weg” ist, wenn das Eigenschaften-Fenster geschlossen wird. Das liegt daran, dass die PlayerControl-Objekte derzeit nicht mehr reference counted sind, das heißt, sie können vom Eigentümer gelöscht werden, selbst wenn noch irgendwo (z.B. in einer asynchronen Nachricht) eine Referenz auf sie herumschwirrt. Ich kann das Problem nur lösen, indem ich für die Player ein reference counting einführe. Das bedeutet aber Aufwand, weil ich jede Menge Interfaces exportieren muss.

Wir müssen mit dieser “race condition” also erstmal leben.

Hab grad leider nicht die Ruhe meine Scripte umzubauen, schaue ich mir später an.

Also irgendwo muss bei Build 553 der Wurm drin sein. Habe nun ein Script auf als funktionierend bekannte Teile gekürzt (siehe unten) aber es wird beim Start direkt x-mal Access violation geworfen, sobald das Script drin ist.

[code]procedure OnStartup;
begin
ComPort(‘COM2’).SendStr(‘RESET’ + #13#10);
end;

procedure OnShutdown;
begin
ComPort(‘COM2’).SendStr(‘ALL 0’ + #13#10);
end;

begin
end.[/code]

Gruß
Dominique Görsch

Stimmt, da ist was faul. Ich kümmere mich drum.

Problem gefunden. Workaround: Die beiden leere Prozeduren OnPlayerStateChange und OnCartPlayerStateChange in alle Notification Scripts kopieren.

Neuer Build kommt aber gleich.

So, Build 555 ist da. Das wird dann auch gleichzeitig Version 3.0.2.

Hallo Torben,

habe die neue Version getestet…DTR wird prima geschaltet und zurückgesetzt.

Leider hat sich wieder ein kleiner Fehler eingeschlichen:

Wenn ich ein Element mit KLick auf dem Player per PFL anhöre (nicht PFL-Player selbst), dann wird der PLayer nicht mehr automatisch aus dem PFL Modus zurückgesetzt…

Irgendwie bin ich zu doof für das GetIndex. Habe zum Testen/Debuggen folgende Zeile unter OnPlayerStart(PlayerControl: IPlayerControl) eingefügt und bekomme immer “Type mismatch”, schon beim Start von mAirList.

SystemLog(PlayerControl.GetIndex)

GetIndex gibt eine Zahl zurück, SystemLog erwartet aber einen String. Du musst “SystemLog(IntToStr(PlayerControl.GetIndex))” schreiben.

Timo, den Bug schaue ich mir an. Aber nicht mehr heute, kriege gleich Besuch (eldoradio*-Techniker-Treffen, sozusagen).

Alles klar, kein Stress :wink:

OK danke, ich mach mich dann mal ans Scripten :wink:

\EDIT: Irgendwie werd ich mit dem RemObjects-Kram ned warm… und die Hilfe hat mir auch ned wirklich weitergeholfen. Wie komme ich nun an den Status des Players in OnPlayerStateChange(PlayerControl: IPlayerControl; OldState: TPlayerState; NewState: TPlayerState)?

Ich habs mit SystemLog(NewState), SystemLog(NewState.GetState) und was weiß ich noch allem probiert, aber ich blick bei den Objekten mal so garnicht durch…

Torben, hast du vielleicht einen Hint für mich? Ist ja nicht so, dass ich ned Programmieren könnte, aber irgendwie blick ich da ned durch.

Gruß
Dominique Görsch

PS: Hätte Scripting in Perl eine Chance auf der Wishlist? g

Perl wird wohl nicht gehen, nein :wink: Ich bin froh, dass Pascal Script so komfortabel funktioniert. Das importiert automatisch alle Schnittstellen in die Scripts, so dass man auf alle mAirList-Objekte zugreifen kann, ohne dass ich irgendeine Zeile Code schreiben müsste.

Pascal ist gar nicht so schwer. Man muss sich nur daran gewöhnen, dass es im Vergleich zu diversen Scriptsprachen (Perl, PHP, JavaScript, …) sehr stark getypt ist. Eine Zahl ist eine Zahl, und ein String ist ein String, und wenn mann die ineinander konvertieren möchte, dann muss man das explizit tun (IntToStr, StrToInt).

Außerdem kann man neue Typen deklarieren. TPlayerState ist so einer, und zwar eine Enumeration. Wenn du in der Script-Hilfe danach suchst, wirst du folgende Definition finden:

TPlayerState = ( psEmpty , psLoading , psLoaded , psPlaying , psFading , psEOF , psError , psPaused , psStopped , psPFL , psFlashEOF , psNext ) ;

Eine Variable vom Typ TPlayerState kann also einen dieser Werte annehmen. (Beachte bitte, dass die letzten drei nur für interne Zwecke - einfaches Auslesen der skin.ini - sind und in der Realität nie eintreten werden.)

Du kannst also einfach mit z.B. “if NewState = psPlaying” abfragen, ob der Player gestartet wurde.

Intern realisiert der Compiler diese Enumerationen als Zahlen (psEmpty = 0, psLoading = 1, etc.). Mit der ord()-Funktion kannst du einen TPlayerState-Wert in die entsprechende Zahl umwandeln, um diese dann zum Beispiel in einen String zu konvertieren und im System-Log auszugeben:

SystemLog('old state: ' + IntToStr(ord(OldState)) + ', new state: ' + IntToStr(ord(NewState)));

Ah… danke. Automatisches casten ist ja manchmal echt ein Fluch, aber ein bisschen flexibler könnte Pascal da schon sein. Mein letzter Kontakt zu Pascal war in der 8. Klasse glaub ich in Form von TurboPascal.

Die Enumeration hatte ich in der Scriptinghilfe schon gefunden, war für mich aber nicht als solche erkennbar. Ich war der Hoffnung es gibt den Status entweder direkt als String, oder als Index (z.b. wie in einem Array) zurück und hatte wohl wissentlich IntToStr() getestet. Auf ord() wäre ich nie gekommen… :wink: Gibts eine einterne Möglichkeit direkt an den “Namen” der Option zu kommen, ohne verschachtelte IF’s oder “Case of”?

Ich werd dann mal ein bissl Scripten… nach dem Frühstück. Schönen Sonntag, und ned vergessen: Muttertag! g

In Delphi direkt ja, aber nur mit großer Trickserei auf der Basis von Laufzeit-Typinformationen. In Scripts wird das nicht gehen.

Ok, dann bau ich mir zum Testen und Debuggen 'ne Funktion auf Basis von Case Of… oder geht das ned in Scripten?