Ansteuerung des OnAirScreen

OK, wenn man den richtigen Befehl absetzt und auch den Port richtig setzt, dann funktioniert das auch.

Kaum macht man’s richtig, schon geht’s.

1 Like

Vielleicht könnte einer der Admins, den Titel mal ändern in “Ansteuerung des OnAirScreen”

Dann können wir diesen Thread wenigstens noch zur Dokumentation verwenden.

procedure OnLoad;
begin
  ShellExecute ('C:\ProgramData\mAirList\6.1\sfk174.exe', 'udpsend 192.168.51.103 3310 "CONF:LED2:autoflash=True"');
  ShellExecute ('C:\ProgramData\mAirList\6.1\sfk174.exe', 'udpsend 192.168.51.103 3310 "CONF:CONF:APPLY=TRUE"');
end;

procedure OnOnAir;
begin
  ShellExecute ('C:\ProgramData\mAirList\6.1\sfk174.exe', 'udpsend 192.168.51.103 3310 "LED1:ON"');
  SystemLog ('C:\ProgramData\mAirList\6.1\sfk174.exe udpsend 192.168.51.103 3310 "LED1:ON"');
end;

procedure OnOffAir;
begin
  ShellExecute ('C:\ProgramData\mAirList\6.1\sfk174.exe', 'udpsend 192.168.51.103 3310 "LED1:OFF"');
  SystemLog ('C:\ProgramData\mAirList\6.1\sfk174.exe udpsend 192.168.51.103 3310 "LED1:OFF"');
end;

procedure OnPlayerEOFWarning(PlaylistIndex: integer; PlayerIndex: integer);
begin
  ShellExecute ('C:\ProgramData\mAirList\6.1\sfk174.exe', 'udpsend 192.168.51.103 3310 "LED2:ON"');
  SystemLog ('C:\ProgramData\mAirList\6.1\sfk174.exe udpsend 192.168.51.103 3310 "LED2:ON"');
end;

procedure OnPlayerStop(PlaylistIndex: integer; PlayerIndex: integer; Duration: TTimeValue; Item: IPlaylistItem);
begin
  ShellExecute ('C:\ProgramData\mAirList\6.1\sfk174.exe', 'udpsend 192.168.51.103 3310 "LED2:OFF"');
  SystemLog ('C:\ProgramData\mAirList\6.1\sfk174.exe udpsend 192.168.51.103 3310 "LED2:OFF"');
end;

procedure OnShutdown; // Sollte den Rechner mit den OnAirScreen herunterfahren, funktioniert bisher aber nicht.
begin
  ShellExecute ('C:\ProgramData\mAirList\6.1\sfk174.exe', 'udpsend 192.168.51.103 3310 "CMD:SHUTDOWN"');
  SystemLog ('C:\ProgramData\mAirList\6.1\sfk174.exe udpsend 192.168.51.103 3310 "CMD:SHUTDOWN"');
end;

Jetzt möchte ich diese art und Weise: "Altes" ONAIR-Script funktioniert nur noch teilweise Nutzen um den Stream Timer zu starten, wenn mindestens einer der Streams verbunden ist und stoppen wenn alle offline sind.

Ausserdem möchte ich aus meinem Gamepad, eine Funktion triggern. Die soll zum einen, hier einen Befehl absetzen und ebenfalls einen Timer starten und zum anderen den dedizierten “Aircheck” recorder starten.

Warscheinlich kann man den ganzen Spaghetti code da oben auch wieder in eine eigene Procedure verpacken und dann nur noch die Befehle übergeben. Dazu später, ich will erst einmal alle Funktionen überhaupt am laufen haben.


“Vielleicht könnte einer der Admins, den Titel mal ändern in “Ansteuerung des OnAirScreen””
done by Mod (es gibt nur einen Admin hier :wink:)

So vielleicht?


const
  IP = '192.168.51.103';                           // <-- IP-Adresse
  PORT = '3310';                                   // <-- Port
  PATH = 'C:\ProgramData\mAirList\6.1\sfk174.exe'; // <-- Pfad

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

