Pluginprogrammierung DMXC2

Aus Deutsches DMXC-Wiki
Zur Navigation springen Zur Suche springen
Achtung wichtiger Hinweis Dieses Wikiartikel wurde aus mehreren, vermutlich veralteten, Wikiartikeln aus dem alten Wiki übertragen.
Daher können einige Informationen nicht mehr stimmen oder unvollständig sein.


In welcher Umgebung kann man eine Plugin-dll entwickeln?

In unserem Projekt arbeiten wir mit Visual Basic 6. [Microsoft] stellte ein kostenloses Ablaufmodell zur Verfügung, (welche ich leider nicht mehr finde und die man heute wohl nur noch auf CDs alter PC-Zeitschriften bekommt). Das ist ein vollwertiges Basic, aber leider kann man damit keine .exe oder dll erzeugen, sondern der Code wird in einer Interpreterumgebung ausgeführt.

Zur Erzeugung von dlls benötigt man z.B. die "Visual Basic Enterprise Edition", die aber nicht mehr im Handel ist, aber sehr häufig bei ebay legal angeboten wird. Für Schüler und Studenten gab es auch eine günstige Version bei [Amazon]. Möglicherweise können sich einige Nutzer sich diese Version aber auch über das MSDN beziehen.

Alternativ gibt es folgende potenzielle Möglichkeiten zur Erzegung von dlls:

  • Es gab von Microsoft auch die kostenlose "Control Creation Edition". Auch diese gibt es anscheinend nicht mehr offiziell, aber dank google findet man das noch im Internet. Im Internet und in PC-Zeitschriften kursieren legale Tricks, wie man damit auch .exe generiert. Welcher Entwickler probiert mal aus, ob das auch für plugins funktioniert?
  • Plugins können prinzipiell auch in jeder anderen Sprache geschrieben werden, in der ein Compiler zur Verfügung steht. Wurde teilweise erfolgreich mit Delphi ausprobiert.
  • Man verwendet das .NET Framework SDK, welches viele kostenlose hilfreiche Tools enthält, z.B. einen Compiler für Visual Basic.NET. Leider ist die zugehörige Entwicklungsumgebung nicht kostenlos, da schafft aber der nächste Punkt eventuell Abhilfe.
  • Es gibt die kostenlose Entwicklungsumgebung SharpDevelop als (wie ich gelesen habe) hervorragende Alternative. Der Name täuscht - diese Umgebung unterstützt auch Visual Basic und liefert einen komfortablen Editor. Leider gibt es wohl noch keinen integrierten Debugger. Man fidet die aktuellste Version unter [SharpDevelop]. Zur Unterstützung wird hier auch die Magic Library genannt, die es unter diesem [link] gibt. Aber auch diesen Weg habe ich noch nicht probieren können.

Elementare Programmierelemente und Konventionen

Wir empfehlen ein 3 schichtiges Design, d.h. für ein Plugin sollten mindestens 3 Module erstellt bzw. angepasst werden.

Daneben sollte wie in diesem Beispiel jedes Plugin ein Hilfefenster besitzen, in dem die Version, der Autor und eine kurze Beschreibung gegeben werden (frmAbout-Form).

Je nach Plugin können natürlich weitere Klassen oder Module hinzukommen, falls Sie vorhandene Controls wiederverwenden möchten.

Der GUI- Modul besteht in VB6 aus einer Form und dazugehörigem Programmcode. Man sollte darauf achten, dass in diesem Modul möglichst nur die Oberflächenaspekte implementiert werden und keine DMX-Wert-Bearbeitung. Das hat zwei Vorteile:

  • man kann leichter die GUI ändern, ohne dass die DMX-Logik „Schaden nimmt“
  • die separat implementierte DMX-Logik kann besser wiederverwendet werden


Der Plugin-Logik Modul befasst sich mit den Algorithmen der Verarbeitung, Analyse und Generierung von DMX-Werten. Dazu empfängt er die von DMXControl ausgegebenen DMX-Werte über interface C und manuelle DMX-Wertänderungen über Interface A. Anderererseits kann dieser Modul über Interface B Werte an DMXControl senden oder über Interface D im GUI-Modul visualisieren lassen.

Der Plugin Interface Klassenmodul hat zwei Aufgaben:

  • Hier werden die call back calls von DMXControl aufgenommen und ausgewertet.
  • Alle notwendigen Konfigurationswerte für die Integration des Plugins in DMXControl werden hier gesetzt, z.B. Name des Plugins oder Verhalten bei der Aktivierung.

