Jump to content
nuts

myExtendedExit, myActions, mySleeptimer, myProcesstaks, myBackup

Recommended Posts

nuts

Hallo zusammen,

in diesem Thread wollte ich eine kleine Skriptsammlung vorstellen, die ich hauptsächlich für den Eigenbedarf geschrieben habe um bestimmte Aktionen am PC (insbesondere HTPC) zu steuern und zu automatisieren.

Im Moment sind diese Skripte verfügbar

  • myExtendedExit.exe
  • myActions.exe
  • mySleeptimer.exe
  • myProcesstasks.exe
  • myBackup (kommt bald ;) )

Alle Skripte unterstützen zahlreiche Befehle wie z.B.:
Standby, Programme ausführen, Prozesse beenden/starten, ActionID zum DVBV schicken, Hardware Reset über devcon, reagieren auf laufende Aufnahmen, pulse-eight CEC Befehle,
Marantz/Denon/Yamaha/Emotiva/Eventghost über das Netzwerk steuern uvm.

Installation

  • myScricts.zip entpacken und an einem geeigneten Ort speichern. Ich verwende dafür das DVBViewer Programm-Verzeichnis (C:\Program Files\DVBViewer\myScripts)
  • Skripte (myActions, myExtendedExit, mySleeptimer), die über das OSD des DVBViewers aufgerufen werden sollen müssen zunächst in den DVBViewer eingebunden werden.

Um myActions, myExtendedExit oder mySleeptimer in den DVBViewer einzubinden gibt es verschiedene Möglichkeiten:

  • Im Download befindet sich eine my_scripts_install.bat. Diese trägt myActions, myExtendedExit, mySleeptimer in die windowdef.xml des DVBV ein und ihr könnt loslegen
  • Man verwendet Menuedit: http://www.DVBViewer.tv/forum/topic/52965-neue-windowdefxml-laesst-sich-mit-menueditor-nicht-aendern/
  • Man opfert eine Taste auf der Fernbedienung und verwendet die command.vbs zusammen mit einem eigenen Input Befehl. Eine Beispiel command.vbs ist im Download (Ordner Examples) enthalten.
  • Jede andere Möglichkeit eine .exe auszuführen funktioniert natürlich genauso gut. Eventghost oder andere Fernbedienungsprogramme können das meistens.

Empfehlung: my_scripts_install.bat ausführen und zusätzlich myActions über die command.vbs auf eine Taste der Fernbedienung legen.


Deinstallation

  • Ordner mit den Skripten löschen
  • Ordner mit den Konfigurationsdateien löschen. Dieser befindet sich in @AppDataCommonDir \myScripts (meist: C:\ProgramData\my_scripts)
  • Ggf. mit Menuedit die OSD Einträge entfernen und ggf. die command.vbs wieder anpassen

Konfiguration

Alle Skripte sind mit den Default-Dateien nutzbar, d.h. für erste Versuch muss nichts weiter unternommen werden.
Da die Verwendung möglichst flexibel sein soll und für die Skripte keine graphische Oberfläche zur Verfügung steht (kommt vielleicht noch), ist die Verwendung von fortgeschrittenen Funktionen etwas knifflig.

Mit der Installation wird ein Konfigurationsordner angelegt: "C:\ProgramData\my_scripts\"
In diesem Ordner befinden sich verschiedene Konfigurationsdateien( *.ini):

my_scripts_config.ini
Alle Skripte teilen sich diese Datei um die dort hinterlegten Stammdaten nur einmal eingeben zu müssen.
Dort müsst ihr zunächst einmal nichts verändern, jedoch erfordern manche Befehle zusätzliche Angaben um verwendet werden zu können.
Soll z.B. ein Denon Receiver über das Netzwerk gesteuert werden muss dort hinterlegt werden unter welcher IP und welchem Port dieser erreichbar ist.

my_scripts_actions.ini
Auch hier muss nichts geändert werden. Diese Datei dient als Sammelort für Escape-Bedingungen und die Resume - Funktion (s. Post 2 zu myExtendedExit.exe).
Dort müsst ihr zunächst einmal nichts verändern.

myExtendedExit_actions.ini | myProcessTasks_actions.ini | mySleeptimer_actions.ini | myProcessTasks_actions.ini
In diesen Dateien werden die Befehlsabfolgen definiert. Der Aufbau ist bei allen Skripten einheitlich.