procedure OnLoad;
begin
  PostOnAirScreen('CONF:LED2:autoflash=True'); 
end;

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

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

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

procedure OnPlayerStop(PlaylistIndex: integer; PlayerIndex: integer; Duration: TTimeValue; Item: IPlaylistItem);
begin
  SPostOnAirScreen('LED2:OFF');
end;

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


begin
end.

Schreibtischtat, ungeprüft. Bitte mal testen.

Verpackte Grüße

TSD

Das eben war nur die Verpackung mit Prozeduren. Jetzt Deine Streamabfrage. Da wir eine procedure OnEncoderStateToggle leider (noch?) nicht besitzen, müssen wir wieder die Timerabfrage bemühen:

const
  iMax = 5;                                        // Hier die maximale Senderanzahl einsetzen
  IP = '192.168.51.103';                           // <-- IP-Adresse
  PORT = '3310';                                   // <-- Port
  PATH = 'C:\ProgramData\mAirList\6.1\sfk174.exe'; // <-- Pfad

var
  EncoderCount, i: integer;
  EcoderState: array[0 .. iMax] of integer;

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

procedure OnLoad;
begin
  EnableTimer(100);
end;

procedure OnTimer;
begin
  for i := 0 to iMax-1 do
    begin
      if (Encoder.GetConnections.GetItem(i).GetState = ecsConnected) then
        EncoderState[i] := 1
      else 
        EncoderState[i] := 0;
    end;
  for i := 0 to iMax-1 do
    begin
      EncoderCount := 0;
      EncoderCount := EncoderCount + EncoderState[i];
    end;
  if EncoderCount = 0 then
    PostOnAirScreen('<Befehl, wenn Streams aus>')
  else
    PostOnAirScreen('<Befehl, wenn ein Stream an>');
end; 


begin
end.

Dieses Skript fragt (wenn es läuft, ist wieder am grünen Tisch entstanden) alle Zehntelsekunde (muß das so oft sein?) den Encoderstatus ab. Ist ein Encoder verbunden, bekommt er eine Eins, wenn nicht, eine Null verpaßt. Dann werden diese Zahlen addiert – sind alle Encoder offline, ist das Ergebnis null und ein enstprechender Befehl für die Shell ergeht. Ist auch nur ein Encoder verbunden, ist das Ergebnis nicht mehr null, ein anderer Befehl ergeht.

(Man könnte das etwas speichersparender programmieren, wenn man wüßte, daß ord(<Boolsche Variable>) funktioniert, das kann ich im Moment aber nicht ausprobieren.)

Rückgemeldete Grüße

TSD

Vielen Dank @Tondose für Deine Mühe.

Ich frage mich gerade was jetzt passier, bzw. was effktiver wäre, wenn ich sowohl den Status der indivduellen Encoder in mAirlist direkt anzeige als auch die gesammlte Übergabe um den Timer zu triggern.
Sollte man einfach 2 Scripte pollen lassen? Oder lieber das Stautsscript so ändern, dass es einen Wert unter “Runtimedata” weg schreibt den das Sceen Script abfragt?
Und nein, es muss nicht so schnell gepollt werden, ich denke 1 Sekunde reicht auch noch komfortabel aus.

Das sieht soweit schon mal wirklich gut aus und funktioniert:

const
  iMax = 5;                                        // Hier die maximale Senderanzahl einsetzen
  IP = '192.168.51.103';                           // <-- IP-Adresse
  PORT = '3310';                                   // <-- Port
  PATH = 'C:\ProgramData\mAirList\6.1\sfk174.exe'; // <-- Pfad
  
var
  EncoderCount, 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));
  //ShellExecute (PATH, 'udpsend ' + IP + Chr(32) + PORT + Chr(32) + Chr(34) + Befehl + Chr(34));
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:LED2:text=EOF'); // Auf dem Button soll EOF stehen.
  PostOnAirScreen('CONF:CONF:APPLY=TRUE'); 
  EnableTimer(1000);
end;

