Ich habe inzwischen an die 20 - 30 Seiten im Netz gefunden auf denen einem Pascal in diversen Vorgehensweisen erklärt wird. Also zumindest die Basics… Allerdings finde ich keine Seite oder ähnliches die das in Zusammenhang mit Delphi tut.
Gibt es zu Delphi / Pascal irgendeine gute Seite oder entsprechende Litheratur?
Dabei suche ich aber eben die reine Programmierung, keine Anleitung für die Delphi-Oberfläche.
Denn so komme ich sonst kaum mit dem Script weiter.
Aber, es kommt immer nur drauf an was in mAirList verfügbar ist. Nicht alle Befehle, Parameter, etc… müssen in mAirList funktionnieren, das kommt drauf an was der Doc als Befehlssatz mit eingebunden hat.
(Siehst du ja an der Variablendeklaration, dass schon solche elementare Sachen nicht immer funzen)
Alternativ kannst du immer noch deinen kompletten Script posten. Wir bekommen den dann schon an’s Laufen…
Das ursprüngliche Script ist ziemlich lang und vermutlich mangels Wissen auch kürzer zu gestalten. Aber bis auf einen Punkt hat es fehlerfrei funktioniert.
Ziel des Scripts:
Bei 5 Encodern plus Aircheck soll folgendes optisch angezeigt werden, wobei der Aircheck nicht abgefragt werden muß.
a) Welcher Encoder ist deaktiviert.
b) Welcher Encoder ist aktiviert und hat die Verbindung zum Server erfolgreich hergestellt.
c) Welcher Encoder ist aktiviert, aber nicht verbunden (hier ist das größte Problem).
zu a)
Der statische Text “Encoder X” ist neutral (weiße Schrift auf schwarzem Grund)
zu b)
Der statische Text “Encoder X” ist aktiv/verbunden (schwarze Schrift auf grünem Grund)
zu c)
Der statische Text “Encoder X” ist aktiv/nicht verbunden (weiße Schrift auf rot blinkendem Grund)
Zusätzlich blinkt dazu abwechselnd der statische Text “Disconnected” rot im Sekundentakt. Dieser ist aber für alle Encoder.
Ich hoffe meine Gedankengänge dazu sind nicht zu verwirrend :o
Es sind genaugenommen zwei Probleme die das Script ausbremsen.
Zum einen entspricht “ecsConnected” nicht dem Gegenteil von “ecsDisconneted”.
“ecsConnected” gilt für den Moment in dem der Encoder tatsächlich mit dem Server eine Verbindung aufgebaut hat. Also alleine das anklicken “Verbinden” reicht hierfür noch nicht.
“ecsDisconnected” hingegen reagiert erst auf das Klicken des Buttons “Trennen”, ein Verbindungsverlust zum Server reicht hier noch nicht aus. (Was aber wünschenswert wäre)
Das Andere ist die Anzeige, dass ein Encoder seine Verbindung nicht hergestellt oder verloren hat, was soweit auch gut funktioniert. Um aber einen Disconnect während einer Sendung deutlich zu machen hatte ich die Idee den Schriftzug mittels “sleep(1000)” jede Sekunde blinken zu lassen. Nicht notwendig, aber nice to have.
Hier werde ich aber wohl auf ein zweites Script ausweichen müssen, denn die kürzere Version des Scripts (siehe unten) würde dann in der For-Schleife jedesmal eine Sekunde hinzuzählen und der Effekt wäre zunichte.
Ja Torben, ecsConnecting wollte ich sowieso auch mit einbinden.
Die Angaben von Anna sind leider widersprüchlich:
"ecsDisconnected" hingegen reagiert erst auf das Klicken des Buttons "Trennen", ein Verbindungsverlust zum Server reicht hier noch nicht aus. (Was aber wünschenswert wäre)
Wie ist das zu verstehen. ecsDisconnected schaltet nicht auf "true" wenn ein Verbindungsverlust stattfindet???
Ja dann ist das Ganze eigentlich 'vergebene Liebesmüh'
Das Andere ist die Anzeige, dass ein Encoder seine Verbindung nicht hergestellt oder verloren hat, was soweit auch gut funktioniert...
Ja wie denn nun? Hier funktionniert es dann plötzlich, obwohl auch nur ecsDisconnected abgefragt wird...
Wenn der Encoder gekickt wurde, geht die Verbindung sofort wieder in den Status ecsConnecting (Verbindung wird wiederhergestellt). Vor dem ersten tatsächlichen Verbindungsversuch wird allerdings zunächst die eingestellte Anzahl an Sekunden gewartet.
active := BASS_Encode_IsActive(fEncoder);
if active <> BASS_ACTIVE_PLAYING then begin
BASS_Encode_Stop(fEncoder);
fEncoder := 0;
DoChangeState(ecsConnecting);
fInstance.Logger.SystemLog(lcError, Format(_('Lost encoder connection: error code %d. Reconnect in %d seconds.'), [active, fReconnectDelay]));
EndUpdate;
try
fConnectThread.WaitForEvent(fReconnectDelay * 1000);
finally
BeginUpdate;
end;
continue;
end;
So, habe das mal mit 2 Aichecks probiert, da ich keinen Teststream zur Verfügung hatte.
Funzt soweit mal.
@Anna, ist es so ungefähr wie du dir das gedacht hast?
In dem Samplecode werden die Status von Encoder 0 und 1 abgefragt. Du hast Encoder 1-5 wenn ich mich recht erinnere.
Musst also nur die for-Schleife entsprechend anpassen.
Für die einzelnen Encoder hast du auch nur die Schriftfarbe und Hintergrundfarbe geändert. Ich habe jetzt zusätzlich noch einen Text eingefügt.
[code]var
Encoderflag, blinkflag: boolean;
procedure OnLoad;
begin
EnableTimer(1000);
end;
procedure OnTimer;
var
i: integer;
begin
// ########## ENCODER STATUS ##########
Encoderflag := false;
for i := 0 to 1 do begin
if (Encoder.GetConnections.GetItem(i).GetEnabled = true) and (Encoder.GetConnections.GetItem(i).GetState = ecsConnecting) then begin
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ TEXT ENCODER CONNECTING’); // Encoder Status
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ FONTCOLOR #FFFFFF’); // Encoder Schrift weiss
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ BACKGROUNDCOLOR #0000FF’); // Encoder Hintergrund blau
end;
if (Encoder.GetConnections.GetItem(i).GetEnabled = true) and (Encoder.GetConnections.GetItem(i).GetState = ecsConnected) then begin
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ TEXT ENCODER CONNECTED’); // Encoder Status
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ FONTCOLOR #000000’); // Encoder Schrift schwarz
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ BACKGROUNDCOLOR #00FF00’); // Encoder Hintergrund grün
end;
if (Encoder.GetConnections.GetItem(i).GetEnabled = true) and (Encoder.GetConnections.GetItem(i).GetState = ecsDisconnected) then begin
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ TEXT ENCODER DISCONNECTED’); // Encoder Status
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ FONTCOLOR #FFFFFF’); // Encoder Schrift weiß
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ BACKGROUNDCOLOR #FF0000’); // Encoder Hintergrund rot
Encoderflag := true;
end;
if Encoder.GetConnections.GetItem(i).GetEnabled = false then begin
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ TEXT ENCODER INACTIVE’); // Encoder Status
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ FONTCOLOR #FFFFFF’); // Encoder Schrift weiß
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ BACKGROUNDCOLOR #000000’); // Encoder Hintergrund schwarz
end;
end;
// ########## ERROR-MELDUNG ##########
if Encoderflag = true then begin
if blinkflag = true then begin
ExecuteCommand(‘ENCODER_ERROR TEXT ENCODER ERROR’); // Error-Meldung
ExecuteCommand(‘ENCODER_ERROR FONTCOLOR #FF0000’); // Error Schrift rot
ExecuteCommand(‘ENCODER_ERROR BACKGROUNDCOLOR #000000’); // Encoder Hintergrund schwarz
end
else begin
ExecuteCommand(‘ENCODER_ERROR TEXT ENCODER ERROR’); // Error-Meldung
ExecuteCommand(‘ENCODER_ERROR FONTCOLOR #000000’); // Error Schrift schwarz
ExecuteCommand(‘ENCODER_ERROR BACKGROUNDCOLOR #FF0000’); // Encoder Hintergrund rot
end;
blinkflag := not blinkflag; // Toggle
end
else begin
ExecuteCommand(‘ENCODER_ERROR TEXT ENCODERS OK’); // Error-Meldung
ExecuteCommand(‘ENCODER_ERROR FONTCOLOR #00FF00’); // Error Schrift grün
ExecuteCommand(‘ENCODER_ERROR BACKGROUNDCOLOR #000000’); // Encoder Hintergrund schwarz
end;
end;
[quote=“radiorom, post:49, topic:8172”]wann wird denn ecsError gesetzt?
Sollte man das eventuell auch mit auswerten?[/quote]
Bei Shoutcast/Icecast-Verbindungen kommt ecsError nicht vor.
Das hat lediglich beim Aircheck (Datei konnte nicht angelegt werden) um beim integrierten Server (Server konnte nicht gestartet werden da Port belegt etc.) eine Relevanz.
Die normalen Shoutcast/Icecast-Verbindungen bleiben im Fehlerfall im Zustand ecsConnecting und versuchen es nach der eingestellten Zeit einen neuen Verbindungsaufbau.
soweit funktioniert das Script jetzt nach drei kleinen Änderungen perfekt.
Zum einen mußte ich in der ersten If-Schleife noch die Variable “Encoderflag := true” setzen. Wenn man ansonsten auf mehrere Encoder streamt und einer verliert die Verbindung, wird nachwievor “ENCODER OK” angezeigt. Jetzt wird sobald ein aktivierter Encoder nicht verbunden wird oder die Verbindung verloren hat eine blinkende Error-Warnung ausgegeben.
Zum anderen habe ich die Encoder Texte rausgenommen “//” da meine Encoder ja nach ihrer Zugehörigkeit beschriftet sind und dann nicht mehr erkennbar wäre welcher Encoder gerade nicht funktioniert. (siehe Bilder)
Zu guter letzt habe ich für die Anzahl der Encoder noch eine Variable vergeben um später das Anpassen für interessierte User zu erleichtern.
Die Lösung für das gleichmäßige Blinken … Respekt … an eine wechselnd durchlaufende Schleife in Verbindung mit dem Timer habe ich nicht gedacht.
Zwei Fragen habe ich noch:
ist es innerhalb eines so großen Programms und eventuell mehrerer Scripte nicht gefährlich nur “i” als Variable für die For-Schleife zu verwenden?
Die Variable “blinkflag” ist doch boolean. Ist diese dann von grundauf “true”? Zudem kann ich mit der Zeile “blinkflag := not blinkflag;” nichts anfangen?
[code]var
Encoderflag, blinkflag: boolean;
procedure OnLoad;
begin
EnableTimer(1000);
end;
procedure OnTimer;
var
i, x: integer;
begin
// ########## ENCODER STATUS ##########
Encoderflag := false;
x := 5; // Anzahl der Encoder ohne Aircheck
for i := 1 to x do begin
if (Encoder.GetConnections.GetItem(i).GetEnabled = true) and (Encoder.GetConnections.GetItem(i).GetState = ecsConnecting) then begin
// ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ TEXT ENCODER CONNECTING’); // Encoder Status
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ FONTCOLOR #FFFFFF’); // Encoder Schrift weiss
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ BACKGROUNDCOLOR #FF0000’); // Encoder Hintergrund rot
Encoderflag := true;
end;
if (Encoder.GetConnections.GetItem(i).GetEnabled = true) and (Encoder.GetConnections.GetItem(i).GetState = ecsConnected) then begin
// ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ TEXT ENCODER CONNECTED’); // Encoder Status
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ FONTCOLOR #000000’); // Encoder Schrift schwarz
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ BACKGROUNDCOLOR #00FF00’); // Encoder Hintergrund grün
end;
if (Encoder.GetConnections.GetItem(i).GetEnabled = true) and (Encoder.GetConnections.GetItem(i).GetState = ecsDisconnected) then begin
// ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ TEXT ENCODER DISCONNECTED’); // Encoder Status
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ FONTCOLOR #FFFFFF’); // Encoder Schrift weiß
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ BACKGROUNDCOLOR #FF0000’); // Encoder Hintergrund rot
Encoderflag := true;
end;
if Encoder.GetConnections.GetItem(i).GetEnabled = false then begin
// ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ TEXT ENCODER INACTIVE’); // Encoder Status
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ FONTCOLOR #FFFFFF’); // Encoder Schrift weiß
ExecuteCommand(‘ENCODER_’ + IntToStr(i) + ’ BACKGROUNDCOLOR #000000’); // Encoder Hintergrund schwarz
end;
end;
// ########## ERROR-MELDUNG ##########
if Encoderflag = true then begin
if blinkflag = true then begin
ExecuteCommand(‘ENCODER_ERROR TEXT ENCODER ERROR’); // Error-Meldung
ExecuteCommand(‘ENCODER_ERROR FONTCOLOR #FF0000’); // Error Schrift rot
ExecuteCommand(‘ENCODER_ERROR BACKGROUNDCOLOR #000000’); // Encoder Hintergrund schwarz
end
else begin
ExecuteCommand(‘ENCODER_ERROR TEXT ENCODER ERROR’); // Error-Meldung
ExecuteCommand(‘ENCODER_ERROR FONTCOLOR #000000’); // Error Schrift schwarz
ExecuteCommand(‘ENCODER_ERROR BACKGROUNDCOLOR #FF0000’); // Encoder Hintergrund rot
end;
blinkflag := not blinkflag; // Toggle
end
else begin
ExecuteCommand(‘ENCODER_ERROR TEXT ENCODERS OK’); // Error-Meldung
ExecuteCommand(‘ENCODER_ERROR FONTCOLOR #00FF00’); // Error Schrift grün
ExecuteCommand(‘ENCODER_ERROR BACKGROUNDCOLOR #000000’); // Encoder Hintergrund schwarz
end;
end;
[quote=“Anna On Air, post:52, topic:8172”]…
Zum einen mußte ich in der ersten If-Schleife noch die Variable “Encoderflag := true” setzen…[/quote]
Das ist Auslegungssache wie man ecsConnecting betrachtet. Für mich bedeutet das: (noch) nicht verbunden.
Ich verstehe aber was du erreichen möchtest. Wirst du vom Stream gekicked verbindet der Encoder sich wieder automatisch und das soll als Fehler angezeigt werden.
[quote=“Anna On Air, post:52, topic:8172”]Zwei Fragen habe ich noch:
ist es innerhalb eines so großen Programms und eventuell mehrerer Scripte nicht gefährlich nur “i” als Variable für die For-Schleife zu verwenden?
Die Variable “blinkflag” ist doch boolean. Ist diese dann von grundauf “true”? Zudem kann ich mit der Zeile “blinkflag := not blinkflag;” nichts anfangen?[/quote]
Zu 1:
‘i’ ist im OnTimer klar zugeordnet, von daher also kein Problem.
Zu 2:
‘blinkflag’ ist zunächst ‘false’ und ändert bei jedem Durchlauf des Timers seinen Status.
‘blinkflag := not blinkflag;’ macht dies. Er wechselt auf den Status den er ‘nicht’ (not) ist.
Also wenn ‘true’ dann auf ‘false’ und umgekehrt. Und da der Timer auf Sekundenbasis läuft, hat sich das ja förmlich angeboten.
Sicher ist das mit dem “ecsConnecting” Auslegungssache, unterm Strich kann man das Script so wie es jetzt ist ja wunderbar an alle individuellen Wünsche anpassen.
Bei den anderen Fragen ist alles klar
Danke Dir vielmals, so habe ich doch wieder einiges hinzugelernt.
Nein, nicht unbedingt. In Pascal sind lokale und globale Variablen per Definition in einem undefinierten Zustand.
Anders ausgedrückt: Es wird zwar Speicher für die Variable reserviert, dieser wird aber nicht mit irgendeinem vorgegebenen Wert (hier: false) initialisiert.
Daher sollte man solche Variablen immer gezielt beim Programmstart (oder hier im OnLoad) initialisieren, wenn sie beim ersten Verwenden einen bestimmten Wert haben sollten.
Ansonsten fällt mir noch auf, dass “Encoderflag” zwar als globale Variable definiert ist, andererseits bei jedem Durchlauf von OnTimer zunächst wieder auf false gesetzt wird. Der zuletzt gespeicherte Wert wird also im nächsten Durchlauf gar nicht verwendet. So gesehen könnte man sie auch gleich als lokale Variable definieren.
Danke Doktor für die Erklärungen. Ich bin ja auch nicht der Delphi Experte
Normalerweise ist aber eine nicht initialisierte Variable ‘normalerweise’ auf false oder 0.
Auf der anderen Seite, wieso geht:
i: integer = 1;
nicht?
Ansonsten fällt mir noch auf, dass "Encoderflag" zwar als globale Variable definiert ist, andererseits bei jedem Durchlauf von OnTimer zunächst wieder auf false gesetzt wird. Der zuletzt gespeicherte Wert wird also im nächsten Durchlauf gar nicht verwendet. So gesehen könnte man sie auch gleich als lokale Variable definieren.
Auf jeden Fall! Move to local declaration (OnTimer bei i,x)
Kommt drauf an, was du mit “normalerweise” meinst. In Delphi ist das, bei lokalen oder globalen Variablen, nicht der Fall. Dort wird einfach der Speicher im Heap bzw. Stack für die Variable reserviert, es kann aber irgendwelcher Müll drinstehen. (Ausnahme sind Felder von Objekten, diese werden mit Nullbytes initialisiert.) Deswegen immer zuerst initialisieren!
Auf der anderen Seite, wieso geht:
[code]i: integer = 1;[/code]
nicht?
Du meinst “assignable typed constants”?
Im Grunde handelt es sich dabei um eine Variable mit explizitem initialen Wert, das stimmt. Allerdings muss das grundsätzlich nicht in den “var”- sondern in den “const”-Abschnitt. Und ich weiß gar nicht, ob die Script-Engine (Pascal Script) dies unterstützt. In Delphi selbst muss man die Unterstützung dafür explizit im Compiler aktivieren.
hatte gestern einen DSL-Absturz und habe es nicht bemerkt. Darufhin habe ich das Forum durchsucht und den o.g. Infoaustausch gefunden . . . . Script läuft und wird mich hoffentlich künftig warnen!