Eine INI ist eine Konfigurationsdatei und besteht grundsätzlich, aus verschiedenen Sektionen, die durch [ und ] gekennzeichnet sind.
In den Sektionen gibt es Key/Value Paare mit den eigentlichen Informationen, wobei der "Key" den gewünschten Befehl definiert und "Value" den für den Befehl benötigten Parameter.

Folgende Befehle (key) sind derzeit verwendbar (s. auch my_scripts_readme.txt im Download):


Keywords for all scripts (Key):
----------------------------------------------------
DVBViewer:
; sendcommand= (DVBViewer Action-ID)
; shader= (activate Pixelshader / none => deactivate sahders)
; audio= (switch to Audio A/B)
; video= (switch to Video A/B)
; showwindow= (WindowID)
; instantrec= (0= stop all instant recordings | > 0 send all instant recordings to recordingservice with +x min)
; debugOSD= (enable/disable a debug OSD for EVR Custom or madVR Renderer)

System:
; shutdown= (0 = Logoff | 1 = Shutdown | 2 = Reboot | 4 = Force | 8 = Power down | 16= Force if hung | 32= Standby | 64= Hibernate)
; resume= (1= run resume-actions after receiving PBT_APMRESUMESUSPEND Message | 0= no action)
; log= (custom log message)
; showwarning= = (1 = show warning on escape condition | 0 = disable show warning)

; sleep= (wait for x seconds)
; run= (runs an external program)
; runwait= (runs an external program and wait until it is finished)
; shellexecute= (runs an external program using the shellExecute API)
; shellexecutewait= (runs an external program using the shellExecute API and wait until it is finished)
; runbybatch= (creates a batchfile that runs an external program and delets the batchfile afterwards)
; processclose= (process name to close)
; processcloseloop= (process name to close => close process until it doesnt exist)
; winclose= ( window title to close )
; execute= (autoit function)
; setdisplay= (refresh rate i.e. 24,50 or 60)
; refreshhdmi= (refresh hdmi connection -> paramater = timeout in seconds between monitor on/off)
; restartservice= (service name)
; stopservice= (service name)
; startservice= (service name)
; sendkeystroke= (send simulate keystrokes to the active window => keystroke codes: https://www.autoitscript.com/autoit3/docs/functions/Send.htm )
; sendkeystrokedvbv= (activate DVBViewer window and send a simulated keystroke to DVBViewer)
; winActivate= (The title/hWnd/class of the window to activate)

External Applications:
; devcon= (hardware ID to restart by devcon => disable + enable)
; devcon2= (hardware ID to restart by devcon => restart)
; cec= (Stdin data to write in cec-client.exe => https://www.pulse-eight.com/ )
; denon= (denon and marantz network control)
; yamaha= (yamaha network control)
; emotiva= (emotiva network control)
; lgtv2012= (LGTV 2012 network control)
; egtcpsend= (send TCP Data to Eventghost)
; wol= (The MAC-Address of the Network Adapter in the format "XXXXXXXXXXXX")
; backup= (0 disable | 1 enable "myScripts" Backupsource | else custom Backupsource)
; backupwait= (0 disable | 1 enable "myScripts" Backupsource | else custom Backupsource)
; updatenoip= (dns update for NoIP 0=disable | 1=enable)

; tcpcontrol)=
; tcpcontrol_local= (IP=127.0.0.1)

Recordingservice:
; processtask (run process task on Recordingservice)

Escape:
; isrecording= (1= check current recordings/timeshift | 0= do not check current recordings/timeshift)
; istimeshift= (1= check current recordings | 0= do not check current timeshift)
; isplaying= (1= check isplaying | 0= do not check isplaying)
; isrecordingRS= (1= check current recordings Recordingservice | 0= do not check current recordings Recordingservice)
; checkprocesslist= (1= check processlist and cancel section if an activ process is found| 0= disbale)
; checkwindowlist= (1= check windowlist and cancel section if a window is found| 0= disbale)


Keywords only for special scripts (Key):
----------------------------------------------------
; loop= (1= keep script alive | 0 = exit skript after actions) !! myActions.exe only !!
; subini= !! myActions.exe only !!
; email= (mail message) ProcesstaskEX and TCP Control only)