procedure OnTimer;
begin
  for i := 0 to iMax-1 do
    begin
      if (Encoder.GetConnections.GetItem(i).GetState = ecsConnected) then
        EncoderState[i] := 1
      else 
        EncoderState[i] := 0;
    end;
  for i := 0 to iMax-1 do
    begin
      EncoderCount := 0;
      EncoderCount := EncoderCount + EncoderState[i];
    end;
  if EncoderCount = 0 then begin
    PostOnAirScreen('AIR4:OFF');
    PostOnAirScreen('AIR4:RESET');
	end
  else
PostOnAirScreen('AIR4:ON');
end; 


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

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

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

procedure OnPlayerStop(PlaylistIndex: integer; PlayerIndex: integer; Duration: TTimeValue; Item: IPlaylistItem);
begin
  PostOnAirScreen('LED2:OFF');
end;

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


begin
end.

Ein paar kleine Schreibfehler aber nicht was derjenige der Softwarefehler lieber mit dem Lötkolben löst, nicht beheben konnte :wink:
Da wo AIR4:OFF steht müsste ich eigentlich einen 2. Befehl absetzen AIR4:REST um den Timer wieder auf null zu stellen, das habe ich dann nicht hin bekommen.
In der PostOnAirScreen Prozedur war das absetzen der Befehle doppelt, da weiß ich nicht genau, wo das her kam, ich hatte vorher den Befehl einfach noch mal ins Log geschrieben?
Habe ich hier mal auskommentiert und auch gleich noch zum ShellexecuteHidden gemacht, dann ploppen keine CMD Fenster mehr auf, die auch noch den Fokus haben.

Jetzt muss ich nur noch ein Gamepad Kommandoe hier rein bekommen, was mir den Talk-Timer startet und stopt. Ich könnte ein Bildschirmobjekt schalter damit triggern und ein Script starten, was irgendwas in runtime setzt, geht das irgnedwie direkt? Kann ich einer Fernsteuerung direkt ein Script zuordnen?
Ah, moment, jetzt wo ich hier schreibe: Irgendwas war doch da mal mit eigene Befehle bauen über Hintergrundscripte. Ich bemühe mal die Forensuche.

EDIT: Ich weiß nicht, wie man hier Text durch streicht. Den doppelten befehl habe ich hinbekommen. Oben geändert.

EDIT2: Ich habe versucht, mit diesem Block unterhalb der OnLoad, einen befehl abzusetzen und habe das gloaben Hotkeys zugewiesen, klappt aber nicht. :thinking:

procedure OnExecuteCommand(Command: string);
begin
  if Command = 'MIC OPEN' then begin
    PostOnAirScreen('AIR1:ON');
  end
  else if Command = 'MIC CLOSE' then begin
  PostOnAirScreen('AIR1:OFF');
  end;
end;

Das wäre die effizientere Methode:

Script für Encoder-Abfrage:

const
  iMax = 5;                                        // <-- Maximale Senderanzahl

var
  EncoderCount, i: integer;
  EncoderState: array[0..iMax] of integer;

procedure OnLoad;
begin
  EnableTimer(1000);
end;

procedure OnRuntimeDataChange(Key, Value: string);
begin
end;

procedure OnTimer;
begin
  for i := 0 to iMax - 1 do
    begin
      if (Encoder.GetConnections.GetItem(i).GetState = ecsConnected) then
        EncoderState[i] := 1
      else 
        EncoderState[i] := 0;
    end;
  for i := 0 to iMax - 1 do
    begin
      EncoderCount := 0;
      EncoderCount := EncoderCount + EncoderState[i];
    end;
  if EncoderCount = 0 then begin
    SetRuntimeData('EncoderStatus', '<Befehl, wenn Streams aus>');
    //ExecuteCommand('<Befehl, um den Stream Timer zu starten'>);  // <-- ??
  end
  else begin
    SetRuntimeData('EncoderStatus', '<Befehl, wenn ein Stream an>');
    //ExecuteCommand('<Befehl, um den Stream Timer zu stoppen'>);  // <-- ??
  end;
end; 

begin
end.


Script für OnAirScreen:

const
  IP = '192.168.51.103';                           // <-- IP-Adresse
  PORT = '3310';                                   // <-- Port
  PATH = 'C:\ProgramData\mAirList\6.1\sfk174.exe'; // <-- Pfad

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