Die Klasse DMXCPlugin_Helper liefert das Interface zum Aufruf der Kommandos durch ein Plugin. Dieses Interface ist im Anhang 1 beschrieben. Ist das Plugin aktiv, werden bestimmte Überwachungen durchgeführt ("Sicherheitsfunktionen" für plug-ins), die die Stabilität des DMXC kernels gewährleisten sollen. Insbesondere entscheidet DMXC, ob aufgrund gewisser Bedingungen bestimmte Operationen überhaupt ausgeführt werden dürfen. (Bisher noch nicht, müsste man überlegen was man sinnvoll kontrollieren kann, ohne zu viele Ressourcen zu verschwenden)

Alle Ausgabe-Plugins unterliegen einer Namenskonvention: Sie müssen mit „.out.dll“ enden. Beispiel: Dmx4All.out.dll Dies gilt nicht für Anwendungsplugins.

Plugin Interface Referenzen

Alle hier genannten Methoden gehören zur Klasse DMXCPlugin_Helper. Daher sind die folgenden Schnittstellen als Methode eines Objektes dieser Klasse aufzurufen.

Die Interfaces sind in in zwei Modulen definiert, diese müssen im Interface-Modul mit importiert werden

Implements IDMXCPlugin
Implements IDMXCModule

Die benötigten Typdefinitionen befinden sich in DMXCTypeLib.dll. Daher muss dieser Modul sowohl im Programmverzeichnis von DMXControl als auch in Ihrer VB6-Umgebung bekannt gemacht werden. Dazu müssen Sie in VB6 unter dem Projektmenü den Punkt "References" aufrufen und die Verknüpfung zu DMXCTypeLib.dll herstellen. Man kann sich z.B. eine lokale Kopie im VB6-Arbeitsverzeichnis erstellen.

Public mHelper

Folgende Interfaces müssen in einem Plugin implementiert werden:

Methode Aufgerufen von Beschreibung Parameter/Variable/Returnwert
Private Function IDMXCPlugin_Configure() As Boolean Plugin-Konfiguration (Button "Konfigurieren") Ruft die GUI für ggfs. erforderliche Plugin-Konfiguration IDMXCPlugin_Configure (Boolean) teilt mit, ob ein Konfigurationsmemü existiert
Private Function IDMXCPlugin_Enable() As Boolean Plugin-Konfiguration/Starten aus dem Menü "Fenster" Kann Funktionsrufe für das Aktivieren des Plugins enthalten (Aktivieren = Haken in Plugin-Liste setzen) IDMXCPlugin_Enable (Boolean) teilt mit, ob die Operationen beim Aktivieren erfolgreich waren
Private Function IDMXCPlugin_Disable() As Boolean DMXControl Kann Funktionsrufe für das Deaktivieren des Plugins enthalten (Deaktivieren = Haken in Plugin-Liste entfernen) IDMXCPlugin_Disable (Boolean) teilt mit, ob die Operationen beim Deaktivieren erfolgreich waren
Private Function IDMXCPlugin_Init(CallingAppTitle As String, MyFilename As String, DMXCPluginHelper As DMXCTypeLib.IPluginHelper) As Boolean DMXControl (Laden beim Programmstart) Kann Funktionsrufe für das Initialisieren des Plugins enthalten (Initialisieren = Laden beim Programmstart)
Private Function IDMXCPlugin_Term() As Boolean DMXControl (Schließen des Plugins) Kann Funktionsrufe für das Terminieren des Plugins enthalten (Terminieren = Schließen des Plugins)
Private Property Get IDMXCPlugin_PluginName() As String Plugin-Konfiguration übergibt der Plugin-Konfiguration den Namen des Plugins IDMXCPlugin_PluginName (String)
Private Property Get IDMXCModule_ModuleInfo() As DMXCTypeLib.Type_Module_Info DMXControl beim Laden des Programms übergibt diverse Informationen über das Plugin (siehe Tabelle unten)


In der Methode IDMXCModule_ModuleInfo sind folgende Datenfelder anzupassen:

