Frage zu einem kleinen Projekt

Hallo,

auch auf die Gefahr hin, mich jetzt lächerlich zu machen, dann wäre dem halt so, wollte ich mal fragen, wie ich bestimmte Parameter von mAirlist an ein anderes Programm übergeben kann um mit diesen Parametern dann in dem zusätzlichen Programm arbeiten zu können.

Kurze Erklärung dazu: Ich möchte einen kleinen Studiomonitor “bauen”, in meinem Fall mit VB, zwar sind meine Kenntnisse in VB jetzt auch nicht auf der Profiebene angesiedelt, aber damit hab ich schon vor einiger Zeit mal gearbeitet und ein wenig ist noch hängen geblieben. Das Fehlende würde ich mir dann wieder durch belesen versuchen anzueignen.

Nun hatte ich gestern schon mal angefangen, den Zustand ob mAirlist gestartet ist oder nicht, erwies sich dabei nun nicht als Problem, jedoch hab ich gerade nicht wirklich einen Ansatzpunkt wie ich weitere Parameter von mAirlist via Script eben an ein zusätzliches Programm zu übergeben.

Es soll sich hier auch logischerweise nicht um einen Grundkurs in Sachen VB oder programmieren handeln, aber vielleicht hat ja jemand einen Tipp, vielleicht auch ein kleines einfaches Beispiel mit dem ich dann weiter machen kann. Ich tüftel mich da gerne rein, bräuchte halt nur mal einen Ansatzpunkt.

Meine erste Idee war, die benötigten Zustände via Script von mAirlist aus in eine *.txt Datei zu speichern und mit dieser dann weiter zuarbeiten. Aber auch hier weiß ich leider nicht, ob es seitens mAirlist möglich ist, eben eine *.txt Datei zu erstellen.

So, jetzt darf von mir aus gerne gelacht werden oder vielleicht auch in kleiner Weise geholfen.

Wie auch immer…

Ich sage schon mal Danke.

Hallo deadpool2016xx,

es wäre schön, wenn Du ein wenig näher erläutern könntest, was Du alles exportieren möchtest. Grundsätzlich wäre die einfachste Methode wohl das http-GET-Logging-Interface. Die verschiedenen Loggingvariablen findest Du hier, und was dort nicht vorhanden ist, ließe sich womöglich per Skript ermitteln und als Runtime-Data übergeben. Oder eben in eine .txt-Datei loggen. (Vielleicht noch einfacher.)

Ganz und gar nicht lächerliche Grüße

TSD

Hallo Tondose,

ja, die HTTP-GET Variante habe ich aktuell noch, davon möchte aber gerne weg und das Ganze lieber als kleines Programm nebenher laufen lassen. Wäre mit ziemlicher Sicherheit auch Ressourcen schonender. Also im Grunde sollen folgende Parameter übergeben werden:

  • ist mAirlist gestartet (erledigt)
  • EOF
  • Mikrofon an/aus
  • Encoder verbunden/getrennt
  • Assist oder Automation

ggf. später noch aktueller Titel.

Wie halt schon erwähnt, meine VB Kenntnisse sind eher Anfänger, hatte zwar mal vor Jahren einiges damit zutun, bin dann aber immer mehr davon abgekommen. Daher ist es vermutlich auch gerade etwas schwierig einen Ansatz zu finden, dennoch bin ich auch motiviert genug, mich dann wieder reinzuarbeiten.

Ob mAirlist gestartet ist oder eben nicht hab ich zur Zeit so gelöst

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles timer_all.Tick
p = Process.GetProcessesByName(“mAirList”)
If p.Count > 0 Then
systemon.Text = “System online”
systemon.BackColor = Color.Red
Else
systemon.Text = “System offline”
systemon.BackColor = Color.Lime
End If
End Sub

Beste Grüße

Bin nahe dran.
 

Spannende Grüße

TSD

Hier sind zwei Skripte. Dieses hier fragt Auto/Assist, Mikrofon im Encoder, den Encoder selber, Player, Titel und EOF ab:

var
  Recurring: boolean;
  EOFCount: integer;
  EncoderStatus: Array[0 .. 255] of boolean;

procedure OnLoad;
begin
  EOFCount := 0;
  EnableTimer(1000);
end;


// Automationsmodus überwachen

procedure OnAutomationOn(PlaylistIndex: integer);
begin
  SetRuntimeData('Auto', 'Auto');
end;

