Vollautomatische Ausspielung von Wiederholungen und Vorproduzierten Sendungen

Danke!

Das ist genau so’n Ding was ich dann immer nicht verstehe. (Das war Westfälisch: Immer nicht verstehe :joy:)
Die Cue Daten kann ich einfach vom Item Lesen aber um das lesen der Tags, muss ich wieder eine weitere Funktion drum herum bauen.
Ob ich das jemals in meinen Kopf kriege…:exploding_head:

Also, dann mal ganz langsam:

  • Factory ist ein Objekt, das Methoden zur Verfügung stellt, über die man alle möglichen anderen Arten von Objekten erzeugen kann.
  • In diesem Fall wollen wir über die Funktion CreateMetadataHandler ein Objekt vom Typ IMetadataHandler erzeugen, mit dem wir die Tags auslesen können.
  • Die Funktion CreateMetadataHandler bekommt dabei als Parameter das PlaylistItem übergeben, auf dem der Handler arbeiten soll - damit der direkt weiß, mit welcher Datei und welchem Item er es zu tun hat.
  • Dann wird dessen Methode ReadNativeTags aufgerufen, um die ID3-Tags zu lesen und in den PlaylistItem-Datensatz zu kopieren.

“Unabgekürzt” (und besser zu verstehen) würde das so aussehen:

item := CurrentPlaylist.GetItem(i);
handler := Factory.CreateMetadataHandler(item);
handler.ReadNativeTags;

Durch die Kurzschreibweise ersparen wir uns die ganzen Variablendeklarationen.

Du siehst, die Interna von mAirList sind manchmal sehr kompliziert. Aber bieten doch eine Menge Funktionalität. Die Script-Engine ist euer Guckloch in diese Welt.

Um die Sache etwas intuitiver zu machen, könnte ich dem IPlaylistItem eine Methode CreateMetadataHandler geben, die nur eine Abkürzung für Factory.CreateMetadataHandler(item) ist. Dann würde es so aussehen:

CurrentPlaylist.GetItem(i).CreateMetadataHandler.ReadNativeTags;

Wäre das besser zu verstehen?

Übrigens, bei den Typen mit “I” vorne (IPlaylistItem, IMetadataHandler, …) handelt es sich allesamt um “Interfaces”, also “indirekte” Verweise auf Objekte. Die dann wiederum Methoden haben, die man aufrufen kann.

Die Verwendung von Interfaces statt normaler Objektreferenzen erlaubt es in Delphi, dass man “reference counting” macht. Also Objekte, die sich selbst aus dem Speicher löschen, sobald niemand mehr auf sie zugreift. Daher der Umweg über Interfaces. Beim Programmieren immer die doppelte Arbeit, da man sowohl das Interface als auch das implementierende Objekt definieren muss. Aber am Ende hat es nur Vorteile.

1 Like

PS: Ich liebe das Markdown vom neuen Forum.

Danke für die Ausführungen. Lange- und kurze Schreibweise bringe ich schon passend zusammen. Auch wenn ich die Syntax immer noch nicht verstanden habe. Schauen wir mal.

Ja, das ist wirklich klasse.

Jetzt muss ich mal sehen, wie ich das noch unterbringe.

Ich würde erst mal den Dateinamen, des aktuellen Items in eine Variable schreiben und .cue anhängen und dann das lesen der Cue Datei triggern.
Wobei ich da sicherlich noch abfangen muss, dass die Cue Datei nicht immer existiert und nur wenn sie existiert, soll sie auch gelesen werden.

const
  MAX_COUNT = 3;

var
  i: integer;
  count: integer;
  cue: IFilePlaylistItem;

begin
  CurrentPlaylist.BeginUpdate;
  try
    count := 0;
    for i := 0 to CurrentPlaylist.GetCount - 1 do
      if CurrentPlaylist.GetItem(i).GetItemType = pitShow then begin
	    Factory.CreateMetadataHandler(CurrentPlaylist.GetItem(i)).ReadNativeTags;
        CurrentPlaylist.GetItem(i).AutoSearchPosition(ptCueIn);
        CurrentPlaylist.GetItem(i).AutoSearchPosition(ptFadeOut);
        CurrentPlaylist.GetItem(i).AutoSearchPosition(ptCueOut);
		cue := FilePlaylistItem.GetFilename(CurrentPlaylist.GetItem(i))+'.cue';
		CurrentPlaylist.GetItem(i).GetCueData.LoadFromCueSheet(cue:);
        count := count + 1;
        if count = MAX_COUNT then break;
      end;
  finally
    CurrentPlaylist.EndUpdate;
  end;