procedure OnLoad;
begin
  PostOnAirScreen('CONF:LED2:autoflash=True'); 
end;

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

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

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

procedure OnPlayerStop(PlaylistIndex: integer; PlayerIndex: integer; Duration: TTimeValue; Item: IPlaylistItem);
begin
  PostOnAirScreen('LED2:OFF');
end;

procedure OnRuntimeDataChange(Key, Value: string);
begin
  if Key = 'EncoderStatus' then
    PostOnAirScreen(Value)
  else if Key = 'GamepadStatus' then
    PostOnAirScreen(Value);
end;
	
procedure OnShutdown; // Sollte den Rechner mit den OnAirScreen herunterfahren, funktioniert bisher aber nicht.
begin
  PostOnAirScreen('CMD:SHUTDOWN');
end;

begin
end.

Und noch das

Script für Gamepad-Steuerung:

{

Fernsteuer-Befehl für Gamepad: GAMEPAD ON AIR

In diesem Beispiel toggelt der Befehl vom Gamepad ein/aus.
Bei Verwendung von zwei Aktoren Muß das Skript entsprechend
abgeändert werden.

}

var
  GamepadOnAirOn: boolean;

procedure OnLoad;
begin
  GamepadOnAirOn := false;
end;

procedure OnTimer;
begin
  ExecuteCommand('<Was immer es sein soll>');
  //Disable Timer;                             // <-- Falls wiederholend, Zeile auskommentieren
end;

procedure OnRuntimeDataChange(Key, Value: string);
begin
end;

procedure OnExecuteCommand(Command: string);
begin
  if NOT GamepadOnAirOn AND (Command = 'GAMEPAD ON AIR') then begin
    GamepadOnAirOn := true;
    SetRuntimeData('GamepadStatus', '<Steuerbefehl vom Gamepad beim Einschalten>');
    //EnableTimer(<Dauer>);
    Encoder.GetConnections.GetItem(<Nummer des Aircheck-Recorders>).SetEnabled(true);
  end
  else if GamepadOnAirOn AND (Command = 'GAMEPAD ON AIR') then begin
    GamepadOnAirOn := false;
    SetRuntimeData('GamepadStatus', '<Steuerbefehl vom Gamepad beim Ausschalten>');
    //DisableTimer;                          // <-- Kommentierung entfernen, falls wiederholend
    Encoder.GetConnections.GetItem(<Nummer des Aircheck-Recorders>).SetEnabled(true);
  end;
end;

begin
end.

Was Du genau mit

meinst, ist mir nicht ganz klar. Ich habe mal einen Befehl eingebaut und auskommentiert, außerdem wird das OnAirScreen-Script verständigt.

Die Prozedur

procedure OnRuntimeDataChange(Key, Value: string);
begin
  if Key = 'EncoderStatus' then
    PostOnAirScreen(Value)
  else if Key = 'GamepadStatus' then
    PostOnAirScreen(Value);
end;

müßte mal ein Fachmann überprüfen, ob die so richtig ist.

Was für Grüße jetzt eigentlich?

TSD


Edit: Unsere Posts haben sich überschnitten, vielleicht bekommst Du ja die Skripts entsprechend selber hinfummeln.

Durchstreichen geht mit [s] und entsprechendem schließenden Tag.

Jetzt erst mal Grill an. :cut_of_meat:

Wieder einmal vielen Dank, ich brauche noch etwas, bis ich das adaptiere.

Der Stream Timer auf dem OnAirScreen. (unten links)


Der ist auf dem Screenshot im Github nicht zu sehen, das hatte ich nicht auf dem Schirm.
Auf der rechten Seite stehen die LED1 bis 4 auf der linken Seite AIR1 bis 4. Die Timer haben aber alle leicht unterschiedliche Features. Der Talk-Timer (Mic) resetten automatisch beim stoppen, der Stream Timer möchte manuell zurückgesetzt werden.
Der Timer darüber erlaubt es sogar eine Zeit zu setzen und dann rückwärts zu zählen.
Da habe ich momentan noch keine Verwendung dafür, kann es aber auch nicht ausblenden. Die Funktion habe ich in Hardware in meinem Pult…