Attribut Beschreibung Kommentar/Beispiel
GUID eindeutige ID für das Plugin "{b61b4c42-17ed-11da-94c3-00e08161165f}" (GUID-Generator)
Name Bezeichnung des Plugins in Konfigurationsliste, Menübaum und Kanalübersicht (Mixerkanäle) "Lauflicht Demo Plugin"
Description zusätzliche Beschreibung, z.Z. ungenutzt "Simple GUI für Lauflichter"
Author Name des Programmierers, z.Z. ungenutzt "Max Mustermann"
Experimental zeigt experimentellen Status im Menübaum an, falls noch nicht ausführlich getestet True/False
ProvidesToolWindow gibt an, ob separates GUI-Fenster für Plugin existiert True/False
Category gibt an, in welche der Kategorien des Menübaums das Plugin einsortiert wird CAT_Control
FormName übergibt VB-Name des Plugin-Formulars (Oberfläche) "frmTutorMain"
Frm übergibt eine Referenz auf das Plugin-Formular Set .Frm = frmTutorMain
ProvidesCommand gibt an, ob Befehl für die Plugin-Funktionalität definiert wird True
ProvidesSceneType gibt an, ob Plugin neuen Szenentype definiert, z.Z. noch nicht unterstützt False
UsesProvidedOutput gibt an, ob Plugin Signale an den Mixer senden möchte True
UsesMessaging gibt an, ob Plugin DMXControl-Messages empfangen möchte True/False
Messages Collection, zu der alle zu empfangenden Messages hinzugefügt werden Messages.Add MSG_Channel_Set

Aus der Plugin-Anwendung können folgende Funktionen gerufen werden:

Methode Beispiel Beschreibung
Public Function SetChannel(Channel As Long, Value As Long, IgnoreChange As Boolean) Call mHelper.MyStream.SetChannel(mDimmerAddr, dmxv, True) Ausgeben eines DMX Wertes auf dem angegebenen Kanal. Der dritte Parameter gibt an, ob diese Wertänderung in der Szenenverwaltung ignoriert werden soll.
Public Function DMXC_Channel_IsDimmer(Channel As Long) As Boolean . Abfrage, ob der Kanal für die Helligkeit eines Gerätes zuständig ist
Public Property Get DMXC_CHANNEL_MAXCHANNELS() As Long Gibt die Nummer des höchsten verwendbaren Kanals zurück
Public Function DMXC_Channel_GetValue(Channel As Long) As Long dmxValue = mHelper.ChannelGetValue(currentChannel) Hiermit kann das Plugin den aktuellen Wert abfragen. Wird z.B. bei der Plugin-Initialisierung benötigt.

Die Interfaces werden laufend erweitert. Bitte diskutiert hier (oder schreibt uns), welche Funktionen ihr für Eure Plugins benötigt.

Plugin Interface Erweiterungen in DMXControl 2.10

In der Version 2.10 wird die Plugin-Schnittstelle um einige wesentliche Funktionen erweitert.

  • Fenster-Management
  • Kommandos

Fenster-Management

Für alle Plugins, die eine graphische Oberfläche haben kann zusätzlich die Schnittstelle "IExternalWindow" implementiert werden. Diese enthält Funktionen zum Fenster-Management des Plugins und ermöglicht es DMXControl den Zustand und die Position des Pluginfensters zu ermitteln, zu speichern und bei Neustart von DMXControl dieses auch direkt an der alten Position zu starten.

Im Formular des Plugins muss die Schnittstelle implementiert werden:

Implements IExternalWindow


und folgende Funktionen/Properties der Schnittstelle muss das Plugin implementieren:

Private Function IExternalWindow_showWindow() As Boolean

Private Function IExternalWindow_hideWindow() As Boolean

Private Function IExternalWindow_loadWindow() As Boolean

Private Function IExternalWindow_unloadWindow() As Boolean

Private Property Get IExternalWindow_isOpen() As Boolean

Private Property Let IExternalWindow_WindowState(RHS As Long)

Private Property Get IExternalWindow_WindowState() As Long


Die Bedeutung der einzelnen Elemente ist eigentlich sprechend, so dass auf eine detaillierte Beschreibung der einzelnen Funktionen hier verzichtet wird.

Kommandos

Die Verwendung von Kommandos in Plugins ist ab DMXControl 2.10 in beide Richtungen möglich. D.h., man kann im Plugin eigene Kommandos definieren, die dann in DMXControl zur Buttonbelegung, Szenendefinition, usw. auftauchen und man kann auch vom Plugin aus auf alle in DMXControl vorhandenen Kommandos zugreifen.


Definition eigener Kommandos

Um eigene Kommandos bereitzustellen, muss das Plugin die Schnittstelle ICommandServer implementieren.