procedure OnAutomationOff(PlaylistIndex: integer);
begin
  SetRuntimeData('Auto', 'Assist');
end;


// Titel und Player überwachen

procedure OnPlayerStart(PlaylistIndex: integer; PlayerIndex: integer;
  Item: IPlaylistItem);
begin
  SetRuntimeData('Title', Item.GetTitle);
  if PlayerIndex = 0 then
    SetRuntimeData('Player', 'A')
  else if PlayerIndex = 1 then
    SetRuntimeData('Player', 'B');
end;


// EOF überwachen

procedure OnPlayerEOFWarning(PlaylistIndex: integer; PlayerIndex: integer);
begin
  SetRuntimeData('EOF' + IntToStr(PlayerIndex + 1), 'EOF' + IntToStr(PlayerIndex + 1) +'On');
  EOFCount := EOFCount + 1;
  SetRuntimeData('EOF', IntToStr(EOFCount));
end;

procedure OnPlayerStop(PlaylistIndex: integer; PlayerIndex: integer; 
  Duration: TTimeValue; Item: IPlaylistItem);
begin
  SetRuntimeData('EOF' + IntToStr(PlayerIndex + 1), 'EOF' + IntToStr(PlayerIndex + 1) +'Off');
  EOFCount := EOFCount - 1;
  SetRuntimeData('EOF', IntToStr(EOFCount));
end;


// Mikrofon überwachen

procedure OnEncoderInputToggle(Input: TEncoderInput; NewState: boolean);
begin
  if Input = eiMic then begin
    if NewState then
      SetRuntimeData('Mic', 'MicOn')
    else
      SetRuntimeData('Mic', 'MicOff');
  end;
end;


// Encoder überwachen. "On" wird signalisiert, wenn mindestens einer von
// beliebig vielen Encodern aufgeschaltet ist.

procedure OnTimer;
var
  Test: boolean;
  i, k: integer;
begin
  try
    for i := 0 to 255 do
    begin
      if Encoder.GetConnections.GetItem(i).GetState = ecsConnected then
        EncoderStatus[i] := true
      else
        EncoderStatus[i] := false;
    end;      
  except
    k := i - 1;
  end;
  for i := 0 to k do
  begin
    Test := true;
    if NOT EncoderStatus[0] AND (EncoderStatus[i] = EncoderStatus[i + 1]) then
    begin
      Test := false;
      Break;
    end;    
  end; 
  if Recurring <> Test then
    if Test then
      SetRuntimeData('Encoder', 'EncOn') 
    else
      SetRuntimeData('Encoder', 'EncOff'); 
  Recurring := Test;
end;


begin
end.


Das zweite schreibt die Daten in ein Textfile, Pfad und Filename sind frei wählbar (innerhalb sinnvoller Grenzen):

const
  PATH = 'C:\Path\to\file\'; // <-- Hier den Pfad zum File eintragen.
  FILENAME = 'Runtime.txt';  // <-- Hier den Filenamen eintragen.
                             //     Anführungszeichen nicht vergessen!
 
var
  StringList: TStringList;
 
procedure OnRuntimeDataChange(Key, Value: string);
begin
  if (Key = 'Auto')
    OR (Key = 'Title')
    OR (Key = 'Player')
    OR (Key = 'EOF')
    OR (Key = 'Mic')
    OR (Key = 'Encoder') then
  begin
    try
      StringList := TStringList.Create;
      StringList.Add('Auto:' + Chr(9) + GetRuntimeData('Auto'));
      StringList.Add('Title:' + Chr(9) + GetRuntimeData('Title'));
      StringList.Add('Player:' + Chr(9) + GetRuntimeData('Player'));
      StringList.Add('EOF1: ' + Chr(9) + GetRuntimeData('EOF1')); 
      StringList.Add('EOF2: ' + Chr(9) + GetRuntimeData('EOF2'));   
      StringList.Add('Mic:' + Chr(9) + GetRuntimeData('Mic'));
      StringList.Add('Enc:' + Chr(9) + GetRuntimeData('Encoder'));
      StringList.SaveToFile(PATH + FILENAME);
    finally
      StringList.Free;
    end;
  end;
end;

    
begin
end.

Probier mal ein bißchen damit rum.

Geloggte Grüße

TSD


Edit: Hinweis: Mit jeder Änderung eines der Zustände wird das File mit den neuen Daten überschrieben.