Außerdem sind bestimmte Parameter (value) vordefiniert damit man z.B. nicht immer den Pfad zur DVBViewer.exe heraussuchen muss.


Keywords for all scripts (value):
----------------------------------------------------
; {DVBViewer} => DVBViewer program folder (i.e. C:\Program Files\DVBViewer\DVBViewer.exe)
; {DVBViewer.exe} => DVBViewer.exe (i.e. C:\Program Files\DVBViewer)
; {CMUV} => DVBViewer config folder (i.e. C:\ProgramData\CMUV)
; {Eventghost} => eventghost program folder (i.e. C:\Program Files\Eventghost)
; {Eventghost.exe} => eventghost.exe (i.e. C:\Program Files\Eventghost\eventghost.exe)
; {myScripts} => myScripts folder (i.e. C:\Program Files\DVBViewer\myScripts)
; {myConfig} => myScripts config folder (i.e. C:\ProgramData\my_scripts)
; {myBackup} => myBackup.exe (i.e. C:\Program Files\DVBViewer\myScripts\myBackup.exe)
; {mySleeptimer} => mySleeptimer (i.e. C:\Program Files\DVBViewer\myScripts\mySleeptimer.exe)
; {myActions} => myActions .exe (i.e. C:\Program Files\DVBViewer\myScripts\myActions.exe)
; {myExtendedExit} => myExtendedExit.exe (i.e. C:\Program Files\DVBViewer\myScripts\myExtendedExit.exe)
; {myProcesstasks} => myProcesstasks.exe (i.e. C:\Program Files\DVBViewer\myScripts\myProcesstasks.exe)



Neben den Default Konfigurationsdateien befindet sich im Download auch noch eine kommentierte Beispieldatei.
Zu den Feinheiten jedes Skripts verweise ich auf die Posts 2-6.

Changelog


1.0 - 17.01.2016
-Initial release



Credits



Lizenz und Programmierung


Ist natürlich kostenlos, opensource und beliebig einsetzbar oder veränderbar.
Den Sourcecode gibt es hier: http://www.DVBViewer.tv/forum/topic/57636-myextendedexit-myactions-mysleeptimer-myprocesstaks-mybackup/?p=440726
Sollten im sourcecode Angaben zum Author sein (sind nicht alle Funktionen von mir ...) bitte ich darum diese Angaben nicht zu entfernen.
Die Skripte sind in der Programmiersprache autoit geschrieben: https://www.autoitscript.com/site/autoit/



Ursprüngliche Threads



English Thread

http://www.DVBViewer.tv/forum/topic/57975-myextendedexit-myactions-mysleeptimer-myprocesstaks-mybackup/

 

 

 

Anregungen, Verbesserungsvorschläge und Fehlermeldungen sind willkommen. :)


Gruß nuts

myScripts.zip

Edited by nuts

Share this post


Link to post
nuts

myExtendedExit

 

Das myExtendedExit Skript soll das normale "Erweitertes Beenden" Menü im DVBViewer ersetzen um die etwas problematischen Abläufe rund um Standby oder Ruhezustande besser kontrollieren zu können.

Nach meiner Erfahrung funktioniert der Standby (S3) über einen langen Zeitraum (>4 Wochen ohne reboot) am besten wenn man vor dem Standby alle relevanten Programm beendet und erst anschließend den Standby einleitet. Zusätzlich soll das aber auch praktisch, denn nach dem Aufwachen möchte man ja keine lieblose Windows Oberfläche sehen, sondern den DVBViewer im Vollbild mit laufendem TV-Programm.

 

Nach diesen Vorgaben sind auch die Default Werte für myExtendedExit in der myExtendedExit_actions.ini gewählt worden. Zum besseren Verständnis möchte ich einmal die Sektion "Standby" durchgehen"

 

 

[standby]

showwarning=1

isrecording=1

istimeshift=1

isrecordingRS=0

sendcommand=12326

sleep=2

shutdown=32

resume=1

1. showwarning=1

Bei erkannter Escape Bedingung wird eine Warnmeldung im OSD angezeigt. Diese ermöglicht den Benutzer trotz erkannter Aufnahme oder Timershift die Standby Aktion durchzuziehen.

 

