Ansteuerung des OnAirScreen

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

Hi,
da ich null Ahnung vom Coden habe frage ich jetzt einfach mal. Wie genau ist es jetzt möglich den OnAirScreen mit mAirList zu verbinden? Wo packe ich die Scipts hin? Ich steige da einfach nicht dahinter…

LG Gregor

Moin Gregor,
ich war der Meinung, dass in einem der alten Handbücher mehr über die Scripts steht, das ist aber nicht so. Ich werde dazu demnächst mal den Scripting-Kurs von @Tondose erweitern, hier im Forum.

In aller Kürze:
Es gibt im Prinzip 2 Script Typen. Scripts die man aus der Oberfläche von mAirlist heraus ausführt, also über das Menü oder beim starten eines (Audio)Elementes, dass ein Script hinterlegt hat oder beim laden einer Playliste und es gibt noch ein paar weitere Stellen, an denen man gezielt auf ein Script verweist.

Die 2. Variante sind Hintergrundscripte oder früher hießen sie mal Notification-Scripts. Diese werden in einem zentralen Bereich der mAirlist Konfiguration definiert.


Das Verzeichnis, was ich hier gewählt habe um die Scripte zu speichern ist nicht unbedingt die beste Wahl, also nimm das bitte nicht als Vorbild, dazu später mehr.

Diese Scripte laufen, wie der Name vermuten lässt, immer im Hintergrund mit und warten auf gewisse Trigger um etwas auszuführen. Welche Trigger das sind und was dann ausgeführt wird, definierst Du innerhalb des Scriptes. Gerade wenn man noch daran schraubt, ist der Haken “Automatisches neu laden, wenn die Datei sich geändert hat”, Gold wert. So kannst Du Dein Hintergrundscript nämlich während mAirlist läuft, in einem Editor bearbeiten und es wird neu eingelesen, wenn Du es dort gespeichert hast. Sobald dann alles läuft kann man diesen Haken eigentlich raus nehmen und etwas Ressourcen sparen.

Also, wo muss das jetzt hin?
Das spielt genau genommen, keine Rolle, Du musst nur wissen wo Du Deine Sctipt Dateien gespeichert hast und der Windows User, mit dem Du mAirlist ausführst muss natürlich Zugriff darauf haben.
Ein dedizierter mAirlist Ordner unter eigene Dateien, wäre z.B. eine Möglichkeit. Etwa so wie bei der mAirlist DB, im Lokalen Modus. Die DB Datei hast Du ja auch irgendwo abgelegt.

Dann musst Du also nur noch Deine Script Dateien hier eintragen und dann laufen die los.
Im Script musst Du natürlich Die “PATH” Variable anpassen, auf den Verzeichnispfad wo du die "Swiss army Knife.exe hingelegt hast.

sorry dass ich dieses thema wieder öffne bei mir klappt das nicht kann mir jemand helfen vielleicht hat sich da was geändert

Hey @shorty.xs,
könntest du mich mal privat anschreiben?

Beste Grüße