Frage zu einem kleinen Projekt

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

:see_no_evil: Aber klar, ich könnte natürlich auch das ’ ’ + komplett weglassen. :smiley: Da war der Wald wieder dichter.

Kümmere mich jetzt erstmal um den Error im Script, auch mit deinem zweiten Script bleibt der Error. Aber ich bin voller Tatendrang und geb nicht auf.

Ja, da habe ich ein try zuviel weggelöscht.

Sorry wenn ich noch mal nerve und fragen muss. Hänge jetzt gut 2 Stunden nur an diesem Problem und komme nicht weiter. Ich möchte noch einen Playerzustand abarbeiten. Nämlich “Pause”. Hatte diesbezüglich auch hier was im Forum gefunden, es entsprechend eingepflegt aber er schreibt nur den “else Zustand” nicht aber den “if Zustand”. Hast du ne Idee wo ich hier einen Fehler habe? Hier mal das was ich dazu benutze. In der *.txt steht also nur 0, nie aber 1 obwohl der OldState stimmt, darum auch extra zur Kontrolle unten der Systemlog.

function StateToString(iState: TPlayerState): string;
begin
  case iState of
//psEmpty: Result := 'Empty';
//psLoading: Result := 'Loading';
psLoaded: Result := 'Loaded';
psPlaying: Result := 'Playing';
//psFading: Result := 'Fading';
//psEOF: Result := 'EOF';
//psError: Result := 'Error';
psPaused: Result := 'Paused';
//psStopped: Result := 'Stopped';
  else
Result := IntToStr(ord(iState));
  end;
end;

procedure OnPlayerStateChange(PlaylistIndex: integer; PlayerIndex: integer; OldState: TPlayerState; NewState: TPlayerState; Item: IPlaylistItem);
begin

  if (StateToString(OldState) = 'Loaded') then
  begin
  Breaks := '1';
  end
  else 
  Begin
  Breaks := '0';
  SystemLog('Player ' + IntToStr(PlayerIndex) + ' old: ' + StateToString(OldState) + ', new: ' + StateToString(NewState));
  end;
end;

Warum so kompliziert?

procedure OnPlayerStateChange(PlaylistIndex: integer; PlayerIndex: integer; 
  OldState: TPlayerState; NewState: TPlayerState; Item: IPlaylistItem);
begin
  if NewState = psPaused then
    Breaks := '1'
  else
    Breaks := '0';
  SetRuntimeData('Paused', Breaks);
  // SystemLog('Player ' + IntToStr(PlayerIndex) + ' old: ' + StateToString(OldState) + ', new: ' + StateToString(NewState));
  end;
end;

Oder sehe ich was nicht?

Blinde (?) Grüße

TSD

Ich hatte das hier nach gemacht, darum sicher auch so umfangreich

Mensch, wie kann ich das nur je wieder gut machen? Ich danke dir, werde das gleich testen.