2. isrecording=1

Der Befehl "isrecording" gehört zu den Escape-Bedingungen. Diese sind notwendig um im Vorfeld abzuprüfen ob man überhaupt in den Standby wechseln sollte.

isrecording=1 stellt die Überprüfung scharf und bricht die Befehlskette bei laufenden Aufnahmen im DVBViewer ab (außer der Benutzer weiss es besser s. "showwarning" ;) )-

isrecording=0 deaktiviert die Überprüfung (Alternativ: den Eintrag einfach aus der Sektion nehmen)

 

3. istimeshift=1

Gleiches Spiel wie bei "isrecording" nur wird diesmal auf timeshift geprüft.

 

4. isrecordingRS=0

Ähnlich wie beiden anderen Überprüfungen nur wird diesmal der Recordingservice auf Aufnahmen gecheckt.

Wird kein lokaler Recordingservice verwendet so wie bei mir, kann man diese Überprüfung deaktivieren (isrecordingRS=0).

Um den Recordingservice abzuprüfen werden zusätzliche Angaben (IP, Port, Benutzername, Passwort) in der my_scripts_config.ini benötigt (s. Post 1)

 

5. sendcommand=12326

Schickt über das COM-Interface des DVBViewers die Action-ID 12326 (=DVBViewer beenden) an den DVBViewer um diesen zu beenden.

 

6. sleep=2

Das Skript wartet 2 Sekunden um dem DVBViewer etwas Zeit zu geben sich richtig zu beenden.

 

7. shutdown=32

Der eigentliche Standby Befehl.

1=shutdown | 2=reboot | 32=standby | 64=hibernate

8. resume=1

Gibt dem Skript die Anweisung sich nicht zu beenden und auf das nächste Aufwachen des Computers zu warten.

Nachdem Aufwachen wird dann die Sektion "Resume" in der my_scripts_actions.ini (s. Post 1) nach dem gleichen Schema abgearbeitet.

[Resume]

log=section "Resume" => log Eintrag "Resume" wird ins Log eingetragen

sleep=2 => 2 Sekunden warten um dem System etwas Zeit zu geben

run={DVBViewer.exe} -x5 => DVBViewer.exe mit dem Kommandoparameter -x5 (=Vollbild) starten

Anschließend beendet sich das Skript.

Mit dem "sleep" Parameter muss man je nach System natürlich etwas spielen um das beste Ergebnis zu erzielen.

 

Besonders wichtig bei myExtendedExit sind die "Escape Befehle", da man diese einsetzen kann um auf bestimmte Bedingungen (laufende Aufnahmen, aktive Prozesse usw.) Rücksicht zu nehmen.

Diese Escape Befehle wurden umgesetzt (s. my_scripts_readme.txt):

Escape:

; isrecording= (1= check current recordings/timeshift | 0= do not check current recordings/timeshift)

; istimeshift= (1= check current recordings | 0= do not check current timeshift)

; isplaying= (1= check isplaying | 0= do not check isplaying)

; isrecordingRS= (1= check current recordings Recordingservice | 0= do not check current recordings Recordingservice)

; checkprocesslist= (1= check processlist and cancel section if an activ process is found| 0= disbale)

; checkwindowlist= (1= check windowlist and cancel section if a window is found| 0= disbale)

Neben dem simplen Abbrechen der Sektion (isrecording=1) ist auch eine Umleitung möglich.

z.B. isrecording=isrecording führt die Sektion "isrecording" in der "my_scripts_actions.ini" aus (Details erkläre ich dazu gern bei Bedarf ;) ).

 

Soweit zu den Befehlsketten. Das "System" ist natürlich etwas tricky in der Einrichtung, aber das Ergebnis ist schon super.

Bei mir wird z.B. neben dem DVBViewer noch Eventghost beendet, der TV + Soundanlage ausgeschaltet und das Licht eingeschaltet. ;)

 

In der my_scripts_config.ini gibt es noch Einträge speziell für myExtendedExit:

[myExtendedExit]

Header=Extended Exit => angezeigte Überschrift im DVBViewer OSD

ExtendedLog=0 => 1 aktiviert ein erweitertes logging für die Fehlersuche

Language=0 => derzeit ohne Funktion