Mensch du bist ja der Hammer, das wird ne lange Nacht. Ich danke dir auf jeden Fall für deine Mühe und dein Engagement. Ich werde gleich loslegen mit testen und gebe dann definitiv Rückmeldung.

Nochmal ganz lieben Dank

Also bisher funktioniert alles super. Zustände werden anständig verarbeitet. Habe noch den Artist hinzugefügt, muss jetzt nur mal schauen, was noch was alles übermittelt wird bzw. was man noch übermitteln kann. Weiß nicht ob es da irgendwo eine Liste gibt, aber da fuchse ich mich schon rein und zur Not kann ich ja dann noch mal fragen. Du hast mich auf jeden Fall ein ganzes Stück weiter gebracht.
Dafür noch mal ein ganz liebes Danke.

Na ja, andersherum würde ein Schuh draus: Du überlegst Dir, was alles exportiert werden soll, und dann versuchen wir herauszufinden, wie wir da rankommen. Ich könnte mir zum Beispiel die Restlaufzeit der Player vorstellen, dann würde allerdings die Exportdatei jede Sekunde überschrieben. Ob man das will, muß man sich halt überlegen.

Die „Ist-mAirList-gestartet“-Frage ließe sich übrigens eleganter mit Bordmitteln lösen:

procedure OnLoad;
begin
  EOFCount := 0;
  EnableTimer(1000);
  SetRuntimeData('Prog', 'Up');
end;

procedure OnUnLoad;
begin
  SetRuntimeData('Prog', 'Down');
end;

… mit entsprechender Anpassung des Write-Skripts.

Ergänzte Grüße

TSD

Ja, genau, das wäre nämlich mein nächstes Ziel gewesen, zum Beispiel die Restlaufzeit und ggf. die Startzeit mit reinzunehmen. Hatte das gestern schon mal mit StartTime usw probiert, aber ich denke, dass ich da noch einen Denkfehler drin hatte.

Habe dann hier und da noch eine Sache hier im Forum gefunden, die natürlich angepasst werden müsste, da sie noch aus älteren mAirlist Zeiten stammen und sicher so nicht mehr funktionieren.

Ok, ich werde mal, deine Variante probieren bezüglich “Ist-mAirlist-gestartet”

Edit: Oki, Deine Variante funktioniert super!

LG

Da die ganzen Daten ohnehin weiterverarbeitet werden sollen, müßten sie auch nicht von Menschen lesbar sein. Allen Ein/Aus-Zuständen könntest Du im Ein-Zustand lediglich Werte zuordnen, z. B.

Programm: 1
Auto:     2
EOF1:     4
EOF2:     8
Mic:     16
Encoder: 32

Wenn Du diese aufaddierst, brauchst Du nur eine Integer zu übergeben, und Dein VB-Programm weiß sofort Bescheid, was los ist. 43 hieße zum Beispiel: „Programm läuft im Auto-Modus, EOF2 blinkt und Encoder ist an.“ (Stichwort: Stellenwerte).

Binäre Grüße

TSD


Edit: Aufaddieren von Strings (die die Zahlen ja noch sind) mit

StrToInt('<Zahl als String>')

Alles klar, ich mache mich direkt mal ran.

LG

Jetzt wird’s kompliziert. Geht aber:

procedure OnPlayerStart(PlaylistIndex: integer; PlayerIndex: integer;
  Item: IPlaylistItem);
begin
  SetRuntimeData('Title', Item.GetTitle);
  if PlayerIndex = 0 then
  begin
    SetRuntimeData('Player', 'A');
    SetRuntimeData('StartA', FormatDateTime('hh:nn:ss', 
      CurrentPlaylist.GetMetadata(CurrentPlaylist.IndexOf(Item)).
      GetStartTime(sttCalculated)));
  end
  else if PlayerIndex = 1 then
  begin
    SetRuntimeData('Player', 'B');
    SetRuntimeData('StartB', FormatDateTime('hh:nn:ss', 
      CurrentPlaylist.GetMetadata(CurrentPlaylist.IndexOf(Item)).
      GetStartTime(sttCalculated)));
  end;
end;


Ellenlange Grüße

TSD

Das mit der Zeit funktioniert super, damit “procedure OnPlayerStart” nicht doppelt drin ist, hab ich dann einfach die schon vorhandene erweitert.

Werde mich jetzt mal mit “aufaddieren” befassen, mal schauen in wie weit ich das verstanden habe.

LG

Genau, das ginge auch gar nicht, zwei gleiche Prozeduren. Sie war zum Ersetzen gedacht.