Da würde mich eher, der laufende Titel noch interessieren, den kann man anstatt der IP Adresse hin schreiben und den folgenden, darunter. Warnmeldungen gibt es auch noch, die man da untern fett hinschreiben kann. Nu muss ich aber erst mal den Rest einbinden.

Doorbell und ARI, habe ich auch noch keine Idee.
Hoffe, das BBQ war gut.:cut_of_meat::cut_of_meat:

Oh, fällt mir gerade erst auf: Die Wort-Uhr ist ja auch klasse “5 Minuten nach halb 13” :thinking:

Und wie! Vielleicht sogar zu gut, siehe den anderen Thread …

Aha, dann ist das nichts spezielles, sondern auch nur ein UDP an die bekannte Adresse. Gut.

Die IP-Adresse tritt ohnehin viel zu stark hervor und lenkt ab. Da würde ich ein ganz frisches aschgrau für nehmen.

Pultseitig ist es nur ein Port am Gamepad/Velleman/IO-Warrior. Türseitig habe ich mal für ein bekanntes Lokalradio aus der Region den Empfänger einer Funkklingel umgewidmet. Bei konservativ verdrahteten Klingeln nimmst Du ein paralleles Relais her. Sind Dir die Kabel widerlich, nimmst Du Relais und Funkklingel. Ran an den Lötkolben!

Wo kommt der ARI/Hinztriller her? Hardware? Dann hat der auch einen Schaltausgang. File? Dann ihm beim abspielen eine Aktion zuordnen. Rest wie oben.

if Stunde > 12 then Stunde := Stunde - 12;

Oder hier.

Zeitige Grüße

TSD

Wenn ich nicht gerade Radio mache, bin ich begeisterter Grillsportler. Also das Sportgerät ist bei mir auch des öfteren am Start.

Ich meinte eher, dass ich die Klingel gar nicht brauche und die Anzeige komplett umfunktioniere.

Selbiges wie oben, ich habe keinen, vielleicht aber ein nettes gimmick. Die Audiodatei für einen Hinztriller habe ich mal irgendwo gefunden, sollte noch irgendwo auf meiner Festplatte rumgeistern. Im Moment bleibt es erst mal bei LED3:OFF und LED4:OFF
Das war ja hier nur die Defaultbeschriftung, die man auch ändern kann.
Aber jetzt wo Du es schreibtst müsste ich das eigentlich machen, einfach nur weil’s geht. :smile: Webradio mit ARI Signalisierung und Hinztriller. :rofl:
Mein Pult hat da noch einen Line-Eingang, der keine Bedienelemete hat. Der muss mal für sowas gewesen sein und da hängt gerade nix dran. Wir werden sehen… Also wenn, dann komplett in Hardware.

Das mit dem Encoder Status, wollte ich hier: "Altes" ONAIR-Script funktioniert nur noch teilweise - #27 by shorty.xs einfach mitählen und in die RuntimeData schreiben.
Oder macht es mehr Sinn das noch mal extra laufen zu lassen?

Hinztriller

Hmm, also die eigen gesetzten Fernsteuerbefehle triggern bei mir nicht.
Das was das GamePad mal machen soll habe ich erst mal auf globale Hotkeys gelegt.

{

Fernsteuer-Befehl für Gamepad: GAMEPAD ON AIR

In diesem Beispiel toggelt der Befehl vom Gamepad ein/aus.
Bei Verwendung von zwei Aktoren Muß das Skript entsprechend
abgeändert werden.

}

var
  GamepadOnAirOn: boolean;

procedure OnLoad;
begin
  GamepadOnAirOn := false;
end;

procedure OnTimer;
begin
  //ExecuteCommand('<Was immer es sein soll>');
  //Disable Timer;                             // <-- Falls wiederholend, Zeile auskommentieren
end;

procedure OnRuntimeDataChange(Key, Value: string);
begin
end;