configINI= => Spezialfall würde unterschiedliche Konfigurationsdateien der verschiedenen Skripte

Im Anhang noch ein Bild vom OSD damit man sich die Geschichte besser vorstellen kann.

Je nach Auswahl wird dann eine entsprechende Sektion abgearbeitet.

Natürlich könnt ihr auch Sektionen ganz löschen (z.B. wenn kein Ruhezustand verwendet wird) oder eigene Hinzufügen.

Im Ordner "Examples" aus dem Dowanload sind alle Default Dateien nochmal verfügbar und können somit leicht wiederhergestellt werden.

post-39934-0-89935200-1453058040_thumb.png

Edited by nuts

Share this post


Link to post
nuts

myActions.exe

post-39934-0-14290800-1453201910_thumb.png

post-39934-0-94420800-1453201919_thumb.png

post-39934-0-72526100-1453201927_thumb.png

Edited by nuts

Share this post


Link to post
nuts

mySleeptimer.exe

 

Der Sleeptimer sollte ein möglichst einfaches Tool werden um den DVBViewer mit der Sleeptimer Funktionalität zu erweitern.

Die Einrichtung der Befehlsketten erfolgt nach dem gleichen Schema wie bei myExtendedExit (s. Post 2).

 

Besonderheiten:

 

Die in Post2 vorgestellten "Escape Befehle" bewirken keinen Abbruch des kompletten Skript, sondern verschieben den Countdown einfach um +15 Minuten

Dadurch wird z.B. bei einer laufenden Aufnahme einfach nach 15min nochmal versucht den PC schlafen zu legen.

 

In der my_scripts_config.ini (s. Post 1) gibt es noch Einträge speziell für mySleeptimer:

[mySleeptimer]

Header=Sleeptimer => s. Post 2

ExtendedLog=0 => 1 aktivert erweitertes loggin für Fehlersuche

Language=0 => ohne Funktion

configINI= (s. Post 2)

Counter=30%60%90%120%180 => hier werden die auswählbaren Countdowns in Minuten definiert

Shutdown Modus=Standby => hier wird die gewünschte Aktion gespeichert

Showwarning=1 => zeigt nach Ende des Countdowns eine OSD Meldung um den Standby noch abzubrechen falls der Benutzer noch wach ist (Showwarning=0 deaktivert diese Meldung)

Showwarningtimeout=30 => timeout in Sekunden für die Warnmeldung, danach geht es schlafen

Hier sind eigentlich keine Änderungen nötig, außer ihr möchtet andere Counter zur Auswahl haben.

 

Auch hier im Anhang ein paar Bilder fürs bessere Verständnis. :)

post-39934-0-50426800-1453059696_thumb.png

post-39934-0-76453600-1453059705_thumb.png

Edited by nuts

Share this post


Link to post
nuts

myProcesstasks.exe

 

Auch bei myProcesstasks werden die Befehlsabfolgen über beliebige Key/Value Paare angelegt, jedoch kommt dieses Skript ganz ohne den DVBViewer und dessen OSD aus und eignet sich somit um als Aufgabe in den Recordingservice eingebunden zu werden.

http://de.DVBViewer.tv/wiki/Optionen_Service_-_Aufgaben

 

Da die Auswahl über das OSD welche Befehlsfolge abgearbeitet werden soll fehlt muss dem Skript auf einem anderen Weg gesagt werden welche Sektion verarbeitet werden soll.

Dies geschieht über Kommandoparameter.

Bsp:

myProcesstasks.exe -reboot => die Sektion "reboot" in der "myProcessTasks_actions.in" wird verarbeitet

 

Wer nur eine Sektion benötigt kann das Skript einfach ohne Kommandoparameter starten.

In diesem Fall wird die Sektion "default" in der "myProcessTasks_actions.in" abgearbeitet.

 

Da das Skript unabhängig von DVBViewer und Recordingservice arbeitet lassen sich damit auch andere Aufgaben am PC automatisieren. ;)

Edited by nuts

Share this post


Link to post
nuts

myBackup (kommt bald ;) )

Edited by nuts

Share this post


Link to post
nuts

Sourcecode (last update: 18.03.2016) including custom UDF's.

 

 

UDF's written by other scripters:

WinHTTP.au3 => trancexx, ProgAndy http://www.autoitscript.com/forum/topic/84133-winhttp-functions/
_XMLDomWrapper.au3 => Stephen Podhajecki http://www.autoitscript.com/forum/topic/19848-xml-dom-wrapper-com/
NOIP.au3 => Nessie http://www.autoitscript.com/forum/topic/150985-no-ip-udf/

myScripts_sourcecode_2016_03_18.zip

Edited by nuts

Share this post


Link to post
cuppie

Hi,

 

Is it possible to start an english topic about this beatifull plugin ?

 

Cuppie

Share this post


Link to post
nuts

Yes of course.

You can post your questions here in english until I created the english topic.

Share this post


Link to post
cuppie

First many thanks for this update.

I was already using extended exit , and mysleeptimer. (e.g. v2)

In the previous version of sleeptimer I was missing the CEC client.

But in the new version , all plugins are using the same configuration.

Again , many thanks for that.

 

I was wondering about the language , in the old version , the sleeptimer was hardcoded german. This version seems to be hardcoded english.

Is it possible to use a luanguage file like other plugins do ?

 

I really like the CEC connectivity.

I've some usb cec adapters , and was already using them with a batch file as a single command (cec-client -s) (very slow.)

But I'm wondering why the cec connection in your scripts is so fast.

Currently i'm only using is for the correct input and power on/off , of the tv.

But i'm looking for using CEC to control volume on the TV.

Maybe the CEC connection is fast enough for that ?

Share this post


Link to post
nuts

Seems like we are using a similar setup. With cec-client extended exit and sleeptimer works perfect for me. :)

 

My scripts are using the cec-client.exe too and I dont know why it is faster than using it with a batch file.

I am using this to commit the action to cec-client.exe https://msdn.microsoft.com/de-de/library/3x292kth.aspx

 

All scripts are prepared for multi language. I will take a look this weekend. :)

Share this post


Link to post
nuts

@cuppie: I am working on multi language right now and I suppose you want not german or english? Than I need your help. ;)

 

dialogs in mysleeptimer:

 

deutsch => "Countdown beendet!"

english => "Countdown finished!"

your lang. => "...."

 

deutsch => "Cancel Action?"

english => "Aktion abbrechen?"

your lang. => "...."

 

deutsch => "Aktion?"

english => "Action?"

your lang. => "...."

 

deutsch => "min"

english => "min" (minutes)

your lang. => "...."

P.S. my code for cec-client use:

 

 

Func _cec_client($s_ini_cecdata, $Stdin_data)

;nuts (www.autoit.de)

 

Local $cec_client = IniRead($s_ini_cecdata, "FilePaths", "cec-client", "") ; get path to cec-client.exe

If Not FileExists($cec_client) Then ; error handling

_Set_myError('Error: Func _cec-client => cec-client.exe not found')

Return SetError(1, 0, 0)

EndIf

 

$cec_client &= " -s" ; add cmdline " -s"

 

Local $run = Run($cec_client, "", @SW_HIDE, $STDIN_CHILD)

 

StdinWrite($run, $Stdin_data) ; stdinwrite to commit the action to cec-client.exe (i.e. turn on/off the TV)

StdinWrite($run)

 

EndFunc ;==>_cec_client

 

Edited by nuts

Share this post


Link to post
cuppie

Sorry for the late reply,

 

My native language is Dutch.

 

This should be like this :

 

deutsch => "Countdown beendet!"
english => "Countdown finished!"
dutch => "Timer voltooid"

deutsch => "Cancel Action?"
english => "Aktion abbrechen?"
dutch => "Actie beëindigen?"

deutsch => "Aktion?"
english => "Action?"
dutch => "Actie?"

deutsch => "min"
english => "min" (minutes)
dutch. => "min"

 

 

 

I think the reason for the fast cec connection , has to do with the fact there is only input , and no output.

Share this post


Link to post
nuts

Here is a test version with multilang. support for mySleeptimer. :)

Please let me know if you find bugs or harcoded german/english text.

 

 

 

P.S. I created a thread for questions in english: http://www.DVBViewer.tv/forum/topic/57975-myextendedexit-myactions-mysleeptimer-myprocesstaks-mybackup/

mySleeptimer.zip

Edited by nuts

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...