Ton auf Hotkey legen, ohne diesen in die Playlist hinzuzufügen

Hi Torben,

Ich suche nach der Funktion, mit einem Hotkey einen bestimmten Ton abzuspielen. Ich habe nur “zur Playlist hinzufügen” gefunden, allerdings bräuchte ich tatsächlich eine Option, um einen Ton abzuspielen, OHNE diesen in eine Playlist einfügen zu müssen. Geschickt werden soll das ganze direkt an den Encoder, also im Prinzip ein “Hinztriller für Arme”.

Gibts sowas/Kann man sowas mit Umwegen lösen/Kann man das einbauen? Danke :slight_smile:
Grüße

Könntest Du nicht einfach eine Cart dafür nutzen?

Wenn man das wirklich an allen Playern und Carts vorbei machen will, ist es leider nicht ganz trivial.

Am besten nutzt man ein Hintergrundscript wie das folgende, das einen neuen Befehl “HINZTRILLER” definiert, den man dann überall (Fernsteuerung, Aktion, …) verwenden kann:

const
  FILENAME = 'Z:\tmp\hinztriller.mp3';
  DEVICE = 'Encoder';

var
  Source: IAudioSource;

procedure OnExecuteCommand(Command: string);
var
  fpi: IFilePlaylistItem;
  dev: IPlaybackDevice;
begin
  if Command = 'HINZTRILLER' then begin
    fpi := Instance.GetFactory.CreateFilePlaylistItem(FILENAME, []);
    dev := IPlaybackDevice(Instance.GetPlaybackDevices.FindByID(DEVICE));
    Source := fpi.BuildSource(dev, nil);
    Source.Start;
  end;
end;

Die Schwierigkeit an der Sache ist, dass der AudioSource “am Leben gelassen” werden muss, bis das File zuende gespielt hat. Andererseits soll das Script auch nicht solange warten - bei langen Elementen wäre das blöd, wenn mAirList dann so lange hängt. Daher hier die Lösung mit dem Hintergrund-Script, das den Source als globale Variable verwaltet.

Danke Torben 8)
@Stefan: die Cart fungiert als CartMax, das hat ein komplett anderes System als die “normale” CW.

Zugegeben dachte ich mir das schon.

Aber ich bin neugierig: Was ist das Besondere an der Funktionalität des CartMax? Kannst Du das mal in zwei, drei Sätzen zusammenfassen? :slight_smile:

Der CartMax funktioniert ganz anders als eine CW, man kann sich aber in mAirList einen Notbehelf bauen:
Oben die CW, drunter Playlisten/Stacks mit Playern daraunter. Hier ist’ ne ziemlich gute Aufnahme: https://www.media-online.de/index.php/2015-04-04-14-27-38/playout/cartmax-is

Das Feld oben ist nur zum Auswählen und Heraussuchen der Elemente, nicht zum Abspielen, dafür müssen die dann von dem Auswahlfeld oben in die Player runtergezogen werden. Ich bin’s so gewohnt und möchte das daher nicht mehr ändern.
Grüße.

Ahja, interessant. Danke Chris.

Im Prinzip sind das ja einfach vier Player (C1–4) mit jeweils einem Stack. Wobei sich der Stack ja von einer Playlist dadurch unterscheidet, dass der Stack rückwärts zu lesen ist. Das nächste Element ist das unterste, fällt quasi nach unten in den Player, richtig?

Das cartwall-ähnliche Raster mit den 4×7 Feldern sind im Grunde einfach Listen, die ich nach Moderator und nach anderen Klassifizierungen filtern kann, auch richtig?

Solche filterbare Listen finde ich sehr interessant und durchaus eine Überlegung wert, ob sich so etwas ähnliches nicht auch in mAirList umsetzen ließe (Hallo Torben :wink: ). Es muss ja nicht so aussehen, wie im cartmax. Ich könnte mir zum Beispiel vorstellen, dass man dem Browser eine Funktionalität verpasst, bei der man nach mehreren Attributen o.ä. filtern kann.

Auch Stacks wären durchaus eine Überlegung wert. Es gab sie ja auch bei der alten Cartwall. Aber da waren sie sehr versteckt. Eine recht einfache Möglichkeit wäre doch zum Beispiel, wenn Torben eine Option “Diese Playlist als Stack anzeigen” einbauen würde. Das wäre eine normale Playliste, deren Elemente jedoch von unten nach oben, statt von oben nach unten angeordnet werden.
Für eine echte Stack-Funktionalität wäre auf längere Sicht denkbar, dass noch Funktionen dazukommen, wie etwa, dass das letzt gespielte Element nach dem Abspielen wieder oben auf den Stack gelegt wird, sodass eine endlose Liste entsteht.

Viele Grüße
Stefan

PS: Ähm, falls wir das weiter diskutieren wollen, sollten wir einen eigenes Thema dafür aufmachen. :wink:

Alles richtig, Stefan!
Ich würde schon so eine Felder-Oberfläche bevorzugen, Frage ist halt, inwieweit Torben das überhaupt “abschauen” darf. Cool wärs natürlich schon :slight_smile:

DEVICE = 'Encoder'; […] dev := IPlaybackDevice(Instance.GetPlaybackDevices.FindByID(DEVICE));

Wenn ich statt eines Encoders direkt auf eine Soundkarte ausgeben möchte, was muss ich dann in die Variable DEVICE reinschreiben?
Wie bekomme ich raus, wie die IDs der PlaybackDevices lauten?