In Sachen Laufzeit: Ich hielte es für sinnvoller, die jeweils verbleibende Zeit auszugeben. Dies geht mit dem beigelegten Skript. Das Dateischreib-Skript muß entsprechend geändert werden.

var
  Recurring: boolean;
  EOFCount: integer;
  StartTimeA, StartTimeB: TTimeValue;
  ItemA, ItemB: IPlaylistItem;
  EncoderStatus: Array[0 .. 255] of boolean;

procedure OnLoad;
begin
  EOFCount := 0;
  EnableTimer(1000);
end;


// Automationsmodus überwachen

procedure OnAutomationOn(PlaylistIndex: integer);
begin
  SetRuntimeData('Auto', 'Auto');
end;

procedure OnAutomationOff(PlaylistIndex: integer);
begin
  SetRuntimeData('Auto', 'Assist');
end;


// Titel und Player überwachen

procedure OnPlayerStart(PlaylistIndex: integer; PlayerIndex: integer;
  Item: IPlaylistItem);
begin
  SetRuntimeData('Title', Item.GetTitle);
  if PlayerIndex = 0 then
  begin
    SetRuntimeData('Player', 'A');
    StartTimeA := CurrentPlaylist.GetMetadata(CurrentPlaylist.IndexOf(Item)).
      GetStartTime(sttCalculated)
    SetRuntimeData('StartA', FormatDateTime('hh:nn:ss', StartTimeA));
    ItemA := Item;
  end
  else if PlayerIndex = 1 then
  begin
    SetRuntimeData('Player', 'B');
    StartTimeB := CurrentPlaylist.GetMetadata(CurrentPlaylist.IndexOf(Item)).
      GetStartTime(sttCalculated)
      SetRuntimeData('StartB', FormatDateTime('hh:nn:ss', StartTimeB));
    ItemB := Item;
  end;
end;


// EOF überwachen

procedure OnPlayerEOFWarning(PlaylistIndex: integer; PlayerIndex: integer);
begin
  SetRuntimeData('EOF' + IntToStr(PlayerIndex + 1), 'EOF' + IntToStr(PlayerIndex + 1) +'On');
  EOFCount := EOFCount + 1;
  SetRuntimeData('EOF', IntToStr(EOFCount));
end;

procedure OnPlayerStop(PlaylistIndex: integer; PlayerIndex: integer; 
  Duration: TTimeValue; Item: IPlaylistItem);
begin
  SetRuntimeData('EOF' + IntToStr(PlayerIndex + 1), 'EOF' + IntToStr(PlayerIndex + 1) +'Off');
  EOFCount := EOFCount - 1;
  SetRuntimeData('EOF', IntToStr(EOFCount));
end;


// Mikrofon überwachen

procedure OnEncoderInputToggle(Input: TEncoderInput; NewState: boolean);
begin
  if Input = eiMic then begin
    if NewState then
      SetRuntimeData('Mic', 'MicOn')
    else
      SetRuntimeData('Mic', 'MicOff');
  end;
end;


// Encoder überwachen. "On" wird signalisiert, wenn mindestens einer von
// beliebig vielen Encodern aufgeschaltet ist.

procedure OnTimer;
var
  Test: boolean;
  i, k: integer;
begin
  try
    for i := 0 to 255 do
    begin
      if Encoder.GetConnections.GetItem(i).GetState = ecsConnected then
        EncoderStatus[i] := true
      else
        EncoderStatus[i] := false;
    end;      
  except
    k := i - 1;
  end;
  for i := 0 to k do
  begin
    Test := true;
    if NOT EncoderStatus[0] AND (EncoderStatus[i] = EncoderStatus[i + 1]) then
    begin
      Test := false;
      Break;
    end;    
  end; 
  if Recurring <> Test then
    if Test then
      SetRuntimeData('Encoder', 'EncOn') 
    else
      SetRuntimeData('Encoder', 'EncOff'); 
  Recurring := Test;
  
  // Laufzeiten der Player
  
  if CurrentPlaybackControl.GetPlayer(0).GetState = psPlaying then
    SetRuntimeData('RunA', FormatDateTime('nn:ss', StartTimeA + 
      CurrentPlaylist.GetItem(CurrentPlaylist.IndexOf(ItemA)).
      GetEffectivePlaybackDuration / 86400 - Instance.FakeNow))
  else
    SetRuntimeData('RunA', '00:00');
  if CurrentPlaybackControl.GetPlayer(1).GetState = psPlaying then
    SetRuntimeData('RunB', FormatDateTime('nn:ss', StartTimeB + 
      CurrentPlaylist.GetItem(CurrentPlaylist.IndexOf(ItemB)).
      GetEffectivePlaybackDuration / 86400 - Instance.FakeNow))
  else
    SetRuntimeData('RunB', '00:00');
