(Die Seite wurde neu angelegt: „'''Für die Benutzung dieser Plugins benötigen Sie DMXControl 2.9 oder 2.10''' Die Dll-Datei eines Plugins muß in das Unterverzeichnis "plugins" des DMXCon…“) |
Jkuehn (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
||
(3 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
{{Infobox Plugin | |||
| Name = Plugin | |||
| Logo = LauflichtDemoPluginMini.jpg | |||
| Beschreibung = | |||
| Hersteller = DMXControl Team | |||
| AktuelleVersion = 2.9 | |||
| AktuelleVersionFreigabeDatum = Dezember 2006 | |||
| Status = | |||
| Funktioniertmit = ab 2.9 | |||
| Programmiersprache = VB | |||
| Kategorie = | |||
| Lizenz = | |||
| Deutsch = | |||
| Email = info@dmxcontrol-projects.org | |||
| Homepage = https://www.dmxcontrol.de | |||
| Download = | |||
}} | |||
Die Dll-Datei eines Plugins muß in das Unterverzeichnis "plugins" des DMXControl-Installationsverzeichnisses kopiert werden. Hinweis: Neben den Plugins, die über eine definierte Schnittstelle mit DMXControl kommunizieren und aus technischer Sicht eine Zusatz-dll für DMXControl bilden, gibt es auch eine Reihe von | =Hinweise= | ||
'''Für die Benutzung des Tutorialplugins benötigen Sie DMXControl 2.9 oder 2.10'''<br /> | |||
Die Dll-Datei eines Plugins muß in das Unterverzeichnis "plugins" des DMXControl-Installationsverzeichnisses kopiert werden.<br /> | |||
Hinweis: Neben den Plugins, die über eine definierte Schnittstelle mit DMXControl kommunizieren und aus technischer Sicht eine Zusatz-dll für DMXControl bilden, gibt es auch eine Reihe von Erweiterungstools, die andere Interfaces zur Kommunikation mit DMXControl verwenden (z.B. MIDI oder Terminal-Schnittstelle). | |||
=Der Sourcecode des Tutorialplugins= | |||
Sie können den Sourcecode des Demo-Plugins im File [[Media:TutorLLSource.2.9.0.zip|DMXC_Demo_Plugin.zip]] komplett ansehen. | |||
Wer nur die dll benötigt, lädt sich dieses file herunter: [[Media:TutorLL.2.9.0.zip|TutorLL.dll]] | |||
Alle APIs finden Sie hier: [[Pluginprogrammierung DMXC2]] | |||
=Tutorial Teil 1= | |||
Dieses Tutorial zeigt Ihnen die Erstellung und praktische Anwendung eines DMXC-PlugIns für eine einfache Lauflichtsteuerung. | |||
==Funktionalitätsspezifikation== | |||
Wir wollen ein Tool als PlugIn erstellen, dass die Erstellung von Szenen für ein 4-kanaliges Lauflicht sehr einfach über eine grafische Eingabe ermöglichen soll. Die Idee ist, dass jede Sekunde eine Szene ausgegeben wird, dabei sind 60 Szenen möglich und graphisch dargestellt. Die Abarbeitung läuft zyklisch, d.h. nach einer Minute (also Ablauf der 60 Szenen) wird mit der ersten Szenen wieder erneut begonnen. | |||
[[Bild:Lauflicht_Demo_plugin.jpg| Die GUI des Tutorial PlugIns]] | |||
Die 4 Zeilen entsprechen den Kanälen eines Dimmerpacks. Die Spalten stellen die Szenen im Sekundentakt dar. Die | |||
gewünschte Szene kann durch Anklicken der Felder mit der linken Maustaste gesetzt werden, wobei in diesem | |||
Beispiel zur Vereinfachung jedem Kanal fest eine Farbe in der GUI zugewiesen wurde. Dabei wird mit dem linken | |||
Kommando-Button (der zwischen den Modes "Full" und "Dim" wechselt) gewählt, ob halbe oder volle Helligkeit | |||
verwendet wird. Ein gedimmter Wert erscheint in der Grafik nur halb gefüllt. | |||
Die Startadresse des Dimmerpacks wird über die Plugin-Konfiguration eingegeben. | |||
Mit dem Startbutton wird das Senden der DMX-Werte gestartet. Gleichzeitig wird auch die Ausgabe der Werte an der | |||
Oberfläche simuliert, indem die aktuelle Szene in leuchtenden Farben dargestellt wird. Zusätzlich wird die | |||
aktuelle Szene durch eine rote Signal-LED dargestellt. | |||
Das Beispiel ist bewußt einfach gehalten, um die Grundkonzepte der PlugIns zu demonstrieren und Sie nicht mit | |||
Programmierdetails zu verwirren. | |||
Somit wurden alle Funktionalitäten weggelassen, die reine Programmierarbeit sind und nichts mit der | |||
unmittelbaren PlugIn-Funktion zu tun haben. Sie können also z.B. | |||
*nicht die erstellten Lauflichtszenen abspeichern, | |||
*nicht den Dimmerkanälen über die GUI ihre eigentlichen Farben zuordnen und | |||
*nicht mehrere Felder gleichzeitig mit der Maus markieren. | |||
Da der Quelltext des Tutorial-PlugIns verfügbar ist, können Sie aber dieses Plugin beliebig erweitern. | |||
In einer zweiten Stufe wird das Plugin mit einen "Rückkanal" erweitert, d.h. es werde nicht nur DMX-Signale | |||
gesendet, sondern auch empfangen. Diese Werte können dann vom Plugin ermittelt und ausgewertet werden. Die Signale | |||
können durch parallele Ausgabe anderer Tools oder Plugins auftreten. | |||
==Das Grundgerüst des PlugIn-Programms== | |||
Der Programmcode besteht im wesentlichen aus drei Teilen, siehe auch Abb. 2.: | |||
*die GUI (hier: frmTutorMain) | |||
*der PlugIn-Logikmodule (DMXCTutorLL.bas) | |||
*die PlugIN driver Klasse (clsDMXCPlugin) | |||
Entsprechend unserer Konvention haben wir natürlich auch ein Hilfefenster, damit andere Nutzer erste Hinweise zur | |||
Funktionalität erhalten können. | |||
Abbildung 2 zeigt im Projektfenster alle Bestandteile unseres Plugins. | |||
[[Bild:Entwicklung_in_VB6.JPG]] | |||
Abbildung 2: Entwicklung in VB6 | |||
==Die GUI== | |||
In diesem Abschnitt werden nur Grundzüge der Oberfläche dargestellt, da die eigentliche Basic-Programmierung als bekannt vorausgesetzt wird bzw. genügend Literatur dazu existiert. Mit Hilfe des GUI-Editors sind die Buttons und der Timer schnell erstellt (siehe Abbildung 2). Diesen Elementen sind über VB entsprechende callback-Routinen zugeordnet. (Hinweis: Dazu hat Microsoft GUI-Design-Regeln veröffentlicht.) | |||
Ab DMX-Control V2.9 müssen Plugins, die eine graphische Oberfläche haben, in der GUI die Klasse IDMXCTool implementieren. Diese Klasse enthält Funktionen, die die Reaktion des Plugins auf Projektwechsel und die Änderung der Ansicht steuern. | |||
Private Function IDMXCTool_AskToSaveProjectData() As Boolean | |||
'should the plugin be asked to save data or configuration when | |||
'the project is changed. | |||
'Debug.Print "[frmTutorMaim] IDMXCTool_AskToSaveProjectData()" | |||
IDMXCTool_AskToSaveProjectData = False | |||
End Function | |||
Private Sub IDMXCTool_ClearProjectData() | |||
'function is called, when the user makes a new project | |||
'msgbox ("[frmTutorMaim] IDMXCTool_ClearProjectData()") | |||
End Sub | |||
Private Sub IDMXCTool_LoadProjectData() | |||
'function is called, when the user loads an other project | |||
'MsgBox ("[frmTutorMaim] IDMXCTool_LoadProjectData()") | |||
End Sub | |||
Private Sub IDMXCTool_SaveProjectData() | |||
'function is called, when the user saves the project | |||
'MsgBox ("[frmTutorMaim] IDMXCTool_SaveProjectData()") | |||
End Sub | |||
Private Property Let IDMXCTool_ViewMode(ByVal RHS As DMXCTypeLib.View) | |||
'Property, which controls the ViewMode of the plugin (Edit-Mode or Execute-Mode) | |||
'Debug.Print "[frmTutorMaim] IDMXCTool_ViewMode" | |||
myViewmode = RHS | |||
End Property | |||
<br> Die Grafik des Matrixfeldes wird zur Laufzeit erzeugt. Innerhalb des Matrixfeldes werden die Mauskoordinaten beim Klick in der Prozedur "Form_MouseDown" ausgewertet und die Nummer der zugehörigen LED-Zelle in der Prozedur "ComputeCellNumber" bestimmt. Alles weitere ist nur noch Zuordnen eines entsprechenden Status der LED-Zelle in Abhängigkeit vom ursprünglichen Status, z.B. LED_On wechselt immer bein Anklicken nach LED_Off. | |||
Über die Plugin-Konfiguration wird die Startadresse des Dimmerpacks zugeordnet. Hier gehört es zum guten Stil, dass Sie jede Eingabe soweit wie möglich prüfen, um spätere Laufzeitfehler auszuschliessen. Sie sollten mindestens den Wertebereich und den Typ des Eingabefeldes prüfen. | |||
<br> | <br> | ||
= Tutorial-Plugins = | Public Sub readTutorLLConfigurationData() | ||
' read only configuration data - start address | |||
' no special form is required for this demo plugin | |||
Dim AddressText As String | |||
Dim ok As Boolean | |||
While Not ok | |||
AddressText = InputBox$("Start Address:", "Demo Plugin Configuration") | |||
ok = True | |||
'make plausibility test | |||
If IsNumeric(AddressText) = False Then | |||
MsgBox Prompt:="Please enter an integer for start address!" | |||
ok = False | |||
End If | |||
If AddressText > 252 Then | |||
MsgBox Prompt:="Please insert a value lower than 252" | |||
ok = False | |||
End If | |||
Wend | |||
For i = 0 To 3 | |||
mDimmerAddr = Int(AddressText) | |||
If Not mHelper.DMXC_Channel_IsDimmer(mDimmerAddr + i) Then | |||
MsgBox ("Warning : Channel " & mDimmerAddr + i & " not dimmable") | |||
End If | |||
Next | |||
End Sub | |||
In der For-Schleife wird zusätzlich geprüft, ob die 4 Kanäle auch verwendet werden und die Helligkeit regeln können (is_Dimmer), also wirklich zu einem Dimmerpack gehören (der mHelper-Mechanismus wird im nächsten Kapitel erklärt). Später werden über die DMXC_PluginHelper-class weitere Methoden verfügbar sein, die zusätzliche Plausibilitätstests erlauben. | |||
Der Start-Button, der Stop-Button und das Timer Control interagieren untereinander über das Setzen des "Enabled"-Attributes des Timers ("timLLTimer"). Der Timer ist auf die Reaktionszeit von 1000ms = 1 sec. gesetzt und weckt nach Ablauf dieser Zeit seine zugehörige Routine timLLTimer_Timer(). | |||
Mit dem linken Kommando-Button wird lediglich der Editiermodus über die globale Variable mblnHalfDensity" umgeschaltet. Je nach Wert, der bis zur nächsten Ändereung permanent eingestellt bleibt, bekommen die Matrixfelder beim Anklicken den Zustandswert LED_on oder LED_dimmed. Sie sehen also, dass sich dieser Modul wirklich weitestgehend nur mit dem Verhalten der Oberfläche beschäftigt. Hier erfolgt keine direkte Steuerung der DMX Signale. | |||
''Tipps:'' - Redraw-Eigenschaft des Fensters auf True setzen, sonst verschwinden Teile der laufzeit-generierten Oberfläche, wenn ein anderes Fenster überlappt | |||
==Der DMX Logikmodul== | |||
Dieser Modul dient dazu, die wesentlichen Algorithmen zur DMX Steuerung zu implementieren. Unser einfaches | |||
Tutorial-Beispiel ist diesbezüglich vom Umfang etwas eingeschränkt, aber bei funktionell hochwertigen PlugIns | |||
werden sich viele Funktionen wie Filterung, Korrelation, Auswertung und algorithmische Berechnungen finden. | |||
Außerdem gehören in diesen Modul alle Geräte-spezifischen Operationen. | |||
Der Modul stellt eine Referenz zum eigentlichen DMXC-Interface mit der Klasse mHelper zur Verfügung. | |||
Public mHelper | |||
Diese Referenz wird im Interfacemodul clsDMXCPlugIn initialisiert (und muss beim Terminieren auch wieder aufgelöst werden!). | |||
Zwecks Implementierung der DMX Logik wird hier auch die "DMXSignalmatrix" , also das eigentliche PlugIn-spezifische | |||
Szenenrepository gehalten. Dazu werden im Array "gLED_matrix" die Beschreibungen der Szenen gespeichert. Sie werden | |||
in Ihrem PlugIn analoge Mittel benötigen. | |||
Public Enum LED_status | |||
LED_off 'LED cell is off - zero signal for this scene | |||
LED_dimmed 'LED cell is dimmed - any mid value for this scene | |||
LED_on 'LED cell is on - maximum signal for this scene | |||
End Enum | |||
Public LED_matrix(1To60, 1To4)As LED_status 'storage of LED statis | |||
Unser DMX-Logigmodul muss nun für die LED-Status-Werte die geeigneten DMX-Werte berechnen. Natürlich ist das in | |||
unserem Fall kein Problem, weil wir hier mit einer fixen Zuordnung auskommen, z.B. | |||
LED_off -> 0 | |||
LED_dim -> 128 | |||
LED_on -> 255 | |||
Aber man kann sich leicht kompliziertere Beispiele mit komplizierten Algorithmen ausdenken, in denen man wirklich Intelligenz benötigt, | |||
insbesondere wenn man zusätzlich empfangene Signale auswerten will. | |||
Wir stellen in diesem Modul eine TutorLLSetDMXValue-Routine bereit, die vom Timer gerufen wird, "wenn es was zu tun gibt": | |||
Public Sub TutorLLSetDMXvalue(ByVal scenenb As Integer) | |||
Dim i As Integer | |||
Dim dmxv As Long | |||
Call mHelper.MyStream.UserInteraction ' new for DMXControl 2.9, | |||
' enables the plugin to send values, independent | |||
' from the active program module | |||
For i = 1 To 4 | |||
Select Case gLED_matrix(sceenb, i) | |||
Case LED_off | |||
dmxv = 0 | |||
Case LED_dimmed | |||
dmxv = 128 | |||
Case LED_on | |||
dmxv = 255 | |||
End Select | |||
Call mHelper.MyStream.SetChannel(mDimmerAddr + i - 1, dmxv, True) ' sends the DMX-values to | |||
' DMXControl | |||
Next | |||
End Sub | |||
Diese Prozedur berechnet für alle 4 Kanäle die aktuell auszugebenden DMX-Werte und sendet sie mit der | |||
SetChannel-Methode. | |||
Bevor ein Plugin DMX-Werte an DMXControl senden kann, muss dieses noch zum gerade aktive Modul erklärt werden. Dies geschieht mit dem Aufruf der UserInteraction-Methode. Dies hängt zusammen mit dem Wegfall der Prioritäten in DMXControl V2.9, wo das gerade vom Anwender benutzte Modul jetzt die Kontrolle hat. | |||
Call mHelper.MyStream.UserInteraction | |||
Beim Senden der DMX-Werte könnte eine Optimierung durchgeführt werden. Eigentlich müssten die Werte nur dann neu gesendet werden, wenn sie sich verändert haben. Dies kann natürlich die DMXLogik im Plugin einfach überprüfen. | |||
Die Kernfunktion hierbei ist die SetChannel Methode der Klasse mHelper: | |||
SetChannel(Channel As Long, Value As Long, IgnoreChange As Boolean) | |||
Bitte achten Sie hier auf die erforderlichen Parametertypen (Long), da es sonst zu Laufzeitfehlern kommt. | |||
Der erste und zweite Parameter "Channel" und "Value" sind selbsterklärend. | |||
Der dritte Parameter "IgnoreChange" hat Einfluß auf die Änderungsmarkierungen bei der Szenenspeicherung in DMXControl. Dort wird im Fenster "Speicherung einer Szene" bekanntlich angezeigt, welche Werte sich geändert haben. Mit dem Parameterwert „True“ wird dieses Verhalten ignoriert, d.h. es wird so getan, als ob es eigentlich keine Änderung gegeben hätte. | |||
==Die DMXControl Interface Klasse== | |||
Hier erfolgt die eigentliche Einbindung des PlugIns in DMXControl, d.h. es werden verschieden Methoden zur | |||
Aktivierung, namentliche Bekanntmachung, Konfiguration und Deaktivierung ausimplementiert. Die Interfaces sind | |||
in in zwei Modulen definiert, daher importieren wir diese mit | |||
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. | |||
Die erforderlichen Implementierungsaufgaben in diesem Modul werden am Tutorialbeispiel sehr deutlich. Die GET-Methode | |||
IDMXCModule_ModuleInfo liefert DMXControl Informationen über das neue Plugin, z.B. Daten die in den Menüs | |||
oder Dialogen eingeblendet werden. Die meisten Attributnamen sind selbsterklärend, bitte paasen Sie die | |||
Attributwerte entsprechend an. | |||
Private Property Get IDMXCModule_ModuleInfo() As DMXCTypeLib.Type_Module_Info | |||
Set IDMXCModule_ModuleInfo = New Type_Module_Info: With IDMXCModule_ModuleInfo | |||
.Guid = "{b61b4c42-17ed-11da-94c3-00e08161165f}" 'adapt this line with unique GUID | |||
.Name = "Lauflicht Demo Plugin" | |||
.Description = "GUI für Lauflichter" | |||
.Author = "Frank Burghardt" | |||
.Experimental = True | |||
.ProvidesToolWindow = True | |||
.Category = CAT_Control | |||
.FormName = "frmTutorMain" | |||
Set .Frm = frmTutorMain | |||
.ProvidesCommand = False | |||
.ProvidesSceneType = False | |||
.UsesProvidedOutput = True | |||
.UsesMessaging = True | |||
With .Messages | |||
.Add MSG_Channel_Set | |||
.Add MSG_Channel_Send | |||
End With | |||
End With | |||
End Property | |||
Hier noch einige zusätzliche Erklärungen. Der GUID (Global Unique Identifier) liefert eine eindeutige Modul-Id. | |||
Die GUID können sie z.B. von http://www.guidgen.com/Index.aspx beziehen. | |||
Die Attribute ProvidesCommand / ProvidesScenetype sind für zukünftige Erweiterungen vorgesehen, wenn DMXControl | |||
neue dynamische Befehle und Szenetypen unterstützen wird. | |||
Unter benutzten Messagetypen müssen Sie vereinbaren, auf welche Nachrichten das Plugin reagieren soll. Bisher | |||
wird das Senden von DMXSignalen ("MSG_Channel_Send") und das Empfangen ("MSG_Channel_Set") unterstützt. | |||
Weiterhin müssen folgende Methoden angepasst werden: | |||
*IDMXCPlugin_Enable() - Aktion beim Aufruf des Plugins (aus der Menüliste) | |||
*IDMXCPlugin_Disable() - Aktionen beim Deaktivieren des Plugins (Schließen des Fensters) | |||
*PlugInName 'Liefert den Namen des Plugins zurück, der im Pluginmanager angezeigt wird | |||
Mit der Methode Configure() kann man einstellen, ob ein Konfigurationsdialog/GUI existiert und welche Aktion | |||
dazu auszuführen ist. In userem Beispiel wird die oben erwähnte Funktion Call frmTutorMain.readTutorLLConfigurationData aufgerufen. | |||
IDMXCPlugin_Init definiert allgemeine einmalige Aktionen beim Laden des Plugins, z.B. Setzen der Referenzen zum | |||
DMXControl-Interface-Objekt. (Das Plugin ist dann aber noch nicht aktiv, sondern erst mit dem Aufruf aus der | |||
Menüliste) Hier können Sie normalerweise den vorgegebenen Code komplett übernehmen. | |||
Die Methode liefert drei Werte: | |||
*Name der Aufrufenden Applikation, wird bei Registryeinträgen benutzt | |||
*Mein Dateiname, wird vom Caller geliefert (Dateiname der aktuellen Instanz, wichtig wenn es mehrere Kopien eines Plugins gibt, damit jedes seine eigenen Einstellungen speichern kann. Zukünftig werden aber Funktionen zum Lesen/Schreiben von Registry-Einstellungen in der HelperClass exportiert werden, die dann gleich den richtigen Pfad verwenden) und schließlich | |||
*als wichtigste Information die Referenz mHelper auf die DMXCPluginHelper-Klasse, die sämtliche benötigten Methoden im Logikmodule bereitstellt. | |||
IDMXCPlugin_Term() wird immer aufgerufen, wenn DMXC beendet wird, hier können Sie z.B. geteilte Resourcen mit anderen Tools freigeben. | |||
Die Funktion IDMXCPlugin_MessageHandle legt fest, was das Plugin tut, wenn eine ([[Pluginprogrammierung_DMXC2#DMXControl-Messages| DMXControl-Nachricht]]) eintrifft, z.B. zur Übermittlung eines DMX-Signals, also dass irgendein Kanal seinen Wert geändert hat. Dies ist sozusagen die “call back”-Funktion von DMXControl, um dem Plugin die Wertänderung mitzuteilen. Man beachte, dass diverse Messagetypen existieren. | |||
In unserem Falle werden nur die "Message_Channel_Send"-Nachrichten ausgewertet (falls der Receivemode) aktiviert ist) und die Methode TutorLLGetDMXValue aus dem Logikmodul aufgerufen. Letztere Methode entscheidet dann, ob die Wertänderungen Auswirkung auf die GUI hat und initiiert gegebenenfalls entsprechende Aktivitäten. | |||
Private Function IDMXCPlugin_MessageHandle(Msg As DMXCTypeLib.MSGs, Arg1 As Long, Arg2 As Long) As Long | |||
Select Case Msg | |||
Case MSG_Channel_Send | |||
If gblnReceiveMode Then | |||
TutorLLGetDMXvalue Arg1, Arg2 | |||
End If | |||
End Select | |||
End Function | |||
==Die Erzeugung der DLL== | |||
Eine Übersicht über mögliche Entwicklungsumgebungen enthält der Artikel [[Pluginprogrammierung_DMXC2#In_welcher_Umgebung_kann_man_eine_Plugin-dll_entwickeln.3F|Plugin_Entwicklungsumgebung]]. In diesem Tutorial bleiben wir bei VB6. | |||
Zu Beginn bietet es sich an, das PlugIn als normales Projekt in VB6 zu entwickeln und somit "offline (von DMXControl)" die GUI | |||
und die DMXLogik zu testen. | |||
Spätestens mit der Einbindung der SetChannel-Methode hat man ein Problem, weil man natürlich ohne DMXControl kein Object von | |||
DMXCPluginHelper zur Verfügung hat. Also müssen wir nachdem das PlugIn eine gewisse Reife hat, nun die dll erzeugen. | |||
Als erstes müssen wir der Entwicklungsumgebung mitteilen, dass wir eine dll erzeugen wollen. Dies passiert mit folgenden | |||
Einstellungen: (hier das Beispiel aus Visual Basic 6) | |||
[[Bild:Plugin_Projekt_Konfiguration.JPG]] | |||
Abbildung 3: Projekt Konfiguration | |||
== DMXC Plugin Tutorial == | Weiterhin sollten angegeben sein: | ||
*im Registerblatt "Compile": Compile to native code | |||
*im Registerblatt "Component": No Compatibility oder Project Compatibility | |||
Die Eigenschaft "Instancing" von clsDMXCPlugin muss unbedingt auf "5 - MultiUse" stehen, sonst wird keine dll erzeugt. | |||
Nun muss man nur noch darauf achten, dass die Compilierung jetzt über das Datei-Menü gestartet wird: | |||
Dort gibt es jetzt den Eintrag "Make TutorLL.dll". | |||
Bitte beim Speichern auf die Namenskonvention achten und den Dateinamen der dll auf "TutorLL.dll" ändern (was dauerhaft | |||
gespeichert wird). | |||
[[Bild:Plugin_Make_Projekt.jpg]] | |||
Abbildung 4: Make Projekt | |||
''Tipps:'' Weitere Fallen, die man beachten muss: | |||
- Man muss unbedingt ein Sub Main() vereinbart haben (kann leer sein) | |||
Es ist theoretisch auch möglich, zum Testen des Plugins im Debugger_mode zu arbeiten. Dazu geben Sie in der Registerkarte | |||
"Debugging" unter der Option "Start Program" den Pfad von DMXControl.exe an und fügen den Kommandoparameter | |||
-debugdll:TutorLL.dll | |||
an (bzw. natürlich den Namen der neuen dll) | |||
[[Bild:plugin_debug_dll.jpg]] | |||
''Hinweis:'' Die Meldung "Not registered DLL xxx.dll for debug purposes!" ist keine Fehlermeldung und sollte nicht | |||
vom Debuggen abschrecken. Man sollte auch dringend vermeiden, alte Versionen des Plugins (z.B. ) unter einem anderen Namen im Plugin-Verzeichnis | |||
zu haben. | |||
In der Praxis gibt es aber dennoch leider manchmal Probleme mit externen Referenzen, so dass der Debug-Mode nicht immer funktioniert. | |||
==Die Integration in DMXControl== | |||
Nachdem die dll erzeugt wurde, muss sie nun noch in das Unterverzeichnis „plugins“ von DMXControl kopiert werden (Wenn es noch nicht vorhanden ist, muss das Unterverzeichnis erst händisch erstellt werden: C:\Programme\DMXControl\plugins ). | |||
Nach dem Aufruf von DMXControl können Sie die erfolgreiche Einbindung überprüfen, indem Sie die Einträge unter Konfiguration->Plugins... überprüfen. | |||
[[Bild:Pluginverwaltung.JPG]] | |||
Abbildung 5: Erfolgreich erkanntes Plugin "Tutorial Lauflicht PlugIn" | |||
Nachdem das Plugin aktiviert wurde, erscheint es in DMXControl im Menü "Fenster" und kann über den entsprechenden Menüpunkt aufgerufen werden (Falls das Plugin nicht im Menü "Fenster" erscheint, dann muss wahrscheinlich in DMXControl im Menü "Konfiguration" noch der Punkt "experimentelle Programmteile anzeigen" aktiviert werden). | |||
Die erfolgreiche Arbeitsweise unseres Plugins kann man z.B. auch im Tool "Kanalübersicht" überprüfen, wo die ausgegebenen Lauflichtwerte angezeigt werden. | |||
[[Bild:Plugin_in_DMXC_de_Umgebung.jpg]] | |||
Abbildung 6: Das Tutorial plugin arbeitet in der DMXC-Umgebung | |||
==Die Konfiguration des Plugins== | |||
Spezielle Parameter, die nicht ständig an der Oberfläche benötigt werden, sollten über die Plugin-Konfiguration administriert werden. | |||
Dieses wird über den Button "Gewähltes Plugin konfigurieren" aufgerufen. In unserem Falle erscheint ein einfaches Input-Fenster für die Dimmerpack-Startadresse. | |||
Hier kann man sich beliebige Erweiterungen vorstellen, z.B. für die Konfiguration von Signalpegel und Farbe. | |||
=Tutorial Teil 2= | |||
In diesem Teil des Tutorials wird auch die '''Rückrichtung''' realisiert, d.h. auch die von DMXControl gesendeten DMX Werte können empfangen werden. | |||
Auch hier gilt, dass das Plugin in die gleichen drei Teile dekomponiert werden sollte, d.h. wir unterscheiden wieder in | |||
*GUI | |||
*Logik des Plugins | |||
*Interface zu DMXControl. | |||
Diese werden im folgenden beispielhaft beschrieben. Dazu wird unser Plugin aus dem ersten Teil um den Empfang von DMX-Signalen | |||
erweitert. Diese Signale, die z.B. vom Submaster oder [[Sound Analyzer]] für die 4 Dimmerkanäle ausgelöst werden können, werden dann | |||
im GUI-Matrixfeld in einer Art Lichtorgel visualisiert. Wie schon im ersten Teil wird hier im Sinne der Einfachheit und | |||
Übersichtlichkeit die einfachste Variante demonstriert, indem je nach Signalwert die Zellen eines Kanals in drei Stufen gefärbt | |||
werden. | |||
Natürlich können Sie dieses Beispiel erweitern, indem z.B. RGB-Werte zur Darstellung einzelner Kanäle oder der gesamten Matrix | |||
verwendet werden. | |||
==GUI Administration== | |||
In der Plugin-Oberfläche gibt es nur eine Änderung, ein zusätzlicher Kommando-Button wurde eingeführt, der als Umschaltbutton | |||
zwischen Sendemode (unveränderter erster Teil des Tutorials) und Empfangsmode (dieser Teil) fungiert. | |||
Das Tutorialbeispiel ist zur besseren Klarheit so konstruiert, dass entweder Signale gesendet oder empfangen werden können (Umschalten mit dem Send/Receive-Button). | |||
Diese Einschränkung ist nicht zwingend. Sie können also in Ihrem Plugin beide Modes kombinieren. | |||
Den anderen Pluginteilen wird über die Variable "gblnReceiveMode" mitgeteilt, welcher Mode gerade aktiviert ist. | |||
[[Bild:Tutorial_Plugin_output.jpg]] | |||
Abbildung 7: DMX-Receive Mode für das Plugin | |||
==Interface zu DMXControl== | |||
Die Methode "IDMXCPlugin_MessageHandle" im Modul clsDMXCPlugIn wird von DMXControl jedesmal aufgerufen, wenn ein DMX-Kanal einen | |||
neuen Wert erhält. Da dieser Modul nur das Interface zu DMXControl implementieren sollte, wird hier lediglich anhand des Wertes der | |||
Variable "gblnReceiveMode" geprüft, ob die empfangenen Signale an die Logik weitergeleitet werden sollen. Im Falle des Sendemodus | |||
werden die Signale einfach ignoriert, ansonsten wird die Routine "TutorLLGetDMXValue" im Modul DMXCTutorLL aufgerufen, weil dort | |||
die Logik implementiert ist, was mit dem empfangenen Signal zu geschehen hat. Natürlich können Sie in Ihrem Plugin die Signale | |||
feiner filtern oder auch andere [[Pluginprogrammierung_DMXC2#DMXControl-Messages|Messages]] empfangen. | |||
Private Function IDMXCPlugin_MessageHandle(Msg As DMXCTypeLib.MSGs, Arg1 As Long, Arg2 As Long) As Long | |||
Select Case Msg | |||
Case MSG_Channel_Send | |||
If gblnReceiveMode Then | |||
TutorLLGetDMXvalue Arg1, Arg2 | |||
End If | |||
End Select | |||
End Function | |||
==Logik== | |||
Im Modul DMXCTutorLL (Routine "TutorLLGetDMXValue") müssen also alle Operationen gestartet werden, die sich mit der Auswertung | |||
und Analyse der emfangenen Werte beschäftigen. | |||
Public Sub TutorLLGetDMXvalue(ByVal Ch As Integer, ByVal Value As Long) | |||
Dim i, Channel As Integer | |||
If Ch >= mDimmerAddr And Ch < mDimmerAddr + 4 Then | |||
Channel = Ch - mDimmerAddr + 1 'map to 1..4 | |||
If Value >= 128 Then | |||
If mcurDMXValues(Channel) < 128 Then | |||
Call frmTutorMain.enlightChannel(Channel, LED_on) | |||
End If | |||
mcurDMXValues(Channel) = Value | |||
Exit Sub 'ready | |||
Else | |||
If Value >= 25 Then | |||
If mcurDMXValues(Channel) > 128 Or mcurDMXValues(Channel) < 25 Then | |||
Call frmTutorMain.enlightChannel(Channel, LED_off) 'reset cell | |||
Call frmTutorMain.enlightChannel(Channel, LED_dimmed) | |||
End If | |||
mcurDMXValues(Channel) = Value | |||
Exit Sub 'ready | |||
Else | |||
' Value < 25 | |||
If mcurDMXValues(Channel) >= 25 Then | |||
Call frmTutorMain.enlightChannel(Channel, LED_off) | |||
End If | |||
mcurDMXValues(Channel) = Value | |||
End If | |||
End If | |||
End If | |||
End Sub | |||
Die Logik ist in unserem Beispiel wieder extrem einfach. Das empfangene Signal wird auf 3 Zustände abgebildet: | |||
Wert 0-25 -> entsprechender Kanal wird logisch auf "aus" gesetzt | |||
Wert 26-127 -> entsprechender Kanal wird logisch auf "dimmed" gesetzt | |||
Wert 128-255 -> entsprechender Kanal wird logisch auf "on" gesetzt | |||
Daher prüft diese Prozedur, in welcher der drei Kategorien der aktuellen Wert liegt. In unserem Beispiel ist es erneut nicht | |||
nötig, dem GUI Modul einen DMX-Wert zu übergeben, sondern es werden wiederum die drei bekannten Zustände verwendet. Dieser | |||
berechnete Zustand wird dem GUI-Teil mitgeteilt, indem die Routine "enligthChannel" gerufen wird. | |||
Es gibt einer zweiten Weg. DMX-Werte zu empfangen, nämlich durch explizite Abfrage, z.B. | |||
dmxValue = mHelper.ChannelGetValue(currentChannel) | |||
Ursprünglich war diese Methode dazu gedacht, bei der Initialisierung des Plugins die aktuellen Werte zu übernehmen.Es gibt | |||
aber auch Anwendungsfälle, wo das zielgerichtete Abfragen ("polling") viel effektiver und weniger Performance-fressend ist, als | |||
ständig auf alle "push"-Werte von DMXControl zu reagieren. | |||
==GUI Anzeige== | |||
Schliesslich bleibt die Aufgabe, anhand des übermittelten Zustandes eine Visualisierung in der Matrix vorzunehmen. Hierzu werden | |||
die bereits bekannten Methoden "colorizeCell" wiederverwendet. | |||
Public Sub enlightChannel(ByVal ch As Integer, ByVal Status As LED_status) | |||
Dim i As Integer | |||
For i = 1 To 60 | |||
LED_matrix(i, ch) = Status | |||
Call ColorizeCurrentCell(i, ch, True) | |||
Next | |||
End Sub | |||
Auch für dieses Tutorialbeispiel gilt, dass vieles optimierter programmiert werden könnte, z.B. Änderung der Zellfarbe nur, wenn | |||
sich wirklich der Wert ändern. Aber das würde die Verständlichkeit des Beispiels verringern. | |||
==Integration in DMXControl== | |||
Da sich an der Modul-Struktur des Plugins nichts geändert hat, gilt hier alles, was im Kapitel 3.6 und 3.7 ([[Pluginprogrammierung_DMXC2_Tut#Tutorial_Teil_1|Plugin Tutorial Teil 1]]) beschrieben wurde. Vergessen Sie beim Ausprobieren nicht, die Startadresse des Dimmerpacks einzustellen und den "Receive"-Mode zu aktivieren. | |||
Mit Hilfe des Submasters können Sie die Änderung der DMX-Werte auf den Dimmerpack-Kanälen vornehmen und dann die visuelle Anzeige in unserem Plugin bestaunen. Es ergibt sich auch tatsächlich ein Lichtorgel-Effekt bei der Benutzung des [[Sound_Analyzer_DMXC2|Sound Analyzer]]s. | |||
Wir wünschen Ihnen nun viel Spaß und Erfolg bei der Erstellung Ihres eigenen Plugins. | |||
[[Image:DMXC-Plugin-Tutorial.jpg]] | =DMXControl Pluginschnittstellen Test= | ||
[[Image:DMXC-Plugin-Tutorial.jpg]] | |||
*'''Datum/Zeit:''' Oktober 2008 | *'''Datum/Zeit:''' Oktober 2008 | ||
Zeile 31: | Zeile 544: | ||
*'''Status:''' für DMXControl 2.10 (wird fortlaufend aktualisiert) | *'''Status:''' für DMXControl 2.10 (wird fortlaufend aktualisiert) | ||
*'''Dateien:''' | *'''Dateien:''' | ||
**Plugin: [ | **Plugin: [https://www.dmxcontrol.de/files/DMXControl_2/plugins/PluginSchnittstellenTest/2.10/DMXCTest.dll DMXCTest.dll] | ||
**Sourcecode: [ | **Sourcecode: [https://www.dmxcontrol.de/files/DMXControl_2/plugins/PluginSchnittstellenTest/2.10/DMXC-Plugin-Tutorial.zip DMXC-Plugin-Tutorial Source] | ||
*'''Beschreibung:''' | *'''Beschreibung:''' Dieses Plugin demonstriert alle Funktionen der Pluginschnittstelle | ||
[[Kategorie:Plugins_DMXControl_2]] |
Aktuelle Version vom 6. Januar 2020, 21:44 Uhr
Plugin | |
---|---|
Entwickler | DMXControl Team |
Aktuelle Version | 2.9 (Dezember 2006) |
Funktioniert mit | ab 2.9 |
Programmiersprache | VB |
Kontakt | info@dmxcontrol-projects.org |
Homepage | https://www.dmxcontrol.de |
Hinweise
Für die Benutzung des Tutorialplugins benötigen Sie DMXControl 2.9 oder 2.10
Die Dll-Datei eines Plugins muß in das Unterverzeichnis "plugins" des DMXControl-Installationsverzeichnisses kopiert werden.
Hinweis: Neben den Plugins, die über eine definierte Schnittstelle mit DMXControl kommunizieren und aus technischer Sicht eine Zusatz-dll für DMXControl bilden, gibt es auch eine Reihe von Erweiterungstools, die andere Interfaces zur Kommunikation mit DMXControl verwenden (z.B. MIDI oder Terminal-Schnittstelle).
Der Sourcecode des Tutorialplugins
Sie können den Sourcecode des Demo-Plugins im File DMXC_Demo_Plugin.zip komplett ansehen.
Wer nur die dll benötigt, lädt sich dieses file herunter: TutorLL.dll
Alle APIs finden Sie hier: Pluginprogrammierung DMXC2
Tutorial Teil 1
Dieses Tutorial zeigt Ihnen die Erstellung und praktische Anwendung eines DMXC-PlugIns für eine einfache Lauflichtsteuerung.
Funktionalitätsspezifikation
Wir wollen ein Tool als PlugIn erstellen, dass die Erstellung von Szenen für ein 4-kanaliges Lauflicht sehr einfach über eine grafische Eingabe ermöglichen soll. Die Idee ist, dass jede Sekunde eine Szene ausgegeben wird, dabei sind 60 Szenen möglich und graphisch dargestellt. Die Abarbeitung läuft zyklisch, d.h. nach einer Minute (also Ablauf der 60 Szenen) wird mit der ersten Szenen wieder erneut begonnen.
Die 4 Zeilen entsprechen den Kanälen eines Dimmerpacks. Die Spalten stellen die Szenen im Sekundentakt dar. Die
gewünschte Szene kann durch Anklicken der Felder mit der linken Maustaste gesetzt werden, wobei in diesem
Beispiel zur Vereinfachung jedem Kanal fest eine Farbe in der GUI zugewiesen wurde. Dabei wird mit dem linken
Kommando-Button (der zwischen den Modes "Full" und "Dim" wechselt) gewählt, ob halbe oder volle Helligkeit
verwendet wird. Ein gedimmter Wert erscheint in der Grafik nur halb gefüllt.
Die Startadresse des Dimmerpacks wird über die Plugin-Konfiguration eingegeben. Mit dem Startbutton wird das Senden der DMX-Werte gestartet. Gleichzeitig wird auch die Ausgabe der Werte an der Oberfläche simuliert, indem die aktuelle Szene in leuchtenden Farben dargestellt wird. Zusätzlich wird die aktuelle Szene durch eine rote Signal-LED dargestellt.
Das Beispiel ist bewußt einfach gehalten, um die Grundkonzepte der PlugIns zu demonstrieren und Sie nicht mit
Programmierdetails zu verwirren.
Somit wurden alle Funktionalitäten weggelassen, die reine Programmierarbeit sind und nichts mit der
unmittelbaren PlugIn-Funktion zu tun haben. Sie können also z.B.
- nicht die erstellten Lauflichtszenen abspeichern,
- nicht den Dimmerkanälen über die GUI ihre eigentlichen Farben zuordnen und
- nicht mehrere Felder gleichzeitig mit der Maus markieren.
Da der Quelltext des Tutorial-PlugIns verfügbar ist, können Sie aber dieses Plugin beliebig erweitern.
In einer zweiten Stufe wird das Plugin mit einen "Rückkanal" erweitert, d.h. es werde nicht nur DMX-Signale gesendet, sondern auch empfangen. Diese Werte können dann vom Plugin ermittelt und ausgewertet werden. Die Signale können durch parallele Ausgabe anderer Tools oder Plugins auftreten.
Das Grundgerüst des PlugIn-Programms
Der Programmcode besteht im wesentlichen aus drei Teilen, siehe auch Abb. 2.:
- die GUI (hier: frmTutorMain)
- der PlugIn-Logikmodule (DMXCTutorLL.bas)
- die PlugIN driver Klasse (clsDMXCPlugin)
Entsprechend unserer Konvention haben wir natürlich auch ein Hilfefenster, damit andere Nutzer erste Hinweise zur Funktionalität erhalten können.
Abbildung 2 zeigt im Projektfenster alle Bestandteile unseres Plugins.
Abbildung 2: Entwicklung in VB6
Die GUI
In diesem Abschnitt werden nur Grundzüge der Oberfläche dargestellt, da die eigentliche Basic-Programmierung als bekannt vorausgesetzt wird bzw. genügend Literatur dazu existiert. Mit Hilfe des GUI-Editors sind die Buttons und der Timer schnell erstellt (siehe Abbildung 2). Diesen Elementen sind über VB entsprechende callback-Routinen zugeordnet. (Hinweis: Dazu hat Microsoft GUI-Design-Regeln veröffentlicht.)
Ab DMX-Control V2.9 müssen Plugins, die eine graphische Oberfläche haben, in der GUI die Klasse IDMXCTool implementieren. Diese Klasse enthält Funktionen, die die Reaktion des Plugins auf Projektwechsel und die Änderung der Ansicht steuern.
Private Function IDMXCTool_AskToSaveProjectData() As Boolean 'should the plugin be asked to save data or configuration when 'the project is changed. 'Debug.Print "[frmTutorMaim] IDMXCTool_AskToSaveProjectData()" IDMXCTool_AskToSaveProjectData = False End Function Private Sub IDMXCTool_ClearProjectData() 'function is called, when the user makes a new project 'msgbox ("[frmTutorMaim] IDMXCTool_ClearProjectData()") End Sub Private Sub IDMXCTool_LoadProjectData() 'function is called, when the user loads an other project 'MsgBox ("[frmTutorMaim] IDMXCTool_LoadProjectData()") End Sub Private Sub IDMXCTool_SaveProjectData() 'function is called, when the user saves the project 'MsgBox ("[frmTutorMaim] IDMXCTool_SaveProjectData()") End Sub Private Property Let IDMXCTool_ViewMode(ByVal RHS As DMXCTypeLib.View) 'Property, which controls the ViewMode of the plugin (Edit-Mode or Execute-Mode) 'Debug.Print "[frmTutorMaim] IDMXCTool_ViewMode" myViewmode = RHS End Property
Die Grafik des Matrixfeldes wird zur Laufzeit erzeugt. Innerhalb des Matrixfeldes werden die Mauskoordinaten beim Klick in der Prozedur "Form_MouseDown" ausgewertet und die Nummer der zugehörigen LED-Zelle in der Prozedur "ComputeCellNumber" bestimmt. Alles weitere ist nur noch Zuordnen eines entsprechenden Status der LED-Zelle in Abhängigkeit vom ursprünglichen Status, z.B. LED_On wechselt immer bein Anklicken nach LED_Off.
Über die Plugin-Konfiguration wird die Startadresse des Dimmerpacks zugeordnet. Hier gehört es zum guten Stil, dass Sie jede Eingabe soweit wie möglich prüfen, um spätere Laufzeitfehler auszuschliessen. Sie sollten mindestens den Wertebereich und den Typ des Eingabefeldes prüfen.
Public Sub readTutorLLConfigurationData() ' read only configuration data - start address ' no special form is required for this demo plugin Dim AddressText As String Dim ok As Boolean While Not ok AddressText = InputBox$("Start Address:", "Demo Plugin Configuration") ok = True 'make plausibility test If IsNumeric(AddressText) = False Then MsgBox Prompt:="Please enter an integer for start address!" ok = False End If If AddressText > 252 Then MsgBox Prompt:="Please insert a value lower than 252" ok = False End If Wend For i = 0 To 3 mDimmerAddr = Int(AddressText) If Not mHelper.DMXC_Channel_IsDimmer(mDimmerAddr + i) Then MsgBox ("Warning : Channel " & mDimmerAddr + i & " not dimmable") End If Next End Sub
In der For-Schleife wird zusätzlich geprüft, ob die 4 Kanäle auch verwendet werden und die Helligkeit regeln können (is_Dimmer), also wirklich zu einem Dimmerpack gehören (der mHelper-Mechanismus wird im nächsten Kapitel erklärt). Später werden über die DMXC_PluginHelper-class weitere Methoden verfügbar sein, die zusätzliche Plausibilitätstests erlauben.
Der Start-Button, der Stop-Button und das Timer Control interagieren untereinander über das Setzen des "Enabled"-Attributes des Timers ("timLLTimer"). Der Timer ist auf die Reaktionszeit von 1000ms = 1 sec. gesetzt und weckt nach Ablauf dieser Zeit seine zugehörige Routine timLLTimer_Timer().
Mit dem linken Kommando-Button wird lediglich der Editiermodus über die globale Variable mblnHalfDensity" umgeschaltet. Je nach Wert, der bis zur nächsten Ändereung permanent eingestellt bleibt, bekommen die Matrixfelder beim Anklicken den Zustandswert LED_on oder LED_dimmed. Sie sehen also, dass sich dieser Modul wirklich weitestgehend nur mit dem Verhalten der Oberfläche beschäftigt. Hier erfolgt keine direkte Steuerung der DMX Signale.
Tipps: - Redraw-Eigenschaft des Fensters auf True setzen, sonst verschwinden Teile der laufzeit-generierten Oberfläche, wenn ein anderes Fenster überlappt
Der DMX Logikmodul
Dieser Modul dient dazu, die wesentlichen Algorithmen zur DMX Steuerung zu implementieren. Unser einfaches Tutorial-Beispiel ist diesbezüglich vom Umfang etwas eingeschränkt, aber bei funktionell hochwertigen PlugIns werden sich viele Funktionen wie Filterung, Korrelation, Auswertung und algorithmische Berechnungen finden.
Außerdem gehören in diesen Modul alle Geräte-spezifischen Operationen. Der Modul stellt eine Referenz zum eigentlichen DMXC-Interface mit der Klasse mHelper zur Verfügung.
Public mHelper
Diese Referenz wird im Interfacemodul clsDMXCPlugIn initialisiert (und muss beim Terminieren auch wieder aufgelöst werden!).
Zwecks Implementierung der DMX Logik wird hier auch die "DMXSignalmatrix" , also das eigentliche PlugIn-spezifische Szenenrepository gehalten. Dazu werden im Array "gLED_matrix" die Beschreibungen der Szenen gespeichert. Sie werden in Ihrem PlugIn analoge Mittel benötigen.
Public Enum LED_status LED_off 'LED cell is off - zero signal for this scene LED_dimmed 'LED cell is dimmed - any mid value for this scene LED_on 'LED cell is on - maximum signal for this scene End Enum Public LED_matrix(1To60, 1To4)As LED_status 'storage of LED statis
Unser DMX-Logigmodul muss nun für die LED-Status-Werte die geeigneten DMX-Werte berechnen. Natürlich ist das in unserem Fall kein Problem, weil wir hier mit einer fixen Zuordnung auskommen, z.B.
LED_off -> 0 LED_dim -> 128 LED_on -> 255
Aber man kann sich leicht kompliziertere Beispiele mit komplizierten Algorithmen ausdenken, in denen man wirklich Intelligenz benötigt, insbesondere wenn man zusätzlich empfangene Signale auswerten will.
Wir stellen in diesem Modul eine TutorLLSetDMXValue-Routine bereit, die vom Timer gerufen wird, "wenn es was zu tun gibt":
Public Sub TutorLLSetDMXvalue(ByVal scenenb As Integer) Dim i As Integer Dim dmxv As Long Call mHelper.MyStream.UserInteraction ' new for DMXControl 2.9, ' enables the plugin to send values, independent ' from the active program module For i = 1 To 4 Select Case gLED_matrix(sceenb, i) Case LED_off dmxv = 0 Case LED_dimmed dmxv = 128 Case LED_on dmxv = 255 End Select Call mHelper.MyStream.SetChannel(mDimmerAddr + i - 1, dmxv, True) ' sends the DMX-values to ' DMXControl Next End Sub
Diese Prozedur berechnet für alle 4 Kanäle die aktuell auszugebenden DMX-Werte und sendet sie mit der SetChannel-Methode.
Bevor ein Plugin DMX-Werte an DMXControl senden kann, muss dieses noch zum gerade aktive Modul erklärt werden. Dies geschieht mit dem Aufruf der UserInteraction-Methode. Dies hängt zusammen mit dem Wegfall der Prioritäten in DMXControl V2.9, wo das gerade vom Anwender benutzte Modul jetzt die Kontrolle hat.
Call mHelper.MyStream.UserInteraction
Beim Senden der DMX-Werte könnte eine Optimierung durchgeführt werden. Eigentlich müssten die Werte nur dann neu gesendet werden, wenn sie sich verändert haben. Dies kann natürlich die DMXLogik im Plugin einfach überprüfen.
Die Kernfunktion hierbei ist die SetChannel Methode der Klasse mHelper:
SetChannel(Channel As Long, Value As Long, IgnoreChange As Boolean)
Bitte achten Sie hier auf die erforderlichen Parametertypen (Long), da es sonst zu Laufzeitfehlern kommt.
Der erste und zweite Parameter "Channel" und "Value" sind selbsterklärend.
Der dritte Parameter "IgnoreChange" hat Einfluß auf die Änderungsmarkierungen bei der Szenenspeicherung in DMXControl. Dort wird im Fenster "Speicherung einer Szene" bekanntlich angezeigt, welche Werte sich geändert haben. Mit dem Parameterwert „True“ wird dieses Verhalten ignoriert, d.h. es wird so getan, als ob es eigentlich keine Änderung gegeben hätte.
Die DMXControl Interface Klasse
Hier erfolgt die eigentliche Einbindung des PlugIns in DMXControl, d.h. es werden verschieden Methoden zur Aktivierung, namentliche Bekanntmachung, Konfiguration und Deaktivierung ausimplementiert. Die Interfaces sind in in zwei Modulen definiert, daher importieren wir diese mit
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.
Die erforderlichen Implementierungsaufgaben in diesem Modul werden am Tutorialbeispiel sehr deutlich. Die GET-Methode IDMXCModule_ModuleInfo liefert DMXControl Informationen über das neue Plugin, z.B. Daten die in den Menüs oder Dialogen eingeblendet werden. Die meisten Attributnamen sind selbsterklärend, bitte paasen Sie die Attributwerte entsprechend an.
Private Property Get IDMXCModule_ModuleInfo() As DMXCTypeLib.Type_Module_Info Set IDMXCModule_ModuleInfo = New Type_Module_Info: With IDMXCModule_ModuleInfo .Guid = "{b61b4c42-17ed-11da-94c3-00e08161165f}" 'adapt this line with unique GUID .Name = "Lauflicht Demo Plugin" .Description = "GUI für Lauflichter" .Author = "Frank Burghardt" .Experimental = True .ProvidesToolWindow = True .Category = CAT_Control .FormName = "frmTutorMain" Set .Frm = frmTutorMain .ProvidesCommand = False .ProvidesSceneType = False .UsesProvidedOutput = True .UsesMessaging = True With .Messages .Add MSG_Channel_Set .Add MSG_Channel_Send End With End With End Property
Hier noch einige zusätzliche Erklärungen. Der GUID (Global Unique Identifier) liefert eine eindeutige Modul-Id. Die GUID können sie z.B. von http://www.guidgen.com/Index.aspx beziehen. Die Attribute ProvidesCommand / ProvidesScenetype sind für zukünftige Erweiterungen vorgesehen, wenn DMXControl neue dynamische Befehle und Szenetypen unterstützen wird. Unter benutzten Messagetypen müssen Sie vereinbaren, auf welche Nachrichten das Plugin reagieren soll. Bisher wird das Senden von DMXSignalen ("MSG_Channel_Send") und das Empfangen ("MSG_Channel_Set") unterstützt.
Weiterhin müssen folgende Methoden angepasst werden:
- IDMXCPlugin_Enable() - Aktion beim Aufruf des Plugins (aus der Menüliste)
- IDMXCPlugin_Disable() - Aktionen beim Deaktivieren des Plugins (Schließen des Fensters)
- PlugInName 'Liefert den Namen des Plugins zurück, der im Pluginmanager angezeigt wird
Mit der Methode Configure() kann man einstellen, ob ein Konfigurationsdialog/GUI existiert und welche Aktion dazu auszuführen ist. In userem Beispiel wird die oben erwähnte Funktion Call frmTutorMain.readTutorLLConfigurationData aufgerufen.
IDMXCPlugin_Init definiert allgemeine einmalige Aktionen beim Laden des Plugins, z.B. Setzen der Referenzen zum
DMXControl-Interface-Objekt. (Das Plugin ist dann aber noch nicht aktiv, sondern erst mit dem Aufruf aus der
Menüliste) Hier können Sie normalerweise den vorgegebenen Code komplett übernehmen.
Die Methode liefert drei Werte:
- Name der Aufrufenden Applikation, wird bei Registryeinträgen benutzt
- Mein Dateiname, wird vom Caller geliefert (Dateiname der aktuellen Instanz, wichtig wenn es mehrere Kopien eines Plugins gibt, damit jedes seine eigenen Einstellungen speichern kann. Zukünftig werden aber Funktionen zum Lesen/Schreiben von Registry-Einstellungen in der HelperClass exportiert werden, die dann gleich den richtigen Pfad verwenden) und schließlich
- als wichtigste Information die Referenz mHelper auf die DMXCPluginHelper-Klasse, die sämtliche benötigten Methoden im Logikmodule bereitstellt.
IDMXCPlugin_Term() wird immer aufgerufen, wenn DMXC beendet wird, hier können Sie z.B. geteilte Resourcen mit anderen Tools freigeben.
Die Funktion IDMXCPlugin_MessageHandle legt fest, was das Plugin tut, wenn eine ( DMXControl-Nachricht) eintrifft, z.B. zur Übermittlung eines DMX-Signals, also dass irgendein Kanal seinen Wert geändert hat. Dies ist sozusagen die “call back”-Funktion von DMXControl, um dem Plugin die Wertänderung mitzuteilen. Man beachte, dass diverse Messagetypen existieren.
In unserem Falle werden nur die "Message_Channel_Send"-Nachrichten ausgewertet (falls der Receivemode) aktiviert ist) und die Methode TutorLLGetDMXValue aus dem Logikmodul aufgerufen. Letztere Methode entscheidet dann, ob die Wertänderungen Auswirkung auf die GUI hat und initiiert gegebenenfalls entsprechende Aktivitäten.
Private Function IDMXCPlugin_MessageHandle(Msg As DMXCTypeLib.MSGs, Arg1 As Long, Arg2 As Long) As Long Select Case Msg Case MSG_Channel_Send If gblnReceiveMode Then TutorLLGetDMXvalue Arg1, Arg2 End If End Select End Function
Die Erzeugung der DLL
Eine Übersicht über mögliche Entwicklungsumgebungen enthält der Artikel Plugin_Entwicklungsumgebung. In diesem Tutorial bleiben wir bei VB6.
Zu Beginn bietet es sich an, das PlugIn als normales Projekt in VB6 zu entwickeln und somit "offline (von DMXControl)" die GUI und die DMXLogik zu testen.
Spätestens mit der Einbindung der SetChannel-Methode hat man ein Problem, weil man natürlich ohne DMXControl kein Object von DMXCPluginHelper zur Verfügung hat. Also müssen wir nachdem das PlugIn eine gewisse Reife hat, nun die dll erzeugen.
Als erstes müssen wir der Entwicklungsumgebung mitteilen, dass wir eine dll erzeugen wollen. Dies passiert mit folgenden Einstellungen: (hier das Beispiel aus Visual Basic 6)
Abbildung 3: Projekt Konfiguration
Weiterhin sollten angegeben sein:
- im Registerblatt "Compile": Compile to native code
- im Registerblatt "Component": No Compatibility oder Project Compatibility
Die Eigenschaft "Instancing" von clsDMXCPlugin muss unbedingt auf "5 - MultiUse" stehen, sonst wird keine dll erzeugt.
Nun muss man nur noch darauf achten, dass die Compilierung jetzt über das Datei-Menü gestartet wird: Dort gibt es jetzt den Eintrag "Make TutorLL.dll".
Bitte beim Speichern auf die Namenskonvention achten und den Dateinamen der dll auf "TutorLL.dll" ändern (was dauerhaft
gespeichert wird).
Abbildung 4: Make Projekt
Tipps: Weitere Fallen, die man beachten muss: - Man muss unbedingt ein Sub Main() vereinbart haben (kann leer sein)
Es ist theoretisch auch möglich, zum Testen des Plugins im Debugger_mode zu arbeiten. Dazu geben Sie in der Registerkarte "Debugging" unter der Option "Start Program" den Pfad von DMXControl.exe an und fügen den Kommandoparameter
-debugdll:TutorLL.dll
an (bzw. natürlich den Namen der neuen dll)
Hinweis: Die Meldung "Not registered DLL xxx.dll for debug purposes!" ist keine Fehlermeldung und sollte nicht vom Debuggen abschrecken. Man sollte auch dringend vermeiden, alte Versionen des Plugins (z.B. ) unter einem anderen Namen im Plugin-Verzeichnis zu haben. In der Praxis gibt es aber dennoch leider manchmal Probleme mit externen Referenzen, so dass der Debug-Mode nicht immer funktioniert.
Die Integration in DMXControl
Nachdem die dll erzeugt wurde, muss sie nun noch in das Unterverzeichnis „plugins“ von DMXControl kopiert werden (Wenn es noch nicht vorhanden ist, muss das Unterverzeichnis erst händisch erstellt werden: C:\Programme\DMXControl\plugins ).
Nach dem Aufruf von DMXControl können Sie die erfolgreiche Einbindung überprüfen, indem Sie die Einträge unter Konfiguration->Plugins... überprüfen.
Abbildung 5: Erfolgreich erkanntes Plugin "Tutorial Lauflicht PlugIn"
Nachdem das Plugin aktiviert wurde, erscheint es in DMXControl im Menü "Fenster" und kann über den entsprechenden Menüpunkt aufgerufen werden (Falls das Plugin nicht im Menü "Fenster" erscheint, dann muss wahrscheinlich in DMXControl im Menü "Konfiguration" noch der Punkt "experimentelle Programmteile anzeigen" aktiviert werden).
Die erfolgreiche Arbeitsweise unseres Plugins kann man z.B. auch im Tool "Kanalübersicht" überprüfen, wo die ausgegebenen Lauflichtwerte angezeigt werden.
Abbildung 6: Das Tutorial plugin arbeitet in der DMXC-Umgebung
Die Konfiguration des Plugins
Spezielle Parameter, die nicht ständig an der Oberfläche benötigt werden, sollten über die Plugin-Konfiguration administriert werden. Dieses wird über den Button "Gewähltes Plugin konfigurieren" aufgerufen. In unserem Falle erscheint ein einfaches Input-Fenster für die Dimmerpack-Startadresse.
Hier kann man sich beliebige Erweiterungen vorstellen, z.B. für die Konfiguration von Signalpegel und Farbe.
Tutorial Teil 2
In diesem Teil des Tutorials wird auch die Rückrichtung realisiert, d.h. auch die von DMXControl gesendeten DMX Werte können empfangen werden.
Auch hier gilt, dass das Plugin in die gleichen drei Teile dekomponiert werden sollte, d.h. wir unterscheiden wieder in
- GUI
- Logik des Plugins
- Interface zu DMXControl.
Diese werden im folgenden beispielhaft beschrieben. Dazu wird unser Plugin aus dem ersten Teil um den Empfang von DMX-Signalen erweitert. Diese Signale, die z.B. vom Submaster oder Sound Analyzer für die 4 Dimmerkanäle ausgelöst werden können, werden dann im GUI-Matrixfeld in einer Art Lichtorgel visualisiert. Wie schon im ersten Teil wird hier im Sinne der Einfachheit und Übersichtlichkeit die einfachste Variante demonstriert, indem je nach Signalwert die Zellen eines Kanals in drei Stufen gefärbt werden. Natürlich können Sie dieses Beispiel erweitern, indem z.B. RGB-Werte zur Darstellung einzelner Kanäle oder der gesamten Matrix verwendet werden.
GUI Administration
In der Plugin-Oberfläche gibt es nur eine Änderung, ein zusätzlicher Kommando-Button wurde eingeführt, der als Umschaltbutton zwischen Sendemode (unveränderter erster Teil des Tutorials) und Empfangsmode (dieser Teil) fungiert. Das Tutorialbeispiel ist zur besseren Klarheit so konstruiert, dass entweder Signale gesendet oder empfangen werden können (Umschalten mit dem Send/Receive-Button). Diese Einschränkung ist nicht zwingend. Sie können also in Ihrem Plugin beide Modes kombinieren.
Den anderen Pluginteilen wird über die Variable "gblnReceiveMode" mitgeteilt, welcher Mode gerade aktiviert ist.
Abbildung 7: DMX-Receive Mode für das Plugin
Interface zu DMXControl
Die Methode "IDMXCPlugin_MessageHandle" im Modul clsDMXCPlugIn wird von DMXControl jedesmal aufgerufen, wenn ein DMX-Kanal einen neuen Wert erhält. Da dieser Modul nur das Interface zu DMXControl implementieren sollte, wird hier lediglich anhand des Wertes der Variable "gblnReceiveMode" geprüft, ob die empfangenen Signale an die Logik weitergeleitet werden sollen. Im Falle des Sendemodus werden die Signale einfach ignoriert, ansonsten wird die Routine "TutorLLGetDMXValue" im Modul DMXCTutorLL aufgerufen, weil dort die Logik implementiert ist, was mit dem empfangenen Signal zu geschehen hat. Natürlich können Sie in Ihrem Plugin die Signale feiner filtern oder auch andere Messages empfangen.
Private Function IDMXCPlugin_MessageHandle(Msg As DMXCTypeLib.MSGs, Arg1 As Long, Arg2 As Long) As Long Select Case Msg Case MSG_Channel_Send If gblnReceiveMode Then TutorLLGetDMXvalue Arg1, Arg2 End If End Select End Function
Logik
Im Modul DMXCTutorLL (Routine "TutorLLGetDMXValue") müssen also alle Operationen gestartet werden, die sich mit der Auswertung und Analyse der emfangenen Werte beschäftigen.
Public Sub TutorLLGetDMXvalue(ByVal Ch As Integer, ByVal Value As Long) Dim i, Channel As Integer If Ch >= mDimmerAddr And Ch < mDimmerAddr + 4 Then Channel = Ch - mDimmerAddr + 1 'map to 1..4 If Value >= 128 Then If mcurDMXValues(Channel) < 128 Then Call frmTutorMain.enlightChannel(Channel, LED_on) End If mcurDMXValues(Channel) = Value Exit Sub 'ready Else If Value >= 25 Then If mcurDMXValues(Channel) > 128 Or mcurDMXValues(Channel) < 25 Then Call frmTutorMain.enlightChannel(Channel, LED_off) 'reset cell Call frmTutorMain.enlightChannel(Channel, LED_dimmed) End If mcurDMXValues(Channel) = Value Exit Sub 'ready Else ' Value < 25 If mcurDMXValues(Channel) >= 25 Then Call frmTutorMain.enlightChannel(Channel, LED_off) End If mcurDMXValues(Channel) = Value End If End If End If End Sub
Die Logik ist in unserem Beispiel wieder extrem einfach. Das empfangene Signal wird auf 3 Zustände abgebildet:
Wert 0-25 -> entsprechender Kanal wird logisch auf "aus" gesetzt Wert 26-127 -> entsprechender Kanal wird logisch auf "dimmed" gesetzt Wert 128-255 -> entsprechender Kanal wird logisch auf "on" gesetzt
Daher prüft diese Prozedur, in welcher der drei Kategorien der aktuellen Wert liegt. In unserem Beispiel ist es erneut nicht
nötig, dem GUI Modul einen DMX-Wert zu übergeben, sondern es werden wiederum die drei bekannten Zustände verwendet. Dieser
berechnete Zustand wird dem GUI-Teil mitgeteilt, indem die Routine "enligthChannel" gerufen wird.
Es gibt einer zweiten Weg. DMX-Werte zu empfangen, nämlich durch explizite Abfrage, z.B.
dmxValue = mHelper.ChannelGetValue(currentChannel)
Ursprünglich war diese Methode dazu gedacht, bei der Initialisierung des Plugins die aktuellen Werte zu übernehmen.Es gibt aber auch Anwendungsfälle, wo das zielgerichtete Abfragen ("polling") viel effektiver und weniger Performance-fressend ist, als ständig auf alle "push"-Werte von DMXControl zu reagieren.
GUI Anzeige
Schliesslich bleibt die Aufgabe, anhand des übermittelten Zustandes eine Visualisierung in der Matrix vorzunehmen. Hierzu werden die bereits bekannten Methoden "colorizeCell" wiederverwendet.
Public Sub enlightChannel(ByVal ch As Integer, ByVal Status As LED_status) Dim i As Integer For i = 1 To 60 LED_matrix(i, ch) = Status Call ColorizeCurrentCell(i, ch, True) Next End Sub
Auch für dieses Tutorialbeispiel gilt, dass vieles optimierter programmiert werden könnte, z.B. Änderung der Zellfarbe nur, wenn sich wirklich der Wert ändern. Aber das würde die Verständlichkeit des Beispiels verringern.
Integration in DMXControl
Da sich an der Modul-Struktur des Plugins nichts geändert hat, gilt hier alles, was im Kapitel 3.6 und 3.7 (Plugin Tutorial Teil 1) beschrieben wurde. Vergessen Sie beim Ausprobieren nicht, die Startadresse des Dimmerpacks einzustellen und den "Receive"-Mode zu aktivieren.
Mit Hilfe des Submasters können Sie die Änderung der DMX-Werte auf den Dimmerpack-Kanälen vornehmen und dann die visuelle Anzeige in unserem Plugin bestaunen. Es ergibt sich auch tatsächlich ein Lichtorgel-Effekt bei der Benutzung des Sound Analyzers.
Wir wünschen Ihnen nun viel Spaß und Erfolg bei der Erstellung Ihres eigenen Plugins.
DMXControl Pluginschnittstellen Test
- Datum/Zeit: Oktober 2008
- Autor: Frank Brüggemann
- Status: für DMXControl 2.10 (wird fortlaufend aktualisiert)
- Dateien:
- Plugin: DMXCTest.dll
- Sourcecode: DMXC-Plugin-Tutorial Source
- Beschreibung: Dieses Plugin demonstriert alle Funktionen der Pluginschnittstelle