Ich habe gerade heute nachmittag für einen Kunden dieses schöne kleine Hintergrund-Script geschrieben, das die Vorgehensweise demonstriert.

Es bearbeitet Befehle der Art "LINER " und spielt die Datei, die sich in dem im Script angegebenen Ordner befinden muss, auf derselben Soundkarte wie Player A ab:

const
  FOLDER = 'C:\temp\';

procedure OnExecuteCommand(Command: string);
begin
  if copy(Command, 1, 6) = 'LINER ' then begin
    CurrentPlaybackControl.PlayItemDetached(
      Factory.CreateFilePlaylistItem(FOLDER + copy(Command, 7, 255), []);
      Instance.GetDeviceConfig.GetPlaybackDevice('Player0_0'),
      Instance.GetDeviceConfig.GetRegionDevices('Player0_0')
    );
  end;
end;

Vielen Dank. :slight_smile:

Kannst Du noch verraten, wie die ID für das Audiodevice der Cartwall lautet?
Oder gibt es sogar irgendwo eine Liste? Suche gerade schon in der mAirListScript.chm, finde es aber nicht.

Schau in die devices.ini :slight_smile:

Ah ;D Da hätte ich ja auch drauf kommen können. Dankeschön.

@Torben: In diesem Skript

const
  FILENAME = 'Z:\tmp\hinztriller.mp3';
  DEVICE = 'Encoder';

var
  Source: IAudioSource;

procedure OnExecuteCommand(Command: string);
var
  fpi: IFilePlaylistItem;
  dev: IPlaybackDevice;
begin
  if Command = 'HINZTRILLER' then begin
    fpi := Instance.GetFactory.CreateFilePlaylistItem(FILENAME, []);
    dev := IPlaybackDevice(Instance.GetPlaybackDevices.FindByID(DEVICE));
    Source := fpi.BuildSource(dev, nil);
    Source.Start;
  end;
end;

bekomme ich den Fehler

[Error] (16:40): Type mismatch

und in diesem Skript

const
  FOLDER = 'C:\temp\';

procedure OnExecuteCommand(Command: string);
begin
  if copy(Command, 1, 6) = 'LINER ' then begin
    CurrentPlaybackControl.PlayItemDetached(
      Factory.CreateFilePlaylistItem(FOLDER + copy(Command, 7, 255), []);
      Instance.GetDeviceConfig.GetPlaybackDevice('Player0_0'),
      Instance.GetDeviceConfig.GetRegionDevices('Player0_0')
    );
  end;
end;

den Fehler

[Error] (8:53): comma (',') expected

Ersetze ich dasdortige Semikolon durch ein Komma, erhalte ich

[Error] (11:6): Invalid number of parameters

Was sagte der Kunde?

Erfolglose Grüße

TSD

Und wiederum bitte ich um Entschuldigung, dass ich in alten Sachen rühre. Bin durch eigenständige Suche auf dieses Thema gekommen, welches einen meiner Wünsche lösen würde. Aber leider:

Denselben Fehler bekomme ich auch. Wurde seinerzeit leider nicht mehr beantwortet. Konnte das unterdessen gelöst werden?

Von mir nicht. Leider.

Schade.
Könnte @Torben vielleicht Licht ins Dunkel bringen, warum das anfangs gepostete script nicht läuft?
Vielleicht gibt es ja mittlerweile ja auch andere Methoden, um das Gewünschte
(ein bestimmtes Audio auf Tastendruck (Hotkey) direkt auf einem Device (in meinem Fall wäre es DEVICE = 'Cartwall_OnAir';) auszuspielen)

zu erreichen?

1 Like

Ansatz für v7.0/7.1:

var
  devices: TPlaybackDeviceSet;

....
devices := Instance.GetPlaybackRouting.GetPlaybackDevices('Cartwall_OnAir');
PlaybackControl(0).PlayItemDetached(fpi, devices);
...

“devices” und “TPlaybackDeviceSet” (als Mehrzahl) deswegen, weil das nicht nur eine einzelne Soundkarte sondern mehrere sind - nämlich für den Fall, dass es sich um ein regionalisiertes Element handelt.

PlayItemDetached ist das, was in der Playlist auch zum Ausblenden von Elementen benutzt wird, die vorzeitig aus einem Player fliegen. Macht nicht viel anderes als das explizite BuildSource und Play, aber man kann es hier bequem für sich nutzen.

2 Likes

Funktioniert!!

const
  FILENAME = 'Z:\tmp\hinztriller.mp3';
  DEVICE = 'Cartwall_OnAir';

var
  Source: IAudioSource;
  devices: TPlaybackDeviceSet;

procedure OnExecuteCommand(Command: string);
var
  fpi: IFilePlaylistItem;
  dev: IPlaybackDevice;
begin
  if Command = 'HINZTRILLER' then begin
    fpi := Instance.GetFactory.CreateFilePlaylistItem(FILENAME, []);
    devices := Instance.GetPlaybackRouting.GetPlaybackDevices(DEVICE);
    PlaybackControl(0).PlayItemDetached(fpi, devices);
  end;
end;

Ganz lieben Dank!!

Anmerkung: Die Zeile …

Source: IAudioSource;

… ist überflüssig (Überbleibsel aus dem Alt-Skript). Die Zeile …

devices: TPlaybackDeviceSet;

… könnte noch unter var innerhalb der procedure verschoben werden. Wir wollen doch schlank bleiben.

1 Like