procedure OnExecuteCommand(Command: string);
begin
  if NOT GamepadOnAirOn AND (Command = 'GAMEPAD ON AIR') then begin
    GamepadOnAirOn := true;
    SetRuntimeData('GamepadStatus', 'AIR1:ON');
    //EnableTimer(<Dauer>);
    SystemLog('GamepadStatus AIR1:ON')
  end
  else if GamepadOnAirOn AND (Command = 'GAMEPAD OFF AIR') then begin
    GamepadOnAirOn := false;
    SetRuntimeData('GamepadStatus', 'AIR1:OFF');
    //DisableTimer;                          // <-- Kommentierung entfernen, falls wiederholend
    SystemLog('GamepadStatus AIR1:OFF')
  end;
end;

begin
end.

Habe ich da noch einen Denkfehler?
An dem Punkt war ich gestern auch schon,Ansteuerung des OnAirScreen (Letzter Code Block) da hatte ich halt noch MIC OPEN und MIC CLOSE drin stehen aber auch da kam nicht mal ein Log Eintrag als ich den gesetzt habe.

Ich bin mir nicht sicher, ob ich das mit der RuntimeData richtig hinbekommen habe. Probiere mal stattdessen TESTBUTTON ON usw.

Evaluierende Grüße

TSD


Ach, und die Geschichte mit GamepadOnAirOn ist nur für toggelnden Betrieb, also beidesmal F11 (siehe Kommentar). Bei F11 und F12 eher so:

{

Fernsteuer-Befehl für Gamepad: GAMEPAD ON AIR

In diesem Beispiel toggelt der Befehl vom Gamepad ein/aus.
Bei Verwendung von zwei Aktoren muß das Skript entsprechend
abgeändert werden.

}

procedure OnTimer;
begin
  //ExecuteCommand('<Was immer es sein soll>');
  //Disable Timer;                             // <-- Falls wiederholend, Zeile auskommentieren
end;

procedure OnRuntimeDataChange(Key, Value: string);
begin
end;

procedure OnExecuteCommand(Command: string);
begin
  if Command = 'GAMEPAD ON AIR' then begin
    SetRuntimeData('GamepadStatus', 'AIR1:ON');
    //EnableTimer(<Dauer>);
    SystemLog('GamepadStatus AIR1:ON');
  end
  else if Command = 'GAMEPAD OFF AIR')then begin
    SetRuntimeData('GamepadStatus', 'AIR1:OFF');
    //DisableTimer;                          // <-- Kommentierung entfernen, falls wiederholend
    SystemLog('GamepadStatus AIR1:OFF');
  end;
end;

begin
end.

Grmpf, ich frage mich gerade was ich da vorher falsch gemacht habe. Also F12 geht generell nicht, warum auch immer. Jetzt funktioniert auch die übergabe über RuntimeData.
Im else if ist eine klamer zu viel vor dem “then”.
Jetzt müsste ich erst mal wieder weiter kommen.

Danke

Klammer vergessen, wegzumähen, sorry.

Weil der Befehl vielleicht in der Systemsteuerung/Konfiguration versehentlich mit einem führenden Leerzeichen eingetragen ist?

Forschende Grüße

TSD

Sooo! Ich bin einen Schritt weiter.

Das Gamepad Script sieht jetzt so aus:

{

Fernsteuer-Befehl für Gamepad: GAMEPAD ON AIR

In diesem Beispiel toggelt der Befehl vom Gamepad ein/aus.
Bei Verwendung von zwei Aktoren muß das Skript entsprechend
abgeändert werden.

}

procedure OnRuntimeDataChange(Key, Value: string);
begin
end;

procedure OnExecuteCommand(Command: string);
begin
  if Command = 'GAMEPAD ON AIR' then begin
    SetRuntimeData('GamepadStatus', 'AIR1:ON');
    ExecuteCommand ('AIRCHECK OPEN');
    ExecuteCommand ('AIRCHECK ON');
	
  end
  else if Command = 'GAMEPAD OFF AIR' then begin
    SetRuntimeData('GamepadStatus', 'AIR1:OFF');
    ExecuteCommand ('AIRCHECK OFF');
    ExecuteCommand ('AIRCHECK CLOSE');
  end;
