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
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.
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;
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.
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.
Oh, fällt mir gerade erst auf: Die Wort-Uhr ist ja auch klasse “5 Minuten nach halb 13”
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.
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. Webradio mit ARI Signalisierung und Hinztriller.
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.
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 F11undF12 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.
{
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.
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.
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.
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…
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.