end;


begin
end.

Die Daten hast Du jetzt. Viel Spaß beim Verwursten. Laß dann mal von Deinem Ergebnis hören.

Neugierige Grüße

TSD

Ich gebe mein Bestes und halte dich auf dem Laufenden. Und vielleicht kommt ja noch die ein oder andere Frage. Ich glaube sie wird sicher kommen, denn eine Sache will ich im Moment nicht so recht verstehen, aber dazu später mehr. Muss erst mal was tun hier.

Und ich sags immer wieder, ganz lieben Dank.

LG

1 Like

Kleiner Zwischenstand. Das mit der Restlaufzeit funktioniert nicht ganz so wie gewünscht. Die Restzeit wird angezeigt, es wird auch runtergezählt ABER nur etwa 20 Sekunden lang. Dann stürzt die Anwendung ab mit der Meldung, dass der Prozess nicht auf die *.txt Datei zugreifen kann, da sie von einem anderen Prozess verwendet wird.

Irgendwo vielleicht auch nachvollziehbar, zum einen schreibst mAirlist via Script in 1000 Millisekunden-Schritten die Restzeit in die Datei und zum anderen liest meine VB Anwendung natürlich diese *.txt Datei aus, was eben früher oder später zu Konflikten kommt.

Nun weiß ich nicht, ob es noch andere Möglichkeiten, ich sag mal elegantere, oder ob ich vielleicht auch einfach etwas ist, auf dass man “verzichten” kann.

LG

Na ja, im schlimmsten Falle schreibst Du die Restlaufzeiten einfach in eine andere Datei.

procedure OnRuntimedataChange(Key, Value: string);
begin
  if (Key = 'Auto')
    OR (Key = 'Mic') then
    begin
      // mach was
    end
    else if (Key = 'RunA')
      OR (Key = 'RunB') then
    begin
      // mach was anderes
    end;
  end;
end;

begin
end.

Achtung: Vor else steht nie ein Semikolon. Näheres unter delphibasics.co.uk oder hier im Forum unter dem Suchbegriff Scripting-Hilfe:

Geteilte Grüße

TSD

Ja ok, dass mit einer zweiten *.txt Datei wäre natürlich eine Möglichkeit. Im Moment bekomme ich aber nur einen Error in mAirlist. Ich werde aber hier im Forum noch mal schauen, ich meine hier mal was gelesen zu haben, wie man den Fehler deutet usw.

08.04.2020 07:47:42 Fehler       Fehler beim Laden des Hintergrund-Scripts C:\*******\mairlist_runtime.mls: [Error] (33:5): Identifier expected

Anmerkung 2020-04-08 075526

Da stimmt was nicht mit Deinen Semikola bzw. end;. So müßte es aussehen:

procedure OnRuntimeDataChange(Key, Value: string);
begin
  if (Key = 'Auto')
    OR (Key = 'Encoder') then
  begin
    // do something
    finally
      StringList.Free;
    end;
  end
  else if (Key = 'RunA') 
    OR (Key = 'RunB') then
  begin
    // do something else
  end;
end;
    
begin
end.

Was versprichst Du Dir vom vorangestellten leeren String in

StringList.Add('' + GetRuntimeData(' RunA'));

Wenn Du ein Leerzeichen einfügen möchtest, mußt Du es auch reinschreiben:

StringList.Add(' ' + GetRuntimeData(' RunA'));

Pingelige Grüße

TSD

(Man muß da aber auch pingelig sein!)

Hehe, alles gut. Warum ich das da einfach leer lasse ist recht einfach.
In meinem Programm frage ich ab, was in Zeile XY steht. z.B. beim Mikrofon. Zu Anfang stand

Mic:   MicOn

drin, jetzt steht halt nur MicOn drin. So hab ich das bei den anderen auch gemacht. Ich denke aber, das wird sich noch ändern, sobald ich mit dem Aufaddieren der Strings klar komme. Hab deinen Scripting-Hilfe Beitrag dazu gefunden, muss es nur noch “verstehen”.

LG