implements ICommandServer

Folgende Funktionen/Properties müssen implementiert werden:

'
' mit diesem Namen taucht das Plugin in der Kommandoliste in DMXC auf
'

Private Property Get ICommandServer_Name() As String
'
' hier wird auf die Kommandos reagiert

Private Function ICommandServer_ExecuteCommand(FirstSelection As String, SecondSelection As String, NewValue As Long, Optional Stream As DMXCTypeLib.IDMXMixerChannel, Optional AdditionalData As PropertyBag) As Variant


'
' hier wird die erste Ebene der Kommandostruktur erstellt

Private Function ICommandServer_GetFirstOptions() As DMXCTypeLib.IKeyCollection
 Set ICommandServer_GetFirstOptions = New KeyCollection
 With ICommandServer_GetFirstOptions
  .Add mHelper.Translator.Translate("Activate Function"), "FUNCTION"
  ...
 End With
End Function
'
' hier wird die zweite Ebene der Kommandostruktur erstellt

Private Function ICommandServer_GetSecondOptions(FirstSelection As String) As DMXCTypeLib.IKeyCollection

 Set ICommandServer_GetSecondOptions = New KeyCollection
 With ICommandServer_GetSecondOptions
  If FirstSelection = "FUNCTION" Then
   .Add mHelper.Translator.Translate("an"), "ON"
   .Add mHelper.Translator.Translate("aus"), "OFF"
  ElseIf FirstSelection = "LISTSELECT" Then
   .Add mHelper.Translator.Translate("nächster"), "NEXT"
   .Add mHelper.Translator.Translate("vorheriger"), "PREVIOUS"
   .Add "-----", "-----"
   .Add "1", "1"
   ...
  ElseIf FirstSelection = "VALUE" Then
   .Add mHelper.Translator.Translate("1. Wert"), "1.VALUE"
   ....

  End If
 End With
End Function

Zugriff auf die Kommandos von DMXControl