end;

begin
end.

Wobei AIRCHECK die Fernsteuer ID ist, die man für as Bildschirmobjekt des Aircheck Recorders vergeben hat. Der Aircheck Recorder ist ein Feature, was für die meisten User nicht zur Home Version dazu gehört. Das erschien mir hier sinnvoller, den Aircheck direkt zu triggern und nicht anhand des RuntimeData Satus aus dem OnAirScreen Script heraus.

Ja klar. Das hat ja auch nichts mit der udp-Geschichte, sondern direkt mit mAirList zu tun. (Du solltest den Kommentar noch entsprechend abändern.)

Direkte Grüße

TSD

Ich habe jetzt das ON-AIR Script, aus dem anderen Beitrag, so angepasst, dass es einfach bei einer bestehenden Verbdindung Den Encoder Count eins hoch zählt und am Ende die RunTimeData aktualisiert. Gleiches habe ich mit mit den Encodern gemacht, die den Status Connecting haben um damit eine Warnmeldung zu triggern.

{
Zwischen die geschweiften Klammern kann der Spickzettel hin, z.B.:

1: SWR, 2: HR, 3: RIAS.
4: NDR, 5: RB; 6: ORF
usw.
}

const
  iMax = 4;                // Hier die maximale Senderanzahl minus 1 einsetzen

var
  EncoderErrorCount,EncoderOldCount,EncoderCount, i: integer;
  EncoderName: array[0 .. iMax] of string;


procedure OnLoad;
  begin
    EncoderName[0] := 's1 live1';
	EncoderName[1] := 's1 live2';
	EncoderName[2] := 's2 live1';
	EncoderName[3] := 's2 live2';
	EncoderName[4] := 'Aircheck';
    EnableTimer(800);
	EncoderOldCount := 0;
  end;

procedure OnTimer;
  begin
    EncoderOldCount := EncoderCount;
    EncoderCount := 0;
    EncoderErrorCount := 0;
    for i := 0 to iMax do
      begin
	     
         if (Encoder.GetConnections.GetItem(i).GetEnabled = true) then begin
          if (Encoder.GetConnections.GetItem(i).GetState = ecsConnected) then begin
            ExecuteCommand('ENCODER'+ IntToStr(i) +' TEXT '+ EncoderName[i] +' ON AIR');
            ExecuteCommand('ENCODER'+ IntToStr(i) +' BACKGROUNDCOLOR #FF0000');
            ExecuteCommand('ENCODER'+ IntToStr(i) +' FONTCOLOR #FFFFFF');
			EncoderCount := EncoderCount + 1;
            end	
          else if (Encoder.GetConnections.GetItem(i).GetState = ecsConnecting) then begin
            ExecuteCommand('ENCODER'+ IntToStr(i) +' TEXT '+ EncoderName[i] +' !OFF AIR!');
            ExecuteCommand('ENCODER'+ IntToStr(i) +' FONTCOLOR #FFFFFF');
            ExecuteCommand('ENCODER'+ IntToStr(i) +' BACKGROUNDCOLOR #FF0000');
			EncoderCount := EncoderCount + 1;
			EncoderErrorCount := EncoderErrorCount + 1;
            end  
          else begin
            ExecuteCommand('ENCODER'+ IntToStr(i) +' BACKGROUNDCOLOR #00FF00');
            ExecuteCommand('ENCODER'+ IntToStr(i) +' FONTCOLOR #000000');
            ExecuteCommand('ENCODER'+ IntToStr(i) +' TEXT '+ EncoderName[i] +' READY!');
            end
          end
      else begin
           ExecuteCommand('ENCODER'+ IntToStr(i) +' BACKGROUNDCOLOR #F0F0F0');
           ExecuteCommand('ENCODER'+ IntToStr(i) +' FONTCOLOR #848484');
           ExecuteCommand('ENCODER'+ IntToStr(i) +' TEXT '+ EncoderName[i] +' AUS');
           end;   
      	
	end;
	if EncoderCount = 0 then begin
      SetRuntimeData('EncoderStatus', 'false');
      end
      else begin
        SetRuntimeData('EncoderStatus', 'true');
    end;	
      if EncoderErrorCount = 0 then begin
      SetRuntimeData('EncoderError', 'WARN:');
      end
      else begin
        SetRuntimeData('EncoderError', 'WARN:Encoder Fehler!');
      end;	