end.

Ich muss dieses Thema noch mal aufgreifen.

Ein Re-Do des AutoCue ist ja seit Version 6.2 Obsolet, das kann ich ja einfach beim Element anhaken.
Wo ich aber immer noch nicht weiter bin ist das neuladen eines Cue-Sheets, was seit Version 6.2 ja noch deutlich interessanter geworden ist, weil man die jetzt sinnvoll bei einer Aufzeichnung erzeugen kann.

Also muss jetzt folgendes passieren.

  1. Syndication Zulieferung, gleichbleibender Dateiname an gleichbleibendem Verzeichnis. Ist ein Cue-Sheet vorhanden, dieses importieren. Ist keins vorhanden, ggf. vorhandene Extra-Cuepunkte löschen.

  2. Ausspielung von Wiederholungen. Der MiniScheduler muss sich anhand von Variablen die richtige Datei suchen. YYYY/KW/Wochentag/Stunde/*.mp3 (es kann hier nur eine liegen, Position im Vezeichnisbaum und Dateiname, sind jedes mal anders. Dann immer AutoCue und falls vorhanden, Cue-Sheet laden. Gelöscht werden muss hier nix, das passiert bereits vorher, es sind also niemals extra Cue-Punkte im Tag.

Hat da jemand eine Idee?

Ja, wenn die Cue-Daten einmal eingelesen sind, kann man sie sowohl im Element, im MMD file, in der Datenbank oder in der Plalyliste speichern, genau so wie alle andren META daten auch.

Entsprechend bleiben die erhalten. Das nutzen wir mehrfach täglich.

Wenn sich die Datei unter gleichem Dateinamen ändert, funktioniert das natürlich nicht mehr. Dazu habe ich noch einen anderen Thread offen aber offensichtlich lässt sich das im Moment auch nicht scripten.

Ja genau, das meinte ich… Beispiel: Ich kriege eine vorproduzierte Sendung Meine_ganz_tolle_Sendung.mp3 und das entsprechende Cue Sheet Meine_ganz_tolle_Sendung.mp3.cue. Diese wurde produziert am 19. August 2019. Nun folgt das Update (die Sendung läuft wöchentlich) der beiden Dateien am 26. August 2019. Inhalt der mp3 und der mp3.cue Datei sind jetzt natürlich anders. Die Titelübertragung ist dann die vom 19. August (Cue-Sheet) und nicht die neue vom 26. August ?!?

Und wenn die vorproduzierte Sendung den Anhang [Nummer der Kalenderwoche] erhält - entweder vom Zulieferer oder von dir?

Vielleicht kann man auch was basteln, dass man das Upload-Datum automatisiert vor das .mp3 einfügen lässt? :thinking:

Das Thema hatte ich hier: Vollautomatische Ausspielung von Wiederholungen und Vorproduzierten Sendungen
Schon mal auf gemacht, bisher aber leider noch keine Lösung gefunden. In der Scripting engine fehlt offensichtlich der Zugriff auf die extra Cues, jedenfalls konnte mir bisher noch niemand sagen, wie ich damit in Scripten umgehen müsste.

Ja… Manchmal ist das so eine Sache mit dem Wald und den Bäumen.

Ich habe mich mal wieder an meine Vollautomatisierung gemacht und das Script von weiter oben, vereinfacht. Wir gehen einfach die ganze Playliste durch, suchen nach dem Item Element “Sendung”, laden erst mal den ID3 Tag und falls eine existiert, auch die Cue-Datei.

var
  i: integer;
  cue: IFilePlaylistItem;

begin
  CurrentPlaylist.BeginUpdate;
  try
    for i := 0 to CurrentPlaylist.GetCount - 1 do
      if CurrentPlaylist.GetItem(i).GetItemType = pitShow then begin
        Factory.CreateMetadataHandler(CurrentPlaylist.GetItem(i)).ReadNativeTags;
        cue := FilePlaylistItem.GetFilename(CurrentPlaylist.GetItem(i))+'.cue';
        CurrentPlaylist.GetItem(i).GetCueData.LoadFromCueSheet(cue);
      end;
  finally
    CurrentPlaylist.EndUpdate;
  end;
end.

Muss ich das laden des Cue-Sheets in eine weitere “Try” Schleife packen oder reicht das erste try vor der for-Schleife dafür auch noch aus?
Ich habe es noch nicht getestet aber passt das halbwegs oder bin ich total auf dem Holzweg?

Hmm :man_facepalming: ich bekomme einen Error (10:81): Type mismatch.

Was mache ich denn schon wieder falsch? :thinking:

Du in diesem Falle gar nichts:

Das kann so nicht funktionieren, da CreateMetaDataHandler ein Objekt vom Typ IFilePlaylistItem benötigt, und nicht IPlaylistItem.

Allerdings bliebe Dein Code auch in der nächsten Zeile hängen:

[Error] (11:16): Unknown identifier 'FilePlaylistItem'

@Torben?


Sonntägliche Grüße

TSD

In meiner Zeitzone ist heute Samstag… wo bist du denn?

Da Urlaub, scheinbares Sonntagsempfinden. Um so besser!
 

Entspannte Grüße

TSD

1 Like
Factory.CreateMetadataHandler(CurrentPlaylist.GetItem(i).AsFile).ReadNativeTags;
1 Like

Gut, dann probiere mal folgendes, @shorty.xs:

var
  i: integer;
  Cue: string;
  Item: IPlaylistItem;
  Meta: IMetadataHandler;

begin
  CurrentPlaylist.BeginUpdate;
  try
    for i := 0 to CurrentPlaylist.GetCount - 1 do
      Item := CurrentPlaylist.GetItem(i);
      if CurrentPlaylist.GetItem(i).GetItemType = pitShow then begin
        Factory.CreateMetadataHandler(Item.AsFile).ReadNativeTags;
        Cue := IFilePlaylistItem(Item).GetFilename + '.cue';
        Item.GetCueData.LoadFromCueSheet(Cue);
      end;
  finally
    CurrentPlaylist.EndUpdate;
  end;
end.


Bereinigte Grüße

TSD

Ach, und die Zeile

Meta: IMetadataHandler;

ist überflüssig, nur vom Ausprobieren noch übrig.

Schlampige Grüße

TSD

Und: Die Zeile

if CurrentPlaylist.GetItem(i).GetItemType = pitShow then begin

sollte schöner heißen

if Item.GetItemType = pitShow then begin

Mußte schnell gehen heute morgen.

TSD

1 Like

Ich bin mal wieder in dieses Thema hier eingestiegen.

Diese Script Syntax bring mich noch mal um (den Vestand).
Das hier kam dann am ende raus.

var
  i: integer;
  Cue: string;
  Item: IPlaylistItem;

begin
  CurrentPlaylist.BeginUpdate;
  try
    for i := 0 to CurrentPlaylist.GetCount - 1 do
      Item := CurrentPlaylist.GetItem(i);
      if Item.GetItemType = pitShow then begin
        Factory.CreateMetadataHandler(Item.AsFile).ReadNativeTags;
        Cue := IFilePlaylistItem(Item).GetFilename + '.cue';
        Item.GetCueData.LoadFromCueSheet(Cue);
      end;
  finally
    CurrentPlaylist.EndUpdate;
  end;
end.

Problem: Es passiert nichts.
Nun wollte ich anfangen, den Fehler zu suchen ud wollte ganz simpel ein SystemLog einfügen.

Nach dem Item über Item := CurrentPlaylist.GetItem(i); gesetzt worden ist, möchte ich mir das ins Log schreiben. Ich hätte angenommen, dass das über SystemLog (Item); hätte funktionieren müssen. Stattdessen bekomme ich einen Type Missmatch. Wahlweise auch SystemLog (Item.GetItemType);

Das gleiche weiter unten, den Inhalt von Cue.

Verzweifelte Grüße

Ins Log kannst Du nur Daten vom Typ String, also Buchstaben, schreiben. Item ist aber ein IPlaylistItem. Vielleicht so:

  …
  SystemLog('Holleri ' + Item.GetTitle);
  …


Syntaktische Grüße

TSD