Über die hier beschriebenen Methoden ist es möglich alle in DMXControl vorhandenen Kommandos zu benutzen. D.H., man kann Szenen und Effekte anwählen, starten, stoppen und vieles mehr (alles, was man auch auf einen Button legen kann). Um auf die Kommandos zugreifen zu können, braucht man ein spezielles ExtendedListView-Control für VB6. Dieses kann man aus dem Internet herunterladen (http://vcreations.net/product.asp?pid=1) und installieren. Mit den in die Plugin-Schnittstelle eingebauten Funktionen kann ein solches ExtListView gefüllt und genutzt werden.


DMXControl-Messages

DMXControl verwendet zur internen Kommunikation eine Reihe von Windows-Messages, um Vorgänge asynchron ausführen zu können. Wenn Sie ein Plugin entwickeln, ist diese Liste für sie wichtig. Jede Message hat zwei zusätzliche Datenparameter, die verschieden benutzt werden: Arg1 und Arg2. Beides sind Variablen vom Typ "Long", es können also keine Zeichenketten direkt übermittelt werden.

Bitte beachten Sie, dass Messages natürlich nur funktionieren können, wenn das entsprechende Empfänger-Fenster auch geöffnet ist.

Folgende Nachrichten sind in DMXC verfügbar:


  • MSG_Channel_Set
    • Der Kanal Arg1 soll auf den Wert Arg2 gesetzt werden. Diese Nachricht wird vom DMX-Mixer bei Werteänderungen erzeugt. Sie gibt nicht den endgültig auszugebeneden Wert wieder, da dieser erst noch vom Core verändert werden kann.


  • MSG_Channel_Send
    • Der Kanal Arg1 soll auf den Wert Arg2 gesetzt werden. Arg2 gibt den endgültigen DMX-Wert an, wie er auch zum Interface gesendet wird. Sie können diese Message verwenden, um über DMX-Werteänderungen informiert zu werden.


  • MSG_Master_Set
    • Der in Arg1 angegebene Fader des Masterfader-Tools wird auf den Wert Arg2 gesetzt. Dabei kann Arg1 folgende Werte annehmen:
      • MST_Grand = 1
      • MST_Flash = 3


  • MSG_SM_Set
    • Der in Arg1 angegebene Submaster (1-12) wird auf den Wert aus Arg2 gesetzt.


  • MSG_SM_Move (Privat)
    • Der in Arg1 angegebene Submaster (1-12) wird um den Wert aus Arg2 geändert.


  • MSG_SM_Flash
    • Der in Arg1 angegebene Submaster (1-12) wird geflasht (Arg2=True) oder "deflashed" (Arg2=False)


  • MSG_Beat_Detected
    • Eines der Sound-Tools hat einen Beat erkannt. Es ist gleichzeitig immer nur eine Beat-Quelle aktiv. Kommt der Beat vom Sound-Analyzer ist Arg1=1, kommt der Beat vom BeatTool ist Arg1=2. Arg2 wird nicht verwendet und ist immer 0.


  • MSG_Command_Blackout
    • Ein Blackout wird aktiviert (Arg1=True) oder deaktiviert (Arg1=False). Arg2 wird nicht ausgewertet.


  • MSG_Device_Changed
    • Die Gerätekonfiguration hat sich geändert. Arg1 kann das geänderte Gerät enthalten, tut dies aber nicht unter allen Umständen.


  • MSG_Modules_Changed
    • Die Modulkonfiguration hat sich verändert. Arg1 gibt die numerische ID des geänderten Moduls an, sollte aber nicht ausgewertet werden.


  • MSG_Config_Changed
    • Eine Einstellung hat sich verändert. Arg1 kann folgende Werte annehmen:
      • CHG_MIDIRemote = 1
      • CHG_Filename = 2
      • CHG_Device = 3
      • CHG_Joystick = 4
      • CHG_Keyboard = 5
      • CHG_DMXInRemote = 6
      • CHG_ProjectFile = 7
    • Beim Auftreten dieser Message mit Arg1=CHG_Filename hat der Benutzer ein anderes Projekt geöffnet. Die Tools müssen die neue Projektdatei laden.


  • MSG_Config_WillChange
    • Eine Einstellung wird sich ändern. Arg1 kann die gleichen Werte wie bei MSG_Config_Changed annehmen. In Verbindung mit Arg1=CHG_Filename tritt diese Message auf, wenn der Benutzer die Projektdatei wechseln möchte, aber noch bevor die Änderung aktiv wird. Daher müssen die Tools nachfragen, ob eventuelle Änderungen gespeichert werden sollen. Anschließend wird meistens MSG_Config_Changed auftreten.


  • MSG_Item_Select (privat)
    • Ein Element wird ausgewählt. Arg1 gibt den Elementtyp an und kann folgende Werte annehmen:
      • ITM_Device = 1
      • ITM_Selection = 4
      • ITM_TapButton = 5
      • ITM_Scenelist = 6
      • ITM_SyncButton = 7
    • Über Arg2 wird das Element spezifiziert. Werte größer oder gleich 0 wählen ein definiertes Element aus, folgende Werte sind ebenfalls möglich:
      • SEL_Next = -1
      • SEL_Prev = -2
      • SEL_Act = -3
      • SEL_Unselect = -4
    • SEL_Next und SEL_Prev wählen das nächte bzw. vorhergehende Element aus. Sel_Act ändert die Auswahl nicht und SEL_Unselect entfernt die Auswahl des Elements.


  • MSG_File_Save
    • Der Benutzer möchte das Projekt speichern. Alle Tools speichern die aktuellen Daten in ihren Projektdateien.


  • MSG_Toggle_OnOff (Privat)
    • Eine Funktion soll ein- oder ausgeschaltet werden. Arg1 gibt die Funktion an und kann folgende Werte annehmen:
      • TGL_Sound2Light = 1
    • Arg2 bestimmt das Umschaltverhalten und kann folgende Werte annehmen:
      • MDE_On = 1
      • MDE_Off = 2
      • MDE_Toggle = 3
    • MDE_On und MDE_Off schalten die Funktion ein- bzw. aus, während MDE_Toggle den aktuellen Zustand umschaltet (On -> Off, Off -> On)


  • MSG_Scenelist_Go (Privat)
    • Der "Go!"-Button der Szenenliste soll ausgelöst werden


  • MSG_Window_View
    • Die Fensteransicht wurde umgeschaltet (Edit/Execution). Arg1 kann folgende Werte annehmen:
      • VIW_Execute = 1
      • VIW_Edit = 2


  • MSG_DMXIn_Channel_Set
    • Der DMX-In-Wert für den Kanal Arg1 wurde auf den Wert Arg2 geändert.


  • MSG_Item_Next (Privat)
    • Der nächste Schritt eines Elements wird ausgeführt. Arg1 und Arg2 sind wie bei MSG_Item_Select belegt.