end; 	    
  
	
  

begin
end.

Das OnAirScreen Script sieth jetzt so aus.
Da ich für diesen Stream Timer 2 Befehle brauche, um ihn zu stoppen habe ich hier noch eine Zwischenwert in die RuntimeData geschrieben und triggere den eigentlichen Befehl im OnAirScreen Script, weshalb hier eine weitere if Schleife her musste.

const
  iMax = 5;                                        // Hier die maximale Senderanzahl einsetzen
  IP = '192.168.51.103';                           // <-- IP-Adresse
  PORT = '3310';                                   // <-- Port
  PATH = 'C:\ProgramData\mAirList\6.1\sfk174.exe'; // <-- Pfad
  
var
  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 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:LED2: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 OnRuntimeDataChange(Key, Value: string);
begin
  if Key = 'EncoderStatus' then begin
	//SystemLog ('EncoderStatus'+ (Value));
    	if Value = ('false') 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 OnOnAir;
begin
  PostOnAirScreen('LED1:ON');
end;

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

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

procedure OnPlayerStop(PlaylistIndex: integer; PlayerIndex: integer; Duration: TTimeValue; Item: IPlaylistItem);
begin
  PostOnAirScreen('LED2:OFF');
end;

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


begin
end.


Der Ensprechende Encoder Status der einzelnen Encoder siehr nach wie vor so aus
grafik

Airtcheck Recoder in Action
grafik

Und entsprechend der Stream Monitor mit dem TalkTimer

1 Like

Ein erster Test am Wochenende lief sehr gut. Den Mikrofontrigger muss ich noch anlöten aber der Rest funktioniert schon mal ziemlich gut.
Ein Problem habe ich mit dem EOF Trigger.
Das hatten wir schon mal irgendwo im Forum, ich weiß aber gerade nicht mehr wo.

Wenn ich 2 Elemente miteinander verkette, dann löst der EOF Trigger am Ende des ersten Elementes aus, danach erfolgt aber kein Player Stop, weil der Player den nächsten Song einfach nachläd und spielt, EOF blinkt also weiter. Eigentlich ist Player Stop, schon der passende Trigger finde ich, funktioniert aber nur im voll manuellen Betrieb.

Weiterer offener Punkt:
In der mAirlist Home-Studio fehlt mir logging per UDP, ansonsten könnte ich den laufenden und den folgenden Titel einfach von dort an den Screen shicken. Nun muss ich das noch irgendwie in das Script fummeln. Bevor es das logging Interface nativ in mAirlist gab, hat man das doch auch mit Scripts gelöst. Funktionieren die noch? Irgendwo Version 1.x oder 2.x

Hatte ich schon mal erwähnt, dass die Suchfunktion in diesem Forum Weltlkasse ist? Ich glaube diesen Monat noch nicht.

Ich habe diesen alten Thread ausgeraben: Codebeispiele mAirListScript
und daraus das OnAirScreen Script etwas erweitert.

const
  iMax = 5;                                        // Hier die maximale Senderanzahl einsetzen
  IP = '192.168.51.103';                           // <-- IP-Adresse
  PORT = '3310';                                   // <-- Port
  PATH = 'C:\ProgramData\mAirList\6.1\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 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:LED2: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 OnRuntimeDataChange(Key, Value: string);
begin
  if Key = 'EncoderStatus' then begin
    if Value = ('false') 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) + '-' + 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('LED2: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('LED2:OFF');
end;

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


begin
end.

Wir haben nun den laufenden Titel und den folgenden Titel gelistet. Müsste man ggf. noch Typfilter einbauen und die Länge begrenzen. Für mich funktioniert das so aber erst mal.

EDIT: Oben war noch ein Copy & Paste Fehler drin.

1 Like