diff --git a/PlayWall/assets/de/tobias/playpad/assets/dialog/launchDialog.fxml b/PlayWall/assets/de/tobias/playpad/assets/dialog/launchDialog.fxml
index 4b68d4f98ea2ddcf32efa55f44b663c240ffdb10..c2a147570763b9d10242ba840bbdd5782fda3487 100644
--- a/PlayWall/assets/de/tobias/playpad/assets/dialog/launchDialog.fxml
+++ b/PlayWall/assets/de/tobias/playpad/assets/dialog/launchDialog.fxml
@@ -11,11 +11,7 @@
    <children>
       <VBox alignment="CENTER" layoutX="24.0" layoutY="5.0" spacing="7.0" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="34.0" AnchorPane.topAnchor="14.0">
          <children>
-            <ImageView fx:id="imageView" fitHeight="144.0" fitWidth="140.0" layoutX="80.0" layoutY="14.0" pickOnBounds="true" preserveRatio="true">
-               <effect>
-                  <DropShadow />
-               </effect>
-            </ImageView>
+            <ImageView fx:id="imageView" fitHeight="144.0" fitWidth="140.0" layoutX="80.0" layoutY="14.0" pickOnBounds="true" preserveRatio="true" />
             <Label fx:id="infoLabel" alignment="CENTER" layoutX="24.0" layoutY="212.0" prefHeight="39.0" prefWidth="310.0" AnchorPane.leftAnchor="24.0" AnchorPane.rightAnchor="266.0" AnchorPane.topAnchor="212.0">
                <font>
                   <Font size="25.0" />
diff --git a/PlayWall/assets/de/tobias/playpad/assets/files/class_obj.png b/PlayWall/assets/de/tobias/playpad/assets/files/class_obj.png
new file mode 100644
index 0000000000000000000000000000000000000000..bc915da4420060b4ea9984fc662935f10f19449a
Binary files /dev/null and b/PlayWall/assets/de/tobias/playpad/assets/files/class_obj.png differ
diff --git a/PlayWall/assets/de/tobias/playpad/assets/files/enum_obj.png b/PlayWall/assets/de/tobias/playpad/assets/files/enum_obj.png
new file mode 100644
index 0000000000000000000000000000000000000000..c2b5d8345058a26e8ffb4262277543bce417535b
Binary files /dev/null and b/PlayWall/assets/de/tobias/playpad/assets/files/enum_obj.png differ
diff --git a/PlayWall/assets/de/tobias/playpad/assets/lang/_de.properties b/PlayWall/assets/de/tobias/playpad/assets/lang/_de.properties
index 69c9133951278d6a9b34823993f296da28be887f..6e553fe7b55f64165bef092e56959af31f7551a3 100644
--- a/PlayWall/assets/de/tobias/playpad/assets/lang/_de.properties
+++ b/PlayWall/assets/de/tobias/playpad/assets/lang/_de.properties
@@ -23,6 +23,7 @@ UI.Window.Main.Title=Play Wall [Projekt: {} - Profil: {}]
 UI.Window.Changelog.Title=Was ist neu?
 UI.Window.Settings.Title=Einstellungen - {}
 UI.Window.PadSettings.Title=Kachel Einstellungen - {} | {}
+UI.Window.PadSettings.Title.Empty=Kachel Einstellungen - {}
 UI.Dialog.DragAndDrop.Title=Drag and Drop
 UI.Dialog.ProjectExport.Title=Projekt exportieren
 UI.Dialog.ErrorSummary.Title=Fehlerbericht
@@ -92,7 +93,7 @@ UI.Dialog.Profile.Delete.Content=Sind Sie sicher, dass Sie das Profil {} l
 
 # UI - Dialog - Info
 UI.Dialog.Info.Header=�ber {}
-UI.Dialog.Info.Content=Version: {} (Build: {})\nAutor: {}\n\nDieses Programm nutzt Bibliotheken. ControlsFX (8.40.10), dom4j (1.6.1), snakeyaml (1.11), guava (15.0), gagawa (1.0.1), TinySound (1.1.1), JLayer (1.0.1), JSPF (1.0.2), json-smart (1.2). \nBesonderen Dank an die Betatester: Stefan, Robert.
+UI.Dialog.Info.Content=Version: {} (Build: {})\nAutor: {}\nGrafiken: Robert Goldmann.\n\nDieses Programm nutzt Bibliotheken. ControlsFX (8.40.10), dom4j (1.6.1), snakeyaml (1.11), guava (15.0), gagawa (1.0.1), TinySound (1.1.1), JLayer (1.0.1), JSPF (1.0.2), json-smart (1.2). \nBesonderen Dank an die Betatester: Stefan, Robert.
 
 # UI - Dialog - Feedback
 UI.Dialog.Feedback.Content=Der Fehlerbericht wird �bermittelt. Dies dauert einen kleinen Moment. Bitte haben Sie etwas Geduld. Ihre Nummer wird am Ende angezeigt.
@@ -162,6 +163,7 @@ Error.Midi.Send=Der Midi Befehl konnte nicht gesendet werden. ({})
 
 # Error - Plugins
 Error.Plugins.Download=Das Plugin {} konnte nicht geladen werden.
+Error.Plugins.Avaiable=Es sind keine Plugins f�r dieses Update Kanal verf�gbar.
 
 #Mapper
 Mapper.Keyboard.Name=Tastatur
@@ -204,13 +206,16 @@ CartAction.Mode.PLAY_HOLD=Play/Hold
 UI.Dialog.AutoUpdate.Header=Updates
 UI.Dialog.AutoUpdate.Content=Es sind Updates verf�gbar. M�chten Sie diese jetzt installieren? (Weitere Informationen finden Sie in den Update Einstellungen.)
 
+# Update Channel - BaseName
+UpdateChannel.STABLE=Stabil
+UpdateChannel.BETA=Beta
+
 # Error - Layout
 Error.Layout.Load=Es gab einen Fehler beim Laden des Layouts ({})
 
 # UI - Dialog - Update
 UI.Dialog.Update.Cell={}: Installiert: {} - Neu: {}
 UI.Window.Settings.Updates.CurrentVersion={} (Build {})
-UI.Window.Settings.Updates.NewVersion={} (Build {})
 
 # Error - Update - Downlaod
 Error.Update.Download=Es ist ein Fehler beim Herunterladen des Updates aufgetreten. Bitte versuchen Sie es sp�ter erneut. ({})
diff --git a/PlayWall/assets/de/tobias/playpad/assets/lang/ui_de.properties b/PlayWall/assets/de/tobias/playpad/assets/lang/ui_de.properties
index 96235bf6de5b7347a56ecff96b82d100a3fa9efa..1ad02a367c7a457e081958a4693bd4964f761953 100644
--- a/PlayWall/assets/de/tobias/playpad/assets/lang/ui_de.properties
+++ b/PlayWall/assets/de/tobias/playpad/assets/lang/ui_de.properties
@@ -69,6 +69,9 @@ settings.update.label.search=Nach Updates suchen:
 settings.update.label.available=Verf�gbare Updates:
 settings.update.button.search=Jetzt suchen
 settings.update.button.install=Aktualisieren und neu starten
+settings.update.label.channel=Update Kanal:
+settings.update.label.infoC=Program
+settings.update.label.infoE=Erweiterung
 
 settings.button.finish=Fertig
 settings.checkbox.activate=Aktivieren
diff --git a/PlayWall/assets/de/tobias/playpad/assets/view/main/mainMenu.fxml b/PlayWall/assets/de/tobias/playpad/assets/view/main/mainMenu.fxml
index 1019034cadcd369e709a0a0091e34f3b7b181c7d..4811fc21c824512215069318915dd99aed3ea491 100644
--- a/PlayWall/assets/de/tobias/playpad/assets/view/main/mainMenu.fxml
+++ b/PlayWall/assets/de/tobias/playpad/assets/view/main/mainMenu.fxml
@@ -48,7 +48,6 @@
             <SeparatorMenuItem mnemonicParsing="false" />
             <MenuItem mnemonicParsing="false" onAction="#pluginMenuItemHandler" text="%main.menuitem.plugins" />
             <SeparatorMenuItem mnemonicParsing="false" />
-            <CheckMenuItem fx:id="quickEditMenuItem" mnemonicParsing="false" onAction="#quickEditMenuHandler" text="Quick Edit" visible="false" />
             <MenuItem fx:id="settingsMenuItem" mnemonicParsing="false" onAction="#settingsHandler" text="%main.menuitem.settings">
                <accelerator>
                   <KeyCodeCombination alt="UP" code="COMMA" control="UP" meta="UP" shift="UP" shortcut="DOWN" />
diff --git a/PlayWall/assets/de/tobias/playpad/assets/view/option/layout/modernLayoutCart.fxml b/PlayWall/assets/de/tobias/playpad/assets/view/option/layout/modernLayoutCart.fxml
index 47f1ad840bd6cebeedff224dff9332c4c32d01a4..0307ce2b59a3e730796a184cb34c75fe027f6320 100644
--- a/PlayWall/assets/de/tobias/playpad/assets/view/option/layout/modernLayoutCart.fxml
+++ b/PlayWall/assets/de/tobias/playpad/assets/view/option/layout/modernLayoutCart.fxml
@@ -30,12 +30,6 @@
                   <Button fx:id="playColorButton" focusTraversable="false" mnemonicParsing="false" onAction="#playColorButtonHandler" prefWidth="150.0" />
                </children>
             </VBox>
-            <VBox maxWidth="1.7976931348623157E308" prefWidth="150.0" spacing="14.0" HBox.hgrow="ALWAYS">
-               <children>
-                  <Label alignment="BOTTOM_LEFT" layoutX="243.0" layoutY="8.0" prefHeight="60.0" prefWidth="150.0" text="%layout.label.animation" wrapText="true" VBox.vgrow="ALWAYS" />
-                  <CheckBox fx:id="warnAnimationCheckBox" mnemonicParsing="false" text="%layout.label.warnAnimation" />
-               </children>
-            </VBox>
          </children>
       </HBox>
       <Button fx:id="resetButton" mnemonicParsing="false" onAction="#resetButtonHandler" text="%layout.button.reset">
diff --git a/PlayWall/assets/de/tobias/playpad/assets/view/option/updateTab.fxml b/PlayWall/assets/de/tobias/playpad/assets/view/option/updateTab.fxml
index 91c68b8a000fcfe5f6028a2d03f1ab06a68131cf..2f2c940576518b11583a9901fd0554f67d96ad10 100644
--- a/PlayWall/assets/de/tobias/playpad/assets/view/option/updateTab.fxml
+++ b/PlayWall/assets/de/tobias/playpad/assets/view/option/updateTab.fxml
@@ -5,7 +5,6 @@
 <?import java.lang.*?>
 <?import javafx.scene.layout.*?>
 
-
 <VBox spacing="14.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
    <children>
       <HBox layoutX="14.0" layoutY="14.0" spacing="14.0">
@@ -14,12 +13,6 @@
             <Label fx:id="currentVersionLabel" layoutX="175.0" layoutY="14.0" text="5.0.1 (stable)" />
          </children>
       </HBox>
-      <HBox layoutX="14.0" layoutY="36.0" spacing="14.0">
-         <children>
-            <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="36.0" prefWidth="150.0" text="%settings.update.label.new" />
-            <Label fx:id="newVersionLabel" layoutX="175.0" layoutY="36.0" text="5.0.2 (stable)" />
-         </children>
-      </HBox>
       <Separator prefWidth="200.0" />
       <HBox spacing="14.0">
          <children>
@@ -27,6 +20,12 @@
             <CheckBox fx:id="automaticSearchCheckBox" layoutX="275.0" layoutY="183.0" mnemonicParsing="false" text="Automatisch" />
          </children>
       </HBox>
+      <HBox alignment="CENTER_LEFT" spacing="14.0">
+         <children>
+            <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%settings.update.label.channel" />
+            <ComboBox fx:id="updateChannelComboBox" prefWidth="150.0" />
+         </children>
+      </HBox>
       <HBox spacing="14.0">
          <children>
             <Label alignment="CENTER_RIGHT" layoutX="106.0" layoutY="222.0" prefWidth="150.0" />
@@ -37,7 +36,17 @@
       <HBox spacing="14.0">
          <children>
             <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%settings.update.label.available" />
-            <ListView fx:id="openUpdateList" prefHeight="200.0" prefWidth="200.0" HBox.hgrow="ALWAYS" />
+            <VBox spacing="14.0" HBox.hgrow="ALWAYS">
+               <children>
+                  <ListView fx:id="openUpdateList" prefHeight="200.0" prefWidth="200.0" HBox.hgrow="ALWAYS" />
+                  <HBox spacing="14.0">
+                     <children>
+                        <Label fx:id="infoCLabel" text="%settings.update.label.infoC" />
+                        <Label fx:id="infoELabel" text="%settings.update.label.infoE" />
+                     </children>
+                  </HBox>
+               </children>
+            </VBox>
          </children>
       </HBox>
       <HBox alignment="TOP_RIGHT">
diff --git a/PlayWall/beta.xml b/PlayWall/beta.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f21bdb1c489d3cec41399ed3e38d30a3cae58478
--- /dev/null
+++ b/PlayWall/beta.xml
@@ -0,0 +1,28 @@
+<project name="Build App" default="buildApp" basedir="/Users/tobias/Documents/Programmieren/Java/eclipse/">
+
+	<taskdef name="bundleapp" classname="com.oracle.appbundler.AppBundlerTask" classpath="/Users/tobias/Documents/Programmieren/Java/ant/lib/appbundler-1.0.jar" />
+	<taskdef name="launch4j" classname="net.sf.launch4j.ant.Launch4jTask" classpath="/Users/tobias/Documents/Programmieren/Java/ant/lib/launch4j/launch4j.jar:${launch4j.dir}/lib/xstream.jar" />
+	<taskdef name="upload" classname="de.tobias.playwallpm.task.PlayWallPMTask" classpath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWallPackageManager/build/PlayWallPM.jar:
+				/Users/tobias/Documents/Programmieren/Java/Libraries/jsch/jsch-0.1.53.jar:
+				/Users/tobias/Documents/Programmieren/Java/Libraries/File Parser/YAML/YAMLStorage.jar:
+				/Users/tobias/Documents/Programmieren/Java/Libraries/File Parser/YAML/snakeyaml-1.11.jar:
+				/Users/tobias/Documents/Programmieren/Java/Libraries/File Parser/YAML/guava-15.0.jar" />
+	<taskdef name="buildNumber" classname="de.tobias.playwallpm.task.BuildNumberTask" classpath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWallPackageManager/build/PlayWallPM.jar:
+				/Users/tobias/Documents/Programmieren/Java/Libraries/jsch/jsch-0.1.53.jar:
+				/Users/tobias/Documents/Programmieren/Java/Libraries/File Parser/YAML/YAMLStorage.jar:
+				/Users/tobias/Documents/Programmieren/Java/Libraries/File Parser/YAML/snakeyaml-1.11.jar:
+				/Users/tobias/Documents/Programmieren/Java/Libraries/File Parser/YAML/guava-15.0.jar" />
+
+	<target name="buildApp">
+		<!-- Upload Jar -->
+		<input addproperty="password">Enter password</input>
+		<upload username="p35947554-pw" password="${password}" host="p35947554.1and1-data.host">
+			<file type="program" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/PlayWall.jar" remotePath="/beta" remoteFileName="PlayWall.jar" />
+			<file type="plugin" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/ActionPlugin.jar" remotePath="/beta/plugins" remoteFileName="ActionPlugin.jar" />
+			<file type="plugin" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/AwakePlugin.jar" remotePath="/beta/plugins" remoteFileName="AwakePlugin.jar" />
+			<file type="plugin" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/EqualizerPlugin.jar" remotePath="/beta/plugins" remoteFileName="EqualizerPlugin.jar" />
+			<file type="plugin" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/LaunchPadPlugin.jar" remotePath="/beta/plugins" remoteFileName="LaunchPadPlugin.jar" />
+			<file type="plugin" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/MediaPlugin.jar" remotePath="/beta/plugins" remoteFileName="MediaPlugin.jar" />
+		</upload>
+	</target>
+</project>
\ No newline at end of file
diff --git a/PlayWall/build.xml b/PlayWall/build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..943ff80ec1870df04b63927711cc03326634723f
--- /dev/null
+++ b/PlayWall/build.xml
@@ -0,0 +1,42 @@
+<project name="Build App" default="buildApp" basedir="/Users/tobias/Documents/Programmieren/Java/eclipse/">
+
+	<taskdef name="bundleapp" classname="com.oracle.appbundler.AppBundlerTask" classpath="/Users/tobias/Documents/Programmieren/Java/ant/lib/appbundler-1.0.jar" />
+	<taskdef name="launch4j" classname="net.sf.launch4j.ant.Launch4jTask" classpath="/Users/tobias/Documents/Programmieren/Java/ant/lib/launch4j/launch4j.jar:${launch4j.dir}/lib/xstream.jar" />
+	<taskdef name="upload" classname="de.tobias.playwallpm.task.PlayWallPMTask" classpath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWallPackageManager/build/PlayWallPM.jar:
+					/Users/tobias/Documents/Programmieren/Java/Libraries/jsch/jsch-0.1.53.jar:
+					/Users/tobias/Documents/Programmieren/Java/Libraries/File Parser/YAML/YAMLStorage.jar:
+					/Users/tobias/Documents/Programmieren/Java/Libraries/File Parser/YAML/snakeyaml-1.11.jar:
+					/Users/tobias/Documents/Programmieren/Java/Libraries/File Parser/YAML/guava-15.0.jar" />
+	<taskdef name="buildNumber" classname="de.tobias.playwallpm.task.BuildNumberTask" classpath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWallPackageManager/build/PlayWallPM.jar:
+					/Users/tobias/Documents/Programmieren/Java/Libraries/jsch/jsch-0.1.53.jar:
+					/Users/tobias/Documents/Programmieren/Java/Libraries/File Parser/YAML/YAMLStorage.jar:
+					/Users/tobias/Documents/Programmieren/Java/Libraries/File Parser/YAML/snakeyaml-1.11.jar:
+					/Users/tobias/Documents/Programmieren/Java/Libraries/File Parser/YAML/guava-15.0.jar" />
+
+	<target name="buildApp">
+		<bundleapp outputdirectory="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/dist" name="Play Wall" displayname="Play Wall" identifier="de.tobias.playwall" mainclassname="de.tobias.playpad.PlayPadMain" icon="/Users/tobias/Documents/Programmieren/Java/git/PlayWall/PlayWall/src/icon.icns">
+			<runtime dir="/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home" />
+			<classpath file="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/PlayWall.jar" />
+		</bundleapp>
+
+		<launch4j>
+			<config headerType="gui" outfile="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/dist/PlayWall.exe" dontWrapJar="false" jarPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/PlayWall.jar" icon="/Users/tobias/Documents/Programmieren/Java/git/PlayWall/PlayWall/src/icon.ico">
+				<classPath mainClass="de.tobias.playpad.PlayPadMain" />
+				<jre minVersion="1.8.0">
+				</jre>
+			</config>
+		</launch4j>
+
+		<input addproperty="password">Enter password</input>
+
+		<upload username="p35947554-pw" password="${password}" host="p35947554.1and1-data.host">
+			<file type="program" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/PlayWall.jar" remotePath="/stable" remoteFileName="PlayWall.jar" />
+			<file type="exe" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/PlayWall.exe" remotePath="/stable" remoteFileName="PlayWall.exe" />
+			<file type="plugin" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/ActionPlugin.jar" remotePath="/stable/plugins" remoteFileName="ActionPlugin.jar" />
+			<file type="plugin" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/AwakePlugin.jar" remotePath="/stable/plugins" remoteFileName="AwakePlugin.jar" />
+			<file type="plugin" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/EqualizerPlugin.jar" remotePath="/stable/plugins" remoteFileName="EqualizerPlugin.jar" />
+			<file type="plugin" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/LaunchPadPlugin.jar" remotePath="/stable/plugins" remoteFileName="LaunchPadPlugin.jar" />
+			<file type="plugin" localPath="/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWall/build/MediaPlugin.jar" remotePath="/stable/plugins" remoteFileName="MediaPlugin.jar" />
+		</upload>
+	</target>
+</project>
\ No newline at end of file
diff --git a/PlayWall/src/application.yml b/PlayWall/src/application.yml
index 399d169517d6e08dec15cc896bcc2c5d0c107625..c955943e2ec0c1f35475d7f79b925ad0d2f6a126 100644
--- a/PlayWall/src/application.yml
+++ b/PlayWall/src/application.yml
@@ -1,6 +1,6 @@
 name: PlayWall
-version: 5.0.0 GM
-build: 26
+version: 5.0.1
+build: 31
 identifier: de.tobias.playpad
 main: de.tobias.playpad.PlayPadMain
 author: Tobias Ullerich
@@ -10,6 +10,8 @@ updateURL: http://tobisan.no-ip.org/files/PlayWall
 userInfo:
   Website: http://tobisan.no-ip.org/
   ErrorURL: http://tobisan.no-ip.org/upload.php
-  PluginsURL: http://tobisan.no-ip.org/files/PlayWall/plugins.yml
+  PluginsURL: 
+     Stable: http://tobisan.no-ip.org/files/PlayWall/stable/plugins.yml
+     Beta: http://tobisan.no-ip.org/files/PlayWall/beta/plugins.yml
   ChangelogURL: http://tobisan.no-ip.org/whatsnew-2.php?id=1
   UpdaterProgram: http://tobisan.no-ip.org/files/Updater/
diff --git a/PlayWall/src/de/tobias/playpad/AppUserInfoStrings.java b/PlayWall/src/de/tobias/playpad/AppUserInfoStrings.java
index df966939ee73d71abe043ee02b458093900bced8..892cf27637337f1ed49fcda4b1ebb86f93af78d1 100644
--- a/PlayWall/src/de/tobias/playpad/AppUserInfoStrings.java
+++ b/PlayWall/src/de/tobias/playpad/AppUserInfoStrings.java
@@ -3,7 +3,8 @@ package de.tobias.playpad;
 public class AppUserInfoStrings {
 
 	public static final String WEBSITE = "Website";
-	public static final String PLUGINS_URL = "PluginsURL";
+	public static final String PLUGINS_URL_STABLE = "PluginsURL.Stable";
+	public static final String PLUGINS_URL_BETA = "PluginsURL.Beta";
 	public static final String ERROR_URL = "ErrorURL";
 	public static final String CHANGELOG_URL = "ChangelogURL";
 	public static final String UPDATER_PROGRAM = "UpdaterProgram";
diff --git a/PlayWall/src/de/tobias/playpad/PlayPadImpl.java b/PlayWall/src/de/tobias/playpad/PlayPadImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..ecff8fee390fa91ea62c2ad024ff452164a7553a
--- /dev/null
+++ b/PlayWall/src/de/tobias/playpad/PlayPadImpl.java
@@ -0,0 +1,166 @@
+package de.tobias.playpad;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+import de.tobias.playpad.plugin.PadListener;
+import de.tobias.playpad.plugin.SettingsListener;
+import de.tobias.playpad.plugin.WindowListener;
+import de.tobias.playpad.project.Project;
+import de.tobias.playpad.viewcontroller.IPadSettingsViewController;
+import de.tobias.playpad.viewcontroller.ISettingsViewController;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+import de.tobias.playpad.viewcontroller.main.MainViewController;
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.container.PathType;
+import de.tobias.utils.util.Worker;
+import javafx.scene.image.Image;
+import net.xeoh.plugins.base.PluginManager;
+import net.xeoh.plugins.base.impl.PluginManagerFactory;
+
+public class PlayPadImpl implements PlayPad {
+
+	private static final String PLUGIN_INFO_TXT = "pluginInfo.txt";
+
+	protected List<WindowListener<IMainViewController>> mainViewListeners = new ArrayList<>();
+	protected List<WindowListener<ISettingsViewController>> settingsViewListeners = new ArrayList<>();
+	protected List<WindowListener<IPadSettingsViewController>> padSettingsViewListeners = new ArrayList<>();
+	protected List<SettingsListener> settingsListeners = new ArrayList<>();
+	protected List<PadListener> padListeners = new ArrayList<>();
+
+	private PluginManager pluginManager;
+	private Set<Path> deletedPlugins;
+
+	private MainViewController mainViewController;
+
+	public PlayPadImpl() {
+		pluginManager = PluginManagerFactory.createPluginManager();
+		deletedPlugins = new HashSet<>();
+	}
+
+	@Override
+	public void addMainViewListener(WindowListener<IMainViewController> listener) {
+		mainViewListeners.add(listener);
+	}
+
+	@Override
+	public void addSettingsListener(SettingsListener listener) {
+		settingsListeners.add(listener);
+	}
+
+	@Override
+	public void removeSettingsListener(SettingsListener listener) {
+		settingsListeners.remove(listener);
+	}
+
+	@Override
+	public List<SettingsListener> getSettingsListener() {
+		return settingsListeners;
+	}
+
+	@Override
+	public void addPadListener(PadListener listener) {
+		padListeners.add(listener);
+	}
+
+	@Override
+	public void removePadListener(PadListener listener) {
+		padListeners.remove(listener);
+	}
+
+	@Override
+	public List<PadListener> getPadListener() {
+		return padListeners;
+	}
+
+	@Override
+	public IMainViewController getMainViewController() {
+		return mainViewController;
+	}
+
+	@Override
+	public Optional<Image> getIcon() {
+		return PlayPadMain.stageIcon;
+	}
+
+	/**
+	 * Fügt ein Plugin hinzu, sich zu löschen.
+	 * 
+	 * @param path
+	 *            Pfad zu einem Plugin
+	 */
+	public void addDeletedPlugin(Path path) {
+		deletedPlugins.add(path);
+	}
+
+	/**
+	 * Gibt alle Plugins zurück, die gelöscht werden sollen.
+	 * 
+	 * @return Plugins
+	 */
+	public Set<Path> getDeletedPlugins() {
+		return deletedPlugins;
+	}
+
+	void deletePlugins() throws IOException {
+		Path pluginInfoPath = ApplicationUtils.getApplication().getPath(PathType.LIBRARY, PLUGIN_INFO_TXT);
+
+		// Delete Plugin
+		if (Files.exists(pluginInfoPath)) {
+			BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(pluginInfoPath)));
+			String line;
+			while ((line = reader.readLine()) != null) {
+				Path plugin = Paths.get(line);
+				Files.deleteIfExists(plugin);
+			}
+			reader.close();
+			Files.delete(pluginInfoPath);
+		}
+
+	}
+
+	@Override
+	public void shutdown() {
+		// Delete Plugins Info Textfile --> Löschen dann beim Start.
+		Path pluginInfoPath = ApplicationUtils.getApplication().getPath(PathType.LIBRARY, PLUGIN_INFO_TXT);
+		try {
+			if (Files.notExists(pluginInfoPath)) {
+				Files.createDirectories(pluginInfoPath.getParent());
+				Files.createFile(pluginInfoPath);
+			}
+			PrintWriter deleteWriter = new PrintWriter(Files.newOutputStream(pluginInfoPath));
+			for (Path path : getDeletedPlugins()) {
+				deleteWriter.println(path.toString());
+			}
+			deleteWriter.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+
+		pluginManager.shutdown();
+		Worker.shutdown();
+	}
+
+	public void loadPlugin(URI uri) {
+		pluginManager.addPluginsFrom(uri);
+	}
+
+	public void openProject(Project project) {
+		if (mainViewController == null) {
+			mainViewController = new MainViewController(project, mainViewListeners);
+		} else {
+			mainViewController.setProject(project);
+		}
+	}
+}
diff --git a/PlayWall/src/de/tobias/playpad/PlayPadMain.java b/PlayWall/src/de/tobias/playpad/PlayPadMain.java
index bf8a5d0b81730e75c89f59269db88722e2b2297d..a399f8561daefd030f8207f3db9cedea6ae18af1 100644
--- a/PlayWall/src/de/tobias/playpad/PlayPadMain.java
+++ b/PlayWall/src/de/tobias/playpad/PlayPadMain.java
@@ -1,20 +1,12 @@
 package de.tobias.playpad;
 
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
 import java.net.MalformedURLException;
-import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
 import java.util.Locale;
 import java.util.Optional;
 import java.util.ResourceBundle;
-import java.util.Set;
 import java.util.UUID;
 
 import de.tobias.playpad.action.ActionRegistery;
@@ -42,9 +34,6 @@ import de.tobias.playpad.pad.content.AudioContentConnect;
 import de.tobias.playpad.pad.drag.MoveDragMode;
 import de.tobias.playpad.pad.drag.PadDragModeRegistery;
 import de.tobias.playpad.pad.drag.ReplaceDragMode;
-import de.tobias.playpad.plugin.PadListener;
-import de.tobias.playpad.plugin.SettingsListener;
-import de.tobias.playpad.plugin.WindowListener;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.ProjectReference;
 import de.tobias.playpad.settings.Profile;
@@ -53,14 +42,12 @@ import de.tobias.playpad.settings.ProfileReference;
 import de.tobias.playpad.tigger.TriggerRegistry;
 import de.tobias.playpad.trigger.CartTriggerItemConnect;
 import de.tobias.playpad.trigger.VolumeTriggerItemConnect;
+import de.tobias.playpad.update.PlayPadUpdater;
+import de.tobias.playpad.update.UpdateRegistery;
+import de.tobias.playpad.update.Updates;
 import de.tobias.playpad.view.MapperOverviewViewController;
-import de.tobias.playpad.viewcontroller.IPadSettingsViewController;
-import de.tobias.playpad.viewcontroller.ISettingsViewController;
 import de.tobias.playpad.viewcontroller.LaunchDialog;
 import de.tobias.playpad.viewcontroller.dialog.ChangelogDialog;
-import de.tobias.playpad.viewcontroller.main.IMainViewController;
-import de.tobias.playpad.viewcontroller.main.MainViewController;
-import de.tobias.playpad.viewcontroller.option.UpdateTabViewController;
 import de.tobias.utils.application.App;
 import de.tobias.utils.application.ApplicationUtils;
 import de.tobias.utils.application.container.PathType;
@@ -68,6 +55,8 @@ import de.tobias.utils.ui.ViewController;
 import de.tobias.utils.util.ConsoleUtils;
 import de.tobias.utils.util.Localization;
 import de.tobias.utils.util.Localization.LocalizationDelegate;
+import de.tobias.utils.util.OS;
+import de.tobias.utils.util.OS.OSType;
 import de.tobias.utils.util.Worker;
 import javafx.application.Application;
 import javafx.application.Platform;
@@ -76,8 +65,6 @@ import javafx.scene.control.Alert.AlertType;
 import javafx.scene.control.ButtonType;
 import javafx.scene.image.Image;
 import javafx.stage.Stage;
-import net.xeoh.plugins.base.PluginManager;
-import net.xeoh.plugins.base.impl.PluginManagerFactory;
 
 /*
  * TODOS
@@ -91,7 +78,6 @@ import net.xeoh.plugins.base.impl.PluginManagerFactory;
 
 // Profile mit UUID
 
-
 // Pad System neu machen
 // Neue PadViewController für jedes pad
 // Midi Modell Überarbeiten
@@ -99,45 +85,38 @@ import net.xeoh.plugins.base.impl.PluginManagerFactory;
 
 // TEST Trigger
 
-
-
 // PlayWall 5.1
 // FEATURE Global Volume Trigger mit x% und 100%
 // FEATURE Option bei Import Media auch Copy Media in Library
 // FEATURE lnk für Windows mit Dateiparameter
 // FEATURE Backups irgendwann löschen
 
-public class PlayPadMain extends Application implements LocalizationDelegate, PlayPad, ProfileListener {
+public class PlayPadMain extends Application implements LocalizationDelegate, ProfileListener {
 
-	private static final String PLUGIN_INFO_TXT = "pluginInfo.txt";
 	private static final String iconPath = "icon_small.png";
 	public static Optional<Image> stageIcon = Optional.empty();
 
 	public static final long displayTimeMillis = 1500;
 
-	public static final String[] projectType = { "*.xml" };
-	public static final String[] projectZIPType = { "*.zip" };
-	public static final String[] midiPresetType = { "*.pre" };
+	public static final String projectType = "*.xml";
+	public static final String projectZIPType = "*.zip";
+	public static final String midiPresetType = "*.pre";
 
 	private static ResourceBundle uiResourceBundle;
-	private static MainViewController mainViewController;
 
+	private static PlayPadImpl impl;
 	private static PlayPadUpdater updater;
-	private static Set<Path> deletedPlugins = new HashSet<>();
-
-	public static void addDeletedPlugin(Path path) {
-		deletedPlugins.add(path);
-	}
-
-	/*
-	 * 
-	 */
 
 	public static ResourceBundle getUiResourceBundle() {
 		return uiResourceBundle;
 	}
 
 	public static void main(String[] args) throws Exception {
+		// Verhindert einen Bug unter Windows 10 mit comboboxen
+		if (OS.getType() == OSType.Windows) {
+			System.setProperty("glass.accessible.force", "false");
+		}
+
 		// Debug
 		System.setOut(ConsoleUtils.convertStream(System.out, "[PlayWall] "));
 		System.setErr(ConsoleUtils.convertStream(System.err, "[PlayWall] "));
@@ -147,11 +126,10 @@ public class PlayPadMain extends Application implements LocalizationDelegate, Pl
 		app.start(args);
 	}
 
-	private static PluginManager pluginManager;
-
 	@Override
 	public void init() throws Exception {
-		PlayPadPlugin.setImplementation(this);
+		impl = new PlayPadImpl();
+		PlayPadPlugin.setImplementation(impl);
 
 		// Localization
 		setupLocalization();
@@ -177,7 +155,15 @@ public class PlayPadMain extends Application implements LocalizationDelegate, Pl
 		updater = new PlayPadUpdater();
 		UpdateRegistery.registerUpdateable(updater);
 		registerComponents();
-		setupPlugins();
+
+		// Load Plugin Path
+		Path pluginFolder;
+		if (getParameters().getNamed().containsKey("plugin")) {
+			pluginFolder = Paths.get(getParameters().getNamed().get("plugin"));
+		} else {
+			pluginFolder = ApplicationUtils.getApplication().getPath(PathType.LIBRARY);
+		}
+		setupPlugins(pluginFolder);
 
 		/*
 		 * Load Data
@@ -196,7 +182,7 @@ public class PlayPadMain extends Application implements LocalizationDelegate, Pl
 		if (getParameters().getRaw().size() > 0) {
 			try {
 				UUID uuid = UUID.fromString(getParameters().getNamed().get("project"));
-				launchProject(Project.load(ProjectReference.getProject(uuid), true, null));
+				impl.openProject(Project.load(ProjectReference.getProject(uuid), true, null));
 				return;
 			} catch (IllegalArgumentException | NullPointerException e) {} catch (Exception e) {
 				e.printStackTrace();
@@ -204,7 +190,6 @@ public class PlayPadMain extends Application implements LocalizationDelegate, Pl
 		}
 
 		ViewController.create(LaunchDialog.class, stage);
-
 	}
 
 	@Override
@@ -216,27 +201,13 @@ public class PlayPadMain extends Application implements LocalizationDelegate, Pl
 			e.printStackTrace(); // Speichern Fehler
 		}
 
+		// Shutdown components
+		// TODO use AutoCloseable
 		TinyAudioHandler.shutdown();
 		ClipAudioHandler.shutdown();
 
-		pluginManager.shutdown();
-
-		Path pluginInfoPath = ApplicationUtils.getApplication().getPath(PathType.LIBRARY, PLUGIN_INFO_TXT);
-		try {
-			if (Files.notExists(pluginInfoPath)) {
-				Files.createDirectories(pluginInfoPath.getParent());
-				Files.createFile(pluginInfoPath);
-			}
-			PrintWriter deleteWriter = new PrintWriter(Files.newOutputStream(pluginInfoPath));
-			for (Path path : deletedPlugins) {
-				deleteWriter.println(path.toString());
-			}
-			deleteWriter.close();
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
+		impl.shutdown();
 
-		Worker.shutdown();
 		Platform.exit();
 		System.exit(0);
 	}
@@ -281,31 +252,12 @@ public class PlayPadMain extends Application implements LocalizationDelegate, Pl
 		Profile.registerListener(this);
 	}
 
-	private void setupPlugins() throws IOException, MalformedURLException {
-		/*
-		 * Plugins
-		 */
-		Path pluginInfoPath = ApplicationUtils.getApplication().getPath(PathType.LIBRARY, PLUGIN_INFO_TXT);
-
-		// Delete Plugin
-		if (Files.exists(pluginInfoPath)) {
-			BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(pluginInfoPath)));
-			String line;
-			while ((line = reader.readLine()) != null) {
-				Path plugin = Paths.get(line);
-				Files.deleteIfExists(plugin);
-			}
-			reader.close();
-			Files.delete(pluginInfoPath);
-		}
+	private void setupPlugins(Path pluginPath) throws IOException, MalformedURLException {
+		// Delete old plugins
+		impl.deletePlugins();
 
 		// Load Plugins
-		pluginManager = PluginManagerFactory.createPluginManager();
-		if (ApplicationUtils.getApplication().isDebug())
-			// DEBUG PLUGINS EINBINDEN
-			pluginManager.addPluginsFrom(Paths.get("/Users/tobias/Documents/Programmieren/Java/eclipse/PlayWallPlugins/bin/").toUri());
-		else
-			pluginManager.addPluginsFrom(ApplicationUtils.getApplication().getPath(PathType.LIBRARY).toUri());
+		impl.loadPlugin(pluginPath.toUri());
 	}
 
 	private void setupLocalization() {
@@ -315,17 +267,16 @@ public class PlayPadMain extends Application implements LocalizationDelegate, Pl
 		uiResourceBundle = Localization.loadBundle("de/tobias/playpad/assets/lang/ui", getClass().getClassLoader());
 	}
 
-	public static void launchProject(Project project) {
-		mainViewController = new MainViewController(project, mainViewListeners, pluginManager);
-	}
-
+	/**
+	 * Handle Auto Update on profile reload
+	 */
 	@Override
-	public void reloadSettings(Profile oldProfile, Profile currentProfile) {
+	public void reloadSettings(Profile oldProfile, Profile newProfile) {
 		// Update PlayWall
-		if (currentProfile.getProfileSettings().isAutoUpdate()) {
+		if (newProfile.getProfileSettings().isAutoUpdate()) {
 			Worker.runLater(() ->
 			{
-				UpdateRegistery.lookupUpdates();
+				UpdateRegistery.lookupUpdates(newProfile.getProfileSettings().getUpdateChannel());
 				if (!UpdateRegistery.getAvailableUpdates().isEmpty()) {
 					Platform.runLater(() ->
 					{
@@ -334,7 +285,11 @@ public class PlayPadMain extends Application implements LocalizationDelegate, Pl
 						alert.setContentText(Localization.getString(Strings.UI_Dialog_AutoUpdate_Content));
 						alert.showAndWait().filter(item -> item == ButtonType.OK).ifPresent(result ->
 						{
-							UpdateTabViewController.update(null);
+							try {
+								Updates.startUpdate();
+							} catch (IOException e) {
+								e.printStackTrace();
+							}
 						});
 					});
 				}
@@ -352,107 +307,15 @@ public class PlayPadMain extends Application implements LocalizationDelegate, Pl
 		return Locale.getDefault();
 	}
 
-	/*
-	 * Plugins
+	/**
+	 * Gibt die Implementierung des Peers für Plugins zurück.
+	 * 
+	 * @return Schnittstelle
+	 * 
+	 * @see PlayPad
 	 */
-	protected static List<WindowListener<IMainViewController>> mainViewListeners = new ArrayList<>();
-	protected static List<WindowListener<ISettingsViewController>> settingsViewListeners = new ArrayList<>();
-	protected static List<WindowListener<IPadSettingsViewController>> padSettingsViewListeners = new ArrayList<>();
-	protected static List<SettingsListener> settingsListeners = new ArrayList<>();
-	protected static List<PadListener> padListeners = new ArrayList<>();
-
-	@Override
-	public void addMainViewListener(WindowListener<IMainViewController> listener) {
-		mainViewListeners.add(listener);
-	}
-
-	@Override
-	public void removeMainViewListener(WindowListener<IMainViewController> listener) {
-		mainViewListeners.remove(listener);
-	}
-
-	@Override
-	public void addSettingsViewListener(WindowListener<ISettingsViewController> listener) {
-		settingsViewListeners.add(listener);
-	}
-
-	@Override
-	public void removeSettingsViewListener(WindowListener<ISettingsViewController> listener) {
-		settingsViewListeners.remove(listener);
-	}
-
-	@Override
-	public List<WindowListener<ISettingsViewController>> getSettingsViewListener() {
-		return settingsViewListeners;
-	}
-
-	@Override
-	public void addPadSettingsViewListener(WindowListener<IPadSettingsViewController> listener) {
-		padSettingsViewListeners.add(listener);
-	}
-
-	@Override
-	public void removePadSettingsViewListener(WindowListener<IPadSettingsViewController> listener) {
-		padSettingsViewListeners.remove(listener);
-	}
-
-	@Override
-	public List<WindowListener<IPadSettingsViewController>> getPadSettingsViewListener() {
-		return padSettingsViewListeners;
-	}
-
-	@Override
-	public void addSettingsListener(SettingsListener listener) {
-		settingsListeners.add(listener);
-	}
-
-	@Override
-	public void removeSettingsListener(SettingsListener listener) {
-		settingsListeners.remove(listener);
-	}
-
-	@Override
-	public List<SettingsListener> getSettingsListener() {
-		return settingsListeners;
-	}
-
-	@Override
-	public void addPadListener(PadListener listener) {
-		padListeners.add(listener);
-	}
-
-	@Override
-	public void removePadListener(PadListener listener) {
-		padListeners.remove(listener);
-	}
-
-	@Override
-	public List<PadListener> getPadListener() {
-		return padListeners;
-	}
-
-	@Override
-	public IMainViewController getMainViewController() {
-		return mainViewController;
-	}
-
-	@Override
-	public PluginManager getPluginManager() {
-		return pluginManager;
-	}
-
-	@Override
-	public String[] getProjectFiles() {
-		return projectType;
-	}
-
-	@Override
-	public Optional<Image> getIcon() {
-		return stageIcon;
-	}
-
-	public static Updatable getUpdater() {
-		return updater;
+	public static PlayPadImpl getProgramInstance() {
+		return impl;
 	}
 
-}
+}
\ No newline at end of file
diff --git a/PlayWall/src/de/tobias/playpad/Strings.java b/PlayWall/src/de/tobias/playpad/Strings.java
index 6443c76d18ff5e5ca372785b6f31588b6eeec5da..57939d09a2c2bce4bdf1d6224442c71a52bc7070 100644
--- a/PlayWall/src/de/tobias/playpad/Strings.java
+++ b/PlayWall/src/de/tobias/playpad/Strings.java
@@ -22,6 +22,7 @@ public class Strings {
 	public static final String UI_Window_Changelog_Title = "UI.Window.Changelog.Title";
 	public static final String UI_Window_Settings_Title = "UI.Window.Settings.Title";
 	public static final String UI_Window_PadSettings_Title = "UI.Window.PadSettings.Title";
+	public static final String UI_Window_PadSettings_Title_Empty = "UI.Window.PadSettings.Title.Empty";
 	public static final String UI_Dialog_DragAndDrop_Title = "UI.Dialog.DragAndDrop.Title";
 	public static final String UI_Dialog_ProjectExport_Title = "UI.Dialog.ProjectExport.Title";
 	public static final String UI_Dialog_ErrorSummary_Title = "UI.Dialog.ErrorSummary.Title";
@@ -155,10 +156,7 @@ public class Strings {
 
 	// Error - Plugins
 	@Deprecated public static final String Error_Plugins_Download = "Error.Plugins.Download";
-
-	/*
-	 * NEU
-	 */
+	public static final String Error_Plugins_Available = "Error.Plugins.Available";
 
 	// Mapper
 	public static final String Mapper_Keyboard_Name = "Mapper.Keyboard.Name";
@@ -197,16 +195,18 @@ public class Strings {
 	public static final String UI_Dialog_AutoUpdate_Header = "UI.Dialog.AutoUpdate.Header";
 	public static final String UI_Dialog_AutoUpdate_Content = "UI.Dialog.AutoUpdate.Content";
 
+	// Update Channel - Basename
+	public static final String Update_Channel_BaseName = "UpdateChannel.";
+
 	// Error - Layout
 	public static final String Error_Layout_Load = "Error.Layout.Load";
 
 	// UI - Dialog - Update
 	public static final String UI_Dialog_Update_Cell = "UI.Dialog.Update.Cell";
 	public static final String UI_Window_Settings_Updates_CurrentVersion = "UI.Window.Settings.Updates.CurrentVersion";
-	public static final String UI_Window_Settings_Updates_NewVersion = "UI.Window.Settings.Updates.NewVersion";
 
 	// Error - Update - Downlaod
-	public static final String Error_Update_Download = "Error.Update.Download";
+	@Deprecated public static final String Error_Update_Download = "Error.Update.Download";
 
 	// Layout
 	public static final String Layout_Modern_Name = "Layout.Modern.Name";
@@ -219,7 +219,7 @@ public class Strings {
 
 	// TriggerPoint - Enum
 	public static final String TriggerPoint_BaseName = "TriggerPoint.";
-	
+
 	// Drag and Drop Mode
 	public static final String DnDMode_Move = "DnDMode.Move";
 	public static final String DnDMode_Replace = "DnDMode.Replace";
diff --git a/PlayWall/src/de/tobias/playpad/VersionUpdater.java b/PlayWall/src/de/tobias/playpad/VersionUpdater.java
index 66a4ce97325f1517ebdd15ce750102ea54354d3d..045a3e7e96923ead258ea4fe3155db83d020843a 100644
--- a/PlayWall/src/de/tobias/playpad/VersionUpdater.java
+++ b/PlayWall/src/de/tobias/playpad/VersionUpdater.java
@@ -19,6 +19,7 @@ import org.dom4j.io.SAXReader;
 import org.dom4j.io.XMLWriter;
 
 import de.tobias.playpad.action.Mapping;
+import de.tobias.playpad.action.MappingSerializer;
 import de.tobias.playpad.action.cartaction.CartAction;
 import de.tobias.playpad.action.cartaction.CartAction.ControlMode;
 import de.tobias.playpad.action.feedback.DoubleSimpleFeedback;
@@ -188,7 +189,9 @@ public class VersionUpdater implements UpdateService {
 
 		for (Mapping mapping : mappings) {
 			Element mappingElement = rootElement.addElement("Mapping");
-			mapping.save(mappingElement);
+
+			MappingSerializer mappingSerializer = new MappingSerializer();
+			mappingSerializer.saveElement(mappingElement, mapping);
 		}
 
 		XMLWriter writer = new XMLWriter(Files.newOutputStream(configPath.resolve("Mapping.xml")), OutputFormat.createPrettyPrint());
@@ -223,7 +226,8 @@ public class VersionUpdater implements UpdateService {
 				newSettingsElement.addElement("Loop").addText(oldPadElement.element("Loop").getStringValue());
 				if (oldPadElement.element("TimeMode") != null)
 					newSettingsElement.addElement("TimeMode").addText(oldPadElement.element("TimeMode").getStringValue());
-			} catch (Exception e) {}
+			} catch (Exception e) {
+			}
 		}
 
 		XMLWriter writer = new XMLWriter(Files.newOutputStream(path), OutputFormat.createPrettyPrint());
diff --git a/PlayWall/src/de/tobias/playpad/action/cartaction/PadPositionWarningListener.java b/PlayWall/src/de/tobias/playpad/action/cartaction/PadPositionWarningListener.java
index 7691158c4d971f4fb1b6fee394c93868e2da9a21..cd3d5a1021f4e379b978844636a7547ed5a8c4f2 100644
--- a/PlayWall/src/de/tobias/playpad/action/cartaction/PadPositionWarningListener.java
+++ b/PlayWall/src/de/tobias/playpad/action/cartaction/PadPositionWarningListener.java
@@ -2,8 +2,8 @@ package de.tobias.playpad.action.cartaction;
 
 import de.tobias.playpad.action.feedback.FeedbackMessage;
 import de.tobias.playpad.pad.Pad;
-import de.tobias.playpad.pad.Warning;
 import de.tobias.playpad.pad.conntent.Durationable;
+import de.tobias.playpad.settings.Warning;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 import javafx.util.Duration;
diff --git a/PlayWall/src/de/tobias/playpad/action/cartaction/PadStatusFeedbackListener.java b/PlayWall/src/de/tobias/playpad/action/cartaction/PadStatusFeedbackListener.java
index 5d1bb8c37cc82cd8189fc2c1821ef60fb723d0be..2dcc8211312456283a3ab3d6076a252f66ce5a50 100644
--- a/PlayWall/src/de/tobias/playpad/action/cartaction/PadStatusFeedbackListener.java
+++ b/PlayWall/src/de/tobias/playpad/action/cartaction/PadStatusFeedbackListener.java
@@ -4,7 +4,7 @@ import de.tobias.playpad.action.feedback.FeedbackMessage;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.pad.conntent.Durationable;
-import de.tobias.playpad.pad.Warning;
+import de.tobias.playpad.settings.Warning;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 import javafx.util.Duration;
diff --git a/PlayWall/src/de/tobias/playpad/audio/ClipAudioHandlerConnect.java b/PlayWall/src/de/tobias/playpad/audio/ClipAudioHandlerConnect.java
index b0428e4db1774e8be59177263e9308bd682ca5a6..e78e6895cc3a546dba104369f15f6e4ae96e80ee 100644
--- a/PlayWall/src/de/tobias/playpad/audio/ClipAudioHandlerConnect.java
+++ b/PlayWall/src/de/tobias/playpad/audio/ClipAudioHandlerConnect.java
@@ -4,7 +4,7 @@ import de.tobias.playpad.pad.conntent.PadContent;
 import de.tobias.playpad.viewcontroller.AudioTypeViewController;
 import de.tobias.playpad.viewcontroller.audio.ClipSettingsViewController;
 
-public class ClipAudioHandlerConnect extends AudioHandlerConnect {
+public class ClipAudioHandlerConnect extends AudioHandlerConnect implements AutoCloseable {
 
 	@Override
 	public AudioHandler createAudioHandler(PadContent content) {
@@ -15,5 +15,10 @@ public class ClipAudioHandlerConnect extends AudioHandlerConnect {
 	public AudioTypeViewController getAudioViewController() {
 		return new ClipSettingsViewController();
 	}
+	
+	@Override
+	public void close() throws Exception {
+		TinyAudioHandler.shutdown();
+	}
 
 }
diff --git a/PlayWall/src/de/tobias/playpad/audio/TinyAudioHandlerConnect.java b/PlayWall/src/de/tobias/playpad/audio/TinyAudioHandlerConnect.java
index 3c97f5f9288fd6981970433cdd61503952aac39d..c8e8904c0b953c3dfa3e99f7e162bbe5ca7cf6c4 100644
--- a/PlayWall/src/de/tobias/playpad/audio/TinyAudioHandlerConnect.java
+++ b/PlayWall/src/de/tobias/playpad/audio/TinyAudioHandlerConnect.java
@@ -4,7 +4,7 @@ import de.tobias.playpad.pad.conntent.PadContent;
 import de.tobias.playpad.viewcontroller.AudioTypeViewController;
 import de.tobias.playpad.viewcontroller.audio.TinySoundSettingsViewController;
 
-public class TinyAudioHandlerConnect extends AudioHandlerConnect {
+public class TinyAudioHandlerConnect extends AudioHandlerConnect implements AutoCloseable {
 
 	@Override
 	public AudioHandler createAudioHandler(PadContent content) {
@@ -16,4 +16,8 @@ public class TinyAudioHandlerConnect extends AudioHandlerConnect {
 		return new TinySoundSettingsViewController();
 	}
 
+	@Override
+	public void close() throws Exception {
+		TinyAudioHandler.shutdown();
+	}
 }
diff --git a/PlayWall/src/de/tobias/playpad/layout/classic/ClassicCartLayout.java b/PlayWall/src/de/tobias/playpad/layout/classic/ClassicCartLayout.java
index 7bd47b406ccf8aba5a185f690b9e0bcac2c31464..0e6d1952c35ea8cc7f3c8ad22c9ee122b1ffd996 100644
--- a/PlayWall/src/de/tobias/playpad/layout/classic/ClassicCartLayout.java
+++ b/PlayWall/src/de/tobias/playpad/layout/classic/ClassicCartLayout.java
@@ -15,8 +15,8 @@ import de.tobias.playpad.PseudoClasses;
 import de.tobias.playpad.layout.CartLayout;
 import de.tobias.playpad.layout.GlobalLayout;
 import de.tobias.playpad.layout.Layout;
-import de.tobias.playpad.pad.Warning;
 import de.tobias.playpad.pad.view.IPadViewController;
+import de.tobias.playpad.settings.Warning;
 import de.tobias.playpad.viewcontroller.IPadView;
 import de.tobias.utils.util.ColorXMLUtils;
 import javafx.application.Platform;
@@ -210,7 +210,7 @@ public class ClassicCartLayout extends Layout implements CartLayout {
 	}
 
 	@Override
-	public void handleWarning(IPadViewController controller, Warning warning) {
+	public void handleWarning(IPadViewController controller, Warning warning, GlobalLayout layout) {
 		final IPadView view = controller.getParent();
 
 		try {
diff --git a/PlayWall/src/de/tobias/playpad/layout/classic/ClassicGlobalLayout.java b/PlayWall/src/de/tobias/playpad/layout/classic/ClassicGlobalLayout.java
index 8618a813cab625a4dca5d5aa260e161fa59be595..2f067be0999ac96553b147d75bde2c479098014b 100644
--- a/PlayWall/src/de/tobias/playpad/layout/classic/ClassicGlobalLayout.java
+++ b/PlayWall/src/de/tobias/playpad/layout/classic/ClassicGlobalLayout.java
@@ -11,9 +11,9 @@ import de.tobias.playpad.layout.CartLayout;
 import de.tobias.playpad.layout.GlobalLayout;
 import de.tobias.playpad.layout.Layout;
 import de.tobias.playpad.pad.Pad;
-import de.tobias.playpad.pad.Warning;
 import de.tobias.playpad.pad.view.IPadViewController;
 import de.tobias.playpad.project.Project;
+import de.tobias.playpad.settings.Warning;
 import de.tobias.playpad.viewcontroller.IPadView;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import de.tobias.utils.application.ApplicationUtils;
diff --git a/PlayWall/src/de/tobias/playpad/layout/modern/ModernLayoutCart.java b/PlayWall/src/de/tobias/playpad/layout/modern/ModernLayoutCart.java
index cbc99d65840c46d882d609515f60dff71f9e85b0..123f41277e3ab741e7744047d36bddb17b92af9e 100644
--- a/PlayWall/src/de/tobias/playpad/layout/modern/ModernLayoutCart.java
+++ b/PlayWall/src/de/tobias/playpad/layout/modern/ModernLayoutCart.java
@@ -9,9 +9,9 @@ import de.tobias.playpad.layout.GlobalLayout;
 import de.tobias.playpad.layout.Layout;
 import de.tobias.playpad.layout.LayoutColorAssociator;
 import de.tobias.playpad.pad.Pad;
-import de.tobias.playpad.pad.Warning;
 import de.tobias.playpad.pad.conntent.Durationable;
 import de.tobias.playpad.pad.view.IPadViewController;
+import de.tobias.playpad.settings.Warning;
 import javafx.scene.paint.Color;
 import javafx.util.Duration;
 
@@ -25,8 +25,6 @@ public class ModernLayoutCart extends Layout implements CartLayout, LayoutColorA
 	private ModernColor backgroundColor = ModernColor.GRAY1;
 	private ModernColor playColor = ModernColor.RED3;
 
-	private boolean isWarnAnimation = true;
-
 	public ModernColor getBackgroundColor() {
 		return backgroundColor;
 	}
@@ -43,19 +41,9 @@ public class ModernLayoutCart extends Layout implements CartLayout, LayoutColorA
 		this.playColor = playColor;
 	}
 
-	public boolean isWarnAnimation() {
-		return isWarnAnimation;
-	}
-
-	public void setWarnAnimation(boolean isWarnAnimation) {
-		this.isWarnAnimation = isWarnAnimation;
-	}
-
 	public void reset() {
 		backgroundColor = ModernColor.GRAY1;
 		playColor = ModernColor.RED1;
-
-		isWarnAnimation = true;
 	}
 
 	@Override
@@ -77,28 +65,18 @@ public class ModernLayoutCart extends Layout implements CartLayout, LayoutColorA
 				e.printStackTrace();
 			}
 		}
-
-		Element animationElement = rootElement.element("Animation");
-		if (animationElement != null) {
-			Element warnAnimationElement = animationElement.element("Warn");
-			if (warnAnimationElement != null) {
-				isWarnAnimation = Boolean.valueOf(warnAnimationElement.getStringValue());
-			}
-		}
 	}
 
 	@Override
 	public void save(Element rootElement) {
 		rootElement.addElement("BackgroundColor").addText(backgroundColor.name());
 		rootElement.addElement("PlayColor").addText(playColor.name());
-		Element animationElement = rootElement.addElement("Animation");
-		animationElement.addElement("Warn").addText(String.valueOf(isWarnAnimation));
 	}
 
 	// Warn Handler -> Animation oder Blinken
 	@Override
-	public void handleWarning(IPadViewController controller, Warning warning) {
-		if (isWarnAnimation) {
+	public void handleWarning(IPadViewController controller, Warning warning, GlobalLayout layout) {
+		if (layout instanceof ModernLayoutGlobal && ((ModernLayoutGlobal) layout).isWarnAnimation()) {
 			warnAnimation(controller, warning);
 		} else {
 			ModernLayoutAnimator.warnFlash(controller);
@@ -204,7 +182,6 @@ public class ModernLayoutCart extends Layout implements CartLayout, LayoutColorA
 			ModernLayoutGlobal modernLayoutGlobal = (ModernLayoutGlobal) globalLayout;
 			backgroundColor = modernLayoutGlobal.getBackgroundColor();
 			playColor = modernLayoutGlobal.getPlayColor();
-			isWarnAnimation = modernLayoutGlobal.isWarnAnimation();
 		}
 	}
 }
diff --git a/PlayWall/src/de/tobias/playpad/layout/modern/ModernLayoutGlobal.java b/PlayWall/src/de/tobias/playpad/layout/modern/ModernLayoutGlobal.java
index 925b392b8eec6daefe124e45c52dd2861fa73f37..c8e79942e2a50cc747ce271d5a55ce805186cf45 100644
--- a/PlayWall/src/de/tobias/playpad/layout/modern/ModernLayoutGlobal.java
+++ b/PlayWall/src/de/tobias/playpad/layout/modern/ModernLayoutGlobal.java
@@ -13,11 +13,11 @@ import de.tobias.playpad.layout.GlobalLayout;
 import de.tobias.playpad.layout.Layout;
 import de.tobias.playpad.layout.LayoutColorAssociator;
 import de.tobias.playpad.pad.Pad;
-import de.tobias.playpad.pad.Warning;
 import de.tobias.playpad.pad.conntent.Durationable;
 import de.tobias.playpad.pad.view.IPadViewController;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.settings.Profile;
+import de.tobias.playpad.settings.Warning;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import de.tobias.utils.application.ApplicationUtils;
 import de.tobias.utils.application.container.PathType;
diff --git a/PlayWall/src/de/tobias/playpad/pad/listener/PadPositionListener.java b/PlayWall/src/de/tobias/playpad/pad/listener/PadPositionListener.java
index 9f582ea5782a13581240ccea9460638627ac5bcb..bdb5f35a716c1a17f448d408aa1cb5d004314f11 100644
--- a/PlayWall/src/de/tobias/playpad/pad/listener/PadPositionListener.java
+++ b/PlayWall/src/de/tobias/playpad/pad/listener/PadPositionListener.java
@@ -2,11 +2,11 @@ package de.tobias.playpad.pad.listener;
 
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadStatus;
-import de.tobias.playpad.pad.Warning;
 import de.tobias.playpad.pad.conntent.Durationable;
 import de.tobias.playpad.pad.conntent.Fadeable;
 import de.tobias.playpad.pad.conntent.PadContent;
 import de.tobias.playpad.settings.Profile;
+import de.tobias.playpad.settings.Warning;
 import de.tobias.playpad.viewcontroller.pad.PadViewController;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
@@ -88,7 +88,7 @@ public class PadPositionListener implements ChangeListener<Duration>, Runnable {
 		Warning warning = pad.getWarning();
 
 		if (pad.isCustomLayout()) {
-			pad.getLayout().handleWarning(controller, warning);
+			pad.getLayout().handleWarning(controller, warning, Profile.currentProfile().currentLayout());
 		} else {
 			Profile.currentProfile().currentLayout().handleWarning(controller, warning);
 		}
diff --git a/PlayWall/src/de/tobias/playpad/PlayPadUpdater.java b/PlayWall/src/de/tobias/playpad/update/PlayPadUpdater.java
similarity index 62%
rename from PlayWall/src/de/tobias/playpad/PlayPadUpdater.java
rename to PlayWall/src/de/tobias/playpad/update/PlayPadUpdater.java
index be3582a6293243e6558a733e46fb16159bed89a5..f7d3c16f59e26a6e2b604215d50327333c54c2db 100644
--- a/PlayWall/src/de/tobias/playpad/PlayPadUpdater.java
+++ b/PlayWall/src/de/tobias/playpad/update/PlayPadUpdater.java
@@ -1,4 +1,4 @@
-package de.tobias.playpad;
+package de.tobias.playpad.update;
 
 import java.io.IOException;
 import java.net.URISyntaxException;
@@ -8,6 +8,8 @@ import java.nio.file.Path;
 import org.bukkit.configuration.file.FileConfiguration;
 import org.bukkit.configuration.file.YamlConfiguration;
 
+import de.tobias.playpad.update.Updatable;
+import de.tobias.playpad.update.UpdateChannel;
 import de.tobias.utils.application.App;
 import de.tobias.utils.application.ApplicationUtils;
 import de.tobias.utils.util.SystemUtils;
@@ -30,47 +32,36 @@ public class PlayPadUpdater implements Updatable {
 
 	@Override
 	public int getNewBuild() {
-		if (newBuild == 0) {
-			checkUpdate();
-		}
 		return newBuild;
 	}
 
 	@Override
 	public String getNewVersion() {
-		if (newVersion == null) {
-			checkUpdate();
-		}
 		return newVersion;
 	}
 
 	@Override
-	public boolean checkUpdate() {
+	public void loadInformation(UpdateChannel channel) throws IOException, URISyntaxException {
 		App app = ApplicationUtils.getMainApplication();
-		try {
-			URL url = new URL(app.getInfo().getUpdateURL() + "/version.yml");
-			FileConfiguration config = YamlConfiguration.loadConfiguration(url.openStream());
-			newBuild = config.getInt("build");
-			newVersion = config.getString("version");
-
-			if (SystemUtils.isExe()) {
-				remotePath = new URL(config.getString("pathExe"));
-			} else {
-				remotePath = new URL(config.getString("pathJar"));				
-			}
-			
-			return getCurrentBuild() < getNewBuild();
-		} catch (IOException | URISyntaxException e) {
-			e.printStackTrace();
+		URL url = new URL(app.getInfo().getUpdateURL() + "/" + channel + "/version.yml");
+		FileConfiguration config = YamlConfiguration.loadConfiguration(url.openStream());
+		newBuild = config.getInt("build");
+		newVersion = config.getString("version");
+
+		if (SystemUtils.isExe() && channel == UpdateChannel.STABLE) { // EXE only for stable release
+			remotePath = new URL(config.getString("pathExe"));
+		} else {
+			remotePath = new URL(config.getString("pathJar"));
 		}
-		return false;
+	}
+
+	@Override
+	public boolean isUpdateAvailable() {
+		return getCurrentBuild() < getNewBuild();
 	}
 
 	@Override
 	public URL getDownloadPath() {
-		if (remotePath == null) {
-			checkUpdate();
-		}
 		return remotePath;
 	}
 
diff --git a/PlayWall/src/de/tobias/playpad/update/Updates.java b/PlayWall/src/de/tobias/playpad/update/Updates.java
new file mode 100644
index 0000000000000000000000000000000000000000..a507e8d4b28ca862fb5a59a0dbf9248366f4145e
--- /dev/null
+++ b/PlayWall/src/de/tobias/playpad/update/Updates.java
@@ -0,0 +1,125 @@
+package de.tobias.playpad.update;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import de.tobias.playpad.AppUserInfoStrings;
+import de.tobias.utils.application.App;
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.NativeLauncher;
+import de.tobias.utils.application.container.PathType;
+import de.tobias.utils.util.IOUtils;
+import de.tobias.utils.util.OS;
+import javafx.application.Platform;
+
+public class Updates {
+
+	// Ornder im App-Folder wo Updates zwischengespeichert werden sollen.
+	private static final String CACHE_FOLER = "Updates";
+
+	// Name der Updater Datei
+	private static String JAR_NAME = "PlayWallUp.jar";
+	private static String EXE_NAME = "PlayWallUp.exe";
+
+	/**
+	 * Sollte in einem Extra Thread gemacht werden, da der Updater gedownloaded wird.
+	 * 
+	 * @throws IOException
+	 */
+	public static void startUpdate() throws IOException {
+		App app = ApplicationUtils.getApplication();
+		String downloadPath = app.getPath(PathType.DOWNLOAD, CACHE_FOLER).toString();
+		String updateParameter = UpdateRegistery.buildParamaterString(downloadPath);
+
+		boolean successfulStartUpdate = false;
+
+		// Start des Update Prozesses
+		if (OS.isWindows()) {
+			successfulStartUpdate = updateWindows(updateParameter, UpdateRegistery.needsAdminPermission());
+		} else if (OS.isMacOS()) {
+			successfulStartUpdate = updateMacOS(updateParameter);
+		}
+
+		if (successfulStartUpdate) {
+			// Kill the program
+			Platform.exit();
+			System.exit(0);
+		}
+	}
+
+	private static boolean updateWindows(String parameter, boolean needAdminPermission) throws IOException {
+		Path path = searchForFile(EXE_NAME);
+		if (path == null) {
+			App app = ApplicationUtils.getApplication();
+
+			String updaterURL = app.getInfo().getUserInfo().get(AppUserInfoStrings.UPDATER_PROGRAM) + EXE_NAME;
+			path = ApplicationUtils.getApplication().getPath(PathType.DOWNLOAD, EXE_NAME);
+
+			downloadUpdater(updaterURL, path);
+		}
+		startExeFile(parameter, path, needAdminPermission);
+		return false;
+	}
+
+	private static boolean updateMacOS(String parameter) throws IOException {
+		Path path = searchForFile(JAR_NAME);
+		if (path == null) {
+			App app = ApplicationUtils.getApplication();
+
+			String updaterURL = app.getInfo().getUserInfo().get(AppUserInfoStrings.UPDATER_PROGRAM) + JAR_NAME;
+			path = ApplicationUtils.getApplication().getPath(PathType.DOWNLOAD, JAR_NAME);
+
+			downloadUpdater(updaterURL, path);
+		}
+		startJarFile(parameter, path);
+		return false;
+	}
+
+	private static void downloadUpdater(String updaterURL, Path path) throws IOException, MalformedURLException {
+		URL url = new URL(updaterURL);
+		InputStream iStr = url.openStream();
+		
+		if (Files.notExists(path)) {
+			Files.createDirectories(path.getParent());
+		}
+
+		IOUtils.copy(iStr, path);
+
+		iStr.close();
+	}
+
+	private static void startExeFile(String parameter, Path fileExe, boolean needAdminPermission) throws IOException {
+		if (needAdminPermission) {
+			NativeLauncher.executeAsAdministrator(fileExe.toAbsolutePath().toString(), parameter);
+		} else {
+			ProcessBuilder builder = new ProcessBuilder(fileExe.toAbsolutePath().toString(), parameter);
+			builder.start();
+		}
+
+		System.exit(0);
+	}
+
+	private static Path searchForFile(String name) {
+		Path file = Paths.get(name);
+		Path fileFolder = ApplicationUtils.getApplication().getPath(PathType.DOWNLOAD, name);
+
+		if (Files.exists(file)) {
+			return file;
+		} else if (Files.exists(fileFolder)) {
+			return fileFolder;
+		}
+		return null;
+	}
+
+	private static void startJarFile(String parameter, Path fileJar) throws IOException {
+		ProcessBuilder builder = new ProcessBuilder("java", "-jar", fileJar.toAbsolutePath().toString(), parameter);
+		builder.start();
+		System.exit(0);
+	}
+
+}
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/LaunchDialog.java b/PlayWall/src/de/tobias/playpad/viewcontroller/LaunchDialog.java
index 5f8e136bf1618202be24fb22469fdfd4f2636195..a1aa93939d236d0703ecfb71a8e02581e609fa3a 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/LaunchDialog.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/LaunchDialog.java
@@ -1,8 +1,13 @@
 package de.tobias.playpad.viewcontroller;
 
+import static de.tobias.utils.util.Localization.getString;
+
 import java.io.File;
+import java.io.IOException;
 import java.nio.file.Path;
 
+import org.dom4j.DocumentException;
+
 import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.project.ProfileChooseable;
@@ -19,8 +24,6 @@ import de.tobias.playpad.viewcontroller.dialog.ProfileChooseDialog;
 import de.tobias.utils.application.App;
 import de.tobias.utils.application.ApplicationUtils;
 import de.tobias.utils.ui.ViewController;
-import de.tobias.utils.util.Localization;
-import de.tobias.utils.util.Worker;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.scene.control.Alert;
@@ -59,7 +62,9 @@ public class LaunchDialog extends ViewController implements ProfileChooseable {
 	@Override
 	public void init() {
 		App app = ApplicationUtils.getApplication();
-		infoLabel.setText(Localization.getString(Strings.UI_Dialog_Launch_Info, app.getInfo().getName(), app.getInfo().getVersion()));
+
+		// Setup launchscreen labels and image
+		infoLabel.setText(getString(Strings.UI_Dialog_Launch_Info, app.getInfo().getName(), app.getInfo().getVersion()));
 		try {
 			imageView.setImage(new Image(IMAGE));
 		} catch (Exception e) {
@@ -69,10 +74,12 @@ public class LaunchDialog extends ViewController implements ProfileChooseable {
 		openButton.setDisable(true);
 		deleteButton.setDisable(true);
 
-		projectListView.setPlaceholder(new Label(Localization.getString(Strings.UI_Placeholder_Project)));
+		// Load project to list
+		projectListView.setPlaceholder(new Label(getString(Strings.UI_Placeholder_Project)));
 		projectListView.setId("list");
 		projectListView.setCellFactory(list -> new ProjectCell());
 
+		// List selection listener
 		projectListView.getSelectionModel().selectedItemProperty().addListener((a, b, c) ->
 		{
 			openButton.setDisable(c == null);
@@ -85,8 +92,7 @@ public class LaunchDialog extends ViewController implements ProfileChooseable {
 			if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {
 				if (mouseEvent.getClickCount() == 2) {
 					if (!projectListView.getSelectionModel().isEmpty()) {
-						ProjectReference ref = projectListView.getSelectionModel().getSelectedItem();
-						launchProject(ref);
+						launchProject(getSelectedProject());
 					}
 				}
 			}
@@ -98,14 +104,9 @@ public class LaunchDialog extends ViewController implements ProfileChooseable {
 		setCSS("style.css", "de/tobias/playpad/assets/");
 		setCSS("launchDialog_style.css", "de/tobias/playpad/assets/style/");
 
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_Launch_Title));
+		stage.setTitle(getString(Strings.UI_Dialog_Launch_Title));
 		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
-
-		stage.setOnCloseRequest(e ->
-		{
-			Worker.shutdown();
-		});
-
+		
 		stage.setResizable(false);
 		stage.setWidth(650);
 		stage.show();
@@ -118,7 +119,7 @@ public class LaunchDialog extends ViewController implements ProfileChooseable {
 
 		Project project = dialog.getProject();
 		if (project != null) {
-			PlayPadMain.launchProject(project);
+			PlayPadMain.getProgramInstance().openProject(project);
 			getStage().close();
 		}
 	}
@@ -126,19 +127,18 @@ public class LaunchDialog extends ViewController implements ProfileChooseable {
 	@FXML
 	private void importProfileButtonHandler(ActionEvent event) {
 		FileChooser chooser = new FileChooser();
-		chooser.getExtensionFilters()
-				.add(new ExtensionFilter(Localization.getString(Strings.File_Filter_ZIP), PlayPadMain.projectZIPType));
+		chooser.getExtensionFilters().add(new ExtensionFilter(getString(Strings.File_Filter_ZIP), PlayPadMain.projectZIPType));
 		File file = chooser.showOpenDialog(getStage());
 		if (file != null) {
 			Path zipFile = file.toPath();
 			try {
-				ProjectReference ref = ProjectImporter.importProject(zipFile, ImportDialog.getInstance(getStage()),
-						ImportDialog.getInstance(getStage()));
+				ImportDialog importDialog = ImportDialog.getInstance(getStage());
+				ProjectReference ref = ProjectImporter.importProject(zipFile, importDialog, importDialog);
 				if (ref != null) {
 					launchProject(ref);
 				}
-			} catch (Exception e) {
-				showErrorMessage(Localization.getString(Strings.Error_Project_Open, e.getLocalizedMessage()));
+			} catch (DocumentException | IOException e) {
+				showErrorMessage(getString(Strings.Error_Project_Open, e.getLocalizedMessage()));
 				e.printStackTrace();
 			}
 		}
@@ -146,36 +146,16 @@ public class LaunchDialog extends ViewController implements ProfileChooseable {
 
 	@FXML
 	private void openButtonHandler(ActionEvent event) {
-		ProjectReference ref = projectListView.getSelectionModel().getSelectedItem();
-		try {
-			if (ref != null) {
-				Project project = Project.load(ref, true, this);
-				PlayPadMain.launchProject(project);
-				getStage().close();
-			}
-		} catch (ProfileNotFoundException e) {
-			e.printStackTrace();
-			showErrorMessage(Localization.getString(Strings.Error_Profile_NotFound, ref.getProfileReference(), e.getLocalizedMessage()));
-
-			// Neues Profile wählen
-			Profile profile = getUnkownProfile();
-			ref.setProfileReference(profile.getRef());
-		} catch (ProjectNotFoundException e) {
-			e.printStackTrace();
-			showErrorMessage(Localization.getString(Strings.Error_Project_NotFound, ref, e.getLocalizedMessage()));
-		} catch (Exception e) {
-			e.printStackTrace();
-			showErrorMessage(Localization.getString(Strings.Error_Project_Open, ref, e.getLocalizedMessage()));
-		}
+		launchProject(getSelectedProject());
 	}
 
 	@FXML
 	private void deleteButtonHandler(ActionEvent event) {
-		if (projectListView.getSelectionModel().getSelectedItem() != null) {
-			ProjectReference ref = projectListView.getSelectionModel().getSelectedItem();
+		if (getSelectedProject() != null) {
+			ProjectReference ref = getSelectedProject();
 
 			Alert alert = new Alert(AlertType.CONFIRMATION);
-			alert.setContentText(Localization.getString(Strings.UI_Dialog_ProjectManager_Delete_Content, ref));
+			alert.setContentText(getString(Strings.UI_Dialog_ProjectManager_Delete_Content, ref));
 
 			Stage dialog = (Stage) alert.getDialogPane().getScene().getWindow();
 			PlayPadMain.stageIcon.ifPresent(dialog.getIcons()::add);
@@ -187,34 +167,50 @@ public class LaunchDialog extends ViewController implements ProfileChooseable {
 				try {
 					ProjectReference.removeDocument(ref);
 					projectListView.getItems().remove(ref); // VIEW
-				} catch (Exception e) {
-					showErrorMessage(Localization.getString(Strings.Error_Project_Delete, e.getLocalizedMessage()));
+				} catch (DocumentException | IOException e) {
+					showErrorMessage(getString(Strings.Error_Project_Delete, e.getLocalizedMessage()));
 				}
 			});
 		}
 	}
 
+	/**
+	 * Gibt das ausgewählte Projekt zurück.
+	 * 
+	 * @return Projekt
+	 */
+	private ProjectReference getSelectedProject() {
+		return projectListView.getSelectionModel().getSelectedItem();
+	}
+
+	/**
+	 * Launch a project and close this view.
+	 * 
+	 * @param ref
+	 *            Project to launch
+	 */
 	private void launchProject(ProjectReference ref) {
 		try {
 			Project project = Project.load(ref, true, this);
-			PlayPadMain.launchProject(project);
+			PlayPadMain.getProgramInstance().openProject(project);
 			getStage().close();
 		} catch (ProfileNotFoundException e) {
 			e.printStackTrace();
-			showErrorMessage(Localization.getString(Strings.Error_Profile_NotFound, ref.getProfileReference(), e.getLocalizedMessage()));
+			showErrorMessage(getString(Strings.Error_Profile_NotFound, ref.getProfileReference(), e.getLocalizedMessage()));
 
 			// Neues Profile wählen
 			Profile profile = getUnkownProfile();
 			ref.setProfileReference(profile.getRef());
 		} catch (ProjectNotFoundException e) {
 			e.printStackTrace();
-			showErrorMessage(Localization.getString(Strings.Error_Project_NotFound, ref, e.getLocalizedMessage()));
+			showErrorMessage(getString(Strings.Error_Project_NotFound, ref, e.getLocalizedMessage()));
 		} catch (Exception e) {
 			e.printStackTrace();
-			showErrorMessage(Localization.getString(Strings.Error_Project_Open, ref, e.getLocalizedMessage()));
+			showErrorMessage(getString(Strings.Error_Project_Open, ref, e.getLocalizedMessage()));
 		}
 	}
 
+	// Zeigt dialog für das Ausfählen eines neuen Profiles.
 	@Override
 	public Profile getUnkownProfile() {
 		ProfileChooseDialog dialog = new ProfileChooseDialog(getStage());
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/cell/PluginCell.java b/PlayWall/src/de/tobias/playpad/viewcontroller/cell/PluginCell.java
index 8406d56263a26a169e89365c5a09141629a35a6d..6deea2a19ee6d00415ee5d33d791fb75f90439ec 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/cell/PluginCell.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/cell/PluginCell.java
@@ -4,9 +4,13 @@ import java.io.IOException;
 import java.net.URL;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
 
 import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.plugin.Plugin;
+import de.tobias.playpad.plugin.Plugins;
+import de.tobias.utils.application.App;
 import de.tobias.utils.application.ApplicationUtils;
 import de.tobias.utils.application.container.PathType;
 import javafx.beans.value.ChangeListener;
@@ -15,7 +19,6 @@ import javafx.geometry.Pos;
 import javafx.scene.control.CheckBox;
 import javafx.scene.control.ListCell;
 import javafx.scene.layout.HBox;
-import net.xeoh.plugins.base.PluginManager;
 
 public class PluginCell extends ListCell<Plugin> implements ChangeListener<Boolean> {
 
@@ -23,11 +26,7 @@ public class PluginCell extends ListCell<Plugin> implements ChangeListener<Boole
 	private HBox buttons;
 	private CheckBox checkBox;
 
-	private PluginManager manager;
-
-	public PluginCell(PluginManager manager) {
-		this.manager = manager;
-
+	public PluginCell() {
 		checkBox = new CheckBox();
 		checkBox.selectedProperty().addListener(this);
 
@@ -47,7 +46,7 @@ public class PluginCell extends ListCell<Plugin> implements ChangeListener<Boole
 				checkBox.setSelected(false);
 			}
 			setGraphic(buttons);
-			checkBox.setText(item.getName());
+			checkBox.setText(item.toString());
 		} else {
 			setGraphic(null);
 		}
@@ -55,24 +54,45 @@ public class PluginCell extends ListCell<Plugin> implements ChangeListener<Boole
 
 	@Override
 	public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
-		Path path = ApplicationUtils.getApplication().getPath(PathType.LIBRARY, plugin.getFileName());
+		App app = ApplicationUtils.getApplication();
+
+		Path path = app.getPath(PathType.LIBRARY, plugin.getFileName());
 		if (newValue) { // Wurde Aktiviert
 			downloadPlugin(plugin, path);
 
 			// Dependencies
-			for (String dependencyName : plugin.getDependencies()) {
-				for (Plugin plugin : Plugin.getPlugins()) {
-					if (plugin.getName().equals(dependencyName)) {
-						Path decPath = ApplicationUtils.getApplication().getPath(PathType.LIBRARY, plugin.getFileName());
-						downloadPlugin(plugin, decPath);
-					}
-				}
-			}
+			loadDependencies(app);
 
-			manager.addPluginsFrom(path.toUri());
+			// Add Plugin to classpath
+			PlayPadMain.getProgramInstance().loadPlugin(path.toUri());
 		} else {
-			PlayPadMain.addDeletedPlugin(path);
+			// Deaktivieren
+			PlayPadMain.getProgramInstance().addDeletedPlugin(path);
+		}
+	}
+
+	private void loadDependencies(App app) {
+		List<Plugin> dependencies = findDependencies();
+		dependencies.forEach(p ->
+		{
+			Path decPath = app.getPath(PathType.LIBRARY, p.getFileName());
+			downloadPlugin(p, decPath);
+
+			// Add Plugin to classpath
+			PlayPadMain.getProgramInstance().loadPlugin(decPath.toUri());
+		});
+	}
+
+	private List<Plugin> findDependencies() {
+		List<Plugin> plugins = new ArrayList<>();
+		for (String dependencyName : plugin.getDependencies()) {
+			for (Plugin plugin : Plugins.getPlugins()) {
+				if (plugin.getName().equals(dependencyName)) {
+					plugins.add(plugin);
+				}
+			}
 		}
+		return plugins;
 	}
 
 	private void downloadPlugin(Plugin plugin, Path path) {
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/cell/ProjectCell.java b/PlayWall/src/de/tobias/playpad/viewcontroller/cell/ProjectCell.java
index 5ee0a1ee42ca3a96948d1f22d28c7694e7c18d15..57d9105b5c6355ee95f0e4e0f9a9269b5d240eb9 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/cell/ProjectCell.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/cell/ProjectCell.java
@@ -5,8 +5,6 @@ import java.nio.file.Path;
 
 import de.tobias.playpad.Displayable;
 import de.tobias.playpad.project.ProjectReference;
-import de.tobias.utils.application.ApplicationUtils;
-import de.tobias.utils.application.container.PathType;
 import de.tobias.utils.ui.icon.FontAwesomeType;
 import de.tobias.utils.ui.icon.FontIcon;
 import javafx.scene.control.ContentDisplay;
@@ -15,14 +13,14 @@ import javafx.scene.paint.Color;
 
 public class ProjectCell extends ListCell<ProjectReference> {
 
-	private Displayable action;
+	private Displayable ref;
 
 	@Override
-	protected void updateItem(ProjectReference action, boolean empty) {
-		super.updateItem(action, empty);
+	protected void updateItem(ProjectReference ref, boolean empty) {
+		super.updateItem(ref, empty);
 		if (!empty) {
-			if (this.action == null || this.action != action) {
-				Path path = ApplicationUtils.getApplication().getPath(PathType.DOCUMENTS, action.getFileName());
+			if (this.ref == null || this.ref != ref) {
+				Path path = ref.getProjectPath();
 				if (Files.notExists(path)) {
 					FontIcon graphics = new FontIcon(FontAwesomeType.WARNING);
 					graphics.setColor(Color.RED);
@@ -30,11 +28,11 @@ public class ProjectCell extends ListCell<ProjectReference> {
 				}
 				setContentDisplay(ContentDisplay.RIGHT);
 
-				textProperty().bind(action.displayProperty());
-				this.action = action;
+				textProperty().bind(ref.displayProperty());
+				this.ref = ref;
 			}
 		} else {
-			this.action = null;
+			this.ref = null;
 			textProperty().unbind();
 
 			setGraphic(null);
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/cell/UpdateCell.java b/PlayWall/src/de/tobias/playpad/viewcontroller/cell/UpdateCell.java
index 48d27b4b90eba7e5e6e99885433f76cb0fd6494e..c33fffdfd7df206c1edeff9ee6a14c09e93a8b25 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/cell/UpdateCell.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/cell/UpdateCell.java
@@ -1,9 +1,11 @@
 package de.tobias.playpad.viewcontroller.cell;
 
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.Updatable;
+import de.tobias.playpad.update.PlayPadUpdater;
+import de.tobias.playpad.update.Updatable;
 import de.tobias.utils.util.Localization;
 import javafx.scene.control.ListCell;
+import javafx.scene.image.ImageView;
 
 public class UpdateCell extends ListCell<Updatable> {
 
@@ -11,6 +13,11 @@ public class UpdateCell extends ListCell<Updatable> {
 	protected void updateItem(Updatable item, boolean empty) {
 		super.updateItem(item, empty);
 		if (!empty) {
+			if (item instanceof PlayPadUpdater) {
+				setGraphic(new ImageView("de/tobias/playpad/assets/files/class_obj.png"));
+			} else {
+				setGraphic(new ImageView("de/tobias/playpad/assets/files/enum_obj.png"));
+			}
 			setText(Localization.getString(Strings.UI_Dialog_Update_Cell, item.name(), item.getCurrentVersion(), item.getNewVersion()));
 		} else {
 			setText("");
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/DuplicateProjectDialog.java b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/DuplicateProjectDialog.java
index d4bbfd864346d13b9efde1988e29e3e8604edf6f..180f5230e0b9fde768b3a71c8e065bf3a65d3b50 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/DuplicateProjectDialog.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/DuplicateProjectDialog.java
@@ -29,8 +29,8 @@ public class DuplicateProjectDialog extends TextInputDialog {
 		setResultConverter(button ->
 		{
 			String param = getEditor().getText();
-			if (!param.endsWith(PlayPadMain.projectType[0].substring(1))) {
-				param += PlayPadMain.projectType[0].substring(1);
+			if (!param.endsWith(PlayPadMain.projectType.substring(1))) {
+				param += PlayPadMain.projectType.substring(1);
 			}
 
 			ButtonData data = button == null ? null : button.getButtonData();
@@ -40,7 +40,7 @@ public class DuplicateProjectDialog extends TextInputDialog {
 		Button button = (Button) getDialogPane().lookupButton(ButtonType.OK);
 		getEditor().textProperty().addListener((a, b, c) ->
 		{
-			if (ProjectReference.getProjects().contains(c) || !c.matches(Project.projectNameEx)) {
+			if (ProjectReference.getProjects().contains(c) || !c.matches(Project.PROJECT_NAME_PATTERN)) {
 				button.setDisable(true);
 			} else {
 				button.setDisable(false);
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/ImportDialog.java b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/ImportDialog.java
index a1e8fbf6ef6d4655147014a4d0a77693a430999e..e5e1ba474bfd3bc71c66e8900381a1e0799f51b6 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/ImportDialog.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/ImportDialog.java
@@ -73,7 +73,7 @@ public class ImportDialog implements Importable, ProfileChooseable {
 
 	@Override
 	public String replaceProject(String name) {
-		TextInputDialog alert = new TextInputDialog(name.replace(PlayPadMain.projectType[0].substring(1), ""));
+		TextInputDialog alert = new TextInputDialog(name.replace(PlayPadMain.projectType.substring(1), ""));
 		alert.initOwner(getStage());
 		alert.initModality(Modality.WINDOW_MODAL);
 		alert.setContentText(Localization.getString(Strings.UI_Dialog_Import_ReplaceProject_ReplaceContent, name));
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/MappingListViewController.java b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/MappingListViewController.java
index e82fd677771bb7798c9881b7895e710c859abb9c..b59e10fc3ea267ae949d7f7d8ac8fb89186dc1b4 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/MappingListViewController.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/MappingListViewController.java
@@ -26,6 +26,12 @@ import javafx.stage.Modality;
 import javafx.stage.Stage;
 import javafx.stage.Window;
 
+/**
+ * Dieser ViewController listet alle Mappings auf. Man kann diese importieren, exportieren und aktivieren/deaktivieren.
+ * 
+ * @author tobias
+ *
+ */
 public class MappingListViewController extends ViewController {
 
 	@FXML private ComboBox<Mapping> presetsListView;
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/NewProjectDialog.java b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/NewProjectDialog.java
index 973a5a43db38b233c796e259acca9db58d28e58c..3a887b229e59c956c3f867761ca6f30de3e581af 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/NewProjectDialog.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/NewProjectDialog.java
@@ -57,7 +57,7 @@ public class NewProjectDialog extends ViewController {
 			if (c.isEmpty()) {
 				finishButton.setDisable(true);
 			} else {
-				if (ProjectReference.getProjects().contains(c) || !c.matches(Project.projectNameEx)) {
+				if (ProjectReference.getProjects().contains(c) || !c.matches(Project.PROJECT_NAME_PATTERN)) {
 					finishButton.setDisable(true);
 					return;
 				}
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/PluginViewController.java b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/PluginViewController.java
similarity index 61%
rename from PlayWall/src/de/tobias/playpad/viewcontroller/PluginViewController.java
rename to PlayWall/src/de/tobias/playpad/viewcontroller/dialog/PluginViewController.java
index d519188a961d87ab1a645dda272b1229635001b7..dbe7f9aefae577b2c99d0e62bc95747d84c760df 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/PluginViewController.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/PluginViewController.java
@@ -1,18 +1,24 @@
-package de.tobias.playpad.viewcontroller;
+package de.tobias.playpad.viewcontroller.dialog;
 
 import java.io.IOException;
 import java.util.Collections;
+import java.util.List;
+
+import org.bukkit.configuration.MemorySection;
 
 import de.tobias.playpad.AppUserInfoStrings;
 import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.plugin.Plugin;
+import de.tobias.playpad.plugin.Plugins;
 import de.tobias.playpad.settings.Profile;
+import de.tobias.playpad.update.UpdateChannel;
 import de.tobias.playpad.viewcontroller.cell.PluginCell;
 import de.tobias.utils.application.ApplicationUtils;
 import de.tobias.utils.ui.ViewController;
 import de.tobias.utils.util.Localization;
 import de.tobias.utils.util.Worker;
+import javafx.application.Platform;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.scene.control.Button;
@@ -21,18 +27,14 @@ import javafx.scene.control.ListView;
 import javafx.stage.Modality;
 import javafx.stage.Stage;
 import javafx.stage.Window;
-import net.xeoh.plugins.base.PluginManager;
 
 public class PluginViewController extends ViewController {
 
 	@FXML private ListView<Plugin> pluginListView;
 	@FXML private Button finishButton;
 
-	private PluginManager manager;
-
-	public PluginViewController(PluginManager manager, Window owner) {
+	public PluginViewController(Window owner) {
 		super("pluginView", "de/tobias/playpad/assets/dialog/", null, PlayPadMain.getUiResourceBundle());
-		this.manager = manager;
 
 		getStage().initOwner(owner);
 		getStage().initModality(Modality.WINDOW_MODAL);
@@ -40,11 +42,28 @@ public class PluginViewController extends ViewController {
 		Worker.runLater(() ->
 		{
 			try {
-				String pluginInfoURL = ApplicationUtils.getApplication().getInfo().getUserInfo().getString(AppUserInfoStrings.PLUGINS_URL);
-				Plugin.load(pluginInfoURL);
-
-				Collections.sort(Plugin.getPlugins());
-				pluginListView.getItems().addAll(Plugin.getPlugins());
+				String pluginInfoURL = null;
+
+				MemorySection userInfo = ApplicationUtils.getApplication().getInfo().getUserInfo();
+				UpdateChannel updateChannel = Profile.currentProfile().getProfileSettings().getUpdateChannel();
+
+				if (updateChannel == UpdateChannel.STABLE) {
+					pluginInfoURL = userInfo.getString(AppUserInfoStrings.PLUGINS_URL_STABLE);
+				} else if (updateChannel == UpdateChannel.BETA) {
+					pluginInfoURL = userInfo.getString(AppUserInfoStrings.PLUGINS_URL_BETA);
+				} else {
+					// No Plugins for this UpdateChannel Available --> Return
+					showInfoMessage(Localization.getString(Strings.Error_Plugins_Available));
+					return;
+				}
+
+				List<Plugin> plugins = Plugins.load(pluginInfoURL, true);
+
+				Collections.sort(plugins);
+				Platform.runLater(() ->
+				{
+					pluginListView.getItems().setAll(plugins);
+				});
 			} catch (IOException e) {
 				e.printStackTrace();
 				showErrorMessage(Localization.getString(Strings.Error_Standard_Gen), PlayPadMain.stageIcon);
@@ -54,7 +73,7 @@ public class PluginViewController extends ViewController {
 
 	@Override
 	public void init() {
-		pluginListView.setCellFactory(list -> new PluginCell(manager));
+		pluginListView.setCellFactory(list -> new PluginCell());
 		pluginListView.setPlaceholder(new Label(Localization.getString(Strings.UI_Placeholder_Plugins)));
 
 		addCloseKeyShortcut(() -> getStage().close());
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/PrintDialog.java b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/PrintDialog.java
similarity index 98%
rename from PlayWall/src/de/tobias/playpad/viewcontroller/PrintDialog.java
rename to PlayWall/src/de/tobias/playpad/viewcontroller/dialog/PrintDialog.java
index 4b88bd8e0cdcbdd10d5c9f5de79ba57e85432bcf..25185126c7e2785dc66c89d749a36c6ec3d200ba 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/PrintDialog.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/PrintDialog.java
@@ -1,4 +1,4 @@
-package de.tobias.playpad.viewcontroller;
+package de.tobias.playpad.viewcontroller.dialog;
 
 import com.hp.gagawa.java.elements.Body;
 import com.hp.gagawa.java.elements.Div;
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/ProjectManagerDialog.java b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/ProjectManagerDialog.java
index da665cd08e7700f55e45b36a6cb304696da54146..6de43dc90b92a830ef846210f318b6513ac58c83 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/ProjectManagerDialog.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/dialog/ProjectManagerDialog.java
@@ -201,7 +201,7 @@ public class ProjectManagerDialog extends ViewController implements Notification
 
 		try {
 			String newProjectName = (String) nameTextField.getText();
-			if (ProjectReference.getProjects().contains(newProjectName) || !nameTextField.getText().matches(Project.projectNameEx)) {
+			if (ProjectReference.getProjects().contains(newProjectName) || !nameTextField.getText().matches(Project.PROJECT_NAME_PATTERN)) {
 				showErrorMessage(Localization.getString(Strings.Error_Standard_NameInUse, nameTextField.getText()));
 				return;
 			}
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/layout/ModernLayoutCartViewController.java b/PlayWall/src/de/tobias/playpad/viewcontroller/layout/ModernLayoutCartViewController.java
index dd3e7bd2cfe6f21f8ab1fbe39d609185c2cb9930..f5c5214f553b3393422300a8142b29022fb74c6c 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/layout/ModernLayoutCartViewController.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/layout/ModernLayoutCartViewController.java
@@ -42,16 +42,10 @@ public class ModernLayoutCartViewController extends CartLayoutViewController {
 	private void setLayout() {
 		backgroundColorButton.setStyle(getLinearGradientCss(cartLayout.getBackgroundColor()));
 		playColorButton.setStyle(getLinearGradientCss(cartLayout.getPlayColor()));
-
-		warnAnimationCheckBox.setSelected(cartLayout.isWarnAnimation());
 	}
 
 	@Override
 	public void init() {
-		warnAnimationCheckBox.selectedProperty().addListener((a, b, c) ->
-		{
-			cartLayout.setWarnAnimation(c);
-		});
 	}
 
 	@FXML
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/main/MainMenuBarController.java b/PlayWall/src/de/tobias/playpad/viewcontroller/main/MainMenuBarController.java
index 2d43a552e31cf04f7a733e6accb2b1061a41fb75..8ed2b134f07c501b1ba28832f18dad8c4845560c 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/main/MainMenuBarController.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/main/MainMenuBarController.java
@@ -10,11 +10,7 @@ import java.util.ResourceBundle;
 
 import de.tobias.playpad.AppUserInfoStrings;
 import de.tobias.playpad.PlayPadMain;
-import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.action.Action;
-import de.tobias.playpad.action.cartaction.CartAction;
-import de.tobias.playpad.action.connect.CartActionConnect;
 import de.tobias.playpad.midi.Midi;
 import de.tobias.playpad.pad.view.IPadViewController;
 import de.tobias.playpad.project.Project;
@@ -24,12 +20,12 @@ import de.tobias.playpad.settings.Profile;
 import de.tobias.playpad.settings.ProfileListener;
 import de.tobias.playpad.settings.ProfileNotFoundException;
 import de.tobias.playpad.settings.ProfileSettings;
-import de.tobias.playpad.viewcontroller.PluginViewController;
-import de.tobias.playpad.viewcontroller.PrintDialog;
 import de.tobias.playpad.viewcontroller.SettingsTabViewController;
 import de.tobias.playpad.viewcontroller.dialog.ErrorSummaryDialog;
 import de.tobias.playpad.viewcontroller.dialog.ImportDialog;
 import de.tobias.playpad.viewcontroller.dialog.NewProjectDialog;
+import de.tobias.playpad.viewcontroller.dialog.PluginViewController;
+import de.tobias.playpad.viewcontroller.dialog.PrintDialog;
 import de.tobias.playpad.viewcontroller.dialog.ProfileViewController;
 import de.tobias.playpad.viewcontroller.dialog.ProjectManagerDialog;
 import de.tobias.playpad.viewcontroller.option.SettingsViewController;
@@ -57,25 +53,23 @@ import javafx.scene.control.MenuBar;
 import javafx.scene.control.MenuItem;
 import javafx.stage.Modality;
 import javafx.stage.Stage;
-import net.xeoh.plugins.base.PluginManager;
 
 public class MainMenuBarController implements EventHandler<ActionEvent>, Initializable, ProfileListener {
 
 	@FXML private MenuBar menuBar;
-	@FXML CheckMenuItem dndModeMenuItem;
-	@FXML CheckMenuItem alwaysOnTopItem;
-	@FXML CheckMenuItem fullScreenMenuItem;
-	@FXML Menu recentOpenMenu;
-	@FXML MenuItem profileMenu;
+	@FXML private CheckMenuItem dndModeMenuItem;
+	@FXML private CheckMenuItem alwaysOnTopItem;
+	@FXML private CheckMenuItem fullScreenMenuItem;
+	@FXML private Menu recentOpenMenu;
+	@FXML private MenuItem profileMenu;
 
-	@FXML CheckMenuItem quickEditMenuItem;
-	@FXML MenuItem settingsMenuItem;
+	@FXML private CheckMenuItem quickEditMenuItem;
+	@FXML private MenuItem settingsMenuItem;
 
-	@FXML Menu extensionMenu;
+	@FXML private Menu extensionMenu;
 
 	// Open Windows
 	private SettingsViewController settingsViewController;
-	private PluginManager manager;
 	private MainViewController mvc;
 
 	private ChangeListener<Boolean> lockedListener;
@@ -170,26 +164,10 @@ public class MainMenuBarController implements EventHandler<ActionEvent>, Initial
 		{
 			ProfileViewController controller = new ProfileViewController(mvc.getStage(), mvc.getProject());
 			controller.getStage().showAndWait();
+			mvc.setTitle();
 		});
 	}
 
-	@FXML
-	private void quickEditMenuHandler(ActionEvent event) {
-		try {
-			for (Action action : Profile.currentProfile().getMappings().getActiveMapping().getActionsOfType(CartActionConnect.TYPE)) {
-				CartAction cartAction = (CartAction) action;
-				if (cartAction.getCart() < mvc.padViewList.size()) {
-					cartAction.getPad().getController().getParent().setBusy(quickEditMenuItem.isSelected());
-					// IPadViewController controller = mvc.padViewList.get(cartAction.getCart());
-					// MapperQuickSettingsView view = new MapperQuickSettingsView((Pane) controller.getParent().getParent());
-					// view.showDropOptions(action.getMappers());
-				}
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
 	@FXML
 	private void settingsHandler(ActionEvent event) {
 		Midi midi = Midi.getInstance();
@@ -217,7 +195,7 @@ public class MainMenuBarController implements EventHandler<ActionEvent>, Initial
 					}
 
 					if (change) {
-						PlayPadPlugin.getImplementation().getSettingsListener().forEach(l -> l.onChange(Profile.currentProfile()));
+						PlayPadMain.getProgramInstance().getSettingsListener().forEach(l -> l.onChange(Profile.currentProfile()));
 					}
 
 					settingsViewController = null;
@@ -318,7 +296,7 @@ public class MainMenuBarController implements EventHandler<ActionEvent>, Initial
 	private void pluginMenuItemHandler(ActionEvent e) {
 		doAction(() ->
 		{
-			PluginViewController controller = new PluginViewController(manager, mvc.getStage());
+			PluginViewController controller = new PluginViewController(mvc.getStage());
 			controller.getStage().showAndWait();
 			mvc.showPage(mvc.getPage());
 		});
@@ -380,10 +358,6 @@ public class MainMenuBarController implements EventHandler<ActionEvent>, Initial
 		});
 	}
 
-	public void setPluginManager(PluginManager manager) {
-		this.manager = manager;
-	}
-
 	public void setMainViewController(MainViewController mvc) {
 		this.mvc = mvc;
 	}
@@ -397,4 +371,18 @@ public class MainMenuBarController implements EventHandler<ActionEvent>, Initial
 		profileSettings.lockedProperty().addListener(lockedListener);
 		lockedListener.changed(profileSettings.lockedProperty(), null, profileSettings.isLocked());
 	}
+
+	// Getter
+
+	public CheckMenuItem getAlwaysOnTopItem() {
+		return alwaysOnTopItem;
+	}
+
+	public Menu getExtensionMenu() {
+		return extensionMenu;
+	}
+
+	public CheckMenuItem getFullScreenMenuItem() {
+		return fullScreenMenuItem;
+	}
 }
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/main/MainViewController.java b/PlayWall/src/de/tobias/playpad/viewcontroller/main/MainViewController.java
index 099975dc2c325b468a4cd510d78db7e2f43a6836..4b4e7031c9dc08d2f3adfd9fd96751405f640808 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/main/MainViewController.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/main/MainViewController.java
@@ -66,8 +66,8 @@ import javafx.scene.shape.Line;
 import javafx.stage.Modality;
 import javafx.stage.Screen;
 import javafx.stage.Stage;
-import net.xeoh.plugins.base.PluginManager;
 
+// TODO Extract Color Adjust methodes
 public class MainViewController extends ViewController implements IMainViewController, NotificationHandler, ProfileListener {
 
 	private static final String CURRENT_PAGE_BUTTON = "current-page-button";
@@ -99,13 +99,12 @@ public class MainViewController extends ViewController implements IMainViewContr
 	// Style
 	private Color gridColor;
 
-	public MainViewController(Project project, List<WindowListener<IMainViewController>> listener, PluginManager manager) {
+	public MainViewController(Project project, List<WindowListener<IMainViewController>> listener) {
 		super("mainView", "de/tobias/playpad/assets/view/main/", null, PlayPadMain.getUiResourceBundle());
 
 		// Include FXML Setup
 		toolbarController.setMainViewController(this);
 		menuBarController.setMainViewController(this);
-		menuBarController.setPluginManager(manager);
 
 		padGridPane.setGridLinesVisible(true);
 
@@ -159,7 +158,7 @@ public class MainViewController extends ViewController implements IMainViewContr
 	public void init() {
 		padGridPane.getStyleClass().add("pad-grid");
 
-		menuBarController.extensionMenu.setVisible(false);
+		menuBarController.getExtensionMenu().setVisible(false);
 
 		liveLabel.setVisible(false);
 		liveLabel.getStyleClass().add("live-label");
@@ -172,7 +171,7 @@ public class MainViewController extends ViewController implements IMainViewContr
 
 		getStage().fullScreenProperty().addListener((a, b, c) ->
 		{
-			menuBarController.fullScreenMenuItem.setSelected(c);
+			menuBarController.getFullScreenMenuItem().setSelected(c);
 		});
 
 		// Lautstärke Veränderung
@@ -189,7 +188,7 @@ public class MainViewController extends ViewController implements IMainViewContr
 		}
 	}
 
-	private void setTitle() {
+	void setTitle() {
 		if (project != null && Profile.currentProfile() != null) {
 			getStage().setTitle(Localization.getString(Strings.UI_Window_Main_Title, project.getRef().getName(),
 					Profile.currentProfile().getRef().getName()));
@@ -656,7 +655,7 @@ public class MainViewController extends ViewController implements IMainViewContr
 		}
 
 		// WINDOW Settings
-		menuBarController.alwaysOnTopItem.setSelected(profilSettings.isWindowAlwaysOnTop());
+		menuBarController.getAlwaysOnTopItem().setSelected(profilSettings.isWindowAlwaysOnTop());
 		getStage().setAlwaysOnTop(profilSettings.isWindowAlwaysOnTop());
 
 		setTitle();
@@ -685,9 +684,9 @@ public class MainViewController extends ViewController implements IMainViewContr
 	 * @since 2.0.0
 	 */
 	public void addMenuItem(MenuItem item) {
-		menuBarController.extensionMenu.getItems().add(item);
-		if (!menuBarController.extensionMenu.isVisible()) {
-			menuBarController.extensionMenu.setVisible(true);
+		menuBarController.getExtensionMenu().getItems().add(item);
+		if (!menuBarController.getExtensionMenu().isVisible()) {
+			menuBarController.getExtensionMenu().setVisible(true);
 		}
 	}
 
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/option/GeneralTabViewController.java b/PlayWall/src/de/tobias/playpad/viewcontroller/option/GeneralTabViewController.java
index dedc6b40dec0b564ee47058c1c5783cd093e11ee..4bb3bedb665346bac197cd878f182a515083b053 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/option/GeneralTabViewController.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/option/GeneralTabViewController.java
@@ -67,9 +67,9 @@ public class GeneralTabViewController extends SettingsTabViewController {
 
 	private boolean changeSettings;
 
-	public GeneralTabViewController(Screen screen, ViewController parentController, boolean activePlayer) {
+	public GeneralTabViewController(Screen currentScreen, ViewController parentController, boolean activePlayer) {
 		super("generalTab", "de/tobias/playpad/assets/view/option/", PlayPadMain.getUiResourceBundle());
-		this.mainWindowScreen = screen;
+		this.mainWindowScreen = currentScreen;
 		this.parentController = parentController;
 
 		if (activePlayer) {
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/option/SettingsViewController.java b/PlayWall/src/de/tobias/playpad/viewcontroller/option/SettingsViewController.java
index 9e9aff7afe1d9708e5331201322811650bd11fd6..8dc5d9b1b85b7e8a3a1f60e77ac049717285483f 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/option/SettingsViewController.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/option/SettingsViewController.java
@@ -4,7 +4,6 @@ import java.util.ArrayList;
 import java.util.List;
 
 import de.tobias.playpad.PlayPadMain;
-import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.midi.Midi;
 import de.tobias.playpad.pad.conntent.PadContentRegistry;
@@ -36,18 +35,18 @@ public class SettingsViewController extends ViewController implements ISettingsV
 
 	protected List<SettingsTabViewController> tabs = new ArrayList<>();
 
-	public SettingsViewController(Midi midiHandler, Screen screen, Window owner, Project project) {
+	public SettingsViewController(Midi midiHandler, Screen currentScreen, Window owner, Project project) {
 		super("settingsView", "de/tobias/playpad/assets/view/option/", null, PlayPadMain.getUiResourceBundle());
 
-		boolean activePlayer = project.getPlayedPlayers() > 0;
+		boolean activePlayer = project.hasPlayedPlayers();
 
-		addTab(new GeneralTabViewController(screen, this, activePlayer));
+		addTab(new GeneralTabViewController(currentScreen, this, activePlayer));
 		addTab(new MappingTabViewController());
 		addTab(new MidiTabViewController());
 		addTab(new LayoutTabViewController());
 		addTab(new PlayerTabViewController());
 
-		// Content Types
+		// Custom Tabs - Content Types
 		for (String type : PadContentRegistry.getTypes()) {
 			try {
 				SettingsTabViewController controller = PadContentRegistry.getPadContentConnect(type).getSettingsTabViewController(activePlayer);
@@ -59,21 +58,12 @@ public class SettingsViewController extends ViewController implements ISettingsV
 			}
 		}
 
-		// Listener
-		PlayPadPlugin.getImplementation().getSettingsViewListener().forEach(l ->
-		{
-			try {
-				l.onInit(this);
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
-		});
 		addTab(new UpdateTabViewController());
 
 		getStage().initOwner(owner);
 
 		// Show Current Settings
-		showCurrentSettings();
+		loadTabs();
 	}
 
 	@Override
@@ -83,21 +73,19 @@ public class SettingsViewController extends ViewController implements ISettingsV
 		// KeyCode
 		addCloseKeyShortcut(() -> finishButton.fire());
 
+		// Look Button Listener
 		lockedButton.setGraphic(new FontIcon(FontAwesomeType.LOCK));
 		lockedButton.setOnAction(e ->
 		{
 			boolean isLocked = lockedButton.isSelected();
-			// Model
 			profileSettings.setLocked(isLocked);
-
-			// SettingsUI
-			tabPane.setDisable(isLocked);
+			setLookEnable(isLocked);
 		});
 
+		// Übernimmt die aktuellen Einstellungen des Look Button
 		if (profileSettings.isLocked()) {
-			// SettingsUI
 			lockedButton.setSelected(true);
-			tabPane.setDisable(true);
+			setLookEnable(true);
 		}
 
 		finishButton.defaultButtonProperty().bind(finishButton.focusedProperty());
@@ -114,37 +102,20 @@ public class SettingsViewController extends ViewController implements ISettingsV
 		Profile.currentProfile().currentLayout().applyCss(getStage());
 	}
 
-	// Copy Of Settings
-	public boolean closeRequest() {
-		boolean valid = true;
-		for (SettingsTabViewController controller : tabs) {
-			if (controller.validSettings() == false) {
-				valid = false;
-			}
-		}
-
-		if (valid) { // Einstellungen sind Valide
-			// Listener
-			PlayPadPlugin.getImplementation().getSettingsViewListener().forEach(l -> l.onClose(this));
-
-			saveChanges();
-			getStage().close();
-			updateData();
-			return true;
-		} else {
-			return false;
-		}
-	}
-
-	// Settings aus AppSettings
-	private void showCurrentSettings() {
+	/**
+	 * Zeigt die aktuellen Einstellungen für die Tabs an.
+	 */
+	private void loadTabs() {
 		Profile profile = Profile.currentProfile();
 		for (SettingsTabViewController controller : tabs) {
 			controller.loadSettings(profile);
 		}
 	}
 
-	private void saveChanges() {
+	/**
+	 * Speichert die Einstellungen der Tabs.
+	 */
+	private void saveTabs() {
 		Profile profile = Profile.currentProfile();
 		for (SettingsTabViewController controller : tabs) {
 			controller.saveSettings(profile);
@@ -158,33 +129,42 @@ public class SettingsViewController extends ViewController implements ISettingsV
 		}
 	}
 
-	public boolean needUpdate() {
-		boolean change = false;
-		for (SettingsTabViewController controller : tabs) {
-			if (controller.needReload()) {
-				change = true;
-			}
-		}
-		return change;
+	public boolean closeRequest() {
+		return onFinish();
 	}
 
+	// Button Listener
 	@FXML
 	private void finishButtonHandler(ActionEvent event) {
-		boolean valid = true;
+		onFinish();
+		getStage().close();
+	}
+
+	/**
+	 * Speichert alle Informationen.
+	 * 
+	 * @return <code>true</code>Alle Einstellungen sind Valid.
+	 */
+	private boolean onFinish() {
 		for (SettingsTabViewController controller : tabs) {
 			if (controller.validSettings() == false) {
-				valid = false;
+				return false;
 			}
 		}
 
-		if (valid) { // Einstellungen sind Valide
-			// Listener
-			PlayPadPlugin.getImplementation().getSettingsViewListener().forEach(l -> l.onClose(this));
+		saveTabs();
+		updateData(); // Reload MainViewController Settings // TODO Rewrite
+		return true;
+	}
 
-			saveChanges();
-			getStage().close();
-			updateData();
-		}
+	/**
+	 * Aktiviert/Deaktiviert den Look Button.
+	 * 
+	 * @param isLocked
+	 *            isLooked
+	 */
+	private void setLookEnable(boolean isLocked) {
+		tabPane.setDisable(isLocked);
 	}
 
 	public void addTab(SettingsTabViewController controller) {
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/option/UpdateTabViewController.java b/PlayWall/src/de/tobias/playpad/viewcontroller/option/UpdateTabViewController.java
index 0edd9042f39d8a1917d7f57927b18b23d6793074..0bf463e78c590218e2303fee471d4475a84323ca 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/option/UpdateTabViewController.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/option/UpdateTabViewController.java
@@ -1,56 +1,37 @@
 package de.tobias.playpad.viewcontroller.option;
 
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Optional;
 
-import de.tobias.playpad.AppUserInfoStrings;
 import de.tobias.playpad.PlayPadMain;
-import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.Updatable;
-import de.tobias.playpad.UpdateRegistery;
 import de.tobias.playpad.settings.Profile;
+import de.tobias.playpad.settings.ProfileSettings;
+import de.tobias.playpad.update.Updatable;
+import de.tobias.playpad.update.UpdateChannel;
+import de.tobias.playpad.update.UpdateRegistery;
+import de.tobias.playpad.update.Updates;
 import de.tobias.playpad.viewcontroller.SettingsTabViewController;
+import de.tobias.playpad.viewcontroller.cell.EnumCell;
 import de.tobias.playpad.viewcontroller.cell.UpdateCell;
 import de.tobias.playpad.viewcontroller.dialog.UpdaterDialog;
+import de.tobias.utils.application.ApplicationInfo;
 import de.tobias.utils.application.ApplicationUtils;
-import de.tobias.utils.application.NativeLauncher;
-import de.tobias.utils.application.container.PathType;
 import de.tobias.utils.util.Localization;
-import de.tobias.utils.util.OS;
-import de.tobias.utils.util.OS.OSType;
 import de.tobias.utils.util.Worker;
 import javafx.application.Platform;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
-import javafx.scene.control.Alert;
-import javafx.scene.control.Alert.AlertType;
 import javafx.scene.control.Button;
 import javafx.scene.control.CheckBox;
+import javafx.scene.control.ComboBox;
 import javafx.scene.control.Label;
 import javafx.scene.control.ListView;
 import javafx.scene.control.ProgressIndicator;
-import javafx.scene.image.Image;
-import javafx.stage.Modality;
-import javafx.stage.Stage;
-import javafx.stage.Window;
+import javafx.scene.image.ImageView;
 
 public class UpdateTabViewController extends SettingsTabViewController {
 
-	private static final String DOWNLOAD_FOLDER = "Updates";
-	private static final String UPDATER_JAR = "Updater.jar";
-	private static final String UPDATER_EXE = "Updater.exe";
-
 	@FXML private Label currentVersionLabel;
-	@FXML private Label newVersionLabel;
 
 	@FXML private CheckBox automaticSearchCheckBox;
 	@FXML private Button manualSearchButton;
@@ -58,35 +39,47 @@ public class UpdateTabViewController extends SettingsTabViewController {
 	@FXML private ListView<Updatable> openUpdateList;
 	@FXML private Button updateButton;
 
+	@FXML private ComboBox<UpdateChannel> updateChannelComboBox;
+
+	@FXML private Label infoCLabel;
+	@FXML private Label infoELabel;
+
+	// Placeholder for List
 	private ProgressIndicator progressIndecator;
 	private Label placeholderLabel;
 
 	public UpdateTabViewController() {
 		super("updateTab", "de/tobias/playpad/assets/view/option/", PlayPadMain.getUiResourceBundle());
 
+		ProfileSettings profileSettings = Profile.currentProfile().getProfileSettings();
+		updateChannelComboBox.setValue(profileSettings.getUpdateChannel());
 		openUpdateList.getItems().setAll(UpdateRegistery.getAvailableUpdates());
 		updateButton.setDisable(openUpdateList.getItems().isEmpty());
 
-		Worker.runLater(() ->
-		{
-			Updatable updater = PlayPadMain.getUpdater();
-			updater.checkUpdate();
-			Platform.runLater(() ->
-			{
-				currentVersionLabel.setText(Localization.getString(Strings.UI_Window_Settings_Updates_CurrentVersion,
-						updater.getCurrentVersion(), updater.getCurrentBuild()));
-				newVersionLabel.setText(Localization.getString(Strings.UI_Window_Settings_Updates_CurrentVersion, updater.getNewVersion(),
-						updater.getNewBuild()));
-			});
-		});
+		ApplicationInfo info = ApplicationUtils.getApplication().getInfo();
+		String currentVersionString = Localization.getString(Strings.UI_Window_Settings_Updates_CurrentVersion, info.getVersion(),
+				info.getBuild());
+		currentVersionLabel.setText(currentVersionString);
 	}
 
 	@Override
 	public void init() {
 		openUpdateList.setCellFactory(list -> new UpdateCell());
+		updateChannelComboBox.getItems().setAll(UpdateChannel.values());
+		updateChannelComboBox.setCellFactory(list -> new EnumCell<>(Strings.Update_Channel_BaseName));
+		updateChannelComboBox.setButtonCell(new EnumCell<>(Strings.Update_Channel_BaseName));
+
+		updateChannelComboBox.valueProperty().addListener((a, b, c) ->
+		{
+			Profile.currentProfile().getProfileSettings().setUpdateChannel(c);
+		});
+
+		infoCLabel.setGraphic(new ImageView("de/tobias/playpad/assets/files/class_obj.png"));
+		infoELabel.setGraphic(new ImageView("de/tobias/playpad/assets/files/enum_obj.png"));
 
 		progressIndecator = new ProgressIndicator(-1);
-		progressIndecator.setMinSize(25, 25);
+		progressIndecator.setMinSize(75, 75);
+		progressIndecator.setMaxSize(75, 75);
 
 		placeholderLabel = new Label(Localization.getString(Strings.UI_Placeholder_Updates));
 		openUpdateList.setPlaceholder(placeholderLabel);
@@ -98,124 +91,42 @@ public class UpdateTabViewController extends SettingsTabViewController {
 	private void manualSearchHandler(ActionEvent event) {
 		openUpdateList.getItems().clear();
 
-		openUpdateList.setPlaceholder(progressIndecator);
-		UpdateRegistery.lookupUpdates();
-		openUpdateList.setPlaceholder(placeholderLabel);
+		Profile profile = Profile.currentProfile();
+		if (profile != null) {
+			openUpdateList.setPlaceholder(progressIndecator);
 
-		openUpdateList.getItems().setAll(UpdateRegistery.getAvailableUpdates());
-		updateButton.setDisable(openUpdateList.getItems().isEmpty());
+			Worker.runLater(() ->
+			{
+				// Search for updates
+				UpdateRegistery.lookupUpdates(profile.getProfileSettings().getUpdateChannel());
+
+				Platform.runLater(() ->
+				{
+					openUpdateList.setPlaceholder(placeholderLabel);
+					openUpdateList.getItems().setAll(UpdateRegistery.getAvailableUpdates());
+					updateButton.setDisable(openUpdateList.getItems().isEmpty());
+				});
+			});
+
+		}
 	}
 
 	@FXML
 	private void updateHandler(ActionEvent event) {
-		update(getStage());
-	}
-
-	public static void update(Window dialogOwner) {
-		String parameter = UpdateRegistery
-				.buildParamaterString(ApplicationUtils.getApplication().getPath(PathType.DOWNLOAD, DOWNLOAD_FOLDER).toString());
-		if (OS.getType() == OSType.Windows) {
-			try {
-				Path fileJar = Paths.get(UPDATER_JAR);
-				Path fileExe = Paths.get(UPDATER_EXE);
-				Path fileJarFolder = ApplicationUtils.getApplication().getPath(PathType.DOWNLOAD, UPDATER_JAR);
-				Path fileExeFolder = ApplicationUtils.getApplication().getPath(PathType.DOWNLOAD, UPDATER_EXE);
-
-				if (Files.exists(fileJar)) {
-					startJarFile(parameter, fileJar);
-				} else if (Files.exists(fileExe)) {
-					startExeFile(parameter, fileExe);
-
-				} else if (Files.exists(fileJarFolder)) {
-					startJarFile(parameter, fileJarFolder);
-				} else if (Files.exists(fileExeFolder)) {
-					startExeFile(parameter, fileExeFolder);
-				} else {
-					UpdaterDialog dialog = new UpdaterDialog(dialogOwner);
-					dialog.show();
+		UpdaterDialog dialog = new UpdaterDialog(getStage());
+		dialog.show();
 
-					Worker.runLater(() ->
-					{
-						String updaterURL = ApplicationUtils.getApplication().getInfo().getUserInfo().get(AppUserInfoStrings.UPDATER_PROGRAM)
-								+ UPDATER_EXE;
-						Path path = ApplicationUtils.getApplication().getPath(PathType.DOWNLOAD, UPDATER_EXE);
-						try {
-							downloadUpdater(updaterURL, path);
-							startExeFile(parameter, path);
-						} catch (Exception e) {
-							e.printStackTrace();
-							String errorMessage = Localization.getString(Strings.Error_Update_Download, e.getMessage());
-							showErrorMessage(errorMessage, PlayPadPlugin.getImplementation().getIcon(), dialogOwner);
-						}
-					});
-				}
-			} catch (Exception ex) {
-				ex.printStackTrace();
-			}
-		} else {
+		Worker.runLater(() ->
+		{
 			try {
-				Path fileJar = Paths.get(UPDATER_JAR);
-				Path fileJarFolder = ApplicationUtils.getApplication().getPath(PathType.DOWNLOAD, UPDATER_JAR);
-
-				if (Files.exists(fileJar)) {
-					startJarFile(parameter, fileJar);
-				} else if (Files.exists(fileJarFolder)) {
-					startJarFile(parameter, fileJarFolder);
-				} else {
-					UpdaterDialog dialog = new UpdaterDialog(dialogOwner);
-					dialog.show();
-
-					Worker.runLater(() ->
-					{
-						String updaterURL = ApplicationUtils.getApplication().getInfo().getUserInfo().get(AppUserInfoStrings.UPDATER_PROGRAM)
-								+ UPDATER_JAR;
-						Path path = ApplicationUtils.getApplication().getPath(PathType.DOWNLOAD, UPDATER_JAR);
-						try {
-							downloadUpdater(updaterURL, path);
-							startJarFile(parameter, path);
-						} catch (Exception e) {
-							e.printStackTrace();
-							String errorMessage = Localization.getString(Strings.Error_Update_Download, e.getMessage());
-							showErrorMessage(errorMessage, PlayPadPlugin.getImplementation().getIcon(), dialogOwner);
-						}
-					});
-				}
-			} catch (Exception ex) {
-				ex.printStackTrace();
+				Updates.startUpdate();
+			} catch (IOException e) {
+				e.printStackTrace();
 			}
-		}
-	}
-
-	private static void downloadUpdater(String updaterURL, Path path) throws IOException, MalformedURLException {
-		if (Files.notExists(path)) {
-			Files.createDirectories(path.getParent());
-			Files.createFile(path);
-		}
-
-		URLConnection conn = new URL(updaterURL).openConnection();
-
-		InputStream iStr = conn.getInputStream();
-		OutputStream oStr = Files.newOutputStream(path);
-
-		byte[] data = new byte[1024];
-		int dataLength = 0;
-		while ((dataLength = iStr.read(data, 0, data.length)) > 0) {
-			oStr.write(data, 0, dataLength);
-		}
-		oStr.close();
-	}
-
-	private static void startExeFile(String parameter, Path fileExeFolder) {
-		NativeLauncher.executeAsAdministrator(fileExeFolder.toAbsolutePath().toString(), parameter);
-		System.exit(0);
-	}
-
-	private static void startJarFile(String parameter, Path fileJarFolder) throws IOException {
-		ProcessBuilder builder = new ProcessBuilder("java", "-jar", fileJarFolder.toAbsolutePath().toString(), parameter);
-		builder.start();
-		System.exit(0);
+		});
 	}
 
+	// Settings Tab Methods
 	@Override
 	public void loadSettings(Profile profile) {
 		automaticSearchCheckBox.setSelected(profile.getProfileSettings().isAutoUpdate());
@@ -240,21 +151,4 @@ public class UpdateTabViewController extends SettingsTabViewController {
 	public String name() {
 		return Localization.getString(Strings.UI_Window_Settings_Updates_Title);
 	}
-
-	private static void showErrorMessage(String message, Optional<Image> icon, Window owner) {
-		if (!Platform.isFxApplicationThread()) {
-			Platform.runLater(() -> showErrorMessage(message, icon, owner));
-			return;
-		}
-
-		Alert alert = new Alert(AlertType.ERROR);
-		alert.initOwner(owner);
-		alert.initModality(Modality.WINDOW_MODAL);
-		alert.setContentText(message);
-		if (icon.isPresent()) {
-			Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
-			stage.getIcons().add(icon.get());
-		}
-		alert.showAndWait();
-	}
 }
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/option/pad/PadSettingsViewController.java b/PlayWall/src/de/tobias/playpad/viewcontroller/option/pad/PadSettingsViewController.java
index f400d434c30605ec46507df430fd88326342276b..8a8c69521c07984f3713b192bb7664c7d72c80f4 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/option/pad/PadSettingsViewController.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/option/pad/PadSettingsViewController.java
@@ -4,9 +4,9 @@ import java.util.ArrayList;
 import java.util.List;
 
 import de.tobias.playpad.PlayPadMain;
-import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.pad.conntent.PadContentConnect;
 import de.tobias.playpad.pad.conntent.PadContentRegistry;
 import de.tobias.playpad.pad.conntent.UnkownPadContentException;
@@ -53,16 +53,6 @@ public class PadSettingsViewController extends ViewController implements IPadSet
 			}
 		}
 
-		// Listener
-		PlayPadPlugin.getImplementation().getPadSettingsViewListener().forEach(l ->
-		{
-			try {
-				l.onInit(this);
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
-		});
-
 		getStage().initOwner(owner);
 
 		// Show Current Settings
@@ -71,7 +61,11 @@ public class PadSettingsViewController extends ViewController implements IPadSet
 	}
 
 	private void setTitle(Pad pad) {
-		getStage().setTitle(Localization.getString(Strings.UI_Window_PadSettings_Title, pad.getIndexReadable(), pad.getName()));
+		if (pad.getStatus() != PadStatus.EMPTY) {
+			getStage().setTitle(Localization.getString(Strings.UI_Window_PadSettings_Title, pad.getIndexReadable(), pad.getName()));
+		} else {
+			getStage().setTitle(Localization.getString(Strings.UI_Window_PadSettings_Title_Empty, pad.getIndexReadable()));
+		}
 	}
 
 	@Override
@@ -110,25 +104,23 @@ public class PadSettingsViewController extends ViewController implements IPadSet
 
 	@Override
 	public boolean closeRequest() {
-		saveChanges();
-
-		// Listener
-		PlayPadPlugin.getImplementation().getPadSettingsViewListener().forEach(l -> l.onClose(this));
+		onFinish();
 		return true;
 	}
 
-	private void saveChanges() {
-		for (PadSettingsTabViewController controller : tabs) {
-			controller.saveSettings(pad);
-		}
-	}
-
 	@FXML
 	private void finishButtonHandler(ActionEvent event) {
-		saveChanges();
-		// Listener
-		PlayPadPlugin.getImplementation().getPadSettingsViewListener().forEach(l -> l.onClose(this));
-		getStage().close();
+		onFinish();
 	}
 
+	/**
+	 * Diese Methode wird aufgerufen, wenn das Fenster geschlossen wird (Per X oder Finish Button). Hier geschehen alle Aktionen zum
+	 * manuellen Speichern.
+	 */
+	private void onFinish() {
+		// Speichern der einzelen Tabs
+		for (PadSettingsTabViewController controller : tabs) {
+			controller.saveSettings(pad);
+		}
+	}
 }
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java b/PlayWall/src/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java
index 6c6274b3da4766dfbba104f2a49e2f59a0648e8c..4cae57b156b833e7b8eb572b7830a9c0a8bbed94 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java
@@ -2,9 +2,9 @@ package de.tobias.playpad.viewcontroller.option.pad;
 
 import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.pad.Fade;
 import de.tobias.playpad.pad.Pad;
-import de.tobias.playpad.pad.Warning;
+import de.tobias.playpad.settings.Fade;
+import de.tobias.playpad.settings.Warning;
 import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
 import de.tobias.playpad.viewcontroller.settings.FadeViewController;
 import de.tobias.playpad.viewcontroller.settings.WarningFeedbackViewController;
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/pad/PadViewController.java b/PlayWall/src/de/tobias/playpad/viewcontroller/pad/PadViewController.java
index e39abcda8c007b79c7a00ea961ba37d1f39a8b73..1f112d73fd2f853ef34bd99a3fe91cb7ed3d676e 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/pad/PadViewController.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/pad/PadViewController.java
@@ -54,6 +54,7 @@ public class PadViewController implements EventHandler<ActionEvent>, IPadViewCon
 	private PadPositionListener padPositionListener;
 
 	private PadDragListener padDragListener;
+	private transient PadSettingsViewController padSettingsViewController;
 
 	public PadViewController() {
 		view = new PadView(this);
@@ -183,13 +184,15 @@ public class PadViewController implements EventHandler<ActionEvent>, IPadViewCon
 			}
 
 			Stage owner = mvc.getStage();
-			PadSettingsViewController controller = new PadSettingsViewController(pad, owner);
-			controller.getStage().setOnHiding(ev ->
-			{
-				if (view != null && pad != null)
-					view.setTriggerLabelActive(pad.hasTriggerItems());
-			});
-			controller.getStage().show();
+			if (padSettingsViewController == null) {
+				padSettingsViewController = new PadSettingsViewController(pad, owner);
+				padSettingsViewController.getStage().setOnHiding(ev ->
+				{
+					if (view != null && pad != null)
+						view.setTriggerLabelActive(pad.hasTriggerItems());
+				});
+			}
+			padSettingsViewController.getStage().show();
 		}
 	}
 
@@ -230,7 +233,7 @@ public class PadViewController implements EventHandler<ActionEvent>, IPadViewCon
 	@Override
 	public void setPad(Pad pad) {
 		unconnectPad();
-		
+
 		this.pad = pad;
 
 		view.setPreviewContent(pad);
diff --git a/PlayWall/src/de/tobias/playpad/viewcontroller/settings/FadeViewController.java b/PlayWall/src/de/tobias/playpad/viewcontroller/settings/FadeViewController.java
index 2a4ee9720e830b10eedb994e8534521a945c4ec2..dfa3c7331e8bdaf6eef9bc609d9f2e3bdbf92cc0 100644
--- a/PlayWall/src/de/tobias/playpad/viewcontroller/settings/FadeViewController.java
+++ b/PlayWall/src/de/tobias/playpad/viewcontroller/settings/FadeViewController.java
@@ -2,7 +2,7 @@ package de.tobias.playpad.viewcontroller.settings;
 
 import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.pad.Fade;
+import de.tobias.playpad.settings.Fade;
 import de.tobias.utils.ui.ContentViewController;
 import de.tobias.utils.util.Localization;
 import javafx.fxml.FXML;
diff --git a/PlayWall/src/icon.icns b/PlayWall/src/icon.icns
index 0b82f6e32cec646a917652b1f7438fe6d9814b27..bf25eb296be13a7463ef87e9e2ec679dc4074607 100644
Binary files a/PlayWall/src/icon.icns and b/PlayWall/src/icon.icns differ
diff --git a/PlayWall/src/icon.ico b/PlayWall/src/icon.ico
index 376f9b44f0795408da217e99f1ad84c7f8382ba1..c890577816398684f920181cadb73af23c3e0b40 100644
Binary files a/PlayWall/src/icon.ico and b/PlayWall/src/icon.ico differ
diff --git a/PlayWall/src/icon.png b/PlayWall/src/icon.png
index e2fe4bc8d837c9cb9a166b85503af202dbf4331f..63b9171fd055ac52d6736f627d13b394f4ac289c 100644
Binary files a/PlayWall/src/icon.png and b/PlayWall/src/icon.png differ
diff --git a/PlayWall/src/icon_small.png b/PlayWall/src/icon_small.png
index e8acf8263a66f86581c5b5f65f0ad11ff11bf60b..d219f3f9f51865239f3be85dbae5cd342955b833 100644
Binary files a/PlayWall/src/icon_small.png and b/PlayWall/src/icon_small.png differ
diff --git a/PlayWallCore/.gitignore b/PlayWallCore/.gitignore
index 94faa17313fb07d638498de2460e291e5d826ed9..960394d9f74e222f50aa4ef2f6b9929f3422feda 100644
--- a/PlayWallCore/.gitignore
+++ b/PlayWallCore/.gitignore
@@ -1,2 +1,3 @@
 /bin/
-/test/
\ No newline at end of file
+/test/
+/doc/
diff --git a/PlayWallCore/src/de/tobias/playpad/PlayPad.java b/PlayWallCore/src/de/tobias/playpad/PlayPad.java
index e0a6546cd2cc96a749fd7c4b648e4c946c6ecf9d..877bd5d97fc07a4e84b89911fa0c063e8663033c 100644
--- a/PlayWallCore/src/de/tobias/playpad/PlayPad.java
+++ b/PlayWallCore/src/de/tobias/playpad/PlayPad.java
@@ -1,21 +1,27 @@
 package de.tobias.playpad;
 
+import java.net.URI;
 import java.util.List;
 import java.util.Optional;
 
 import de.tobias.playpad.plugin.PadListener;
 import de.tobias.playpad.plugin.SettingsListener;
 import de.tobias.playpad.plugin.WindowListener;
-import de.tobias.playpad.viewcontroller.IPadSettingsViewController;
-import de.tobias.playpad.viewcontroller.ISettingsViewController;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import javafx.scene.image.Image;
-import net.xeoh.plugins.base.PluginManager;
 
+/**
+ * Hauptfunktionen für Listener und zur Programmsteuerung für Plugins.
+ * 
+ * @author tobias
+ * 
+ * @since 5.0.0
+ *
+ */
 public interface PlayPad {
 
 	/**
-	 * Fügt einen Listener für das Hauptfenster hinzu
+	 * Fügt einen Listener für das Hauptfenster hinzu.
 	 * 
 	 * @param listener
 	 * 
@@ -24,85 +30,80 @@ public interface PlayPad {
 	public void addMainViewListener(WindowListener<IMainViewController> listener);
 
 	/**
-	 * Entfernt ein registrierten Listener des Hauptfensters
+	 * Fügt einen Settings Listener hinzu.
 	 * 
 	 * @param listener
 	 * 
 	 * @since 2.0.0
 	 */
-	public void removeMainViewListener(WindowListener<IMainViewController> listener);
+	public void addSettingsListener(SettingsListener listener);
 
 	/**
-	 * Fügt einen Listener zum Settings Fenster hinzu
+	 * Entfernt einen Settings Listener.
 	 * 
 	 * @param listener
 	 * 
 	 * @since 2.0.0
 	 */
-	public void addSettingsViewListener(WindowListener<ISettingsViewController> listener);
+	public void removeSettingsListener(SettingsListener listener);
 
 	/**
-	 * Entfernt einen Listener des Settings Fensters
-	 * 
-	 * @param listener
+	 * Gibt alle SettingListener zurück.
 	 * 
-	 * @since 2.0.0
+	 * @return Settingslistener
 	 */
-	public void removeSettingsViewListener(WindowListener<ISettingsViewController> listener);
-
-	public List<WindowListener<ISettingsViewController>> getSettingsViewListener();
+	public List<SettingsListener> getSettingsListener();
 
 	/**
-	 * Fügt einen Listener zum PadSettings Fenster hinzu
+	 * Fügt ein PadListener zum System hinzu. Der Listener gilt für alle Pads.
 	 * 
 	 * @param listener
-	 * 
-	 * @since 2.0.0
+	 *            Listener
+	 * @since 5.0.0
 	 */
-	public void addPadSettingsViewListener(WindowListener<IPadSettingsViewController> listener);
+	public void addPadListener(PadListener listener);
 
 	/**
-	 * Entfernt einen Listener vom PadSettings Fenster
+	 * Entfernt ein Pad Listener.
 	 * 
 	 * @param listener
-	 * 
-	 * @since 2.0.0
+	 *            Listener
 	 */
-	public void removePadSettingsViewListener(WindowListener<IPadSettingsViewController> listener);
-
-	public List<WindowListener<IPadSettingsViewController>> getPadSettingsViewListener();
+	public void removePadListener(PadListener listener);
 
 	/**
-	 * Fügt einen Settings Listener hinzu
+	 * Gibt alle PadListener zurück.
 	 * 
-	 * @param listener
+	 * @return PadListener
 	 * 
-	 * @since 2.0.0
+	 * @see 5.0.0
 	 */
-	public void addSettingsListener(SettingsListener listener);
+	public List<PadListener> getPadListener();
 
 	/**
-	 * Entfernt einen Settings Listener
+	 * Gibt eine Refernz auf das Hauptfenster zurück.
 	 * 
-	 * @param listener
-	 * 
-	 * @since 2.0.0
+	 * @return Main ViewController
 	 */
-	public void removeSettingsListener(SettingsListener listener);
-
-	public List<SettingsListener> getSettingsListener();
-
-	public void addPadListener(PadListener listener);
-
-	public void removePadListener(PadListener listener);
-
-	public List<PadListener> getPadListener();
-
 	public IMainViewController getMainViewController();
 
-	public PluginManager getPluginManager();
+	/**
+	 * Gibt das Programm Icon zurück.
+	 * 
+	 * @return Programmicon
+	 */
+	public Optional<Image> getIcon();
 
-	public String[] getProjectFiles();
+	/**
+	 * Beendet PlayWall.
+	 */
+	public void shutdown();
 
-	public Optional<Image> getIcon();
+	/**
+	 * Lädt ein Plugin sofort ins System.
+	 * 
+	 * @param uri
+	 *            Quelle des Plugin
+	 */
+	public void loadPlugin(URI uri);
 }
diff --git a/PlayWallCore/src/de/tobias/playpad/action/ActionSerializer.java b/PlayWallCore/src/de/tobias/playpad/action/ActionSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca46cf05a6719eeaf52ac4800910b48596c31553
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/action/ActionSerializer.java
@@ -0,0 +1,51 @@
+package de.tobias.playpad.action;
+
+import java.util.List;
+
+import org.dom4j.Element;
+
+import de.tobias.playpad.action.mapper.Mapper;
+import de.tobias.playpad.xml.XMLDeserializer;
+import de.tobias.playpad.xml.XMLHandler;
+import de.tobias.playpad.xml.XMLSerializer;
+
+public class ActionSerializer implements XMLSerializer<Action>, XMLDeserializer<Action> {
+
+	private static final String ACTION_TYPE = "type";
+	private static final String MAPPER = "Mapper";
+
+	private Mapping mapping;
+
+	public ActionSerializer(Mapping mapping) {
+		this.mapping = mapping;
+	}
+
+	@Override
+	public Action loadElement(Element element) {
+		String tpye = element.attributeValue(ACTION_TYPE);
+
+		Action action = ActionRegistery.getActionConnect(tpye).newInstance();
+		action.load(element);
+
+		boolean added = mapping.addActionIfNotContains(action);
+
+		if (added) {
+			XMLHandler<Mapper> handler = new XMLHandler<>(element);
+			List<Mapper> mappers = handler.loadElements(MAPPER, new MapperSerializer(action));
+			mappers.forEach(action::addMapper);
+		}
+
+		return action;
+	}
+
+	@Override
+	public void saveElement(Element newElement, Action data) {
+		newElement.addAttribute(ACTION_TYPE, data.getType());
+
+		data.save(newElement);
+
+		XMLHandler<Mapper> handler = new XMLHandler<>(newElement);
+		handler.saveElements(MAPPER, data.getMappers(), new MapperSerializer(data));
+	}
+
+}
diff --git a/PlayWallCore/src/de/tobias/playpad/action/MapperSerializer.java b/PlayWallCore/src/de/tobias/playpad/action/MapperSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..c9b60ef86ddb4c0bc8895726bda8a2da324a3fc8
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/action/MapperSerializer.java
@@ -0,0 +1,36 @@
+package de.tobias.playpad.action;
+
+import org.dom4j.Element;
+
+import de.tobias.playpad.action.mapper.Mapper;
+import de.tobias.playpad.action.mapper.MapperRegistry;
+import de.tobias.playpad.xml.XMLDeserializer;
+import de.tobias.playpad.xml.XMLSerializer;
+
+public class MapperSerializer implements XMLSerializer<Mapper>, XMLDeserializer<Mapper> {
+
+	private static final String MAPPER_TYPE = "type";
+
+	private Action action;
+
+	public MapperSerializer(Action action) {
+		this.action = action;
+	}
+
+	@Override
+	public Mapper loadElement(Element element) {
+		String mapperType = element.attributeValue(MAPPER_TYPE);
+
+		Mapper mapper = MapperRegistry.getMapperConnect(mapperType).createNewMapper();
+		mapper.load(element, action);
+		return mapper;
+	}
+
+	@Override
+	public void saveElement(Element newElement, Mapper data) {
+		newElement.addAttribute(MAPPER_TYPE, data.getType());
+		data.save(newElement, action);
+
+	}
+
+}
diff --git a/PlayWallCore/src/de/tobias/playpad/action/Mapping.java b/PlayWallCore/src/de/tobias/playpad/action/Mapping.java
index b451611d56c5073846b874c42e7f1d2f30123f20..ccfe4072ff62b21e960c0358bf915f196cdfd884 100644
--- a/PlayWallCore/src/de/tobias/playpad/action/Mapping.java
+++ b/PlayWallCore/src/de/tobias/playpad/action/Mapping.java
@@ -7,8 +7,6 @@ import java.util.Set;
 import java.util.UUID;
 import java.util.stream.Collectors;
 
-import org.dom4j.Element;
-
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.action.mapper.Mapper;
 import de.tobias.playpad.action.mapper.MapperConnect;
@@ -160,68 +158,6 @@ public class Mapping implements Cloneable, ActionDisplayable {
 		getActions().forEach(action -> action.clearFeedback());
 	}
 
-	private static final String NAME = "name";
-	private static final String UUID_NAME = "uuid";
-	private static final String ACTION = "Action";
-	private static final String ACTION_TYPE = "type";
-	private static final String MAPPER = "Mapper";
-	private static final String MAPPER_TYPE = "type";
-
-	public void load(Element element, Profile profile) {
-		name = element.attributeValue(NAME);
-		if (element.attributeValue(UUID_NAME) != null)
-			uuid = UUID.fromString(element.attributeValue(UUID_NAME));
-		else
-			uuid = UUID.randomUUID();
-
-		for (Object obj : element.elements(ACTION)) {
-			if (obj instanceof Element) {
-				Element actionElement = (Element) obj;
-				String tpye = actionElement.attributeValue(ACTION_TYPE);
-
-				Action action = ActionRegistery.getActionConnect(tpye).newInstance();
-				action.load(actionElement);
-
-				boolean added = addActionIfNotContains(action);
-
-				if (added) {
-					for (Object mapperObj : actionElement.elements(MAPPER)) {
-						if (mapperObj instanceof Element) {
-							Element mapperElement = (Element) mapperObj;
-							String mapperType = mapperElement.attributeValue(MAPPER_TYPE);
-
-							Mapper mapper = MapperRegistry.getMapperConnect(mapperType).createNewMapper();
-							mapper.load(mapperElement, action);
-							action.addMapper(mapper);
-						}
-					}
-				}
-			}
-		}
-
-		initActionType(profile); // Update Actions, damit alle da sind und keine fehlt (falls eine gelöscht wurde auf der Datei)
-		updateDisplayProperty();
-	}
-
-	public void save(Element element) {
-		element.addAttribute(NAME, name);
-		element.addAttribute(UUID_NAME, uuid.toString());
-
-		for (Action action : mapping.keySet()) {
-			Element actionElement = element.addElement(ACTION);
-			actionElement.addAttribute(ACTION_TYPE, action.getType());
-
-			action.save(actionElement);
-
-			for (Mapper mapper : mapping.get(action)) {
-				Element mapperElement = actionElement.addElement(MAPPER);
-				mapperElement.addAttribute(MAPPER_TYPE, mapper.getType());
-
-				mapper.save(mapperElement, action);
-			}
-		}
-	}
-
 	@Override
 	public Mapping clone() throws CloneNotSupportedException {
 		Mapping clone = (Mapping) super.clone();
@@ -256,7 +192,7 @@ public class Mapping implements Cloneable, ActionDisplayable {
 		return displayProperty;
 	}
 
-	private void updateDisplayProperty() {
+	void updateDisplayProperty() {
 		displayProperty.set(toString());
 	}
 }
diff --git a/PlayWallCore/src/de/tobias/playpad/action/MappingList.java b/PlayWallCore/src/de/tobias/playpad/action/MappingList.java
index 05517382dc227e540d93b8e2211a2b19c7ab0ba9..542f990dd43b94f82651f87c102881f3ff40cd0c 100644
--- a/PlayWallCore/src/de/tobias/playpad/action/MappingList.java
+++ b/PlayWallCore/src/de/tobias/playpad/action/MappingList.java
@@ -5,6 +5,7 @@ import java.io.UnsupportedEncodingException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.UUID;
 
 import org.dom4j.Document;
@@ -16,6 +17,7 @@ import org.dom4j.io.SAXReader;
 import org.dom4j.io.XMLWriter;
 
 import de.tobias.playpad.settings.Profile;
+import de.tobias.playpad.xml.XMLHandler;
 
 public class MappingList extends ArrayList<Mapping> {
 
@@ -62,16 +64,16 @@ public class MappingList extends ArrayList<Mapping> {
 				mappings.activeMapping = UUID.fromString(rootElement.attributeValue(ACTIVE_ATTR));
 			}
 
-			for (Object mappingObj : rootElement.elements(MAPPING)) {
-				if (mappingObj instanceof Element) {
-					Element mappingElement = (Element) mappingObj;
-
-					Mapping mapping = new Mapping(false, profile);
-					mapping.load(mappingElement, profile);
-
-					mappings.add(mapping);
-				}
-			}
+			// Load Mappings
+			XMLHandler<Mapping> handler = new XMLHandler<>(rootElement);
+			List<Mapping> loadMappings = handler.loadElements(MAPPING, new MappingSerializer(profile));
+			loadMappings.forEach(mapping ->
+			{
+				mapping.initActionType(profile); // Update Actions, damit alle da sind und keine fehlt (falls eine
+													// gelöscht wurde auf der Datei)
+				mapping.updateDisplayProperty();
+				mappings.add(mapping);
+			});
 		}
 
 		// Init mappings, if non exists
@@ -89,14 +91,9 @@ public class MappingList extends ArrayList<Mapping> {
 		if (activeMapping != null)
 			rootElement.addAttribute(ACTIVE_ATTR, activeMapping.toString());
 
-		for (Mapping mapping : this) {
-			Element mappingElement = rootElement.addElement(MAPPING);
-			mapping.save(mappingElement);
-		}
-
-		XMLWriter writer = new XMLWriter(Files.newOutputStream(path), OutputFormat.createPrettyPrint());
-		writer.write(document);
-		writer.close();
+		XMLHandler<Mapping> handler = new XMLHandler<>(rootElement);
+		handler.saveElements(MAPPING, this, new MappingSerializer());
+		XMLHandler.save(path, document);
 	}
 
 	public static Mapping importMappingPreset(Path path, Profile profile) throws DocumentException, IOException {
@@ -106,7 +103,8 @@ public class MappingList extends ArrayList<Mapping> {
 		Document document = reader.read(Files.newInputStream(path));
 		Element rootElement = document.getRootElement();
 
-		mapping.load(rootElement, profile);
+		MappingSerializer mappingSerializer = new MappingSerializer(profile);
+		mapping = mappingSerializer.loadElement(rootElement);		
 		mapping.setUuid(UUID.randomUUID());
 
 		return mapping;
@@ -115,7 +113,9 @@ public class MappingList extends ArrayList<Mapping> {
 	public static void exportMidiPreset(Path path, Mapping preset) throws IOException {
 		Document docoment = DocumentHelper.createDocument();
 		Element rootElement = docoment.addElement(MAPPING);
-		preset.save(rootElement);
+
+		MappingSerializer mappingSerializer = new MappingSerializer();
+		mappingSerializer.saveElement(rootElement, preset);
 
 		XMLWriter writer = new XMLWriter(Files.newOutputStream(path), OutputFormat.createPrettyPrint());
 		writer.write(docoment);
diff --git a/PlayWallCore/src/de/tobias/playpad/action/MappingSerializer.java b/PlayWallCore/src/de/tobias/playpad/action/MappingSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..e1885680e2aed52d687d4cb6d4cdf0fb52a18382
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/action/MappingSerializer.java
@@ -0,0 +1,55 @@
+package de.tobias.playpad.action;
+
+import java.util.UUID;
+
+import org.dom4j.Element;
+
+import de.tobias.playpad.settings.Profile;
+import de.tobias.playpad.xml.XMLDeserializer;
+import de.tobias.playpad.xml.XMLHandler;
+import de.tobias.playpad.xml.XMLSerializer;
+
+public class MappingSerializer implements XMLSerializer<Mapping>, XMLDeserializer<Mapping> {
+
+	private static final String NAME = "name";
+	private static final String UUID_NAME = "uuid";
+	private static final String ACTION = "Action";
+
+	private Profile profile;
+
+	public MappingSerializer() {
+
+	}
+
+	public MappingSerializer(Profile profile) {
+		this.profile = profile;
+	}
+
+	@Override
+	public Mapping loadElement(Element element) {
+		Mapping mapping = new Mapping(false, profile);
+
+		mapping.setName(element.attributeValue(NAME));
+
+		UUID uuid;
+		if (element.attributeValue(UUID_NAME) != null)
+			uuid = UUID.fromString(element.attributeValue(UUID_NAME));
+		else
+			uuid = UUID.randomUUID();
+		mapping.setUuid(uuid);
+
+		XMLHandler<Action> handler = new XMLHandler<>(element);
+		handler.loadElements(ACTION, new ActionSerializer(mapping));
+
+		return mapping;
+	}
+
+	@Override
+	public void saveElement(Element newElement, Mapping data) {
+		newElement.addAttribute(NAME, data.getName());
+		newElement.addAttribute(UUID_NAME, data.getUuid().toString());
+
+		XMLHandler<Action> handler = new XMLHandler<>(newElement);
+		handler.saveElements(ACTION, data.getActions(), new ActionSerializer(data));
+	}
+}
diff --git a/PlayWallCore/src/de/tobias/playpad/layout/CartLayout.java b/PlayWallCore/src/de/tobias/playpad/layout/CartLayout.java
index 851d42c6e2ec04a1d056b6b28d3bdd9607e6dab1..9f9fabc5ddee03ced42dca9441a1e62c451fd8f9 100644
--- a/PlayWallCore/src/de/tobias/playpad/layout/CartLayout.java
+++ b/PlayWallCore/src/de/tobias/playpad/layout/CartLayout.java
@@ -2,8 +2,8 @@ package de.tobias.playpad.layout;
 
 import org.dom4j.Element;
 
-import de.tobias.playpad.pad.Warning;
 import de.tobias.playpad.pad.view.IPadViewController;
+import de.tobias.playpad.settings.Warning;
 
 public interface CartLayout {
 
@@ -25,11 +25,11 @@ public interface CartLayout {
 	 * @param controller
 	 * @param warning
 	 */
-	public abstract void handleWarning(IPadViewController controller, Warning warning);
+	public abstract void handleWarning(IPadViewController controller, Warning warning, GlobalLayout animate);
 
 	public default void stopWarning(IPadViewController controller) {}
 
 	public void reset();
-	
+
 	public void copyGlobalLayout(GlobalLayout globalLayout);
 }
diff --git a/PlayWallCore/src/de/tobias/playpad/layout/GlobalLayout.java b/PlayWallCore/src/de/tobias/playpad/layout/GlobalLayout.java
index 8622bca5cdd319fd08d446261301b58052d5b4aa..e7b95f72544c09c02a9168923ffc74bdacdffb0a 100644
--- a/PlayWallCore/src/de/tobias/playpad/layout/GlobalLayout.java
+++ b/PlayWallCore/src/de/tobias/playpad/layout/GlobalLayout.java
@@ -14,9 +14,9 @@ import org.dom4j.io.OutputFormat;
 import org.dom4j.io.SAXReader;
 import org.dom4j.io.XMLWriter;
 
-import de.tobias.playpad.pad.Warning;
 import de.tobias.playpad.pad.view.IPadViewController;
 import de.tobias.playpad.project.Project;
+import de.tobias.playpad.settings.Warning;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import javafx.stage.Stage;
 
diff --git a/PlayWallCore/src/de/tobias/playpad/pad/Pad.java b/PlayWallCore/src/de/tobias/playpad/pad/Pad.java
index 71dbdce75429f5ed3679a906edc08ba57b5a5856..ae4adf2d2df16e8188455b46ec81dc8f01df1aa1 100644
--- a/PlayWallCore/src/de/tobias/playpad/pad/Pad.java
+++ b/PlayWallCore/src/de/tobias/playpad/pad/Pad.java
@@ -3,23 +3,20 @@ package de.tobias.playpad.pad;
 import java.nio.file.Path;
 import java.util.HashMap;
 
-import org.dom4j.Element;
-
 import de.tobias.playpad.layout.CartLayout;
 import de.tobias.playpad.layout.LayoutRegistry;
 import de.tobias.playpad.pad.conntent.PadContent;
-import de.tobias.playpad.pad.conntent.PadContentRegistry;
 import de.tobias.playpad.pad.conntent.Pauseable;
-import de.tobias.playpad.pad.conntent.UnkownPadContentException;
 import de.tobias.playpad.pad.triggerlistener.PadTriggerContentListener;
 import de.tobias.playpad.pad.triggerlistener.PadTriggerDurationListener;
 import de.tobias.playpad.pad.triggerlistener.PadTriggerStatusListener;
 import de.tobias.playpad.pad.view.IPadViewController;
 import de.tobias.playpad.project.Project;
+import de.tobias.playpad.settings.Fade;
 import de.tobias.playpad.settings.Profile;
+import de.tobias.playpad.settings.Warning;
 import de.tobias.playpad.tigger.Trigger;
 import de.tobias.playpad.tigger.TriggerPoint;
-import de.tobias.utils.settings.UserDefaults;
 import javafx.beans.binding.BooleanBinding;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
@@ -73,9 +70,8 @@ public class Pad {
 	private transient IPadViewController controller;
 	private transient Project project;
 
-	public Pad(Project project, Element element) {
+	public Pad(Project project) {
 		this.project = project;
-		load(element);
 
 		initPadListener();
 		// Update Trigger ist nicht notwendig, da es in load(Element) ausgerufen wird
@@ -373,7 +369,7 @@ public class Pad {
 		this.ignoreTrigger = ignoreTrigger;
 	}
 
-	private void updateTrigger() {
+	void updateTrigger() {
 		for (TriggerPoint point : TriggerPoint.values()) {
 			if (!triggers.containsKey(point)) {
 				Trigger trigger = new Trigger(point);
@@ -418,163 +414,6 @@ public class Pad {
 		}
 	}
 
-	// Storage
-	private static final String INDEX_ATTR = "index";
-	private static final String NAME_ATTR = "name";
-	private static final String STATUS_ATTR = "status";
-
-	private static final String SETTINGS_ELEMENT = "Settings";
-	private static final String VOLUME_ELEMENT = "Volume";
-	private static final String LOOP_ELEMENT = "Loop";
-	private static final String TIMEMODE_ELEMENT = "TimeMode";
-	private static final String FADE_ELEMENT = "Fade";
-	private static final String WARNING_ELEMENT = "Warning";
-
-	private static final String LAYOUTS_ELEMENT = "Layouts";
-	private static final String LAYOUT_ACTIVE_ATTR = "active";
-	private static final String LAYOUT_TYPE_ATTR = "type";
-	private static final String LAYOUT_ELEMENT = "Layout";
-
-	private static final String CUSTOM_SETTINGS_ITEM_ELEMENT = "Item";
-	private static final String CUSTOM_SETTINGS_TYPE_ATTR = "key";
-	private static final String CUSTOM_SETTINGS_ELEMENT = "CustomSettings";
-
-	public static final String CONTENT_ELEMENT = "Content";
-	private static final String CONTENT_TYPE_ATTR = "type";
-
-	public void load(Element element) {
-		indexProperty.set(Integer.valueOf(element.attributeValue(INDEX_ATTR)));
-		nameProperty.set(element.attributeValue(NAME_ATTR));
-		PadStatus status = PadStatus.valueOf(element.attributeValue(STATUS_ATTR));
-		if (status == PadStatus.EMPTY || status == PadStatus.READY)
-			statusProperty.set(status);
-
-		// Settings
-		Element settingsElement = element.element(SETTINGS_ELEMENT);
-		if (settingsElement.element(VOLUME_ELEMENT) != null)
-			volumeProperty.set(Double.valueOf(settingsElement.element(VOLUME_ELEMENT).getStringValue()));
-		if (settingsElement.element(LOOP_ELEMENT) != null)
-			loopProperty.set(Boolean.valueOf(settingsElement.element(LOOP_ELEMENT).getStringValue()));
-		if (settingsElement.element(TIMEMODE_ELEMENT) != null)
-			timeModeProperty.set(TimeMode.valueOf(settingsElement.element(TIMEMODE_ELEMENT).getStringValue()));
-		if (settingsElement.element(FADE_ELEMENT) != null)
-			fadeProperty.set(Fade.load(settingsElement.element(FADE_ELEMENT)));
-		if (settingsElement.element(WARNING_ELEMENT) != null)
-			warningProperty.set(Warning.load(settingsElement.element(WARNING_ELEMENT)));
-
-		// Laoyut
-		Element layoutsElement = settingsElement.element(LAYOUTS_ELEMENT);
-		if (layoutsElement != null) {
-			if (layoutsElement.attributeValue(LAYOUT_ACTIVE_ATTR) != null) {
-				customLayoutProperty.set(Boolean.valueOf(layoutsElement.attributeValue(LAYOUT_ACTIVE_ATTR)));
-			}
-
-			for (Object layoutObj : layoutsElement.elements(LAYOUT_ELEMENT)) {
-				if (layoutObj instanceof Element) {
-					Element layoutElement = (Element) layoutObj;
-					String type = layoutElement.attributeValue(LAYOUT_TYPE_ATTR);
-					CartLayout layout = LayoutRegistry.getLayout(type).newCartLayout();
-					layout.load(layoutElement);
-
-					layouts.put(type, layout);
-				}
-			}
-		}
-
-		Element userInfoElement = settingsElement.element(CUSTOM_SETTINGS_ELEMENT);
-		if (userInfoElement != null) {
-			for (Object object : userInfoElement.elements()) {
-				if (object instanceof Element) {
-					Element item = (Element) object;
-					String key = item.attributeValue(CUSTOM_SETTINGS_TYPE_ATTR);
-					Object data = UserDefaults.loadElement(item);
-					customSettings.put(key, data);
-				}
-			}
-		}
-
-		// Trigger
-		Element triggersElement = element.element("Triggers");			// TODO Externalize
-		if (triggersElement != null) {
-			for (Object triggerObj : triggersElement.elements("Trigger")) {
-				if (triggerObj instanceof Element) {
-					Element triggerElement = (Element) triggerObj;
-					Trigger trigger = new Trigger();
-					trigger.load(triggerElement);
-					triggers.put(trigger.getTriggerPoint(), trigger);
-				}
-			}
-		}
-		updateTrigger(); // Damit alle Points da sind
-
-		// Content
-		Element contentElement = element.element(CONTENT_ELEMENT);
-		if (contentElement != null) {
-			String contentType = contentElement.attributeValue(CONTENT_TYPE_ATTR);
-			try {
-				PadContent content = PadContentRegistry.getPadContentConnect(contentType).newInstance(this);
-				content.load(contentElement);
-				setContent(content);
-			} catch (UnkownPadContentException e) {
-				e.printStackTrace();
-				throwException(null, e);
-			}
-		}
-	}
-
-	public void save(Element element) {
-		element.addAttribute(INDEX_ATTR, String.valueOf(indexProperty.get()));
-		element.addAttribute(NAME_ATTR, nameProperty.get());
-		if (statusProperty.get() == PadStatus.EMPTY || statusProperty.get() == PadStatus.ERROR) {
-			element.addAttribute(STATUS_ATTR, PadStatus.EMPTY.name());
-		} else {
-			element.addAttribute(STATUS_ATTR, PadStatus.READY.name());
-		}
-
-		// Settings
-		Element settingsElement = element.addElement(SETTINGS_ELEMENT);
-		settingsElement.addElement(VOLUME_ELEMENT).addText(String.valueOf(volumeProperty.get()));
-		settingsElement.addElement(LOOP_ELEMENT).addText(String.valueOf(loopProperty.get()));
-		if (timeModeProperty.isNotNull().get())
-			settingsElement.addElement(TIMEMODE_ELEMENT).addText(String.valueOf(timeModeProperty.get()));
-		if (warningProperty.isNotNull().get())
-			warningProperty.get().save(settingsElement.addElement(WARNING_ELEMENT));
-		if (fadeProperty.isNotNull().get())
-			fadeProperty.get().save(settingsElement.addElement(FADE_ELEMENT));
-
-		// Layout
-		Element layoutsElement = settingsElement.addElement(LAYOUTS_ELEMENT);
-		layoutsElement.addAttribute(LAYOUT_ACTIVE_ATTR, String.valueOf(customLayoutProperty.get()));
-		for (String layoutType : layouts.keySet()) {
-			Element layoutElement = layoutsElement.addElement(LAYOUT_ELEMENT);
-			layoutElement.addAttribute(LAYOUT_TYPE_ATTR, layoutType);
-
-			CartLayout cartLayout = layouts.get(layoutType);
-			cartLayout.save(layoutElement);
-		}
-
-		Element userInfoElement = settingsElement.addElement(CUSTOM_SETTINGS_ELEMENT);
-		for (String key : customSettings.keySet()) {
-			Element itemElement = userInfoElement.addElement(CUSTOM_SETTINGS_ITEM_ELEMENT);
-			UserDefaults.save(itemElement, customSettings.get(key), key);
-		}
-
-		// Trigger
-		Element triggersElement = element.addElement("Triggers");
-		for (TriggerPoint point : triggers.keySet()) {
-			Trigger trigger = triggers.get(point);
-			Element triggerElement = triggersElement.addElement("Trigger");
-			trigger.save(triggerElement);
-		}
-
-		// Content
-		if (contentProperty.get() != null) {
-			Element contentElement = element.addElement(CONTENT_ELEMENT);
-			contentElement.addAttribute(CONTENT_TYPE_ATTR, contentProperty.get().getType());
-			contentProperty.get().save(contentElement);
-		}
-	}
-
 	@Override
 	public String toString() {
 		return "Pad: " + indexProperty.get() + " - " + nameProperty.get();
@@ -596,4 +435,8 @@ public class Pad {
 	public DoubleProperty customVolumeProperty() {
 		return customVolumeProperty;
 	}
+
+	HashMap<String, CartLayout> getLayouts() {
+		return layouts;
+	}
 }
diff --git a/PlayWallCore/src/de/tobias/playpad/pad/PadSerializer.java b/PlayWallCore/src/de/tobias/playpad/pad/PadSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..298456087dcecb18d89aa53c655a4472979a247d
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/pad/PadSerializer.java
@@ -0,0 +1,191 @@
+package de.tobias.playpad.pad;
+
+import org.dom4j.Element;
+
+import de.tobias.playpad.layout.CartLayout;
+import de.tobias.playpad.layout.LayoutRegistry;
+import de.tobias.playpad.pad.conntent.PadContent;
+import de.tobias.playpad.pad.conntent.PadContentRegistry;
+import de.tobias.playpad.pad.conntent.UnkownPadContentException;
+import de.tobias.playpad.project.Project;
+import de.tobias.playpad.settings.Fade;
+import de.tobias.playpad.settings.Warning;
+import de.tobias.playpad.tigger.Trigger;
+import de.tobias.playpad.tigger.TriggerPoint;
+import de.tobias.playpad.xml.XMLDeserializer;
+import de.tobias.playpad.xml.XMLSerializer;
+import de.tobias.utils.settings.UserDefaults;
+
+public class PadSerializer implements XMLSerializer<Pad>, XMLDeserializer<Pad> {
+
+	private static final String INDEX_ATTR = "index";
+	private static final String NAME_ATTR = "name";
+	private static final String STATUS_ATTR = "status";
+
+	private static final String SETTINGS_ELEMENT = "Settings";
+	private static final String VOLUME_ELEMENT = "Volume";
+	private static final String LOOP_ELEMENT = "Loop";
+	private static final String TIMEMODE_ELEMENT = "TimeMode";
+	private static final String FADE_ELEMENT = "Fade";
+	private static final String WARNING_ELEMENT = "Warning";
+
+	private static final String LAYOUTS_ELEMENT = "Layouts";
+	private static final String LAYOUT_ACTIVE_ATTR = "active";
+	private static final String LAYOUT_TYPE_ATTR = "type";
+	private static final String LAYOUT_ELEMENT = "Layout";
+
+	private static final String CUSTOM_SETTINGS_ITEM_ELEMENT = "Item";
+	private static final String CUSTOM_SETTINGS_TYPE_ATTR = "key";
+	private static final String CUSTOM_SETTINGS_ELEMENT = "CustomSettings";
+
+	public static final String CONTENT_ELEMENT = "Content";
+	private static final String CONTENT_TYPE_ATTR = "type";
+
+	// TODO Remove project var
+	private Project project;
+
+	public PadSerializer(Project project) {
+		this.project = project;
+	}
+
+	public PadSerializer() {}
+
+	@Override
+	public Pad loadElement(Element element) {
+		Pad pad = new Pad(project);
+
+		pad.setIndex(Integer.valueOf(element.attributeValue(INDEX_ATTR)));
+		pad.setName(element.attributeValue(NAME_ATTR));
+		PadStatus status = PadStatus.valueOf(element.attributeValue(STATUS_ATTR));
+		if (status == PadStatus.EMPTY || status == PadStatus.READY)
+			pad.setStatus(status);
+
+		// Settings
+		Element settingsElement = element.element(SETTINGS_ELEMENT);
+		if (settingsElement.element(VOLUME_ELEMENT) != null)
+			pad.setVolume(Double.valueOf(settingsElement.element(VOLUME_ELEMENT).getStringValue()));
+		if (settingsElement.element(LOOP_ELEMENT) != null)
+			pad.setLoop(Boolean.valueOf(settingsElement.element(LOOP_ELEMENT).getStringValue()));
+		if (settingsElement.element(TIMEMODE_ELEMENT) != null)
+			pad.setTimeMode(TimeMode.valueOf(settingsElement.element(TIMEMODE_ELEMENT).getStringValue()));
+		if (settingsElement.element(FADE_ELEMENT) != null)
+			pad.setFade(Fade.load(settingsElement.element(FADE_ELEMENT)));
+		if (settingsElement.element(WARNING_ELEMENT) != null)
+			pad.setWarning(Warning.load(settingsElement.element(WARNING_ELEMENT)));
+
+		// Laoyut
+		Element layoutsElement = settingsElement.element(LAYOUTS_ELEMENT);
+		if (layoutsElement != null) {
+			if (layoutsElement.attributeValue(LAYOUT_ACTIVE_ATTR) != null) {
+				pad.setCustomLayout(Boolean.valueOf(layoutsElement.attributeValue(LAYOUT_ACTIVE_ATTR)));
+			}
+
+			for (Object layoutObj : layoutsElement.elements(LAYOUT_ELEMENT)) {
+				if (layoutObj instanceof Element) {
+					Element layoutElement = (Element) layoutObj;
+					String type = layoutElement.attributeValue(LAYOUT_TYPE_ATTR);
+					CartLayout layout = LayoutRegistry.getLayout(type).newCartLayout();
+					layout.load(layoutElement);
+
+					pad.setLayout(layout, type);
+				}
+			}
+		}
+
+		Element userInfoElement = settingsElement.element(CUSTOM_SETTINGS_ELEMENT);
+		if (userInfoElement != null) {
+			for (Object object : userInfoElement.elements()) {
+				if (object instanceof Element) {
+					Element item = (Element) object;
+					String key = item.attributeValue(CUSTOM_SETTINGS_TYPE_ATTR);
+					Object data = UserDefaults.loadElement(item);
+					pad.getCustomSettings().put(key, data);
+				}
+			}
+		}
+
+		// Trigger
+		Element triggersElement = element.element("Triggers"); // TODO Externalize
+		if (triggersElement != null) {
+			for (Object triggerObj : triggersElement.elements("Trigger")) {
+				if (triggerObj instanceof Element) {
+					Element triggerElement = (Element) triggerObj;
+					Trigger trigger = new Trigger();
+					trigger.load(triggerElement);
+					pad.getTriggers().put(trigger.getTriggerPoint(), trigger);
+				}
+			}
+		}
+		pad.updateTrigger(); // Damit alle Points da sind
+
+		// Content
+		Element contentElement = element.element(CONTENT_ELEMENT);
+		if (contentElement != null) {
+			String contentType = contentElement.attributeValue(CONTENT_TYPE_ATTR);
+			try {
+				PadContent content = PadContentRegistry.getPadContentConnect(contentType).newInstance(pad);
+				content.load(contentElement);
+				pad.setContent(content);
+			} catch (UnkownPadContentException e) {
+				e.printStackTrace();
+				pad.throwException(null, e);
+			}
+		}
+
+		return pad;
+	}
+
+	@Override
+	public void saveElement(Element element, Pad data) {
+		element.addAttribute(INDEX_ATTR, String.valueOf(data.getIndex()));
+		element.addAttribute(NAME_ATTR, data.getName());
+		if (data.getStatus() == PadStatus.EMPTY || data.getStatus() == PadStatus.ERROR) {
+			element.addAttribute(STATUS_ATTR, PadStatus.EMPTY.name());
+		} else {
+			element.addAttribute(STATUS_ATTR, PadStatus.READY.name());
+		}
+
+		// Settings
+		Element settingsElement = element.addElement(SETTINGS_ELEMENT);
+		settingsElement.addElement(VOLUME_ELEMENT).addText(String.valueOf(data.getVolume()));
+		settingsElement.addElement(LOOP_ELEMENT).addText(String.valueOf(data.isLoop()));
+		if (data.getTimeMode() != null)
+			settingsElement.addElement(TIMEMODE_ELEMENT).addText(String.valueOf(data.getTimeMode()));
+		if (data.isCustomWarning() != false)
+			data.getWarning().save(settingsElement.addElement(WARNING_ELEMENT));
+		if (data.getFade() != null)
+			data.getFade().save(settingsElement.addElement(FADE_ELEMENT));
+
+		// Layout
+		Element layoutsElement = settingsElement.addElement(LAYOUTS_ELEMENT);
+		layoutsElement.addAttribute(LAYOUT_ACTIVE_ATTR, String.valueOf(data.isCustomLayout()));
+		for (String layoutType : data.getLayouts().keySet()) {
+			Element layoutElement = layoutsElement.addElement(LAYOUT_ELEMENT);
+			layoutElement.addAttribute(LAYOUT_TYPE_ATTR, layoutType);
+
+			CartLayout cartLayout = data.getLayouts().get(layoutType);
+			cartLayout.save(layoutElement);
+		}
+
+		Element userInfoElement = settingsElement.addElement(CUSTOM_SETTINGS_ELEMENT);
+		for (String key : data.getCustomSettings().keySet()) {
+			Element itemElement = userInfoElement.addElement(CUSTOM_SETTINGS_ITEM_ELEMENT);
+			UserDefaults.save(itemElement, data.getCustomSettings().get(key), key);
+		}
+
+		// Trigger
+		Element triggersElement = element.addElement("Triggers");
+		for (TriggerPoint point : data.getTriggers().keySet()) {
+			Trigger trigger = data.getTriggers().get(point);
+			Element triggerElement = triggersElement.addElement("Trigger");
+			trigger.save(triggerElement);
+		}
+
+		// Content
+		if (data.getContent() != null) {
+			Element contentElement = element.addElement(CONTENT_ELEMENT);
+			contentElement.addAttribute(CONTENT_TYPE_ATTR, data.getContent().getType());
+			data.getContent().save(contentElement);
+		}
+	}
+}
diff --git a/PlayWallCore/src/de/tobias/playpad/plugin/PadListener.java b/PlayWallCore/src/de/tobias/playpad/plugin/PadListener.java
index 0d6349a2196269b18434cb77256ea9c3cf82c94e..26ba636bfc86ef54d0eea5717acb960b7e7c9733 100644
--- a/PlayWallCore/src/de/tobias/playpad/plugin/PadListener.java
+++ b/PlayWallCore/src/de/tobias/playpad/plugin/PadListener.java
@@ -2,10 +2,30 @@ package de.tobias.playpad.plugin;
 
 import de.tobias.playpad.pad.Pad;
 
+/**
+ * Listener für ein Pad.
+ * 
+ * @author tobias
+ * 
+ * @see Pad
+ *
+ */
 public interface PadListener {
 
-	public default void onPlay(Pad pad) {}
+	/**
+	 * Wird aufgerufen, sobald ein Pad wiedergegeben wird.
+	 * 
+	 * @param pad
+	 *            Pad
+	 */
+	public void onPlay(Pad pad);
 
-	public default void onStop(Pad pad) {}
+	/**
+	 * Wird aufgerufen, sobald ein Pad gestoppt wird.
+	 * 
+	 * @param pad
+	 *            Pad
+	 */
+	public void onStop(Pad pad);
 
 }
\ No newline at end of file
diff --git a/PlayWallCore/src/de/tobias/playpad/plugin/Plugin.java b/PlayWallCore/src/de/tobias/playpad/plugin/Plugin.java
index 4d7684d0f8d15f3497114df28761e1561795ca64..fcbe98abe97596e8ecc83b62c0eefa2ebb30d9a6 100644
--- a/PlayWallCore/src/de/tobias/playpad/plugin/Plugin.java
+++ b/PlayWallCore/src/de/tobias/playpad/plugin/Plugin.java
@@ -1,36 +1,26 @@
 package de.tobias.playpad.plugin;
 
-import java.io.IOException;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
 import java.util.List;
 
-import org.bukkit.configuration.file.FileConfiguration;
-import org.bukkit.configuration.file.YamlConfiguration;
-
-import de.tobias.utils.application.ApplicationUtils;
-import de.tobias.utils.application.container.PathType;
-
 public class Plugin implements Comparable<Plugin> {
 
 	private String name;
 	private String fileName;
 	private String url;
-	private boolean active;
-	private List<String> dependencies;
 
-	private static List<Plugin> plugins;
+	private String version;
+	private long build;
 
-	static {
-		plugins = new ArrayList<>();
-	}
+	private boolean active;
+	private List<String> dependencies;
 
-	public Plugin(String name, String fileName, String url, boolean active, List<String> dependencies) {
+	public Plugin(String name, String fileName, String url, String version, long build, boolean active,
+			List<String> dependencies) {
 		this.name = name;
 		this.fileName = fileName;
 		this.url = url;
+		this.version = version;
+		this.build = build;
 		this.active = active;
 		this.dependencies = dependencies;
 	}
@@ -78,32 +68,8 @@ public class Plugin implements Comparable<Plugin> {
 		return getName().compareTo(o.getName());
 	}
 
-	public static void load(String pluginInfoURL) throws IOException {
-		plugins.clear();
-		URL url = new URL(pluginInfoURL);
-
-		FileConfiguration cfg = YamlConfiguration.loadConfiguration(url.openStream());
-
-		// Iterate over all plugins that are online avialable
-		for (String key : cfg.getConfigurationSection("plugins").getKeys(false)) {
-			String name = new String(cfg.getString("plugins." + key + ".name").getBytes(), "UTF-8");
-			String pluginUrl = cfg.getString("plugins." + key + ".url");
-			String fileName = cfg.getString("plugins." + key + ".filename");
-
-			List<String> dependencies = cfg.getStringList("plugins." + key + ".dependencies");
-
-			boolean active = false;
-
-			Path path = ApplicationUtils.getApplication().getPath(PathType.LIBRARY, fileName);
-			if (Files.exists(path))
-				active = true;
-
-			Plugin plugin = new Plugin(name, fileName, pluginUrl, active, dependencies);
-			plugins.add(plugin);
-		}
-	}
-
-	public static List<Plugin> getPlugins() {
-		return plugins;
+	@Override
+	public String toString() {
+		return name + " " + version + " (" + build + ")";
 	}
 }
diff --git a/PlayWallCore/src/de/tobias/playpad/plugin/Plugins.java b/PlayWallCore/src/de/tobias/playpad/plugin/Plugins.java
new file mode 100644
index 0000000000000000000000000000000000000000..9cb3749a8f036e5f01a3cecb88c3a1e3eb5e577b
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/plugin/Plugins.java
@@ -0,0 +1,57 @@
+package de.tobias.playpad.plugin;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.container.PathType;
+
+public class Plugins {
+
+	private static List<Plugin> plugins;
+
+	static {
+		plugins = new ArrayList<>();
+	}
+
+	public static List<Plugin> load(String pluginInfoURL, boolean fetch) throws IOException {
+		if (plugins.isEmpty() || fetch) {
+			plugins.clear();
+			URL url = new URL(pluginInfoURL);
+
+			FileConfiguration cfg = YamlConfiguration.loadConfiguration(url.openStream());
+
+			// Iterate over all plugins that are online avialable
+			for (String key : cfg.getConfigurationSection("plugins").getKeys(false)) {
+				String name = new String(cfg.getString("plugins." + key + ".name").getBytes(), "UTF-8");
+				String pluginUrl = cfg.getString("plugins." + key + ".url");
+				String fileName = cfg.getString("plugins." + key + ".filename");
+				String version = cfg.getString("plugins." + key + ".version");
+				long build = cfg.getLong("plugins." + key + ".build");
+
+				List<String> dependencies = cfg.getStringList("plugins." + key + ".dependencies");
+
+				boolean active = false;
+
+				Path path = ApplicationUtils.getApplication().getPath(PathType.LIBRARY, fileName);
+				if (Files.exists(path))
+					active = true;
+
+				Plugin plugin = new Plugin(name, fileName, pluginUrl, version, build, active, dependencies);
+				plugins.add(plugin);
+			}
+		}
+		return plugins;
+	}
+
+	public static List<Plugin> getPlugins() {
+		return plugins;
+	}
+}
diff --git a/PlayWallCore/src/de/tobias/playpad/project/Importable.java b/PlayWallCore/src/de/tobias/playpad/project/Importable.java
index 0193b48f4fed7a801e8b6c791213e98c41fbc907..1b3e860e99d59b2f5a84abbb7f9d5bfdb6b4d5e1 100644
--- a/PlayWallCore/src/de/tobias/playpad/project/Importable.java
+++ b/PlayWallCore/src/de/tobias/playpad/project/Importable.java
@@ -2,11 +2,37 @@ package de.tobias.playpad.project;
 
 import java.nio.file.Path;
 
+/**
+ * Delegate Methode vom Model zum Import eines Projektes (mit Profile und Medien optionmal)
+ * 
+ * @author tobias
+ * 
+ * @since 5.0.0
+ */
 public interface Importable {
 
+	/**
+	 * Wenn ein Profil bereits vorhanden ist, wird hier nach einem neuen Namen gefragt.
+	 * 
+	 * @param name
+	 *            Alter name
+	 * @return Neuer Name oder null (dann wird nichts importiert)
+	 */
 	public String replaceProfile(String name);
 
+	/**
+	 * Wenn ein Projekt bereits vorhanden ist, wird hier nach einem neuen Namen gefragt.
+	 * 
+	 * @param name
+	 *            Alter name
+	 * @return Neuer Name oder null (dann wird nichts importiert)
+	 */
 	public String replaceProject(String name);
 
+	/**
+	 * Frage nach dem Ordner für die Mediendateien.
+	 * 
+	 * @return Ordner zum Import.
+	 */
 	public Path mediaFolder();
 }
\ No newline at end of file
diff --git a/PlayWallCore/src/de/tobias/playpad/project/ProfileChooseable.java b/PlayWallCore/src/de/tobias/playpad/project/ProfileChooseable.java
index 36d4062ce19de24bb6c68650d25f2ca34bf3a7e8..11b53720e3d2b07284cc7c6ad77b8e208abd8b01 100644
--- a/PlayWallCore/src/de/tobias/playpad/project/ProfileChooseable.java
+++ b/PlayWallCore/src/de/tobias/playpad/project/ProfileChooseable.java
@@ -2,7 +2,19 @@ package de.tobias.playpad.project;
 
 import de.tobias.playpad.settings.Profile;
 
+/**
+ * Dieses Interface stellt Methoden für die Wahl des Profiles für ein Projekt bereit.
+ * 
+ * @author tobias
+ *
+ * @since 5.0.0
+ */
 public interface ProfileChooseable {
 
+	/**
+	 * Wird von der API beim Projekt laden aufgerunfen, wenn das referenzierte Projekt nicht gefunden wurde.
+	 * 
+	 * @return Neues Profile
+	 */
 	public Profile getUnkownProfile();
 }
\ No newline at end of file
diff --git a/PlayWallCore/src/de/tobias/playpad/project/Project.java b/PlayWallCore/src/de/tobias/playpad/project/Project.java
index d0d6e24a10a778d9c999657e78e32a456667c6a3..f166c6d300916a1308b6a757d67879d4f6284d77 100644
--- a/PlayWallCore/src/de/tobias/playpad/project/Project.java
+++ b/PlayWallCore/src/de/tobias/playpad/project/Project.java
@@ -5,70 +5,125 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 
 import org.dom4j.Document;
 import org.dom4j.DocumentException;
 import org.dom4j.DocumentHelper;
 import org.dom4j.Element;
-import org.dom4j.io.OutputFormat;
-import org.dom4j.io.SAXReader;
-import org.dom4j.io.XMLWriter;
 
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadException;
+import de.tobias.playpad.pad.PadSerializer;
 import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.settings.Profile;
 import de.tobias.playpad.settings.ProfileNotFoundException;
-import de.tobias.utils.application.ApplicationUtils;
-import de.tobias.utils.application.container.PathType;
+import de.tobias.playpad.xml.XMLHandler;
 import javafx.application.Platform;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 
+/**
+ * Hold all information about the pads and it's settings.
+ * 
+ * @author tobias
+ *
+ */
 public class Project {
 
-	public static final String projectNameEx = "\\w{1}[\\w\\s-_]{0,}";
+	/**
+	 * Pattern für den Namen des Projekts
+	 */
+	public static final String PROJECT_NAME_PATTERN = "\\w{1}[\\w\\s-_]{0,}";
+	/**
+	 * Dateiendung für eine projekt Datei
+	 */
 	public static final String FILE_EXTENSION = ".xml";
 
+	/**
+	 * Die projektreferenz gibt auskunft über den Namen und die UUID des Projektes
+	 */
 	private ProjectReference ref;
+	/**
+	 * Liste mit allen Pads.
+	 */
 	private HashMap<Integer, Pad> pads;
+	/**
+	 * Liste mit den aktuellen Laufzeitfehlern.
+	 */
 	private ObservableList<PadException> exceptions;
 
+	/**
+	 * Erstellt ein neues leeres Projekt mit einer Referenz.
+	 * 
+	 * @param ref
+	 *            Referenz mit Namen des Projekts.
+	 */
 	public Project(ProjectReference ref) {
 		this.ref = ref;
 		this.pads = new HashMap<>();
 		this.exceptions = FXCollections.observableArrayList();
 	}
 
+	/**
+	 * Gibt die Projekt Referenz zurück. Dazu zählen Name und UUID sowie das zugehörige Profile.
+	 * 
+	 * @return Referenz.
+	 */
 	public ProjectReference getRef() {
 		return ref;
 	}
 
+	// TODO Update in 5.1.0
+	/**
+	 * Gibt ein Pad an einem Index zurück. Sollte kein pad vorhanden sein (weil null, so wird vorher ein neues erzeugt.)
+	 * 
+	 * @param index
+	 *            Index
+	 * @return Pad am Index i
+	 */
 	public Pad getPad(int index) {
-		if (pads.containsKey(index)) {
-			return pads.get(index);
-		} else {
-			pads.put(index, new Pad(this, index)); // Create Pad if not exists
-			return pads.get(index);
+		if (!pads.containsKey(index)) {
+			addPadForIndex(index);
 		}
+		return pads.get(index);
+	}
+
+	/**
+	 * Erstellt ein neues leeres Pad (mit Referenz zu diesem Projekt) am Index i.
+	 * 
+	 * @param index
+	 *            Index i
+	 */
+	private void addPadForIndex(int index) {
+		pads.put(index, new Pad(this, index));
 	}
 
+	/**
+	 * Ersetz ein Pad an einem Index i.
+	 * 
+	 * @param index
+	 *            Index i
+	 * @param pad
+	 *            Neues Pad für den Index i
+	 */
 	public void setPad(int index, Pad pad) {
 		pad.setIndex(index);
 		pads.put(index, pad);
 	}
 
+	/*
+	 * Speichern und Laden
+	 */
+
 	private static final String ROOT_ELEMENT = "Project";
-	static final String PAD_ELEMENT = "Pad";
+	protected static final String PAD_ELEMENT = "Pad";
 
 	public static Project load(ProjectReference ref, boolean loadMedia, ProfileChooseable profileChooseable)
 			throws DocumentException, IOException, ProfileNotFoundException, ProjectNotFoundException {
+		Path projectPath = ref.getProjectPath();
 
-		Path projectPath = ApplicationUtils.getApplication().getPath(PathType.DOCUMENTS, ref.getFileName());
 		if (Files.exists(projectPath)) {
-			SAXReader reader = new SAXReader();
-			Document document = reader.read(Files.newInputStream(projectPath));
-
 			if (ref.getProfileReference() != null) {
 				Profile.load(ref.getProfileReference()); // Lädt das entsprechende Profile und aktiviert es
 			} else {
@@ -78,22 +133,13 @@ public class Project {
 
 			Project project = new Project(ref);
 
-			Element rootElement = document.getRootElement();
-
-			for (Object padObj : rootElement.elements(PAD_ELEMENT)) {
-				if (padObj instanceof Element) {
-					Element padElement = (Element) padObj;
+			XMLHandler<Pad> handler = new XMLHandler<>(projectPath);
+			List<Pad> pads = handler.loadElements(PAD_ELEMENT, new PadSerializer(project));
 
-					// Load Pad Settings
-					Pad pad = new Pad(project, padElement);
-
-					// Load Media
-					if (loadMedia) {
-						pad.loadContent();
-					}
-
-					project.pads.put(pad.getIndex(), pad);
-				}
+			for (Pad pad : pads) {
+				if (loadMedia)
+					pad.loadContent();
+				project.pads.put(pad.getIndex(), pad);
 			}
 
 			return project;
@@ -103,25 +149,19 @@ public class Project {
 	}
 
 	public void save() throws IOException {
-		Path projectPath = ApplicationUtils.getApplication().getPath(PathType.DOCUMENTS, ref.getFileName());
+		Path projectPath = ref.getProjectPath();
 		Document document = DocumentHelper.createDocument();
 
 		Element rootElement = document.addElement(ROOT_ELEMENT);
-		for (int index : pads.keySet()) {
-			Pad pad = pads.get(index);
 
-			Element padElement = rootElement.addElement(PAD_ELEMENT);
-			pad.save(padElement);
-		}
+		XMLHandler<Pad> handler = new XMLHandler<>(rootElement);
+		handler.saveElements(PAD_ELEMENT, pads.values(), new PadSerializer());
 
 		if (Files.notExists(projectPath)) {
 			Files.createDirectories(projectPath.getParent());
 			Files.createFile(projectPath);
 		}
-
-		XMLWriter writer = new XMLWriter(Files.newOutputStream(projectPath), OutputFormat.createPrettyPrint());
-		writer.write(document);
-		writer.close();
+		XMLHandler.save(projectPath, document);
 	}
 
 	public HashMap<Integer, Pad> getPads() {
@@ -138,6 +178,10 @@ public class Project {
 		return count;
 	}
 
+	public boolean hasPlayedPlayers() {
+		return getPlayedPlayers() > 0;
+	}
+
 	// Exceptions
 	public void addException(Pad pad, Path path, Exception exception) {
 		if (!Platform.isFxApplicationThread()) {
diff --git a/PlayWallCore/src/de/tobias/playpad/project/ProjectExporter.java b/PlayWallCore/src/de/tobias/playpad/project/ProjectExporter.java
index 01267080ca680f5b267373814cb8bf08cf02ebbf..756c508a2f5e922ea8609f02905b295ce50d2456 100644
--- a/PlayWallCore/src/de/tobias/playpad/project/ProjectExporter.java
+++ b/PlayWallCore/src/de/tobias/playpad/project/ProjectExporter.java
@@ -15,6 +15,7 @@ import org.dom4j.io.SAXReader;
 import org.dom4j.io.XMLWriter;
 
 import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadSerializer;
 import de.tobias.playpad.settings.ProfileReference;
 import de.tobias.utils.application.App;
 import de.tobias.utils.application.ApplicationUtils;
@@ -115,9 +116,11 @@ public class ProjectExporter {
 			if (padObj instanceof Element) {
 				Element padElement = (Element) padObj;
 
-				Pad pad = new Pad(null, padElement); // Null für Project, da das pad nicht weiter verwendet wird
+				PadSerializer serializer = new PadSerializer();
+				Pad pad = serializer.loadElement(padElement);
+
 				if (pad.getContent() != null) {
-					pad.getContent().exportMedia(zip, padElement.element(Pad.CONTENT_ELEMENT));
+					pad.getContent().exportMedia(zip, padElement.element(PadSerializer.CONTENT_ELEMENT));
 				}
 			}
 
diff --git a/PlayWallCore/src/de/tobias/playpad/project/ProjectImporter.java b/PlayWallCore/src/de/tobias/playpad/project/ProjectImporter.java
index d7c075fcec6fbde1c463e28b655b5c03f975a8f9..57ebef70dc69976a9c3c1c20afd0c11549659e30 100644
--- a/PlayWallCore/src/de/tobias/playpad/project/ProjectImporter.java
+++ b/PlayWallCore/src/de/tobias/playpad/project/ProjectImporter.java
@@ -15,6 +15,7 @@ import org.dom4j.io.SAXReader;
 import org.dom4j.io.XMLWriter;
 
 import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadSerializer;
 import de.tobias.playpad.settings.Profile;
 import de.tobias.playpad.settings.ProfileReference;
 import de.tobias.utils.application.App;
@@ -161,9 +162,11 @@ public class ProjectImporter {
 			if (padObj instanceof Element) {
 				Element padElement = (Element) padObj;
 
-				Pad pad = new Pad(null, padElement); // Null für Project, da das pad nicht weiter verwendet wird
+				PadSerializer serializer = new PadSerializer();
+				Pad pad = serializer.loadElement(padElement);
+
 				if (pad.getContent() != null) {
-					pad.getContent().importMedia(destination, zip, padElement.element(Pad.CONTENT_ELEMENT));
+					pad.getContent().importMedia(destination, zip, padElement.element(PadSerializer.CONTENT_ELEMENT));
 				}
 			}
 		}
diff --git a/PlayWallCore/src/de/tobias/playpad/project/ProjectReference.java b/PlayWallCore/src/de/tobias/playpad/project/ProjectReference.java
index aabe28711f4c3f573085e4d6697c7d6807498668..44724c67c6a3815083e9c4eac9bb2b697f63acf9 100644
--- a/PlayWallCore/src/de/tobias/playpad/project/ProjectReference.java
+++ b/PlayWallCore/src/de/tobias/playpad/project/ProjectReference.java
@@ -13,12 +13,11 @@ import org.dom4j.Document;
 import org.dom4j.DocumentException;
 import org.dom4j.DocumentHelper;
 import org.dom4j.Element;
-import org.dom4j.io.OutputFormat;
-import org.dom4j.io.SAXReader;
-import org.dom4j.io.XMLWriter;
 
 import de.tobias.playpad.Displayable;
 import de.tobias.playpad.settings.ProfileReference;
+import de.tobias.playpad.xml.XMLHandler;
+import de.tobias.utils.application.App;
 import de.tobias.utils.application.ApplicationUtils;
 import de.tobias.utils.application.container.PathType;
 import javafx.beans.property.SimpleStringProperty;
@@ -26,31 +25,7 @@ import javafx.beans.property.StringProperty;
 
 public class ProjectReference implements Displayable {
 
-	private static List<ProjectReference> projects = new ArrayList<ProjectReference>() {
-
-		private static final long serialVersionUID = 1L;
-
-		public boolean contains(Object o) {
-			if (o instanceof String) {
-				for (ProjectReference reference : this) {
-					if (reference.getName().equals(o)) {
-						return true;
-					} else if (reference.toString().equals(o)) {
-						return true;
-					}
-				}
-			} else if (o instanceof ProjectReference) {
-				for (ProjectReference reference : this) {
-					if (reference.getName() == o) {
-						return true;
-					} else if (reference.getName() == ((ProjectReference) o).getName()) {
-						return true;
-					}
-				}
-			}
-			return super.contains(o);
-		};
-	};
+	private static List<ProjectReference> projects = new ProjectReferenceList();
 	private static boolean loadedProjectOverview = false;
 
 	/**
@@ -143,14 +118,18 @@ public class ProjectReference implements Displayable {
 		ProjectReference newProjectReference = new ProjectReference(UUID.randomUUID(), name, currentProject.getProfileReference());
 		addProject(newProjectReference);
 
-		Path oldPath = ApplicationUtils.getApplication().getPath(PathType.DOCUMENTS, currentProject.getName());
-		Path newPath = ApplicationUtils.getApplication().getPath(PathType.DOCUMENTS, newProjectReference.getName());
-		Files.copy(oldPath, newPath, StandardCopyOption.COPY_ATTRIBUTES);
+		duplicateFiles(currentProject, newProjectReference);
 
 		saveProjects();
 		return newProjectReference;
 	}
 
+	private static void duplicateFiles(ProjectReference currentProject, ProjectReference newProjectReference) throws IOException {
+		Path oldPath = ApplicationUtils.getApplication().getPath(PathType.DOCUMENTS, currentProject.getName());
+		Path newPath = ApplicationUtils.getApplication().getPath(PathType.DOCUMENTS, newProjectReference.getName());
+		Files.copy(oldPath, newPath, StandardCopyOption.COPY_ATTRIBUTES);
+	}
+
 	public static List<ProjectReference> getProjects() {
 		if (!loadedProjectOverview)
 			try {
@@ -161,59 +140,33 @@ public class ProjectReference implements Displayable {
 		return projects;
 	}
 
-	private static final String UUID_ATTR = "uuid";
-	private static final String NAME_ATTR = "name";
-	private static final String PROFILE_ATTR = "profile";
+	// Load and Save
+	private static final String FILE_NAME = "Projects.xml";
+	private static final String PROJECT_ELEMENT = "Project";
+	private static final String ROOT_ELEMENT = "Settings";
 
 	public static void loadProjects() throws DocumentException, IOException {
-		projects.clear();
-
-		Path path = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, "Projects.xml");
-
+		Path path = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, FILE_NAME);
 		if (Files.exists(path)) {
-			SAXReader reader = new SAXReader();
-			Document document = reader.read(Files.newInputStream(path));
-			Element root = document.getRootElement();
-
-			for (Object object : root.elements("Project")) {
-				Element element = (Element) object;
-
-				UUID uuid = UUID.fromString(element.attributeValue(UUID_ATTR));
-				String name = element.attributeValue(NAME_ATTR);
-				UUID profile = UUID.fromString(element.attributeValue(PROFILE_ATTR));
-
-				ProfileReference profileRef = ProfileReference.getReference(profile);
-				ProjectReference ref = new ProjectReference(uuid, name, profileRef);
-
-				Path projectPath = ApplicationUtils.getApplication().getPath(PathType.DOCUMENTS, ref.getFileName());
-				if (Files.exists(projectPath)) {
-					ref.setLastMofied(Files.getLastModifiedTime(projectPath).toMillis());
-					ref.setSize(Files.size(projectPath));
-				}
-
-				projects.add(ref);
-			}
-
-			loadedProjectOverview = true;
+			XMLHandler<ProjectReference> loader = new XMLHandler<>(path);
+			projects = loader.loadElements(PROJECT_ELEMENT, new ProjectReferenceSerializer());
 		}
+		loadedProjectOverview = true;
 	}
 
 	public static void saveProjects() throws UnsupportedEncodingException, IOException {
 		Document document = DocumentHelper.createDocument();
-		Element root = document.addElement("Settings");
+		Element root = document.addElement(ROOT_ELEMENT);
 
-		for (ProjectReference project : projects) {
-			Element projectElement = root.addElement("Project");
-			projectElement.addAttribute(UUID_ATTR, project.uuid.toString());
-			projectElement.addAttribute(NAME_ATTR, project.name);
-			projectElement.addAttribute(PROFILE_ATTR, project.profileReference.getUuid().toString());
-		}
-
-		Path path = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, "Projects.xml");
+		XMLHandler<ProjectReference> handler = new XMLHandler<>(root);
+		handler.saveElements(PROJECT_ELEMENT, projects, new ProjectReferenceSerializer());
 
-		XMLWriter writer = new XMLWriter(Files.newOutputStream(path), OutputFormat.createPrettyPrint());
-		writer.write(document);
-		writer.close();
+		Path path = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, FILE_NAME);
+		if (Files.notExists(path)) {
+			Files.createDirectories(path.getParent());
+			Files.createFile(path);
+		}
+		XMLHandler.save(path, document);
 	}
 
 	public static List<ProjectReference> getProjectsSorted() {
@@ -237,6 +190,12 @@ public class ProjectReference implements Displayable {
 		return uuid + Project.FILE_EXTENSION;
 	}
 
+	public Path getProjectPath() {
+		App application = ApplicationUtils.getApplication();
+		Path projectPath = application.getPath(PathType.DOCUMENTS, getFileName());
+		return projectPath;
+	}
+
 	public static ProjectReference getProject(UUID project) {
 		for (ProjectReference ref : projects) {
 			if (ref.uuid.equals(project)) {
diff --git a/PlayWallCore/src/de/tobias/playpad/project/ProjectReferenceList.java b/PlayWallCore/src/de/tobias/playpad/project/ProjectReferenceList.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9d7ea8412887f1f5173b1a3416018271e59a29b
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/project/ProjectReferenceList.java
@@ -0,0 +1,37 @@
+package de.tobias.playpad.project;
+
+import de.tobias.utils.list.UniqList;
+
+/**
+ * Liste, wo nur ProjektRefernzen gespeichert werden, deren Namen Unique ist.
+ * 
+ * @author tobias
+ *
+ * @since 5.0.1
+ * @see ProjectReference
+ */
+final class ProjectReferenceList extends UniqList<ProjectReference> {
+
+	private static final long serialVersionUID = 1L;
+
+	public boolean contains(Object o) {
+		if (o instanceof String) {
+			for (ProjectReference reference : this) {
+				if (reference.getName().equals(o)) {
+					return true;
+				} else if (reference.toString().equals(o)) {
+					return true;
+				}
+			}
+		} else if (o instanceof ProjectReference) {
+			for (ProjectReference reference : this) {
+				if (reference.getName() == o) {
+					return true;
+				} else if (reference.getName().equals(((ProjectReference) o).getName())) { // TODO Check
+					return true;
+				}
+			}
+		}
+		return super.contains(o);
+	}
+}
\ No newline at end of file
diff --git a/PlayWallCore/src/de/tobias/playpad/project/ProjectReferenceSerializer.java b/PlayWallCore/src/de/tobias/playpad/project/ProjectReferenceSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..009b68e7171f8ed1ef6bdd1442070abf48a6fe3f
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/project/ProjectReferenceSerializer.java
@@ -0,0 +1,49 @@
+package de.tobias.playpad.project;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.UUID;
+
+import org.dom4j.Element;
+
+import de.tobias.playpad.settings.ProfileReference;
+import de.tobias.playpad.xml.XMLDeserializer;
+import de.tobias.playpad.xml.XMLSerializer;
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.container.PathType;
+
+public class ProjectReferenceSerializer implements XMLDeserializer<ProjectReference>, XMLSerializer<ProjectReference> {
+
+	private static final String UUID_ATTR = "uuid";
+	private static final String NAME_ATTR = "name";
+	private static final String PROFILE_ATTR = "profile";
+
+	@Override
+	public ProjectReference loadElement(Element element) {
+		UUID uuid = UUID.fromString(element.attributeValue(UUID_ATTR));
+		String name = element.attributeValue(NAME_ATTR);
+		UUID profile = UUID.fromString(element.attributeValue(PROFILE_ATTR));
+
+		ProfileReference profileRef = ProfileReference.getReference(profile);
+		ProjectReference ref = new ProjectReference(uuid, name, profileRef);
+
+		Path projectPath = ApplicationUtils.getApplication().getPath(PathType.DOCUMENTS, ref.getFileName());
+		if (Files.exists(projectPath)) {
+			try {
+				ref.setLastMofied(Files.getLastModifiedTime(projectPath).toMillis());
+				ref.setSize(Files.size(projectPath));
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+		return ref;
+	}
+
+	@Override
+	public void saveElement(Element newElement, ProjectReference data) {
+		newElement.addAttribute(UUID_ATTR, data.getUuid().toString());
+		newElement.addAttribute(NAME_ATTR, data.getName());
+		newElement.addAttribute(PROFILE_ATTR, data.getProfileReference().getUuid().toString());
+	}
+}
diff --git a/PlayWallCore/src/de/tobias/playpad/pad/Fade.java b/PlayWallCore/src/de/tobias/playpad/settings/Fade.java
similarity index 98%
rename from PlayWallCore/src/de/tobias/playpad/pad/Fade.java
rename to PlayWallCore/src/de/tobias/playpad/settings/Fade.java
index 09e47651733eafbee7c39a7639d089c25a38efe5..73d9ba15ff65457e984f61d95bb43b9981af6b97 100644
--- a/PlayWallCore/src/de/tobias/playpad/pad/Fade.java
+++ b/PlayWallCore/src/de/tobias/playpad/settings/Fade.java
@@ -1,4 +1,4 @@
-package de.tobias.playpad.pad;
+package de.tobias.playpad.settings;
 
 import org.dom4j.Element;
 
diff --git a/PlayWallCore/src/de/tobias/playpad/settings/Profile.java b/PlayWallCore/src/de/tobias/playpad/settings/Profile.java
index db0b7ea64dccd1216bba78ddf58a5c80854589f1..7e55988c26d8adbfa59e1b5494c3766d760595dd 100644
--- a/PlayWallCore/src/de/tobias/playpad/settings/Profile.java
+++ b/PlayWallCore/src/de/tobias/playpad/settings/Profile.java
@@ -20,6 +20,10 @@ import de.tobias.utils.application.container.PathType;
 
 public class Profile {
 
+	private static final String PROFILE_SETTINGS_XML = "ProfileSettings.xml";
+	private static final String MAPPING_XML = "Mapping.xml";
+	private static final String LAYOUT_XML = "Layout.xml";
+
 	public static final String profileNameEx = "\\w{1}[\\w\\s-_]{0,}";
 
 	private static List<ProfileListener> listeners = new ArrayList<>();
@@ -97,10 +101,9 @@ public class Profile {
 
 		if (Files.exists(app.getPath(PathType.CONFIGURATION, ref.getFileName()))) {
 
-			ProfileSettings profileSettings = ProfileSettings
-					.load(app.getPath(PathType.CONFIGURATION, ref.getFileName(), "ProfileSettings.xml"));
+			ProfileSettings profileSettings = ProfileSettings.load(app.getPath(PathType.CONFIGURATION, ref.getFileName(), PROFILE_SETTINGS_XML));
 			HashMap<String, GlobalLayout> layouts = GlobalLayout
-					.loadGlobalLayout(app.getPath(PathType.CONFIGURATION, ref.getFileName(), "Layout.xml"));
+					.loadGlobalLayout(app.getPath(PathType.CONFIGURATION, ref.getFileName(), LAYOUT_XML));
 
 			profile.profileSettings = profileSettings;
 			profile.layouts = layouts;
@@ -116,7 +119,7 @@ public class Profile {
 			});
 
 			// Mapping erst danach, weil das auf current Profile zugreifen muss
-			MappingList mappings = MappingList.load(app.getPath(PathType.CONFIGURATION, ref.getFileName(), "Mapping.xml"), profile);
+			MappingList mappings = MappingList.load(app.getPath(PathType.CONFIGURATION, ref.getFileName(), MAPPING_XML), profile);
 			profile.mappings = mappings;
 
 			setCurrentProfile(profile);
@@ -141,9 +144,14 @@ public class Profile {
 		if (Files.notExists(root))
 			Files.createDirectories(root);
 
-		profileSettings.save(app.getPath(PathType.CONFIGURATION, ref.getFileName(), "ProfileSettings.xml"));
-		mappings.save(app.getPath(PathType.CONFIGURATION, ref.getFileName(), "Mapping.xml"));
-		GlobalLayout.saveGlobal(layouts, app.getPath(PathType.CONFIGURATION, ref.getFileName(), "Layout.xml"));
+		profileSettings.save(getProfilePath(PROFILE_SETTINGS_XML));
+		mappings.save(getProfilePath(MAPPING_XML));
+		GlobalLayout.saveGlobal(layouts, getProfilePath(LAYOUT_XML));
+	}
+
+	private Path getProfilePath(String fileName) {
+		App app = ApplicationUtils.getApplication();
+		return app.getPath(PathType.CONFIGURATION, ref.getFileName(), fileName);
 	}
 
 	@Override
diff --git a/PlayWallCore/src/de/tobias/playpad/settings/ProfileReference.java b/PlayWallCore/src/de/tobias/playpad/settings/ProfileReference.java
index 103c9f9b0eda1250c26bd0818f074559424159e1..ba3a13d08fed86e8553a404235e11a69e8c57d3b 100644
--- a/PlayWallCore/src/de/tobias/playpad/settings/ProfileReference.java
+++ b/PlayWallCore/src/de/tobias/playpad/settings/ProfileReference.java
@@ -9,79 +9,102 @@ import java.util.List;
 import java.util.UUID;
 
 import org.dom4j.Document;
+import org.dom4j.DocumentException;
 import org.dom4j.DocumentHelper;
 import org.dom4j.Element;
-import org.dom4j.io.OutputFormat;
-import org.dom4j.io.SAXReader;
-import org.dom4j.io.XMLWriter;
 
 import de.tobias.playpad.Displayable;
+import de.tobias.playpad.xml.XMLHandler;
 import de.tobias.utils.application.ApplicationUtils;
 import de.tobias.utils.application.container.PathType;
-import de.tobias.utils.list.UniqList;
 import de.tobias.utils.util.FileUtils;
-import de.tobias.utils.util.FileUtils.FileAction;
+import de.tobias.utils.util.FileUtils.FileActionAdapter;
 import javafx.beans.property.SimpleStringProperty;
 import javafx.beans.property.StringProperty;
 
+/**
+ * Container für Profile Referenzen
+ * 
+ * @author tobias
+ * 
+ * @see Profile
+ * @since 5.0.0
+ */
 public class ProfileReference implements Displayable {
 
 	private static final String DEFAULT_PROFILE_NAME = "Default";
 
-	private static List<ProfileReference> profiles = new UniqList<ProfileReference>() {
-
-		private static final long serialVersionUID = 1L;
-
-		public boolean contains(Object o) {
-			if (o instanceof String) {
-				for (ProfileReference reference : this) {
-					if (reference.getName().equals(o)) {
-						return true;
-					} else if (reference.toString().equals(o)) {
-						return true;
-					}
-				}
-			} else if (o instanceof ProfileReference) {
-				for (ProfileReference reference : this) {
-					if (reference.getName() == o) {
-						return true;
-					} else if (reference.getName() == ((ProfileReference) o).getName()) {
-						return true;
-					}
-				}
-			}
-			return super.contains(o);
-		};
-	};
-
 	private final UUID uuid;
 	private String name;
 
+	/**
+	 * Erstellt eine neue Referenz mit einer Random UUID.
+	 * 
+	 * @param name
+	 *            Name
+	 */
 	public ProfileReference(String name) {
 		this.name = name;
 		this.uuid = UUID.randomUUID();
 		updateDisplayProperty();
 	}
 
+	/**
+	 * Erstellt eine neue Referenz mit Namen und UUID.
+	 * 
+	 * @param uuid
+	 *            UUID
+	 * @param name
+	 *            Name
+	 */
 	public ProfileReference(UUID uuid, String name) {
 		this.uuid = uuid;
 		this.name = name;
 		updateDisplayProperty();
 	}
 
+	/**
+	 * Gibt den Namen zurück
+	 * 
+	 * @return Name
+	 */
 	public String getName() {
 		return name;
 	}
 
+	/**
+	 * Gibt die UUID zurück
+	 * 
+	 * @return uudi
+	 */
 	public UUID getUuid() {
 		return uuid;
 	}
 
+	/**
+	 * Setzt einen neuen Namen.
+	 * 
+	 * @param name
+	 *            Neuer Name
+	 */
 	public void setName(String name) {
 		this.name = name;
 		updateDisplayProperty();
 	}
 
+	// Verwaltungsmethoden für Profile Referenzen // TODO Extract in Extra Class
+
+	/**
+	 * Liste mit allen Referenzen
+	 */
+	private static List<ProfileReference> profiles = new ProfileReferenceList();
+
+	/**
+	 * Sucht eine Referenz zu einer UUID raus.
+	 * 
+	 * @param profile
+	 * @return
+	 */
 	public static ProfileReference getReference(UUID profile) {
 		for (ProfileReference ref : profiles) {
 			if (ref.uuid.equals(profile)) {
@@ -91,6 +114,11 @@ public class ProfileReference implements Displayable {
 		return null;
 	}
 
+	/**
+	 * Listet alle verfügbaren Profil Refernzen auf.
+	 * 
+	 * @return Liste von Referenzen (Name, UUID)
+	 */
 	public static List<ProfileReference> getProfiles() {
 		return profiles;
 	}
@@ -103,6 +131,7 @@ public class ProfileReference implements Displayable {
 	 * @return
 	 * @throws UnsupportedEncodingException
 	 * @throws IOException
+	 *             IO Fehler
 	 */
 	public static Profile newProfile(String name) throws UnsupportedEncodingException, IOException {
 		ProfileReference ref = new ProfileReference(UUID.randomUUID(), name);
@@ -114,9 +143,17 @@ public class ProfileReference implements Displayable {
 		return profile;
 	}
 
+	/**
+	 * Fügt ein Profile hinzu und erstellt den Ordner auf der Festplatte.
+	 * 
+	 * @param ref
+	 *            Referenz zu diesem Profile (Name, UUID)
+	 */
 	public static void addProfile(ProfileReference ref) {
+		// MODEL
 		profiles.add(ref);
 
+		// DRIVE
 		Path path = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, ref.getFileName());
 		if (Files.notExists(path)) {
 			try {
@@ -128,19 +165,19 @@ public class ProfileReference implements Displayable {
 	}
 
 	/**
-	 * Duplicate one profile on drive. To use the new profile, it must be load manually.
-	 * 
+	 * Dupliziert eine Profile. Dabei werden die Dateien auf der Festplatte auch dupliziert.
 	 * 
 	 * @param src
-	 *            Name of the original Profile
+	 *            Name des Orginalprofiles
 	 * @param des
-	 *            Name of the new Profile
+	 *            Name des neuen Profiles
 	 * @throws IOException
+	 *             IO Fehler
 	 */
 	public static void duplicate(ProfileReference src, ProfileReference des) throws IOException {
 		if (!des.equals(src)) {
 			FileUtils.loopThroughDirectory(ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, src.getFileName()),
-					new FileAction() {
+					new FileActionAdapter() {
 
 						@Override
 						public void onFile(Path file) throws IOException {
@@ -151,18 +188,25 @@ public class ProfileReference implements Displayable {
 							}
 							Files.copy(file, desPath, StandardCopyOption.REPLACE_EXISTING);
 						}
-
-						@Override
-						public void onDirectory(Path file) throws IOException {}
 					});
 
 			profiles.add(des);
 		}
 	}
 
+	/**
+	 * Entfernt eine ProfileReferenz und das Profile.
+	 * 
+	 * @param ref
+	 *            Profile Referenz
+	 * @throws IOException
+	 *             IO Fehler
+	 */
 	public static void removeProfile(ProfileReference ref) throws IOException {
+		// Model
 		profiles.remove(ref);
 
+		// DRIVE
 		Path root = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, ref.getFileName());
 		if (Files.exists(root)) {
 			Files.walk(root).forEach(path ->
@@ -178,58 +222,78 @@ public class ProfileReference implements Displayable {
 		}
 	}
 
+	// Load and Save
+
+	private static final String FILE_NAME = "Profiles.xml";
 	private static final String ROOT_ELEMENT = "Settings";
 	private static final String PROFILE_ELEMENT = "Profile";
-	private static final String UUID_ATTR = "uuid";
-	private static final String NAME_ATTR = "name";
 
-	public static void loadProfiles() throws Exception {
+	/**
+	 * Lädt alle Profile Referenzen.
+	 * 
+	 * @throws IOException
+	 *             IO Fehler
+	 * @throws DocumentException
+	 *             XML Fehler
+	 */
+	public static void loadProfiles() throws IOException, DocumentException {
 		profiles.clear();
 
-		Path path = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, "Profiles.xml");
+		Path path = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, FILE_NAME);
 
 		if (Files.exists(path)) {
-			SAXReader reader = new SAXReader();
-			Document document = reader.read(Files.newInputStream(path));
-			Element root = document.getRootElement();
-			for (Object object : root.elements(PROFILE_ELEMENT)) {
-				Element element = (Element) object;
-
-				UUID uuid = UUID.fromString(element.attributeValue(UUID_ATTR));
-				String name = element.attributeValue(NAME_ATTR);
-
-				ProfileReference ref = new ProfileReference(uuid, name);
-				profiles.add(ref);
-			}
+			// Load data from xml
+			XMLHandler<ProfileReference> handler = new XMLHandler<>(path);
+			profiles = handler.loadElements(PROFILE_ELEMENT, new ProfileReferenceSerializer());
+			System.out.println(profiles);
 		}
 
+		// Add Default Element if list is empty
 		if (profiles.isEmpty()) {
 			Profile profile = newProfile(DEFAULT_PROFILE_NAME);
 			profile.save();
 		}
 	}
 
+	/**
+	 * Speichert alle Profile Referenzen in eine Datei.
+	 * 
+	 * @throws UnsupportedEncodingException
+	 *             XML Fehler
+	 * @throws IOException
+	 *             IO Fehler
+	 */
 	public static void saveProfiles() throws UnsupportedEncodingException, IOException {
 		Document document = DocumentHelper.createDocument();
 		Element root = document.addElement(ROOT_ELEMENT);
 
-		for (ProfileReference ref : profiles) {
-			Element element = root.addElement(PROFILE_ELEMENT);
+		// Save data to xml
+		XMLHandler<ProfileReference> handler = new XMLHandler<>(root);
+		handler.saveElements(PROFILE_ELEMENT, profiles, new ProfileReferenceSerializer());
 
-			element.addAttribute(UUID_ATTR, ref.uuid.toString());
-			element.addAttribute(NAME_ATTR, ref.name);
+		Path path = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, FILE_NAME);
+		if (Files.notExists(path)) {
+			Files.createDirectories(path.getParent());
+			Files.createFile(path);
 		}
-
-		Path path = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, "Profiles.xml");
-		XMLWriter writer = new XMLWriter(Files.newOutputStream(path), OutputFormat.createPrettyPrint());
-		writer.write(document);
-		writer.close();
+		XMLHandler.save(path, document);
 	}
 
+	/**
+	 * Gibt einen Pfad für einen Dateinamen in diesem Profile zurück.
+	 * 
+	 * @param name
+	 * @return
+	 */
 	public Path getCustomFilePath(String name) {
 		return ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, getFileName(), name);
 	}
 
+	/**
+	 * Gibt den internen (File-) Namen des Profiles zurück.
+	 * 
+	 * @return Ordnernamen
+	 */
 	public String getFileName() {
 		return uuid.toString();
 	}
@@ -239,6 +303,7 @@ public class ProfileReference implements Displayable {
 		return name;
 	}
 
+	// Displayable
 	private StringProperty displayProperty = new SimpleStringProperty(toString());
 
 	@Override
diff --git a/PlayWallCore/src/de/tobias/playpad/settings/ProfileReferenceList.java b/PlayWallCore/src/de/tobias/playpad/settings/ProfileReferenceList.java
new file mode 100644
index 0000000000000000000000000000000000000000..01bf7b7d7a68a3253c946e964ebfa14800796f31
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/settings/ProfileReferenceList.java
@@ -0,0 +1,37 @@
+package de.tobias.playpad.settings;
+
+import de.tobias.utils.list.UniqList;
+
+/**
+ * Liste, wo nur ProfileRefernzen gespeichert werden, deren Namen Unique ist.
+ * 
+ * @author tobias
+ *
+ * @since 5.0.1
+ * @see ProfileReference
+ */
+final class ProfileReferenceList extends UniqList<ProfileReference> {
+
+	private static final long serialVersionUID = 1L;
+
+	public boolean contains(Object o) {
+		if (o instanceof String) {
+			for (ProfileReference reference : this) {
+				if (reference.getName().equals(o)) {
+					return true;
+				} else if (reference.toString().equals(o)) {
+					return true;
+				}
+			}
+		} else if (o instanceof ProfileReference) {
+			for (ProfileReference reference : this) {
+				if (reference.getName() == o) {
+					return true;
+				} else if (reference.getName() == ((ProfileReference) o).getName()) {
+					return true;
+				}
+			}
+		}
+		return super.contains(o);
+	}
+}
\ No newline at end of file
diff --git a/PlayWallCore/src/de/tobias/playpad/settings/ProfileReferenceSerializer.java b/PlayWallCore/src/de/tobias/playpad/settings/ProfileReferenceSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a281ef16c223a94c255b4d18591bcaf7423c2bd
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/settings/ProfileReferenceSerializer.java
@@ -0,0 +1,38 @@
+package de.tobias.playpad.settings;
+
+import java.util.UUID;
+
+import org.dom4j.Element;
+
+import de.tobias.playpad.xml.XMLDeserializer;
+import de.tobias.playpad.xml.XMLSerializer;
+
+/**
+ * Util zum arbeiten mit XML und ProfileReference
+ * 
+ * @author tobias
+ * 
+ * @since 5.0.1
+ * @see ProfileReference
+ */
+public class ProfileReferenceSerializer implements XMLSerializer<ProfileReference>, XMLDeserializer<ProfileReference> {
+
+	private static final String UUID_ATTR = "uuid";
+	private static final String NAME_ATTR = "name";
+
+	@Override
+	public ProfileReference loadElement(Element element) {
+		UUID uuid = UUID.fromString(element.attributeValue(UUID_ATTR));
+		String name = element.attributeValue(NAME_ATTR);
+
+		ProfileReference ref = new ProfileReference(uuid, name);
+		return ref;
+	}
+
+	@Override
+	public void saveElement(Element newElement, ProfileReference data) {
+		newElement.addAttribute(UUID_ATTR, data.getUuid().toString());
+		newElement.addAttribute(NAME_ATTR, data.getName());
+	}
+
+}
diff --git a/PlayWallCore/src/de/tobias/playpad/settings/ProfileSettings.java b/PlayWallCore/src/de/tobias/playpad/settings/ProfileSettings.java
index 3cf852a167e03b5c83f619f2c63583c4fe51e0eb..9189fb33224213e3ba3a70be6b65029f6aa29baf 100644
--- a/PlayWallCore/src/de/tobias/playpad/settings/ProfileSettings.java
+++ b/PlayWallCore/src/de/tobias/playpad/settings/ProfileSettings.java
@@ -17,9 +17,8 @@ import org.dom4j.io.XMLWriter;
 
 import de.tobias.playpad.audio.AudioRegistry;
 import de.tobias.playpad.layout.LayoutRegistry;
-import de.tobias.playpad.pad.Fade;
 import de.tobias.playpad.pad.TimeMode;
-import de.tobias.playpad.pad.Warning;
+import de.tobias.playpad.update.UpdateChannel;
 import de.tobias.utils.application.ApplicationUtils;
 import de.tobias.utils.application.container.PathType;
 import de.tobias.utils.settings.SettingsSerializable;
@@ -73,8 +72,9 @@ public class ProfileSettings implements SettingsSerializable {
 	// Folder
 	@Storable private Path cachePath = ApplicationUtils.getApplication().getPath(PathType.CACHE);
 
-	// Update
+	// Update - TODO GlobalSettings
 	@Storable private boolean autoUpdate = true;
+	@Storable private UpdateChannel updateChannel = UpdateChannel.STABLE;
 
 	public boolean isLocked() {
 		return lockedProperty.get();
@@ -179,6 +179,10 @@ public class ProfileSettings implements SettingsSerializable {
 		return autoUpdate;
 	}
 
+	public UpdateChannel getUpdateChannel() {
+		return updateChannel;
+	}
+
 	// Setter
 	public void setMidiDeviceName(String midiDevice) {
 		this.midiDevice = midiDevice;
@@ -258,6 +262,10 @@ public class ProfileSettings implements SettingsSerializable {
 		this.autoUpdate = autoUpdate;
 	}
 
+	public void setUpdateChannel(UpdateChannel updateChannel) {
+		this.updateChannel = updateChannel;
+	}
+
 	// Properties
 	public DoubleProperty volumeProperty() {
 		return volumeProperty;
@@ -266,6 +274,7 @@ public class ProfileSettings implements SettingsSerializable {
 	private static final String LOCKED_ELEMENT = "Locked";
 	private static final String ITEM_ELEMENT = "Item";
 	private static final String AUTO_UPDATE_ELEMENT = "AutoUpdate";
+	private static final String UPDATE_CHANNEL_ELEMENT = "UpdateChannel";
 	private static final String CACHE_PATH_ELEMENT = "Cache-Path";
 	private static final String VOLUME_ELEMENT = "Volume";
 	private static final String KEY_ATTRIBUTE = "key";
@@ -378,6 +387,10 @@ public class ProfileSettings implements SettingsSerializable {
 			if (root.element(AUTO_UPDATE_ELEMENT) != null) {
 				profileSettings.setAutoUpdate(Boolean.valueOf(root.element(AUTO_UPDATE_ELEMENT).getStringValue()));
 			}
+
+			if (root.element(UPDATE_CHANNEL_ELEMENT) != null) {
+				profileSettings.setUpdateChannel(UpdateChannel.valueOf(root.element(UPDATE_CHANNEL_ELEMENT).getStringValue()));
+			}
 		}
 		return profileSettings;
 	}
@@ -410,7 +423,7 @@ public class ProfileSettings implements SettingsSerializable {
 		liveElement.addAttribute(LIVE_MODE_DRAG_ATTR, String.valueOf(liveModeDrag));
 		liveElement.addAttribute(LIVE_MODE_FILE_ATTR, String.valueOf(liveModeFile));
 		liveElement.addAttribute(LIVE_MODE_SETTINGS_ATTR, String.valueOf(liveModeSettings));
-		
+
 		root.addElement(WINDOW_ALWAYS_ON_TOP_ELEMENT).addText(String.valueOf(windowAlwaysOnTop));
 
 		// Audio
@@ -424,7 +437,10 @@ public class ProfileSettings implements SettingsSerializable {
 
 		// Paths
 		root.addElement(CACHE_PATH_ELEMENT).addText(cachePath.toString());
+		
+		// Update
 		root.addElement(AUTO_UPDATE_ELEMENT).addText(String.valueOf(autoUpdate));
+		root.addElement(UPDATE_CHANNEL_ELEMENT).addText(updateChannel.name());
 
 		XMLWriter writer = new XMLWriter(Files.newOutputStream(path), OutputFormat.createPrettyPrint());
 		writer.write(document);
diff --git a/PlayWallCore/src/de/tobias/playpad/pad/Warning.java b/PlayWallCore/src/de/tobias/playpad/settings/Warning.java
similarity index 96%
rename from PlayWallCore/src/de/tobias/playpad/pad/Warning.java
rename to PlayWallCore/src/de/tobias/playpad/settings/Warning.java
index 11cef9723bf8cc315d29160979934c37f1e8043d..56de8f3d2bdbb892aff6966cd72384500d339cb5 100644
--- a/PlayWallCore/src/de/tobias/playpad/pad/Warning.java
+++ b/PlayWallCore/src/de/tobias/playpad/settings/Warning.java
@@ -1,4 +1,4 @@
-package de.tobias.playpad.pad;
+package de.tobias.playpad.settings;
 
 import org.dom4j.Element;
 
diff --git a/PlayWallCore/src/de/tobias/playpad/Updatable.java b/PlayWallCore/src/de/tobias/playpad/update/Updatable.java
similarity index 56%
rename from PlayWallCore/src/de/tobias/playpad/Updatable.java
rename to PlayWallCore/src/de/tobias/playpad/update/Updatable.java
index 8ae1166bbd82243e86f5db429da899cbea1e722b..88c493aec8cd4b9741f2e46dadfb71df421aec90 100644
--- a/PlayWallCore/src/de/tobias/playpad/Updatable.java
+++ b/PlayWallCore/src/de/tobias/playpad/update/Updatable.java
@@ -1,5 +1,7 @@
-package de.tobias.playpad;
+package de.tobias.playpad.update;
 
+import java.io.IOException;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.nio.file.Path;
 
@@ -13,7 +15,9 @@ public interface Updatable {
 
 	public String getNewVersion();
 
-	public boolean checkUpdate();
+	public boolean isUpdateAvailable();
+	
+	public void loadInformation(UpdateChannel channel) throws IOException, URISyntaxException;
 
 	public URL getDownloadPath();
 	
diff --git a/PlayWallCore/src/de/tobias/playpad/update/UpdateChannel.java b/PlayWallCore/src/de/tobias/playpad/update/UpdateChannel.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca0367b83d6e1209be9076f625caafde2e759364
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/update/UpdateChannel.java
@@ -0,0 +1,18 @@
+package de.tobias.playpad.update;
+
+public enum UpdateChannel {
+
+	STABLE("stable"),
+	BETA("beta");
+
+	private String name;
+
+	private UpdateChannel(String name) {
+		this.name = name;
+	}
+
+	@Override
+	public String toString() {
+		return name;
+	}
+}
diff --git a/PlayWallCore/src/de/tobias/playpad/UpdateRegistery.java b/PlayWallCore/src/de/tobias/playpad/update/UpdateRegistery.java
similarity index 67%
rename from PlayWallCore/src/de/tobias/playpad/UpdateRegistery.java
rename to PlayWallCore/src/de/tobias/playpad/update/UpdateRegistery.java
index 2ce10162e60434ca84d3b2fa6e355e5cfeb8341a..9b2274c4c31ced8afdd4342024a88c6ea83d5083 100644
--- a/PlayWallCore/src/de/tobias/playpad/UpdateRegistery.java
+++ b/PlayWallCore/src/de/tobias/playpad/update/UpdateRegistery.java
@@ -1,9 +1,12 @@
-package de.tobias.playpad;
+package de.tobias.playpad.update;
 
+import java.io.IOException;
 import java.net.URISyntaxException;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.List;
 
+import de.tobias.utils.util.OS;
 import de.tobias.utils.util.SystemUtils;
 import net.minidev.json.JSONArray;
 import net.minidev.json.JSONObject;
@@ -22,11 +25,16 @@ public class UpdateRegistery {
 		return availableUpdates;
 	}
 
-	public static List<Updatable> lookupUpdates() {
+	public static List<Updatable> lookupUpdates(UpdateChannel channel) {
 		availableUpdates.clear();
 		for (Updatable updatable : UpdateRegistery.updatables) {
-			if (updatable.checkUpdate()) {
-				availableUpdates.add(updatable);
+			try {
+				updatable.loadInformation(channel);
+				if (updatable.isUpdateAvailable()) {
+					availableUpdates.add(updatable);
+				}
+			} catch (IOException | URISyntaxException e) {
+
 			}
 		}
 		return availableUpdates;
@@ -59,4 +67,20 @@ public class UpdateRegistery {
 		String json = data.toJSONString(JSONStyle.MAX_COMPRESS);
 		return json;
 	}
+
+	public static boolean needsAdminPermission() {
+		for (Updatable updatable : availableUpdates) {
+			if (!Files.isWritable(updatable.getLocalPath())) {
+				return true;
+			}
+			if (OS.isWindows()) {
+				try {
+					if (Files.getOwner(updatable.getLocalPath()).getName().toLowerCase().contains("admin")) {
+						return true;
+					}
+				} catch (IOException e) {}
+			}
+		}
+		return false;
+	}
 }
diff --git a/PlayWallCore/src/de/tobias/playpad/viewcontroller/ISettingsViewController.java b/PlayWallCore/src/de/tobias/playpad/viewcontroller/ISettingsViewController.java
index 5b7373d51483b85de5fd7341ff83d33ad312bca3..173055b25647b514d39da9f6005ea04a3959a80b 100644
--- a/PlayWallCore/src/de/tobias/playpad/viewcontroller/ISettingsViewController.java
+++ b/PlayWallCore/src/de/tobias/playpad/viewcontroller/ISettingsViewController.java
@@ -1,7 +1,20 @@
 package de.tobias.playpad.viewcontroller;
 
+/**
+ * Schnittstelle um die ProfileSettingsView zu ändern.
+ * 
+ * @author tobias
+ *
+ * @since 5.0.0
+ */
 public interface ISettingsViewController {
 
+	/**
+	 * Fügt en Tab hinzu.
+	 * 
+	 * @param videoSettingsTabViewController
+	 *            tab
+	 */
 	public void addTab(SettingsTabViewController videoSettingsTabViewController);
 
 }
diff --git a/PlayWallCore/src/de/tobias/playpad/viewcontroller/SettingsTabViewController.java b/PlayWallCore/src/de/tobias/playpad/viewcontroller/SettingsTabViewController.java
index 6a64bfc43502ca3065d135f54d4e6eb706730c22..fba59413967875b1b17a348a546158b8016ceda5 100644
--- a/PlayWallCore/src/de/tobias/playpad/viewcontroller/SettingsTabViewController.java
+++ b/PlayWallCore/src/de/tobias/playpad/viewcontroller/SettingsTabViewController.java
@@ -7,21 +7,77 @@ import de.tobias.playpad.settings.Profile;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import de.tobias.utils.ui.ContentViewController;
 
+/**
+ * Abstract Tab für SettingsViewController.
+ * 
+ * @author tobias
+ * 
+ * @since 5.0.0
+ *
+ */
 public abstract class SettingsTabViewController extends ContentViewController {
 
+	/**
+	 * Erstellt einen neuen Tab.
+	 * 
+	 * @param name
+	 *            Name der FXML
+	 * @param path
+	 *            Pfad zu FXML (ohne Dateiname)
+	 * @param localization
+	 *            ResourceBundle oder null
+	 */
 	public SettingsTabViewController(String name, String path, ResourceBundle localization) {
 		super(name, path, localization);
 	}
 
+	/**
+	 * Lädt alle Einstellungen vom Model in die GUI.
+	 * 
+	 * @param profile
+	 *            Aktuelles Profile
+	 */
 	public abstract void loadSettings(Profile profile);
 
+	/**
+	 * Speichert alle Änderungen in das Model.
+	 * 
+	 * @param profile
+	 *            Aktuelles Profile
+	 */
 	public abstract void saveSettings(Profile profile);
 
+	/**
+	 * Gibt <code>true</code> zurück, wenn im Hauptprogramm etwas neu geladen werden muss. Der eigentliche Reload wird in
+	 * {@link #reload(Profile, Project, IMainViewController)} ausgeführt.
+	 * 
+	 * @return <code>true</code> Benötigt Reload
+	 */
 	public abstract boolean needReload();
 
+	/**
+	 * Lädt gestimmte Einstellungen für die GUI neu.
+	 * 
+	 * @param profile
+	 *            Aktuelles Profile
+	 * @param project
+	 *            Aktuelles Projekt
+	 * @param controller
+	 *            Main View Controller
+	 */
 	public void reload(Profile profile, Project project, IMainViewController controller) {}
 
+	/**
+	 * Prüft ob die eingetragen Einstellungen erlaubt sind. Bei falschen Eingaben können die Einstellungen nicht geschlossen werden.
+	 * 
+	 * @return <code>true</code> Einstellungen erlaubt. <code>false</code> Einstellungen fehlerhaft.
+	 */
 	public abstract boolean validSettings();
 
+	/**
+	 * Gibt den Namen für den Tab zurück.
+	 * 
+	 * @return
+	 */
 	public abstract String name();
 }
diff --git a/PlayWallCore/src/de/tobias/playpad/xml/XMLDeserializer.java b/PlayWallCore/src/de/tobias/playpad/xml/XMLDeserializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..b458b2bbbbbe92ee5f73321857d5574db09fb816
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/xml/XMLDeserializer.java
@@ -0,0 +1,23 @@
+package de.tobias.playpad.xml;
+
+import org.dom4j.Element;
+
+/**
+ * Schnittstelle um ein Object auf einem XML Tree zu deserialisieren.
+ * 
+ * @author tobias
+ *
+ * @param <T>
+ *            Typ der Daten
+ */
+public interface XMLDeserializer<T> {
+
+	/**
+	 * Lädt ein Object auf XML Daten.
+	 * 
+	 * @param element
+	 * @return
+	 */
+	public T loadElement(Element element);
+
+}
diff --git a/PlayWallCore/src/de/tobias/playpad/xml/XMLHandler.java b/PlayWallCore/src/de/tobias/playpad/xml/XMLHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ba39178b14a48772acb9a7abde893467bd36055
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/xml/XMLHandler.java
@@ -0,0 +1,120 @@
+package de.tobias.playpad.xml;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.dom4j.io.OutputFormat;
+import org.dom4j.io.SAXReader;
+import org.dom4j.io.XMLWriter;
+
+/**
+ * Util Methods zum Laden von XML Files.
+ * 
+ * @author tobias
+ * 
+ * @since 5.0.1
+ */
+public class XMLHandler<T> {
+
+	private Element rootElement;
+
+	/**
+	 * Lädt ein XML Dokument und speichert sich den RootNode.
+	 * 
+	 * @param path
+	 *            Path zu XML Datei
+	 * @throws DocumentException
+	 *             Fehler in der XML Datei
+	 * @throws IOException
+	 *             IO Fehler (Bsp. Datei nicht vorhanden)
+	 */
+	public XMLHandler(Path path) throws DocumentException, IOException {
+		if (Files.exists(path)) {
+			SAXReader reader = new SAXReader();
+			Document document = reader.read(Files.newInputStream(path));
+			rootElement = document.getRootElement();
+		} else {
+			throw new FileNotFoundException(path.toString());
+		}
+	}
+
+	/**
+	 * Erstellt einen neuen Handler mit einem RootElement.
+	 * 
+	 * @param rootElement
+	 *            RootElement
+	 */
+	public XMLHandler(Element rootElement) {
+		this.rootElement = rootElement;
+	}
+
+	/**
+	 * Lädt ein Datenrecord auf einem Array von Daten
+	 * 
+	 * @param listElementTag
+	 *            Datentype
+	 * @param deserializer
+	 *            Deserializer
+	 * @return Liste von Daten
+	 */
+	public List<T> loadElements(String listElementTag, XMLDeserializer<T> deserializer) {
+		List<T> list = new ArrayList<>();
+
+		for (Object object : rootElement.elements(listElementTag)) {
+			if (object instanceof Element) {
+				Element element = (Element) object;
+				T data = deserializer.loadElement(element);
+				list.add(data);
+			}
+		}
+
+		return list;
+	}
+
+	/**
+	 * Speichert eine Liste von Objekten mittels Serializer.
+	 * 
+	 * @param listElementTag
+	 *            Name der XML Element
+	 * @param list
+	 *            Liste der Daten
+	 * @param serializer
+	 *            Serializer
+	 */
+	public void saveElements(String listElementTag, Iterable<T> list, XMLSerializer<T> serializer) {
+		for (T data : list) {
+			Element element = rootElement.addElement(listElementTag);
+			serializer.saveElement(element, data);
+		}
+	}
+
+	/**
+	 * Speichert eine XML in einem Path.
+	 * 
+	 * @param path
+	 *            Path der Datei
+	 * @param document
+	 *            XML Document
+	 * @throws UnsupportedEncodingException
+	 *             Falsches Encoding
+	 * @throws IOException
+	 *             IO Fehler (Bsp. File nicht vorhanden)
+	 */
+	public static void save(Path path, Document document) throws UnsupportedEncodingException, IOException {
+		if (Files.exists(path)) {
+			XMLWriter writer = new XMLWriter(Files.newOutputStream(path), OutputFormat.createPrettyPrint());
+			writer.write(document);
+			writer.close();
+		} else {
+			throw new FileNotFoundException(path.toString());
+		}
+	}
+}
diff --git a/PlayWallCore/src/de/tobias/playpad/xml/XMLSerializer.java b/PlayWallCore/src/de/tobias/playpad/xml/XMLSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..824741866bf6a72c89126febc81415cecb63869a
--- /dev/null
+++ b/PlayWallCore/src/de/tobias/playpad/xml/XMLSerializer.java
@@ -0,0 +1,26 @@
+package de.tobias.playpad.xml;
+
+import org.dom4j.Element;
+
+/**
+ * Schnittstelle um ein Object in eine XML Struktur zu überführen.
+ * 
+ * @author tobias
+ *
+ * @param <T>
+ *            Typ der Daten
+ */
+public interface XMLSerializer<T> {
+
+	/**
+	 * Überführt ein Object in eine XML Struktur. Dafür wird bereits ein XML Object angelegt, zu dem Attribute und Sub Elemente hinzugefügt
+	 * werden können.
+	 * 
+	 * @param newElement
+	 *            XML Object
+	 * @param data
+	 *            Daten
+	 */
+	public void saveElement(Element newElement, T data);
+
+}
diff --git a/PlayWallPlugins/.classpath b/PlayWallPlugins/.classpath
new file mode 100644
index 0000000000000000000000000000000000000000..dff7fdd8d23f0ac9b407b77addb5d79e1997cc9f
--- /dev/null
+++ b/PlayWallPlugins/.classpath
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry excluding="de/tobias/playpad/launchpadplugin/midi/device/s/LaunchPadSOld.java|de/tobias/playpad/launchpadplugin/midi/device/mk2/LaunchPadMK2Old.java|de/tobias/playpad/launchpadplugin/midi/device/s/MultipleFeedbackSViewController.java|de/tobias/playpad/launchpadplugin/midi/device/s/SimpleFeedbackSViewController.java|de/tobias/playpad/launchpadplugin/midi/device/mk2/MultipleFeedbackMK2ViewController.java|de/tobias/playpad/launchpadplugin/midi/device/mk2/SimpleFeedbackMK2ViewController.java|de/tobias/playpad/launchpadplugin/impl/FeedbackMessageTypeCell.java|de/tobias/playpad/launchpadplugin/midi/device/mk2/WarningFeedbackViewControllerMK2.java|de/tobias/playpad/launchpadplugin/midi/device/s/WarningFeedbackViewControllerS.java" kind="src" path="launchpadplugin"/>
+	<classpathentry kind="src" path="awakeplugin"/>
+	<classpathentry excluding="de/tobias/playpad/midiactions/muteaction/MuteActionSettingsViewController.java|de/tobias/playpad/midiactions/muteaction/MuteActionType.java|de/tobias/playpad/midiactions/muteaction/MuteEvent.java|de/tobias/playpad/midiactions/muteaction/MuteListener.java" kind="src" path="actionsplugin"/>
+	<classpathentry kind="src" path="mediaplugin"/>
+	<classpathentry kind="src" path="equalizerplugin"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Plugins"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/XML"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/libUtils"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ControlFx"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/PlayWallCore"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/YML"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/PlayWallPlugins/.gitignore b/PlayWallPlugins/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..65776c32fc48190de1439385c361505b36591c1c
--- /dev/null
+++ b/PlayWallPlugins/.gitignore
@@ -0,0 +1 @@
+/bin/
\ No newline at end of file
diff --git a/PlayWallPlugins/.project b/PlayWallPlugins/.project
new file mode 100644
index 0000000000000000000000000000000000000000..e6c6a8fdfb3cb5e2db27ac851af8b452264268b5
--- /dev/null
+++ b/PlayWallPlugins/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>PlayWallPlugins</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/PlayWallPlugins/.settings/org.eclipse.jdt.core.prefs b/PlayWallPlugins/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..3a21537071bf4118b9e1ee864cb4bc258aa48211
--- /dev/null
+++ b/PlayWallPlugins/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/ActionsPlugin.java b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/ActionsPlugin.java
new file mode 100644
index 0000000000000000000000000000000000000000..13aec012801daff5a9206c7ec8ed05d980b0e042
--- /dev/null
+++ b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/ActionsPlugin.java
@@ -0,0 +1,7 @@
+package de.tobias.playpad.actionsplugin;
+
+import net.xeoh.plugins.base.Plugin;
+
+public interface ActionsPlugin extends Plugin {
+
+}
diff --git a/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/assets/actions_de.properties b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/assets/actions_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..6659bdcf4fa25d66e2b12da2973d3ee84aade5d4
--- /dev/null
+++ b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/assets/actions_de.properties
@@ -0,0 +1,2 @@
+muteaction.name=Ton stumm schalten
+stopaction.name=Stopp
\ No newline at end of file
diff --git a/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/impl/ActionsPluginImpl.java b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/impl/ActionsPluginImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..e2eada8fc11a706ef0200fd4f5224cf366bca4fd
--- /dev/null
+++ b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/impl/ActionsPluginImpl.java
@@ -0,0 +1,156 @@
+package de.tobias.playpad.actionsplugin.impl;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.action.ActionRegistery;
+import de.tobias.playpad.actionsplugin.ActionsPlugin;
+import de.tobias.playpad.actionsplugin.muteaction.MuteActionConnect;
+import de.tobias.playpad.actionsplugin.stopaction.StopActionConnect;
+import de.tobias.playpad.plugin.WindowListener;
+import de.tobias.playpad.settings.Profile;
+import de.tobias.playpad.settings.ProfileListener;
+import de.tobias.playpad.update.UpdateRegistery;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+import de.tobias.utils.ui.HUD;
+import de.tobias.utils.ui.icon.FontIcon;
+import de.tobias.utils.ui.icon.MaterialDesignIcon;
+import de.tobias.utils.util.Localization;
+import javafx.application.Platform;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.geometry.Pos;
+import javafx.scene.control.CheckMenuItem;
+import javafx.scene.layout.Pane;
+import javafx.scene.paint.Color;
+import net.xeoh.plugins.base.annotations.PluginImplementation;
+import net.xeoh.plugins.base.annotations.events.PluginLoaded;
+import net.xeoh.plugins.base.annotations.events.Shutdown;
+
+@PluginImplementation
+public class ActionsPluginImpl implements ActionsPlugin, ChangeListener<Boolean>, ProfileListener {
+
+	private static ResourceBundle bundle;
+	public static CheckMenuItem muteMenuItem;
+
+	private static BooleanProperty muteProperty;
+	private static ChangeListener<Number> volumeListener;
+
+	private HUD muteHUD;
+
+	@PluginLoaded
+	public void onEnable(ActionsPlugin plugin) {
+		muteProperty = new SimpleBooleanProperty();
+		try {
+			bundle = Localization.loadBundle("de/tobias/playpad/actionsplugin/assets/actions", ActionsPluginImpl.class.getClassLoader());
+		} catch (MissingResourceException e) {
+			System.err.println("Cannot find resource for actions plugin: " + e.getLocalizedMessage());
+		}
+
+		if (muteHUD == null) {
+			Platform.runLater(() ->
+			{
+				FontIcon icon = new FontIcon(MaterialDesignIcon.FONT_FILE, MaterialDesignIcon.VOLUME_OFF);
+				icon.setSize(60);
+				icon.getStyleClass().remove(FontIcon.STYLE_CLASS);
+				icon.setColor(Color.WHITE);
+				icon.setAlignment(Pos.CENTER);
+				muteHUD = new HUD(icon);
+				muteHUD.setMinWidth(200);
+				muteHUD.setMinHeight(100);
+			});
+
+			PlayPadPlugin.getImplementation().addMainViewListener(new WindowListener<IMainViewController>() {
+
+				@Override
+				public void onInit(IMainViewController t) {
+					t.getVolumeSlider().valueChangingProperty().addListener(new ChangeListener<Boolean>() {
+
+						@Override
+						public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
+							if (newValue && volume == -1 && Profile.currentProfile().getProfileSettings().getVolume() != 0) {
+								volume = Profile.currentProfile().getProfileSettings().getVolume();
+							} else {
+								volume = -1;
+							}
+						}
+					});
+				}
+			});
+
+			volumeListener = (a, b, c) ->
+			{
+				double newVolume = c.doubleValue();
+				double oldVolume = b.doubleValue();
+
+				if (newVolume != 0 && oldVolume == 0 && muteProperty.get()) {
+					muteProperty.set(false);
+				} else if (newVolume == 0 && oldVolume != 0 && !muteProperty.get()) {
+					muteProperty.set(true);
+				}
+			};
+		}
+
+		UpdateRegistery.registerUpdateable(new ActionsPluginUpdater());
+		Profile.registerListener(this);
+
+		ActionRegistery.registerActionConnect(new MuteActionConnect());
+		ActionRegistery.registerActionConnect(new StopActionConnect());
+
+		muteProperty.addListener(this);
+
+		System.out.println("Enable Action Plugin");
+
+	}
+
+	@Override
+	public void reloadSettings(Profile oldProfile, Profile currentProfile) {
+		if (oldProfile != null) {
+			oldProfile.getProfileSettings().volumeProperty().removeListener(volumeListener);
+		}
+		currentProfile.getProfileSettings().volumeProperty().addListener(volumeListener);
+	}
+
+	public static BooleanProperty muteProperty() {
+		return muteProperty;
+	}
+
+	@Shutdown
+	public void onDisable() {
+		System.out.println("Disable Action Plugin");
+	}
+
+	public static ResourceBundle getBundle() {
+		return bundle;
+	}
+
+	private double volume = -1;
+
+	@Override
+	public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
+		Platform.runLater(() ->
+		{
+			if (newValue) {
+				if (volume == -1) {
+					volume = Profile.currentProfile().getProfileSettings().getVolume();
+				}
+				Profile.currentProfile().getProfileSettings().setVolume(0);
+
+				Pane root = (Pane) PlayPadPlugin.getImplementation().getMainViewController().getParent();
+				if (muteHUD != null)
+					muteHUD.addToParent(root);
+			} else {
+				if (volume == 0) {
+					volume = 1;
+				}
+				Profile.currentProfile().getProfileSettings().setVolume(volume);
+
+				muteHUD.removeFromParent();
+				volume = -1;
+			}
+		});
+	}
+}
diff --git a/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/impl/ActionsPluginUpdater.java b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/impl/ActionsPluginUpdater.java
new file mode 100644
index 0000000000000000000000000000000000000000..79d76c4ee3d1b50b7cbe0f9f54bb540ac7e547f5
--- /dev/null
+++ b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/impl/ActionsPluginUpdater.java
@@ -0,0 +1,79 @@
+package de.tobias.playpad.actionsplugin.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Path;
+
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import de.tobias.playpad.update.Updatable;
+import de.tobias.playpad.update.UpdateChannel;
+import de.tobias.utils.application.App;
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.container.PathType;
+
+public class ActionsPluginUpdater implements Updatable {
+
+	private int newBuild;
+	private String newVersion;
+	private URL remotePath;
+
+	private String localFileName;
+	private String name;
+
+	@Override
+	public int getCurrentBuild() {
+		return 3;
+	}
+
+	@Override
+	public String getCurrentVersion() {
+		return "3.0";
+	}
+
+	@Override
+	public int getNewBuild() {
+		return newBuild;
+	}
+
+	@Override
+	public String getNewVersion() {
+		return newVersion;
+	}
+
+	@Override
+	public void loadInformation(UpdateChannel channel) throws IOException {
+		App app = ApplicationUtils.getMainApplication();
+		URL url = new URL(app.getInfo().getUpdateURL() + "/" + channel + "/plugins.yml");
+		FileConfiguration config = YamlConfiguration.loadConfiguration(url.openStream());
+
+		newBuild = config.getInt("plugins.action.build");
+		newVersion = config.getString("plugins.action.version");
+		remotePath = new URL(config.getString("plugins.action.url"));
+		localFileName = config.getString("plugins.action.filename");
+		name = config.getString("plugins.action.name");
+
+	}
+
+	@Override
+	public boolean isUpdateAvailable() {
+		return getCurrentBuild() < getNewBuild();
+	}
+
+	@Override
+	public URL getDownloadPath() {
+		return remotePath;
+	}
+
+	@Override
+	public Path getLocalPath() {
+		return ApplicationUtils.getApplication().getPath(PathType.LIBRARY, localFileName);
+	}
+
+	@Override
+	public String name() {
+		return name;
+	}
+
+}
diff --git a/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/muteaction/MuteAction.java b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/muteaction/MuteAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..79108172ab2f6cfc937db836cddbdbf0110be61a
--- /dev/null
+++ b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/muteaction/MuteAction.java
@@ -0,0 +1,99 @@
+package de.tobias.playpad.actionsplugin.muteaction;
+
+import org.dom4j.Element;
+
+import de.tobias.playpad.Displayable;
+import de.tobias.playpad.action.Action;
+import de.tobias.playpad.action.InputType;
+import de.tobias.playpad.action.feedback.FeedbackMessage;
+import de.tobias.playpad.action.feedback.FeedbackType;
+import de.tobias.playpad.actionsplugin.impl.ActionsPluginImpl;
+import de.tobias.playpad.project.Project;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+import de.tobias.utils.ui.icon.FontIcon;
+import de.tobias.utils.ui.icon.MaterialDesignIcon;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.beans.value.ChangeListener;
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+
+public class MuteAction extends Action implements Displayable {
+
+	private ChangeListener<Boolean> muteListener;
+
+	public MuteAction() {
+		muteListener = (a, b, c) ->
+		{
+			if (c) {
+				handleFeedback(FeedbackMessage.EVENT);
+			} else {
+				handleFeedback(FeedbackMessage.STANDARD);
+			}
+		};
+	}
+
+	@Override
+	public void performAction(InputType type, Project project, IMainViewController mainViewController) {
+		if (type == InputType.PRESSED) {
+			ActionsPluginImpl.muteProperty().set(!ActionsPluginImpl.muteProperty().get());
+		}
+	}
+
+	@Override
+	public void clearFeedback() {
+		ActionsPluginImpl.muteProperty().removeListener(muteListener);
+	}
+
+	@Override
+	public void initFeedback(Project project, IMainViewController controller) {
+		// Listener für Eingaben
+		BooleanProperty muteProperty = ActionsPluginImpl.muteProperty();
+		muteProperty.removeListener(muteListener);
+		muteProperty.addListener(muteListener);
+
+		// Handle Current Feedback
+		muteListener.changed(muteProperty, null, muteProperty.getValue());
+	}
+
+	@Override
+	public FeedbackType geFeedbackType() {
+		return FeedbackType.DOUBLE;
+	}
+
+	@Override
+	public String getType() {
+		return MuteActionConnect.TYPE;
+	}
+
+	@Override
+	public void load(Element root) {}
+
+	@Override
+	public void save(Element root) {}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj.getClass().equals(getClass())) {
+			return true;
+		}
+		return super.equals(obj);
+	}
+
+	@Override
+	public StringProperty displayProperty() {
+		return new SimpleStringProperty(ActionsPluginImpl.getBundle().getString("muteaction.name"));
+	}
+
+	@Override
+	public Node getGraphics() {
+		return new Label("", new FontIcon(MaterialDesignIcon.FONT_FILE, MaterialDesignIcon.VOLUME_OFF));
+	}
+
+	@Override
+	public Action cloneAction() throws CloneNotSupportedException {
+		MuteAction actionClone = (MuteAction) super.clone();
+		return actionClone;
+	}
+}
diff --git a/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/muteaction/MuteActionConnect.java b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/muteaction/MuteActionConnect.java
new file mode 100644
index 0000000000000000000000000000000000000000..e48dafbea5d7637d2252ee6993b28d2b0d0deebf
--- /dev/null
+++ b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/muteaction/MuteActionConnect.java
@@ -0,0 +1,42 @@
+package de.tobias.playpad.actionsplugin.muteaction;
+
+import java.util.List;
+
+import de.tobias.playpad.action.Action;
+import de.tobias.playpad.action.ActionConnect;
+import de.tobias.playpad.action.ActionDisplayable;
+import de.tobias.playpad.action.ActionType;
+import de.tobias.playpad.action.Mapping;
+import de.tobias.playpad.settings.Profile;
+import javafx.scene.control.TreeItem;
+
+public class MuteActionConnect extends ActionConnect {
+
+	public static final String TYPE = "MUTE";
+
+	@Override
+	public TreeItem<ActionDisplayable> getTreeViewForActions(List<Action> actions, Mapping mapping) {
+		TreeItem<ActionDisplayable> item = new TreeItem<>(actions.get(0));
+		return item;
+	}
+
+	@Override
+	public void initActionType(Mapping mapping, Profile profile) {
+		mapping.addActionIfNotContains(new MuteAction());
+	}
+
+	@Override
+	public Action newInstance() {
+		return new MuteAction();
+	}
+	
+	@Override
+	public ActionType geActionType() {
+		return ActionType.SETTINGS;
+	}
+	
+	@Override
+	public String getType() {
+		return TYPE;
+	}
+}
diff --git a/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/stopaction/StopAction.java b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/stopaction/StopAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..b417358e2a044cc8940383a012d45127d50b6c5b
--- /dev/null
+++ b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/stopaction/StopAction.java
@@ -0,0 +1,80 @@
+package de.tobias.playpad.actionsplugin.stopaction;
+
+import org.dom4j.Element;
+
+import de.tobias.playpad.action.Action;
+import de.tobias.playpad.action.InputType;
+import de.tobias.playpad.action.feedback.FeedbackMessage;
+import de.tobias.playpad.action.feedback.FeedbackType;
+import de.tobias.playpad.actionsplugin.impl.ActionsPluginImpl;
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadStatus;
+import de.tobias.playpad.project.Project;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+import de.tobias.utils.ui.icon.FontAwesomeType;
+import de.tobias.utils.ui.icon.FontIcon;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+
+public class StopAction extends Action {
+
+	@Override
+	public String getType() {
+		return StopActionConnect.TYPE;
+	}
+
+	@Override
+	public void performAction(InputType type, Project project, IMainViewController mainViewController) {
+		for (Pad pad : project.getPads().values()) {
+			if (pad.getStatus() == PadStatus.PLAY || pad.getStatus() == PadStatus.PAUSE)
+				pad.setStatus(PadStatus.STOP, true);
+		}
+	}
+
+	@Override
+	public void initFeedback(Project project, IMainViewController controller) {
+		handleFeedback(FeedbackMessage.STANDARD);
+	}
+
+	@Override
+	public void clearFeedback() {
+		handleFeedback(FeedbackMessage.OFF);
+	}
+
+	@Override
+	public FeedbackType geFeedbackType() {
+		return FeedbackType.SINGLE;
+	}
+
+	@Override
+	public void load(Element root) {}
+
+	@Override
+	public void save(Element root) {}
+
+	@Override
+	public StringProperty displayProperty() {
+		return new SimpleStringProperty(ActionsPluginImpl.getBundle().getString("stopaction.name"));
+	}
+
+	@Override
+	public Node getGraphics() {
+		return new Label("", new FontIcon(FontAwesomeType.STOP));
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj.getClass().equals(getClass())) {
+			return true;
+		}
+		return super.equals(obj);
+	}
+
+	@Override
+	public Action cloneAction() throws CloneNotSupportedException {
+		return (Action) super.clone();
+	}
+
+}
diff --git a/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/stopaction/StopActionConnect.java b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/stopaction/StopActionConnect.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f7cab1c9d67335aebdb7c3c1883aafd1f11993f
--- /dev/null
+++ b/PlayWallPlugins/actionsplugin/de/tobias/playpad/actionsplugin/stopaction/StopActionConnect.java
@@ -0,0 +1,42 @@
+package de.tobias.playpad.actionsplugin.stopaction;
+
+import java.util.List;
+
+import de.tobias.playpad.action.Action;
+import de.tobias.playpad.action.ActionConnect;
+import de.tobias.playpad.action.ActionDisplayable;
+import de.tobias.playpad.action.ActionType;
+import de.tobias.playpad.action.Mapping;
+import de.tobias.playpad.settings.Profile;
+import javafx.scene.control.TreeItem;
+
+public class StopActionConnect extends ActionConnect {
+
+	public static final String TYPE = "STOP";
+
+	@Override
+	public TreeItem<ActionDisplayable> getTreeViewForActions(List<Action> actions, Mapping mapping) {
+		TreeItem<ActionDisplayable> item = new TreeItem<>(actions.get(0));
+		return item;
+	}
+
+	@Override
+	public void initActionType(Mapping mapping, Profile profile) {
+		mapping.addActionIfNotContains(newInstance());
+	}
+
+	@Override
+	public Action newInstance() {
+		return new StopAction();
+	}
+
+	@Override
+	public ActionType geActionType() {
+		return ActionType.CONTROL;
+	}
+
+	@Override
+	public String getType() {
+		return TYPE;
+	}
+}
diff --git a/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/AwakePlugin.java b/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/AwakePlugin.java
new file mode 100644
index 0000000000000000000000000000000000000000..abda3de1f2a37514e3f7180328e2f2fc3ca0adb2
--- /dev/null
+++ b/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/AwakePlugin.java
@@ -0,0 +1,7 @@
+package de.tobias.playpad.awakeplugin;
+
+import net.xeoh.plugins.base.Plugin;
+
+public interface AwakePlugin extends Plugin {
+
+}
diff --git a/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/AwakeSettings.java b/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/AwakeSettings.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a1508e178ae426d261cce129e73365d40a69d9b
--- /dev/null
+++ b/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/AwakeSettings.java
@@ -0,0 +1,48 @@
+package de.tobias.playpad.awakeplugin;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+import org.dom4j.io.OutputFormat;
+import org.dom4j.io.SAXReader;
+import org.dom4j.io.XMLWriter;
+
+public class AwakeSettings {
+
+	public boolean active = false;
+
+	private static final String ACTIVE_ELEMENT = "Active";
+
+	public static AwakeSettings load(Path path) throws DocumentException, IOException {
+		AwakeSettings settings = new AwakeSettings();
+		SAXReader reader = new SAXReader();
+		Document document = reader.read(Files.newInputStream(path));
+
+		Element rootElement = document.getRootElement();
+		settings.active = Boolean.valueOf(rootElement.element(ACTIVE_ELEMENT).getStringValue());
+
+		return settings;
+	}
+
+	public void save(Path path) throws UnsupportedEncodingException, IOException {
+		Document document = DocumentHelper.createDocument();
+		Element rootElement = document.addElement("Settings");
+
+		Element activeElement = rootElement.addElement(ACTIVE_ELEMENT);
+		activeElement.addText(String.valueOf(active));
+
+		if (Files.notExists(path)) {
+			Files.createDirectories(path.getParent());
+			Files.createFile(path);
+		}
+		XMLWriter writer = new XMLWriter(Files.newOutputStream(path), OutputFormat.createPrettyPrint());
+		writer.write(document);
+		writer.close();
+	}
+}
diff --git a/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/assets/awake_de.properties b/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/assets/awake_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..745ae728a30e3c2a58a2ac45213763c3fdd1e178
--- /dev/null
+++ b/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/assets/awake_de.properties
@@ -0,0 +1 @@
+menutitle=Ruhezustand verhindern
\ No newline at end of file
diff --git a/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/impl/AwakePluginImpl.java b/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/impl/AwakePluginImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..42b536e0ec16ed773b68a36db6a505652ed05dab
--- /dev/null
+++ b/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/impl/AwakePluginImpl.java
@@ -0,0 +1,183 @@
+package de.tobias.playpad.awakeplugin.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.util.ResourceBundle;
+
+import org.dom4j.DocumentException;
+
+import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.awakeplugin.AwakePlugin;
+import de.tobias.playpad.awakeplugin.AwakeSettings;
+import de.tobias.playpad.plugin.SettingsListener;
+import de.tobias.playpad.plugin.WindowListener;
+import de.tobias.playpad.settings.Profile;
+import de.tobias.playpad.update.UpdateRegistery;
+import de.tobias.playpad.viewcontroller.main.IMainToolbarViewController;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.container.PathType;
+import de.tobias.utils.ui.icon.FontAwesomeType;
+import de.tobias.utils.ui.icon.FontIcon;
+import de.tobias.utils.util.AwakeUtils;
+import de.tobias.utils.util.IOUtils;
+import de.tobias.utils.util.Kernel32;
+import de.tobias.utils.util.Localization;
+import de.tobias.utils.util.OS;
+import de.tobias.utils.util.OS.OSType;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.scene.control.CheckMenuItem;
+import javafx.scene.control.Label;
+import net.xeoh.plugins.base.annotations.PluginImplementation;
+import net.xeoh.plugins.base.annotations.events.PluginLoaded;
+import net.xeoh.plugins.base.annotations.events.Shutdown;
+
+@PluginImplementation
+public class AwakePluginImpl implements AwakePlugin, WindowListener<IMainViewController>, EventHandler<ActionEvent>, SettingsListener {
+
+	private static final String SETTINGS_FILENAME = "Awake.xml";
+
+	private CheckMenuItem activeMenu;
+	private Label iconLabel;
+
+	private AwakeSettings settings = new AwakeSettings();
+
+	private ResourceBundle bundle;
+
+	@PluginLoaded
+	public void onLoad(AwakePlugin plugin) {
+		bundle = Localization.loadBundle("de/tobias/playpad/awakeplugin/assets/awake", getClass().getClassLoader());
+
+		UpdateRegistery.registerUpdateable(new AwakePluginUpdater());
+
+		if (OS.getType() == OSType.Windows) {
+			try {
+				loadJNA();
+				PlayPadPlugin.getImplementation().loadPlugin(ApplicationUtils.getApplication().getPath(PathType.LIBRARY, "jna").toUri());
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		} else if (OS.getType() == OSType.MacOSX) {
+			try {
+				Path file = loadLibMac();
+				AwakeUtils.load(file.toString());
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+
+		PlayPadPlugin.getImplementation().addMainViewListener(this);
+		PlayPadPlugin.getImplementation().addSettingsListener(this);
+		System.out.println("Enable Awake Plugin");
+	}
+
+	@Shutdown
+	public void onDisable() {
+		System.out.println("Disable Awake Plugin");
+	}
+
+	private Path loadLibMac() throws IOException {
+		Path folder = ApplicationUtils.getApplication().getPath(PathType.LIBRARY, "awakelib.dylib");
+		if (Files.notExists(folder)) {
+			Files.createFile(folder);
+			URL url = new URL(ApplicationUtils.getApplication().getInfo().getUpdateURL() + "/plugins/libAwake/libAwakeLib.dylib");
+			System.out.println("Downlaod " + url);
+			IOUtils.copy(url.openStream(), folder);
+		}
+		return folder;
+	}
+
+	private void loadJNA() throws IOException {
+		Path folder = ApplicationUtils.getApplication().getPath(PathType.LIBRARY, "jna");
+
+		Path jnaFile = folder.resolve("jna.jar");
+		Path jnaPlatformFile = folder.resolve("jna-platform.jar");
+
+		if (Files.notExists(jnaFile)) {
+			Files.createDirectories(folder);
+			URL url = new URL(ApplicationUtils.getApplication().getInfo().getUpdateURL() + "/plugins/jna/jna.jar");
+			System.out.println("Downlaod " + url);
+			IOUtils.copy(url.openStream(), jnaFile);
+		}
+
+		if (Files.notExists(jnaPlatformFile)) {
+			Files.createDirectories(folder);
+			URL url = new URL(ApplicationUtils.getApplication().getInfo().getUpdateURL() + "/plugins/jna/jna-platform.jar");
+			System.out.println("Downlaod " + url);
+			IOUtils.copy(url.openStream(), jnaPlatformFile);
+		}
+	}
+
+	@Override
+	public void onLoad(Profile profile) {
+		Path path = profile.getRef().getCustomFilePath(SETTINGS_FILENAME);
+
+		try {
+			settings = AwakeSettings.load(path);
+		} catch (NoSuchFileException e) {
+			System.out.println("No Awake.xml config on folder");
+		} catch (DocumentException | IOException e) {
+			e.printStackTrace();
+		}
+
+		activeSleep(settings.active);
+		if (activeMenu != null)
+			activeMenu.setSelected(settings.active);
+	}
+
+	@Override
+	public void onSave(Profile profile) {
+		Path path = profile.getRef().getCustomFilePath(SETTINGS_FILENAME);
+
+		try {
+			settings.save(path);
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public void onInit(IMainViewController t) {
+		activeMenu = new CheckMenuItem();
+		activeMenu.setOnAction(this);
+		activeMenu.setText(bundle.getString("menutitle"));
+		activeMenu.setSelected(settings.active);
+		t.addMenuItem(activeMenu);
+
+		iconLabel = new Label();
+		iconLabel.setGraphic(new FontIcon(FontAwesomeType.MOON_ALT));
+	}
+
+	@Override
+	public void handle(ActionEvent event) {
+		activeSleep(activeMenu.isSelected());
+		settings.active = activeMenu.isSelected();
+
+		IMainToolbarViewController toolbarController = PlayPadPlugin.getImplementation().getMainViewController().getToolbarController();
+		if (settings.active) {
+			toolbarController.showIcon(iconLabel);
+		} else {
+			toolbarController.hideIcon(iconLabel);
+		}
+	}
+
+	public void activeSleep(boolean activate) {
+		if (activate) {
+			if (OS.getType() == OSType.Windows) {
+				Kernel32.INSTANCE.SetThreadExecutionState(Kernel32.ES_CONTINUOUS | Kernel32.ES_DISPLAY_REQUIRED | Kernel32.ES_SYSTEM_REQUIRED);
+			} else if (OS.getType() == OSType.MacOSX) {
+				AwakeUtils.getInstance().lock();
+			}
+		} else {
+			if (OS.getType() == OSType.Windows) {
+				Kernel32.INSTANCE.SetThreadExecutionState(Kernel32.ES_CONTINUOUS);
+			} else if (OS.getType() == OSType.MacOSX) {
+				AwakeUtils.getInstance().unlock();
+			}
+		}
+	}
+}
diff --git a/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/impl/AwakePluginUpdater.java b/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/impl/AwakePluginUpdater.java
new file mode 100644
index 0000000000000000000000000000000000000000..bf34dd937f9c683362234f497c0693bfada5764a
--- /dev/null
+++ b/PlayWallPlugins/awakeplugin/de/tobias/playpad/awakeplugin/impl/AwakePluginUpdater.java
@@ -0,0 +1,79 @@
+package de.tobias.playpad.awakeplugin.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Path;
+
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import de.tobias.playpad.update.Updatable;
+import de.tobias.playpad.update.UpdateChannel;
+import de.tobias.utils.application.App;
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.container.PathType;
+
+public class AwakePluginUpdater implements Updatable {
+
+	private int newBuild;
+	private String newVersion;
+	private URL remotePath;
+
+	private String localFileName;
+	private String name;
+
+	@Override
+	public int getCurrentBuild() {
+		return 2;
+	}
+
+	@Override
+	public String getCurrentVersion() {
+		return "2.0";
+	}
+
+	@Override
+	public int getNewBuild() {
+		return newBuild;
+	}
+
+	@Override
+	public String getNewVersion() {
+		return newVersion;
+	}
+
+	@Override
+	public void loadInformation(UpdateChannel channel) throws IOException {
+		App app = ApplicationUtils.getMainApplication();
+		URL url = new URL(app.getInfo().getUpdateURL() + "/" + channel + "/plugins.yml");
+		FileConfiguration config = YamlConfiguration.loadConfiguration(url.openStream());
+
+		newBuild = config.getInt("plugins.awake.build");
+		newVersion = config.getString("plugins.awake.version");
+		remotePath = new URL(config.getString("plugins.awake.url"));
+		localFileName = config.getString("plugins.awake.filename");
+		name = config.getString("plugins.awake.name");
+
+	}
+
+	@Override
+	public boolean isUpdateAvailable() {
+		return getCurrentBuild() < getNewBuild();
+	}
+
+	@Override
+	public URL getDownloadPath() {
+		return remotePath;
+	}
+
+	@Override
+	public Path getLocalPath() {
+		return ApplicationUtils.getApplication().getPath(PathType.LIBRARY, localFileName);
+	}
+
+	@Override
+	public String name() {
+		return name;
+	}
+
+}
diff --git a/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/assets/equalizerView.fxml b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/assets/equalizerView.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..83248d0f5488bc042f557652e10a793bd4e8c7d2
--- /dev/null
+++ b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/assets/equalizerView.fxml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.*?>
+<?import java.lang.*?>
+<?import javafx.scene.layout.*?>
+
+<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
+   <children>
+      <HBox fx:id="equalizerView" prefHeight="353.0" prefWidth="600.0" AnchorPane.bottomAnchor="47.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
+      <CheckBox fx:id="enableCheckBox" layoutX="14.0" layoutY="368.0" mnemonicParsing="false" onAction="#enableCheckBoxHandler" text="%eq.checkbox.enabled" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0" />
+      <HBox layoutX="420.0" layoutY="364.0" spacing="14.0" AnchorPane.bottomAnchor="14.0" AnchorPane.rightAnchor="14.0">
+         <children>
+            <Button fx:id="resetButton" layoutX="471.0" layoutY="364.0" mnemonicParsing="false" onAction="#resetButtonHandler" text="%eq.button.reset" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="76.0" />
+            <Button fx:id="finishButton" layoutX="534.0" layoutY="364.0" mnemonicParsing="false" onAction="#finishButtonHandler" text="%eq.button.finish" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="14.0" />
+         </children>
+      </HBox>
+   </children>
+</AnchorPane>
diff --git a/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/assets/equalizer_de.properties b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/assets/equalizer_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..9afc1e473d5f70819edcc109629b30e69c6b8c01
--- /dev/null
+++ b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/assets/equalizer_de.properties
@@ -0,0 +1,7 @@
+eq.checkbox.enabled=Equalizer aktiviert
+eq.button.reset=Zur�cksetzen
+eq.button.finish=Fertig
+eq.slider=Hz
+
+eq.menuitem.name=Equalizer
+eq.title=Equalizer
\ No newline at end of file
diff --git a/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/assets/style.css b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/assets/style.css
new file mode 100644
index 0000000000000000000000000000000000000000..d43b5b9d68fc3388f6880749de09ccfd6fb3f259
--- /dev/null
+++ b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/assets/style.css
@@ -0,0 +1,7 @@
+.equalizer-box {
+	-fx-padding: 5px;
+}
+
+.equalizer-bandbox {
+	-fx-spacing: 10px;
+}
\ No newline at end of file
diff --git a/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/Equalizer.java b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/Equalizer.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ab02029ceeb4c474a995a5e352562697f2f5437
--- /dev/null
+++ b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/Equalizer.java
@@ -0,0 +1,120 @@
+package de.tobias.playpad.equalizerplugin.main;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Set;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+import org.dom4j.io.OutputFormat;
+import org.dom4j.io.SAXReader;
+import org.dom4j.io.XMLWriter;
+
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.DoubleProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleDoubleProperty;
+
+public class Equalizer {
+
+	private static Equalizer instance;
+
+	static {
+		instance = new Equalizer();
+	}
+
+	public static Equalizer getInstance() {
+		return instance;
+	}
+
+	private HashMap<Integer, DoubleProperty> bands;
+	private BooleanProperty enable;
+
+	private Equalizer() {
+		bands = new HashMap<>();
+		bands.put(19, new SimpleDoubleProperty());
+		bands.put(39, new SimpleDoubleProperty());
+		bands.put(78, new SimpleDoubleProperty());
+		bands.put(156, new SimpleDoubleProperty());
+		bands.put(312, new SimpleDoubleProperty());
+		bands.put(625, new SimpleDoubleProperty());
+		bands.put(1250, new SimpleDoubleProperty());
+		bands.put(2500, new SimpleDoubleProperty());
+		bands.put(5000, new SimpleDoubleProperty());
+		bands.put(10000, new SimpleDoubleProperty());
+
+		enable = new SimpleBooleanProperty(false);
+	}
+
+	public Set<Integer> getBands() {
+		return bands.keySet();
+	}
+
+	public Double getGain(int band) {
+		return bands.get(band).get();
+	}
+
+	public void setGain(int band, double value) {
+		this.bands.get(band).set(value);
+	}
+
+	public DoubleProperty gainProperty(int band) {
+		return bands.get(band);
+	}
+
+	public boolean isEnable() {
+		return enable.get();
+	}
+
+	public void setEnable(boolean enable) {
+		this.enable.set(enable);
+	}
+
+	public BooleanProperty enableProperty() {
+		return enable;
+	}
+
+	private static final String ENABLE_ELEMENT = "enable";
+	private static final String WIDTH_ATTR = "width";
+	private static final String BAND_ELEMENT = "band";
+	private static final String EQUALIZER_ELEMENT = "equalizer";
+
+	public static void save(Path path) throws IOException {
+		Document document = DocumentHelper.createDocument();
+		Element root = document.addElement(EQUALIZER_ELEMENT);
+		for (int band : instance.bands.keySet()) {
+			root.addElement(BAND_ELEMENT).addAttribute(WIDTH_ATTR, String.valueOf(band)).addText(String.valueOf(instance.bands.get(band).get()));
+		}
+		root.addElement(ENABLE_ELEMENT).addText(String.valueOf(instance.enable.get()));
+
+		if (Files.notExists(path)) {
+			Files.createDirectories(path.getParent());
+			Files.createFile(path);
+		}
+
+		XMLWriter writer = new XMLWriter(Files.newOutputStream(path), OutputFormat.createPrettyPrint());
+		writer.write(document);
+		writer.close();
+	}
+
+	public static void load(Path path) throws DocumentException, IOException {
+		if (Files.exists(path)) {
+			SAXReader reader = new SAXReader();
+			Document document = reader.read(Files.newInputStream(path));
+
+			Element root = document.getRootElement();
+			for (Object bandObj : root.elements(BAND_ELEMENT)) {
+				Element element = (Element) bandObj;
+				int bandwidth = Integer.valueOf(element.attribute(WIDTH_ATTR).getValue());
+				double gain = Double.valueOf(element.getStringValue());
+				instance.setGain(bandwidth, gain);
+			}
+			if (root.element(ENABLE_ELEMENT) != null)
+				instance.setEnable(Boolean.valueOf(root.element(ENABLE_ELEMENT).getStringValue()));
+		}
+	}
+}
diff --git a/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/EqualizerPlugin.java b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/EqualizerPlugin.java
new file mode 100644
index 0000000000000000000000000000000000000000..93b16f1acdd36bc81219fabae3c646090bf5b386
--- /dev/null
+++ b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/EqualizerPlugin.java
@@ -0,0 +1,8 @@
+package de.tobias.playpad.equalizerplugin.main;
+
+import net.xeoh.plugins.base.Plugin;
+
+
+public interface EqualizerPlugin extends Plugin {
+
+}
diff --git a/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/impl/EqualizerPluginImpl.java b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/impl/EqualizerPluginImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..54282b74205cbd36efc93cc0d8b20964c81a7f1c
--- /dev/null
+++ b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/impl/EqualizerPluginImpl.java
@@ -0,0 +1,122 @@
+package de.tobias.playpad.equalizerplugin.main.impl;
+
+import java.io.IOException;
+import java.util.ResourceBundle;
+
+import org.dom4j.DocumentException;
+
+import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.audio.Equalizable;
+import de.tobias.playpad.equalizerplugin.main.Equalizer;
+import de.tobias.playpad.equalizerplugin.main.EqualizerPlugin;
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.conntent.PadContent;
+import de.tobias.playpad.plugin.PadListener;
+import de.tobias.playpad.plugin.WindowListener;
+import de.tobias.playpad.update.UpdateRegistery;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.container.PathType;
+import de.tobias.utils.util.Localization;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.fxml.FXML;
+import javafx.scene.control.MenuItem;
+import javafx.scene.media.AudioEqualizer;
+import javafx.scene.media.EqualizerBand;
+import javafx.stage.Stage;
+import net.xeoh.plugins.base.annotations.PluginImplementation;
+import net.xeoh.plugins.base.annotations.events.PluginLoaded;
+import net.xeoh.plugins.base.annotations.events.Shutdown;
+
+@PluginImplementation
+public class EqualizerPluginImpl implements EqualizerPlugin, WindowListener<IMainViewController>, EventHandler<ActionEvent>, PadListener {
+
+	private Stage mainStage;
+	private EqualizerViewController equalizerViewController;
+	private static ResourceBundle bundle;
+
+	private MenuItem eqMenuItem;
+
+	public static ResourceBundle getBundle() {
+		return bundle;
+	}
+
+	@PluginLoaded
+	public void onEnable(EqualizerPlugin plugin) {
+		bundle = Localization.loadBundle("de/tobias/playpad/equalizerplugin/assets/equalizer", EqualizerPluginImpl.class.getClassLoader());
+		try {
+			Equalizer.load(ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, "equalizer.xml"));
+		} catch (DocumentException | IOException e) {
+			e.printStackTrace();
+		}
+
+		UpdateRegistery.registerUpdateable(new EqualizerPluginUpdater());
+
+		PlayPadPlugin.getImplementation().addMainViewListener(this);
+		PlayPadPlugin.getImplementation().addPadListener(this);
+
+		System.out.println("Enable Equalizer Plugin");
+	}
+
+	@Shutdown
+	public void onDisable() {
+		System.out.println("Disable Equalizer Plugin");
+	}
+
+	@Override
+	public void onInit(IMainViewController t) {
+		mainStage = t.getStage();
+
+		eqMenuItem = new MenuItem();
+		eqMenuItem.setText(bundle.getString("eq.menuitem.name"));
+		eqMenuItem.setOnAction(this);
+		t.addMenuItem(eqMenuItem);
+	}
+
+	@Override
+	public void onPlay(Pad pad) {
+		PadContent content = pad.getContent();
+		if (content != null && content instanceof Equalizable) {
+
+			// Equalizer
+			Equalizable equalizable = (Equalizable) content;
+			AudioEqualizer audioEqualizer = equalizable.getAudioEqualizer();
+			if (audioEqualizer != null) {
+				for (EqualizerBand band : audioEqualizer.getBands()) {
+					band.gainProperty().bind(Equalizer.getInstance().gainProperty((int) band.getBandwidth()));
+				}
+				audioEqualizer.enabledProperty().bind(Equalizer.getInstance().enableProperty());
+			}
+		}
+	}
+
+	@Override
+	public void onStop(Pad pad) {
+		PadContent content = pad.getContent();
+		if (content != null && content instanceof Equalizable) {
+
+			// Equalizer
+			Equalizable equalizable = (Equalizable) content;
+			AudioEqualizer audioEqualizer = equalizable.getAudioEqualizer();
+			if (audioEqualizer != null) {
+				for (EqualizerBand band : audioEqualizer.getBands()) {
+					band.gainProperty().bind(Equalizer.getInstance().gainProperty((int) band.getBandwidth()));
+				}
+				audioEqualizer.enabledProperty().bind(Equalizer.getInstance().enableProperty());
+			}
+		}
+	}
+
+	@FXML
+	public void handle(ActionEvent event) {
+		if (equalizerViewController == null) {
+			equalizerViewController = new EqualizerViewController(mainStage);
+			equalizerViewController.getStage().show();
+		} else if (equalizerViewController.getStage().isShowing()) {
+			equalizerViewController.getStage().toFront();
+		} else {
+			equalizerViewController.getStage().show();
+		}
+	}
+}
\ No newline at end of file
diff --git a/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/impl/EqualizerPluginUpdater.java b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/impl/EqualizerPluginUpdater.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8de63641b5a027f7e71c1689712636f356a3d20
--- /dev/null
+++ b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/impl/EqualizerPluginUpdater.java
@@ -0,0 +1,78 @@
+package de.tobias.playpad.equalizerplugin.main.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Path;
+
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import de.tobias.playpad.update.Updatable;
+import de.tobias.playpad.update.UpdateChannel;
+import de.tobias.utils.application.App;
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.container.PathType;
+
+public class EqualizerPluginUpdater implements Updatable {
+
+	private int newBuild;
+	private String newVersion;
+	private URL remotePath;
+
+	private String localFileName;
+	private String name;
+
+	@Override
+	public int getCurrentBuild() {
+		return 4;
+	}
+
+	@Override
+	public String getCurrentVersion() {
+		return "4.0";
+	}
+
+	@Override
+	public int getNewBuild() {
+		return newBuild;
+	}
+
+	@Override
+	public String getNewVersion() {
+		return newVersion;
+	}
+
+	@Override
+	public void loadInformation(UpdateChannel channel) throws IOException {
+		App app = ApplicationUtils.getMainApplication();
+		URL url = new URL(app.getInfo().getUpdateURL() + "/" + channel + "/plugins.yml");
+		FileConfiguration config = YamlConfiguration.loadConfiguration(url.openStream());
+
+		newBuild = config.getInt("plugins.equalizer.build");
+		newVersion = config.getString("plugins.equalizer.version");
+		remotePath = new URL(config.getString("plugins.equalizer.url"));
+		localFileName = config.getString("plugins.equalizer.filename");
+		name = config.getString("plugins.equalizer.name");
+	}
+
+	@Override
+	public boolean isUpdateAvailable() {
+		return getCurrentBuild() < getNewBuild();
+	}
+
+	@Override
+	public URL getDownloadPath() {
+		return remotePath;
+	}
+
+	@Override
+	public Path getLocalPath() {
+		return ApplicationUtils.getApplication().getPath(PathType.LIBRARY, localFileName);
+	}
+
+	@Override
+	public String name() {
+		return name;
+	}
+
+}
diff --git a/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/impl/EqualizerViewController.java b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/impl/EqualizerViewController.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7e2f72353621c2f6836e6fe4b4629c55506558c
--- /dev/null
+++ b/PlayWallPlugins/equalizerplugin/de/tobias/playpad/equalizerplugin/main/impl/EqualizerViewController.java
@@ -0,0 +1,125 @@
+package de.tobias.playpad.equalizerplugin.main.impl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.equalizerplugin.main.Equalizer;
+import de.tobias.playpad.settings.Profile;
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.container.PathType;
+import de.tobias.utils.ui.ViewController;
+import de.tobias.utils.util.Localization;
+import de.tobias.utils.util.NumberUtils;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.geometry.Orientation;
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.control.CheckBox;
+import javafx.scene.control.Label;
+import javafx.scene.control.Slider;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+import javafx.scene.media.EqualizerBand;
+import javafx.stage.Stage;
+import javafx.stage.Window;
+
+public class EqualizerViewController extends ViewController {
+
+	@FXML private HBox equalizerView;
+	@FXML private Button resetButton;
+	@FXML private Button finishButton;
+	@FXML private CheckBox enableCheckBox;
+
+	public EqualizerViewController(Window owner) {
+		super("equalizerView", "de/tobias/playpad/equalizerplugin/assets/", null, EqualizerPluginImpl.getBundle());
+
+		getStage().initOwner(owner);
+
+		Equalizer eq = Equalizer.getInstance();
+
+		List<Integer> bands = new ArrayList<>(eq.getBands());
+		Collections.sort(bands);
+
+		for (int band : bands) {
+			VBox bandBox = new VBox();
+
+			Slider slider = new Slider(EqualizerBand.MIN_GAIN, EqualizerBand.MAX_GAIN, eq.getGain(band));
+			slider.setOrientation(Orientation.VERTICAL);
+			slider.setMajorTickUnit(6);
+			slider.setShowTickLabels(true);
+			slider.setShowTickMarks(true);
+			slider.setMaxHeight(Double.MAX_VALUE);
+			slider.getStyleClass().add("equalizer-slider");
+			slider.setUserData(band);
+
+			Label infoLabel = new Label(NumberUtils.numberToString(band, 0) + EqualizerPluginImpl.getBundle().getString("eq.slider"));
+			infoLabel.getStyleClass().add("equalizer-label");
+
+			bandBox.getChildren().addAll(slider, infoLabel);
+			bandBox.prefWidthProperty().bind(equalizerView.widthProperty().divide(bands.size()));
+			VBox.setVgrow(slider, Priority.ALWAYS);
+			bandBox.setAlignment(Pos.CENTER);
+			bandBox.getStyleClass().add("equalizer-bandbox");
+
+			equalizerView.getChildren().add(bandBox);
+			equalizerView.getStyleClass().add("equalizer-box");
+
+			// Data Binding
+			eq.gainProperty(band).bindBidirectional(slider.valueProperty());
+		}
+
+		// Setup
+		enableCheckBox.setSelected(eq.isEnable());
+		equalizerView.setDisable(!enableCheckBox.isSelected());
+	}
+
+	@Override
+	public void init() {
+		enableCheckBox.selectedProperty().addListener((a, b, c) ->
+		{
+			equalizerView.setDisable(!c);
+		});
+
+		addCloseKeyShortcut(() -> getStage().close());
+	}
+
+	@Override
+	public void initStage(Stage stage) {
+		PlayPadPlugin.getImplementation().getIcon().ifPresent(stage.getIcons()::add);
+
+		stage.setTitle(EqualizerPluginImpl.getBundle().getString("eq.title"));
+		stage.setMinWidth(500);
+		stage.setMinHeight(250);
+
+		Profile.currentProfile().currentLayout().applyCss(getStage());
+	}
+
+	@FXML
+	private void enableCheckBoxHandler(ActionEvent event) {
+		Equalizer.getInstance().setEnable(enableCheckBox.isSelected());
+	}
+
+	@FXML
+	private void resetButtonHandler(ActionEvent event) {
+		for (int band : Equalizer.getInstance().getBands()) {
+			Equalizer.getInstance().setGain(band, 0);
+		}
+	}
+
+	@FXML
+	private void finishButtonHandler(ActionEvent event) {
+		try {
+			Equalizer.save(ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, "equalizer.xml"));
+		} catch (IOException e) {
+			showErrorMessage(Localization.getString("error.file.save", e.getLocalizedMessage()),
+					PlayPadPlugin.getImplementation().getIcon().orElse(null));
+			e.printStackTrace();
+		}
+		getStage().close();
+	}
+}
diff --git a/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/LaunchpadPlugin.java b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/LaunchpadPlugin.java
new file mode 100644
index 0000000000000000000000000000000000000000..1508fc74c06a2e3892c4bb90150670da800e2713
--- /dev/null
+++ b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/LaunchpadPlugin.java
@@ -0,0 +1,7 @@
+package de.tobias.playpad.launchpadplugin;
+
+import net.xeoh.plugins.base.Plugin;
+
+public interface LaunchpadPlugin extends Plugin {
+
+}
diff --git a/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/assets/launchpad_de.properties b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/assets/launchpad_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/assets/launchpad_mk2.map b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/assets/launchpad_mk2.map
new file mode 100644
index 0000000000000000000000000000000000000000..f29e22ce294b0084e431542a728cd78ead39fb6c
--- /dev/null
+++ b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/assets/launchpad_mk2.map
@@ -0,0 +1,39 @@
+0xef9a9aff=C107
+0xef5350ff=C4
+0xe53935ff=C72
+
+0xd92349ff=C5
+0xc92349ff=C72
+0xa90329ff=C72
+
+0xf48fb1ff=C59
+0xec407aff=C58
+0xd81b60ff=C57
+
+0xce93d8ff=C52
+0xab47bcff=C82
+0x8e24aaff=C53
+
+0x80deeaff=C36
+0x26c6daff=C37
+0x00acc1ff=C78
+
+0x90caf9ff=C41
+0x42a5f5ff=C79
+0x1e88e5ff=C67
+
+0xc5e1a5ff=C88
+0x9ccc65ff=C25
+0x7cb342ff=C21
+
+0xfff59dff=C12
+0xffee58ff=C14
+0xfdd835ff=C13
+
+0xffcc80ff=C11
+0xffa726ff=C61
+0xfb8c00ff=C84
+
+0xeeeeeeff=C119
+0xccccccff=C119
+0x555555ff=C2
\ No newline at end of file
diff --git a/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/impl/LaunchPadPluginUpdater.java b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/impl/LaunchPadPluginUpdater.java
new file mode 100644
index 0000000000000000000000000000000000000000..51690d36ff5bec4a4099dff0c8ee8c16721ed4c3
--- /dev/null
+++ b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/impl/LaunchPadPluginUpdater.java
@@ -0,0 +1,79 @@
+package de.tobias.playpad.launchpadplugin.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Path;
+
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import de.tobias.playpad.update.Updatable;
+import de.tobias.playpad.update.UpdateChannel;
+import de.tobias.utils.application.App;
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.container.PathType;
+
+public class LaunchPadPluginUpdater implements Updatable {
+
+	private int newBuild;
+	private String newVersion;
+	private URL remotePath;
+
+	private String localFileName;
+	private String name;
+
+	@Override
+	public int getCurrentBuild() {
+		return 3;
+	}
+
+	@Override
+	public String getCurrentVersion() {
+		return "3.0";
+	}
+
+	@Override
+	public int getNewBuild() {
+		return newBuild;
+	}
+
+	@Override
+	public String getNewVersion() {
+		return newVersion;
+	}
+
+	@Override
+	public void loadInformation(UpdateChannel channel) throws IOException {
+		App app = ApplicationUtils.getMainApplication();
+		URL url = new URL(app.getInfo().getUpdateURL() + "/" + channel + "/plugins.yml");
+		FileConfiguration config = YamlConfiguration.loadConfiguration(url.openStream());
+
+		newBuild = config.getInt("plugins.launchpad.build");
+		newVersion = config.getString("plugins.launchpad.version");
+		remotePath = new URL(config.getString("plugins.launchpad.url"));
+		localFileName = config.getString("plugins.launchpad.filename");
+		name = config.getString("plugins.launchpad.name");
+
+	}
+
+	@Override
+	public boolean isUpdateAvailable() {
+		return getCurrentBuild() < getNewBuild();
+	}
+
+	@Override
+	public URL getDownloadPath() {
+		return remotePath;
+	}
+
+	@Override
+	public Path getLocalPath() {
+		return ApplicationUtils.getApplication().getPath(PathType.LIBRARY, localFileName);
+	}
+
+	@Override
+	public String name() {
+		return name;
+	}
+
+}
diff --git a/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..fabff9d69c470b5bb7a76feffae9889d44c91606
--- /dev/null
+++ b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java
@@ -0,0 +1,42 @@
+package de.tobias.playpad.launchpadplugin.impl;
+
+import java.util.ResourceBundle;
+
+import de.tobias.playpad.launchpadplugin.LaunchpadPlugin;
+import de.tobias.playpad.launchpadplugin.midi.device.mk2.LaunchPadMK2;
+import de.tobias.playpad.launchpadplugin.midi.device.s.LaunchPadS;
+import de.tobias.playpad.midi.device.DeviceRegistry;
+import de.tobias.playpad.update.UpdateRegistery;
+import de.tobias.utils.util.Localization;
+import net.xeoh.plugins.base.annotations.PluginImplementation;
+import net.xeoh.plugins.base.annotations.events.PluginLoaded;
+import net.xeoh.plugins.base.annotations.events.Shutdown;
+
+@PluginImplementation
+public class LaunchpadPluginImpl implements LaunchpadPlugin {
+
+	private static ResourceBundle bundle;
+
+	@PluginLoaded
+	public void onLoaded(LaunchpadPlugin plugin) {
+		bundle = Localization.loadBundle("de/tobias/playpad/launchpadplugin/assets/launchpad", LaunchpadPluginImpl.class.getClassLoader());
+
+		UpdateRegistery.registerUpdateable(new LaunchPadPluginUpdater());
+
+		DeviceRegistry deviceFactory = DeviceRegistry.getFactoryInstance();
+
+		deviceFactory.registerDevice(LaunchPadMK2.NAME, LaunchPadMK2.class);
+		deviceFactory.registerDevice(LaunchPadS.NAME, LaunchPadS.class);
+		System.out.println("Enable LaunchPad Plugin");
+	}
+
+	@Shutdown
+	public void onShutdown() {
+		System.out.println("Disable LaunchPad Plugin");
+	}
+
+	public static ResourceBundle getBundle() {
+		return bundle;
+	}
+
+}
diff --git a/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/impl/MapParser.java b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/impl/MapParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..021469d2baa1920bd6f90ab0ba5086c947ce4145
--- /dev/null
+++ b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/impl/MapParser.java
@@ -0,0 +1,25 @@
+package de.tobias.playpad.launchpadplugin.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import de.tobias.utils.util.FileUtils;
+
+public class MapParser {
+
+	public static Map<String, String> load(URL resource) throws IOException {
+		Map<String, String> items = new HashMap<>();
+		for (String line : FileUtils.readURL(resource).split("\n")) {
+			String[] split = line.split("=");
+			if (split.length == 2) {
+				String color = split[0];
+				String val = split[1];
+				items.put(color, val);
+			}
+		}
+		;
+		return items;
+	}
+}
diff --git a/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/midi/device/mk2/LaunchPadMK2.java b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/midi/device/mk2/LaunchPadMK2.java
new file mode 100644
index 0000000000000000000000000000000000000000..01a33d47e0a9d1dde2fe6c4e5f2e69faebf200d5
--- /dev/null
+++ b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/midi/device/mk2/LaunchPadMK2.java
@@ -0,0 +1,128 @@
+package de.tobias.playpad.launchpadplugin.midi.device.mk2;
+
+import java.net.URL;
+import java.util.Map;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.ShortMessage;
+
+import de.tobias.playpad.action.feedback.DisplayableFeedbackColor;
+import de.tobias.playpad.action.feedback.Feedback;
+import de.tobias.playpad.action.feedback.FeedbackMessage;
+import de.tobias.playpad.action.mididevice.Device;
+import de.tobias.playpad.action.mididevice.DeviceColorAssociatorConnector;
+import de.tobias.playpad.launchpadplugin.impl.MapParser;
+import de.tobias.playpad.midi.Midi;
+import javafx.scene.paint.Color;
+
+public class LaunchPadMK2 extends Device implements DeviceColorAssociatorConnector {
+
+	public static final String NAME = "Launchpad MK2";
+	private static Map<String, String> mapProperties;
+
+	public LaunchPadMK2() {
+		try {
+			URL resource = getClass().getClassLoader().getResource("de/tobias/playpad/launchpadplugin/assets/launchpad_mk2.map");
+			mapProperties = MapParser.load(resource);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public String getName() {
+		return NAME;
+	}
+
+	@Override
+	public boolean supportFeedback() {
+		return true;
+	}
+
+	@Override
+	public void initFeedback() {}
+
+	@Override
+	public void handleFeedback(FeedbackMessage type, int key, Feedback feedback) {
+		if (type != FeedbackMessage.WARNING) {
+			try {
+				int value = feedback.getValueForFeedbackMessage(type);
+				if (key >= 104 && key <= 111) {
+					Midi.getInstance().sendMessage(176, key, value);
+				} else {
+					Midi.getInstance().sendMessage(144, key, value);
+				}
+			} catch (MidiUnavailableException | InvalidMidiDataException e) {
+				e.printStackTrace();
+			}
+		} else {
+			try {
+				Midi.getInstance().sendMessage(145, key, feedback.getValueForFeedbackMessage(FeedbackMessage.STANDARD));
+			} catch (MidiUnavailableException | InvalidMidiDataException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	@Override
+	public void clearFeedback() {
+		final int maxMainKeyNumber = 89;
+
+		for (int i = 11; i <= maxMainKeyNumber; i++) {
+			// Node_On = 144
+			try {
+				Midi.getInstance().sendMessage(ShortMessage.NOTE_ON, i, 0);
+			} catch (MidiUnavailableException | InvalidMidiDataException e) {
+				e.printStackTrace();
+			}
+		}
+
+		// Obere Reihe an Tasten
+		final int liveKeyMin = 104;
+		final int liveKeyMax = 111;
+
+		for (int i = liveKeyMin; i <= liveKeyMax; i++) {
+			// Control_Change = 176
+			try {
+				Midi.getInstance().sendMessage(ShortMessage.CONTROL_CHANGE, i, 0);
+			} catch (MidiUnavailableException | InvalidMidiDataException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	@Override
+	public DisplayableFeedbackColor getColor(int id) {
+		return LaunchPadMK2Color.valueOf(id);
+	}
+
+	@Override
+	public DisplayableFeedbackColor[] getColors() {
+		return LaunchPadMK2Color.values();
+	}
+
+	@Override
+	public DisplayableFeedbackColor getDefaultEventColor() {
+		return LaunchPadMK2Color.C5;
+	}
+
+	@Override
+	public DisplayableFeedbackColor getDefaultStandardColor() {
+		return LaunchPadMK2Color.C36;
+	}
+
+	@Override
+	public DisplayableFeedbackColor map(Color color) {
+		try {
+			URL resource = getClass().getClassLoader().getResource("de/tobias/playpad/launchpadplugin/assets/launchpad_mk2.map");
+			mapProperties = MapParser.load(resource);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		if (mapProperties.containsKey(color.toString())) {
+			return LaunchPadMK2Color.valueOf(mapProperties.get(color.toString()));
+		}
+		return null;
+	}
+}
diff --git a/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/midi/device/mk2/LaunchPadMK2Color.java b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/midi/device/mk2/LaunchPadMK2Color.java
new file mode 100644
index 0000000000000000000000000000000000000000..931b455a19bd03cfa642bad8e1e8acd5b51520aa
--- /dev/null
+++ b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/midi/device/mk2/LaunchPadMK2Color.java
@@ -0,0 +1,84 @@
+package de.tobias.playpad.launchpadplugin.midi.device.mk2;
+
+import de.tobias.playpad.action.feedback.DisplayableFeedbackColor;
+import javafx.scene.paint.Color;
+
+public enum LaunchPadMK2Color implements DisplayableFeedbackColor {
+
+	C0(0, Color.rgb(0, 0, 0)), // BLACK
+	C2(2, Color.rgb(125, 125, 125)), // GRAY
+	C3(3, Color.rgb(255, 255, 255)), // WHITE
+	C4(4, Color.rgb(255, 74, 76)), // RED
+	C5(5, Color.rgb(255, 0, 24)), // RED
+	C6(6, Color.rgb(93, 1, 3)), // DARK_RED
+	C8(8, Color.rgb(254, 188, 112)), // LIGHT_ORGANGE
+	C9(9, Color.rgb(255, 83, 35)), // ORANGE
+	C10(10, Color.rgb(92, 28, 6)), // BRAUN
+	C11(11, Color.rgb(255, 189, 112)), // ORNAGE ! DARK
+	C12(12, Color.rgb(253, 252, 91)), // YELLOW
+	C13(13, Color.rgb(253, 252, 85)), // YELLOW
+	C14(14, Color.rgb(88, 88, 24)), // YELLOW
+	C16(16, Color.rgb(117, 253, 92)), // LIGHT_GREEN
+	C17(17, Color.rgb(117, 253, 92)), // LIGHT_GREEN
+	C21(21, Color.rgb(0, 253, 81)), // LIGHT_GREEN
+	C25(25, Color.rgb(0, 253, 81)), // LIGHT_GREEN
+	C28(28, Color.rgb(0, 253, 143)), // LIGHT GRREN
+	C32(32, Color.rgb(0, 252, 184)), // TURQUOISE
+	C36(36, Color.rgb(36, 194, 250)), // LIGHT_BLUE
+	C37(37, Color.rgb(0, 169, 249)), // LIGHT_BLUE
+	C40(40, Color.rgb(60, 137, 248)), // BLUE
+	C41(41, Color.rgb(0, 87, 246)), // BLUE
+	C45(45, Color.rgb(7, 32, 245)), // BLUE
+	C52(52, Color.rgb(255, 78, 247)), // PURPLE
+	C53(53, Color.rgb(255, 23, 246)), // PINK
+	C56(56, Color.rgb(255, 76, 131)), // PINK
+	C57(57, Color.rgb(255, 0, 83)), // PINK
+	C58(58, Color.rgb(93, 1, 27)), // PINK
+	C59(59, Color.rgb(34, 0, 16)), // PINK
+	C60(60, Color.rgb(255, 12, 25)), // RED
+	C61(61, Color.rgb(159, 52, 18)), // ORANGE !
+	C67(67, Color.rgb(7, 32, 245)), // BLUE !
+	C72(72, Color.rgb(255, 0, 24)), // RED
+	C76(76, Color.rgb(0, 136, 40)), // GREEN
+	C78(78, Color.rgb(0, 169, 249)), // LIGHT_BLUE
+	C79(79, Color.rgb(5, 44, 245)), // BLUE
+	C90(90, Color.rgb(0, 252, 207)), // TURKY
+	C81(81, Color.rgb(123, 31, 245)), // PURPULE
+	C82(82, Color.rgb(185, 24, 123)), // PURPULE
+	C84(84, Color.rgb(255, 71, 32)), // ORANGE !
+	C88(88, Color.rgb(0, 253, 81)), // GREEN !
+	C92(92, Color.rgb(37, 81, 194)), // BLUE
+	C96(96, Color.rgb(255, 189, 112)), // ORANGE
+	C106(106, Color.rgb(176, 0, 12)), // RED
+	C107(107, Color.rgb(230, 79, 61)), // RED
+	C116(116, Color.rgb(142, 102, 247)), // PURPLE
+	C119(119, Color.rgb(221, 252, 252)), // WHITE
+	C120(120, Color.rgb(168, 2, 12)); // RED
+
+	private int midi;
+	private Color color;
+
+	private LaunchPadMK2Color(int midi, Color color) {
+		this.midi = midi;
+		this.color = color;
+	}
+
+	@Override
+	public int midiVelocity() {
+		return midi;
+	}
+
+	@Override
+	public Color getPaint() {
+		return color;
+	}
+
+	public static DisplayableFeedbackColor valueOf(int id) {
+		for (LaunchPadMK2Color color : values()) {
+			if (color.midiVelocity() == id) {
+				return color;
+			}
+		}
+		return null;
+	}
+}
diff --git a/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/midi/device/s/LaunchPadS.java b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/midi/device/s/LaunchPadS.java
new file mode 100644
index 0000000000000000000000000000000000000000..64b9651e27d0de4f83858259eec37c8a2ed7a902
--- /dev/null
+++ b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/midi/device/s/LaunchPadS.java
@@ -0,0 +1,94 @@
+package de.tobias.playpad.launchpadplugin.midi.device.s;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MidiUnavailableException;
+
+import de.tobias.playpad.action.feedback.DisplayableFeedbackColor;
+import de.tobias.playpad.action.feedback.Feedback;
+import de.tobias.playpad.action.feedback.FeedbackMessage;
+import de.tobias.playpad.action.mididevice.Device;
+import de.tobias.playpad.action.mididevice.DeviceColorAssociatorConnector;
+import de.tobias.playpad.midi.Midi;
+import javafx.scene.paint.Color;
+
+public class LaunchPadS extends Device implements DeviceColorAssociatorConnector {
+
+	public static final String NAME = "Launchpad S";
+
+	@Override
+	public String getName() {
+		return NAME;
+	}
+
+	@Override
+	public boolean supportFeedback() {
+		return true;
+	}
+
+	@Override
+	public void initFeedback() {
+		// Flash Enable
+		try {
+			Midi.getInstance().sendMessage(176, 0, 40);
+		} catch (MidiUnavailableException | InvalidMidiDataException e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public void handleFeedback(FeedbackMessage type, int key, Feedback feedback) {
+		initFeedback();
+
+		int command = 144;
+
+		if (key >= 104 && key <= 111) {
+			command = 176;
+		}
+
+		try {
+			if (type != FeedbackMessage.WARNING) {
+				int value = feedback.getValueForFeedbackMessage(type);
+				Midi.getInstance().sendMessage(command, key, value);
+			} else {
+				int midiVelocity = feedback.getValueForFeedbackMessage(FeedbackMessage.EVENT) - 4;
+				Midi.getInstance().sendMessage(command, key, midiVelocity);
+			}
+		} catch (MidiUnavailableException | InvalidMidiDataException e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public void clearFeedback() {
+		try {
+			Midi.getInstance().sendMessage(176, 0, 0);
+		} catch (MidiUnavailableException | InvalidMidiDataException e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public DisplayableFeedbackColor getColor(int id) {
+		return LaunchPadSColor.valueOf(id);
+	}
+
+	@Override
+	public DisplayableFeedbackColor[] getColors() {
+		return LaunchPadSColor.values();
+	}
+
+	@Override
+	public DisplayableFeedbackColor getDefaultEventColor() {
+		return LaunchPadSColor.RED;
+	}
+
+	@Override
+	public DisplayableFeedbackColor getDefaultStandardColor() {
+		return LaunchPadSColor.GREEN;
+	}
+
+	@Override
+	public DisplayableFeedbackColor map(Color color) {
+		return null;
+	}
+}
diff --git a/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/midi/device/s/LaunchPadSColor.java b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/midi/device/s/LaunchPadSColor.java
new file mode 100644
index 0000000000000000000000000000000000000000..1094ba3119cd89eff93603069c9e8af7a9ef2b24
--- /dev/null
+++ b/PlayWallPlugins/launchpadplugin/de/tobias/playpad/launchpadplugin/midi/device/s/LaunchPadSColor.java
@@ -0,0 +1,40 @@
+package de.tobias.playpad.launchpadplugin.midi.device.s;
+
+import de.tobias.playpad.action.feedback.DisplayableFeedbackColor;
+import javafx.scene.paint.Color;
+
+public enum LaunchPadSColor implements DisplayableFeedbackColor {
+
+	YELLOW(62, Color.YELLOW),
+	AMBER(63, Color.WHEAT),
+	GREEN(60, Color.GREEN),
+	RED(15, Color.RED),
+	BLACK(0, Color.BLACK);
+
+	private int midi;
+	private Color color;
+
+	private LaunchPadSColor(int midi, Color color) {
+		this.midi = midi;
+		this.color = color;
+	}
+
+	@Override
+	public int midiVelocity() {
+		return midi;
+	}
+
+	@Override
+	public Color getPaint() {
+		return color;
+	}
+
+	public static DisplayableFeedbackColor valueOf(int id) {
+		for (LaunchPadSColor color : values()) {
+			if (color.midiVelocity() == id) {
+				return color;
+			}
+		}
+		return null;
+	}
+}
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/assets/settingsPadPane.fxml b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/assets/settingsPadPane.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..64628f11d369910dcfa1bdfc5984bcc69a69e39e
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/assets/settingsPadPane.fxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.*?>
+<?import java.lang.*?>
+<?import javafx.scene.layout.*?>
+
+<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
+   <children>
+      <HBox spacing="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="14.0">
+         <children>
+            <Label alignment="BASELINE_RIGHT" maxHeight="1.7976931348623157E308" prefWidth="150.0" text="%pad.label.lastFrame" />
+            <CheckBox fx:id="lastFrameCheckBox" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" text="%pad.checkbox.lastFrame" />
+         </children>
+      </HBox>
+   </children>
+</AnchorPane>
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/assets/settingsPane.fxml b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/assets/settingsPane.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..797144dc10b1adcf08cdda5fd17fb121003ec508
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/assets/settingsPane.fxml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import javafx.geometry.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+
+<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
+   <children>
+      <VBox prefHeight="200.0" prefWidth="645.0" spacing="14.0" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="14.0">
+         <children>
+            <Label text="%settings.video.label.screens" />
+            <VBox alignment="TOP_CENTER">
+               <children>
+                  <Pane fx:id="screenViewPane" prefWidth="617.0" VBox.vgrow="ALWAYS" />
+               </children>
+            </VBox>
+            <HBox prefHeight="100.0" prefWidth="200.0" spacing="14.0">
+               <children>
+                  <Label text="%settings.video.label.screenChoice">
+                     <HBox.margin>
+                        <Insets top="4.0" />
+                     </HBox.margin>
+                  </Label>
+                  <VBox prefHeight="88.0" prefWidth="325.0" spacing="14.0" HBox.hgrow="ALWAYS">
+                     <children>
+                        <ComboBox fx:id="screenComboBox" prefWidth="150.0" />
+                        <CheckBox fx:id="fullscreenCheckBox" mnemonicParsing="false" text="%settings.video.checkbox.fullscreen" />
+                        <CheckBox fx:id="videoOpenAtLaunchCheckBox" mnemonicParsing="false" text="%settings.video.checkbox.openAtLaunch" />
+                     </children>
+                  </VBox>
+               </children>
+            </HBox>
+         </children>
+      </VBox>
+   </children>
+</AnchorPane>
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/assets/video_de.properties b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/assets/video_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..01d06be333d3f2492e0554d74bef51d7eb44a87f
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/assets/video_de.properties
@@ -0,0 +1,15 @@
+settings.tab=Video/Bild
+
+settings.video.tab=Video
+settings.video.label.screens=Bildschirme:
+settings.video.label.screenChoice=Bildschirm f�r Videowiedergabe:
+settings.video.checkbox.fullscreen=Vollbild
+settings.video.checkbox.openAtLaunch=Fenster beim Start �ffnen
+
+pad.label.lastFrame=Letztes Bild am Ende des Videos einfrieren (Freeze)
+pad.checkbox.lastFrame=Aktivieren
+
+blindaction.name=Schwarzbild Video
+
+Content.Video.Name=Video
+Content.Image.Name=Bild
\ No newline at end of file
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/blindaction/BlindAction.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/blindaction/BlindAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..ce74283ac852c79616bbc92a74d9eaa96f7426c5
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/blindaction/BlindAction.java
@@ -0,0 +1,99 @@
+package de.tobias.playpad.mediaplugin.blindaction;
+
+import org.dom4j.Element;
+
+import de.tobias.playpad.Displayable;
+import de.tobias.playpad.action.Action;
+import de.tobias.playpad.action.InputType;
+import de.tobias.playpad.action.feedback.FeedbackMessage;
+import de.tobias.playpad.action.feedback.FeedbackType;
+import de.tobias.playpad.mediaplugin.main.impl.MediaPluginImpl;
+import de.tobias.playpad.project.Project;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+import de.tobias.utils.ui.icon.FontAwesomeType;
+import de.tobias.utils.ui.icon.FontIcon;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.beans.value.ChangeListener;
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+
+public class BlindAction extends Action implements Displayable {
+
+	private ChangeListener<Boolean> blindFeedbackListener;
+
+	public BlindAction() {
+		blindFeedbackListener = (a, b, c) ->
+		{
+			if (c) {
+				handleFeedback(FeedbackMessage.EVENT);
+			} else {
+				handleFeedback(FeedbackMessage.STANDARD);
+			}
+		};
+	}
+
+	@Override
+	public void performAction(InputType type, Project project, IMainViewController mainViewController) {
+		if (type == InputType.PRESSED) {
+			MediaPluginImpl.blindProperty().set(!MediaPluginImpl.blindProperty().get());
+		}
+	}
+
+	@Override
+	public void clearFeedback() {
+		MediaPluginImpl.blindProperty().removeListener(blindFeedbackListener);
+	}
+
+	@Override
+	public void initFeedback(Project project, IMainViewController controller) {
+		// Listener für Eingaben
+		BooleanProperty blindProperty = MediaPluginImpl.blindProperty();
+		blindProperty.removeListener(blindFeedbackListener);
+		blindProperty.addListener(blindFeedbackListener);
+
+		// Handle Current Feedback
+		blindFeedbackListener.changed(blindProperty, null, blindProperty.getValue());
+	}
+
+	@Override
+	public FeedbackType geFeedbackType() {
+		return FeedbackType.DOUBLE;
+	}
+
+	@Override
+	public String getType() {
+		return BlindActionConnect.TYPE;
+	}
+
+	@Override
+	public void load(Element root) {}
+
+	@Override
+	public void save(Element root) {}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj.getClass().equals(getClass())) {
+			return true;
+		}
+		return super.equals(obj);
+	}
+
+	@Override
+	public StringProperty displayProperty() {
+		return new SimpleStringProperty(MediaPluginImpl.getInstance().getBundle().getString("blindaction.name"));
+	}
+
+	@Override
+	public Node getGraphics() {
+		return new Label("", new FontIcon(FontAwesomeType.DESKTOP));
+	}
+
+	@Override
+	public Action cloneAction() throws CloneNotSupportedException {
+		BlindAction actionClone = (BlindAction) super.clone();
+		return actionClone;
+	}
+}
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/blindaction/BlindActionConnect.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/blindaction/BlindActionConnect.java
new file mode 100644
index 0000000000000000000000000000000000000000..65aafefd5529e8d889542ee5ede01e9bbcac26fb
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/blindaction/BlindActionConnect.java
@@ -0,0 +1,42 @@
+package de.tobias.playpad.mediaplugin.blindaction;
+
+import java.util.List;
+
+import de.tobias.playpad.action.Action;
+import de.tobias.playpad.action.ActionConnect;
+import de.tobias.playpad.action.ActionDisplayable;
+import de.tobias.playpad.action.ActionType;
+import de.tobias.playpad.action.Mapping;
+import de.tobias.playpad.settings.Profile;
+import javafx.scene.control.TreeItem;
+
+public class BlindActionConnect extends ActionConnect {
+
+	public static final String TYPE = "BLIND";
+
+	@Override
+	public TreeItem<ActionDisplayable> getTreeViewForActions(List<Action> actions, Mapping mapping) {
+		TreeItem<ActionDisplayable> item = new TreeItem<>(actions.get(0));
+		return item;
+	}
+
+	@Override
+	public void initActionType(Mapping mapping, Profile profile) {
+		mapping.addActionIfNotContains(new BlindAction());
+	}
+
+	@Override
+	public Action newInstance() {
+		return new BlindAction();
+	}
+	
+	@Override
+	public ActionType geActionType() {
+		return ActionType.SETTINGS;
+	}
+	
+	@Override
+	public String getType() {
+		return TYPE;
+	}
+}
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/VideoPlugin.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/VideoPlugin.java
new file mode 100644
index 0000000000000000000000000000000000000000..715650a73a239e4c1a948a52e363958577b22f1f
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/VideoPlugin.java
@@ -0,0 +1,8 @@
+package de.tobias.playpad.mediaplugin.main;
+
+import net.xeoh.plugins.base.Plugin;
+
+
+public interface VideoPlugin extends Plugin {
+
+}
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/VideoSettings.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/VideoSettings.java
new file mode 100644
index 0000000000000000000000000000000000000000..147e22d7f266be71a474b015a4a7abfa77743bbd
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/VideoSettings.java
@@ -0,0 +1,79 @@
+package de.tobias.playpad.mediaplugin.main;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+import org.dom4j.io.OutputFormat;
+import org.dom4j.io.SAXReader;
+import org.dom4j.io.XMLWriter;
+
+public class VideoSettings {
+
+	private int screenId = 0;
+	private boolean fullScreen = true;
+	private boolean openAtLaunch = false;
+
+	public int getScreenId() {
+		return screenId;
+	}
+
+	public boolean isFullScreen() {
+		return fullScreen;
+	}
+
+	public boolean isOpenAtLaunch() {
+		return openAtLaunch;
+	}
+
+	public void setFullScreen(boolean fullScreen) {
+		this.fullScreen = fullScreen;
+	}
+
+	public void setOpenAtLaunch(boolean openAtLaunch) {
+		this.openAtLaunch = openAtLaunch;
+	}
+
+	public void setScreenId(int screenId) {
+		this.screenId = screenId;
+	}
+
+	private static final String OPEN_AT_LAUNCH_ELEMENT = "OpenAtLaunch";
+	private static final String FULL_SCREEN_ELEMENT = "FullScreen";
+	private static final String SCREEN_ID_ELEMENT = "ScreenID";
+
+	public void load(Path path) throws DocumentException, IOException {
+		if (Files.exists(path)) {
+			SAXReader reader = new SAXReader();
+			Document document = reader.read(Files.newInputStream(path));
+			Element root = document.getRootElement();
+			if (root.element(SCREEN_ID_ELEMENT) != null)
+				setScreenId(Integer.valueOf(root.element(SCREEN_ID_ELEMENT).getStringValue()));
+			if (root.element(FULL_SCREEN_ELEMENT) != null)
+				setFullScreen(Boolean.valueOf(root.element(FULL_SCREEN_ELEMENT).getStringValue()));
+			if (root.element(OPEN_AT_LAUNCH_ELEMENT) != null)
+				setOpenAtLaunch(Boolean.valueOf(root.element(OPEN_AT_LAUNCH_ELEMENT).getStringValue()));
+		}
+	}
+
+	public void save(Path path) throws IOException {
+		if (Files.notExists(path)) {
+			Files.createDirectories(path.getParent());
+			Files.createFile(path);
+		}
+		Document document = DocumentHelper.createDocument();
+		Element root = document.addElement("Config");
+
+		root.addElement(SCREEN_ID_ELEMENT).addText(String.valueOf(screenId));
+		root.addElement(FULL_SCREEN_ELEMENT).addText(String.valueOf(fullScreen));
+		root.addElement(OPEN_AT_LAUNCH_ELEMENT).addText(String.valueOf(openAtLaunch));
+
+		XMLWriter writer = new XMLWriter(Files.newOutputStream(path), OutputFormat.createPrettyPrint());
+		writer.write(document);
+		writer.close();
+	}
+}
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/MediaPluginImpl.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/MediaPluginImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..a430a722c38d923f74bfb3e38897e50dfa402a8d
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/MediaPluginImpl.java
@@ -0,0 +1,156 @@
+package de.tobias.playpad.mediaplugin.main.impl;
+
+import java.io.IOException;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.util.ResourceBundle;
+
+import org.dom4j.DocumentException;
+
+import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.action.ActionRegistery;
+import de.tobias.playpad.mediaplugin.blindaction.BlindActionConnect;
+import de.tobias.playpad.mediaplugin.main.VideoPlugin;
+import de.tobias.playpad.mediaplugin.main.VideoSettings;
+import de.tobias.playpad.mediaplugin.video.VideoContentConntect;
+import de.tobias.playpad.pad.conntent.PadContentRegistry;
+import de.tobias.playpad.plugin.SettingsListener;
+import de.tobias.playpad.plugin.image.ImageContentConntect;
+import de.tobias.playpad.settings.Profile;
+import de.tobias.playpad.update.UpdateRegistery;
+import de.tobias.utils.ui.HUD;
+import de.tobias.utils.ui.icon.FontAwesomeType;
+import de.tobias.utils.ui.icon.FontIcon;
+import de.tobias.utils.util.Localization;
+import javafx.application.Platform;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.geometry.Pos;
+import javafx.scene.layout.Pane;
+import javafx.scene.paint.Color;
+import net.xeoh.plugins.base.annotations.PluginImplementation;
+import net.xeoh.plugins.base.annotations.events.PluginLoaded;
+import net.xeoh.plugins.base.annotations.events.Shutdown;
+
+@PluginImplementation
+public class MediaPluginImpl implements VideoPlugin, SettingsListener, ChangeListener<Boolean> {
+
+	private static MediaPluginImpl instance;
+	private MediaViewController videoViewController;
+	private VideoSettings settings = new VideoSettings();
+
+	private ResourceBundle bundle;
+	private HUD blindHUD;
+	private static BooleanProperty blindProperty;
+
+	private static final String SETTINGS_FILENAME = "Media.xml";
+
+	@PluginLoaded
+	public void onEnable(VideoPlugin plugin) {
+		instance = this;
+		blindProperty = new SimpleBooleanProperty();
+
+		bundle = Localization.loadBundle("de/tobias/playpad/mediaplugin/assets/video", getClass().getClassLoader());
+		videoViewController = new MediaViewController(settings);
+
+		PadContentRegistry.registerActionConnect(new VideoContentConntect());
+		PadContentRegistry.registerActionConnect(new ImageContentConntect());
+
+		PlayPadPlugin.getImplementation().addSettingsListener(this);
+
+		if (Profile.currentProfile() != null) {
+			onLoad(Profile.currentProfile());
+			onChange(Profile.currentProfile());
+		}
+
+		if (blindHUD == null) {
+			Platform.runLater(() ->
+			{
+				FontIcon icon = new FontIcon(FontAwesomeType.DESKTOP);
+				icon.setSize(60);
+				icon.getStyleClass().remove(FontIcon.STYLE_CLASS);
+				icon.setColor(Color.WHITE);
+				icon.setAlignment(Pos.CENTER);
+				blindHUD = new HUD(icon);
+				blindHUD.setPosition(Pos.TOP_CENTER);
+				blindHUD.setMinWidth(200);
+				blindHUD.setMinHeight(100);
+			});
+		}
+
+		UpdateRegistery.registerUpdateable(new MediaPluginUpdater());
+		ActionRegistery.registerActionConnect(new BlindActionConnect());
+
+		blindProperty.addListener(this);
+
+		System.out.println("Enable Media Plugin");
+	}
+
+	@Shutdown
+	public void onDisable() {
+		Platform.runLater(() -> videoViewController.getStage().close());
+		System.out.println("Disable Media Plugin");
+	}
+
+	@Override
+	public void onLoad(Profile profile) {
+		Path path = profile.getRef().getCustomFilePath(SETTINGS_FILENAME);
+
+		try {
+			settings.load(path);
+		} catch (NoSuchFileException e) {
+			System.out.println("No Awake.xml config on folder");
+		} catch (DocumentException | IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public void onSave(Profile profile) {
+		Path path = profile.getRef().getCustomFilePath(SETTINGS_FILENAME);
+
+		try {
+			settings.save(path);
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	public VideoSettings getCurrentSettings() {
+		return settings;
+	}
+
+	public static MediaPluginImpl getInstance() {
+		return instance;
+	}
+
+	public MediaViewController getVideoViewController() {
+		return videoViewController;
+	}
+
+	public ResourceBundle getBundle() {
+		return bundle;
+	}
+
+	public static BooleanProperty blindProperty() {
+		return blindProperty;
+	}
+
+	@Override
+	public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
+		Platform.runLater(() ->
+		{
+			if (newValue) {
+				videoViewController.blind(true);
+				Pane root = (Pane) PlayPadPlugin.getImplementation().getMainViewController().getParent();
+				if (blindHUD != null)
+					blindHUD.addToParent(root);
+			} else {
+				videoViewController.blind(false);
+				blindHUD.removeFromParent();
+			}
+		});
+	}
+}
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/MediaPluginUpdater.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/MediaPluginUpdater.java
new file mode 100644
index 0000000000000000000000000000000000000000..93e343a88736fe4d493a6c5fecdaf54fe5c2eabb
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/MediaPluginUpdater.java
@@ -0,0 +1,79 @@
+package de.tobias.playpad.mediaplugin.main.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Path;
+
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import de.tobias.playpad.update.Updatable;
+import de.tobias.playpad.update.UpdateChannel;
+import de.tobias.utils.application.App;
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.container.PathType;
+
+public class MediaPluginUpdater implements Updatable {
+
+	private int newBuild;
+	private String newVersion;
+	private URL remotePath;
+
+	private String localFileName;
+	private String name;
+
+	@Override
+	public int getCurrentBuild() {
+		return 5;
+	}
+
+	@Override
+	public String getCurrentVersion() {
+		return "4.1";
+	}
+
+	@Override
+	public int getNewBuild() {
+		return newBuild;
+	}
+
+	@Override
+	public String getNewVersion() {
+		return newVersion;
+	}
+
+	@Override
+	public void loadInformation(UpdateChannel channel) throws IOException {
+		App app = ApplicationUtils.getMainApplication();
+		URL url = new URL(app.getInfo().getUpdateURL() + "/" + channel + "/plugins.yml");
+		FileConfiguration config = YamlConfiguration.loadConfiguration(url.openStream());
+
+		newBuild = config.getInt("plugins.media.build");
+		newVersion = config.getString("plugins.media.version");
+		remotePath = new URL(config.getString("plugins.media.url"));
+		localFileName = config.getString("plugins.media.filename");
+		name = config.getString("plugins.media.name");
+
+	}
+
+	@Override
+	public boolean isUpdateAvailable() {
+		return getCurrentBuild() < getNewBuild();
+	}
+
+	@Override
+	public URL getDownloadPath() {
+		return remotePath;
+	}
+
+	@Override
+	public Path getLocalPath() {
+		return ApplicationUtils.getApplication().getPath(PathType.LIBRARY, localFileName);
+	}
+
+	@Override
+	public String name() {
+		return name;
+	}
+
+}
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/MediaSettingsTabViewController.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/MediaSettingsTabViewController.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ebe6c7e678a04fa952aba4b8a5eb60bff3ce694
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/MediaSettingsTabViewController.java
@@ -0,0 +1,134 @@
+package de.tobias.playpad.mediaplugin.main.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+
+import de.tobias.playpad.mediaplugin.main.VideoSettings;
+import de.tobias.playpad.project.Project;
+import de.tobias.playpad.settings.Profile;
+import de.tobias.playpad.viewcontroller.SettingsTabViewController;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+import javafx.fxml.FXML;
+import javafx.scene.control.CheckBox;
+import javafx.scene.control.ComboBox;
+import javafx.scene.control.Label;
+import javafx.scene.layout.Pane;
+import javafx.scene.layout.StackPane;
+import javafx.scene.paint.Color;
+import javafx.scene.shape.Rectangle;
+import javafx.stage.Screen;
+
+public class MediaSettingsTabViewController extends SettingsTabViewController {
+
+	@FXML private Pane screenViewPane;
+	@FXML private ComboBox<Integer> screenComboBox;
+	@FXML private CheckBox fullscreenCheckBox;
+	@FXML private CheckBox videoOpenAtLaunchCheckBox;
+
+	private VideoSettings settings;
+	private ResourceBundle bundle;
+
+	private boolean changeSettings = false;
+
+	public MediaSettingsTabViewController(VideoSettings settings) {
+		super("settingsPane", "de/tobias/playpad/mediaplugin/assets/", MediaPluginImpl.getInstance().getBundle());
+		this.settings = settings;
+		this.bundle = MediaPluginImpl.getInstance().getBundle();
+	}
+
+	@Override
+	public void init() {
+		// Video
+		createScreenView();
+	}
+
+	private void createScreenView() {
+		List<Screen> screens = Screen.getScreens();
+		List<StackPane> rects = new ArrayList<>();
+
+		screenComboBox.getItems().clear();
+
+		double minX = 0;
+		double minY = 0;
+		int index = 1;
+
+		for (Screen screen : screens) {
+			screenComboBox.getItems().add(index);
+
+			StackPane stackPane = new StackPane();
+			stackPane.relocate(screen.getBounds().getMinX() * 0.1, screen.getBounds().getMinY() * 0.1);
+			stackPane.resize(screen.getBounds().getWidth() * 0.1, screen.getBounds().getHeight() * 0.1);
+
+			Rectangle rec = new Rectangle(screen.getBounds().getWidth() * 0.1, screen.getBounds().getHeight() * 0.1);
+			rec.setStrokeWidth(1.0);
+			rec.setStroke(Color.BLACK);
+			rec.setFill(Color.TRANSPARENT);
+
+			stackPane.getChildren().addAll(rec, new Label(String.valueOf(index++)));
+
+			if (minX > screen.getBounds().getMinX() * 0.1)
+				minX = screen.getBounds().getMinX() * 0.1;
+			if (minY > screen.getBounds().getMinY() * 0.1)
+				minY = screen.getBounds().getMinY() * 0.1;
+			rects.add(stackPane);
+			screenViewPane.getChildren().add(stackPane);
+
+		}
+
+		double width = 0;
+		double height = 0;
+		for (StackPane stackPane : rects) {
+			stackPane.relocate(stackPane.getLayoutX() - minX, stackPane.getLayoutY() - minY);
+			width += stackPane.getWidth();
+			if (height < stackPane.getHeight() + stackPane.getLayoutX())
+				height = stackPane.getHeight() + stackPane.getLayoutX();
+		}
+
+		screenViewPane.setMaxWidth(width);
+		screenViewPane.setMaxHeight(height + 20);
+	}
+
+	@Override
+	public void loadSettings(Profile profile) {
+		screenComboBox.setValue(settings.getScreenId() + 1);
+		fullscreenCheckBox.setSelected(settings.isFullScreen());
+		videoOpenAtLaunchCheckBox.setSelected(settings.isOpenAtLaunch());
+	}
+
+	@Override
+	public void saveSettings(Profile profile) {
+		if (settings.getScreenId() != (screenComboBox.getValue() != null ? screenComboBox.getValue() - 1 : 0)) {
+			changeSettings = true;
+		}
+		if (settings.isFullScreen() != fullscreenCheckBox.isSelected()) {
+			changeSettings = true;
+		}
+		if (settings.isOpenAtLaunch() != videoOpenAtLaunchCheckBox.isSelected()) {
+			changeSettings = true;
+		}
+		settings.setScreenId(screenComboBox.getValue() != null ? screenComboBox.getValue() - 1 : 0);
+		settings.setFullScreen(fullscreenCheckBox.isSelected());
+		settings.setOpenAtLaunch(videoOpenAtLaunchCheckBox.isSelected());
+	}
+
+	@Override
+	public boolean needReload() {
+		return changeSettings;
+	}
+
+	@Override
+	public void reload(Profile profile, Project project, IMainViewController controller) {
+		MediaPluginImpl.getInstance().getVideoViewController().reloadSettings();
+	}
+
+	@Override
+	public boolean validSettings() {
+		return true;
+	}
+
+	@Override
+	public String name() {
+		return bundle.getString("settings.tab");
+	}
+}
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/MediaViewController.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/MediaViewController.java
new file mode 100644
index 0000000000000000000000000000000000000000..307b2e60c947dc85fbdbe6bad4f03c8dc7816428
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/MediaViewController.java
@@ -0,0 +1,196 @@
+package de.tobias.playpad.mediaplugin.main.impl;
+
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.mediaplugin.main.VideoSettings;
+import de.tobias.playpad.mediaplugin.video.VideoContent;
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadStatus;
+import de.tobias.playpad.plugin.image.ImageContent;
+import de.tobias.playpad.settings.Profile;
+import de.tobias.playpad.settings.ProfileListener;
+import de.tobias.utils.application.ApplicationUtils;
+import de.tobias.utils.application.container.PathType;
+import de.tobias.utils.util.OS;
+import de.tobias.utils.util.OS.OSType;
+import javafx.application.Platform;
+import javafx.geometry.Pos;
+import javafx.geometry.Rectangle2D;
+import javafx.scene.Scene;
+import javafx.scene.layout.Background;
+import javafx.scene.layout.BackgroundFill;
+import javafx.scene.layout.Pane;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.StackPane;
+import javafx.scene.layout.VBox;
+import javafx.scene.media.MediaPlayer;
+import javafx.scene.media.MediaPlayer.Status;
+import javafx.scene.media.MediaView;
+import javafx.scene.paint.Color;
+import javafx.stage.Screen;
+import javafx.stage.Stage;
+
+public class MediaViewController implements ProfileListener {
+
+	private MediaView mediaView;
+	private Pane imageView;
+
+	private Stage stage;
+
+	private boolean finish = true;
+	private VideoSettings settings;
+
+	private Pad currentDisplayedPad;
+
+	public MediaViewController(VideoSettings settings) {
+		Profile.registerListener(this);
+		this.settings = settings;
+
+		mediaView = new MediaView();
+		imageView = new Pane();
+
+		VBox root = new VBox(mediaView);
+		root.setAlignment(Pos.CENTER);
+
+		StackPane stackPane = new StackPane(root, imageView);
+		stackPane.setBackground(new Background(new BackgroundFill(Color.BLACK, null, null)));
+		stackPane.setAlignment(Pos.CENTER);
+		stackPane.prefWidthProperty().bind(root.widthProperty());
+
+		mediaView.fitHeightProperty().bind(root.heightProperty());
+		VBox.setVgrow(mediaView, Priority.ALWAYS);
+
+		imageView.prefWidthProperty().bind(stackPane.widthProperty());
+		imageView.prefHeightProperty().bind(stackPane.heightProperty());
+		imageView.getStyleClass().add("image-style");
+
+		stage = new Stage();
+		stage.setScene(new Scene(stackPane, Color.BLACK));
+		PlayPadPlugin.getImplementation().getIcon().ifPresent(stage.getIcons()::add);
+
+		Path path = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, "style.css");
+		if (Files.exists(path))
+			getStage().getScene().getStylesheets().add(path.toUri().toString());
+
+		stage.setMinWidth(600);
+		stage.setMinHeight(400);
+		if (OS.getType() == OSType.Windows)
+			stage.setAlwaysOnTop(true);
+
+		getStage().setOnCloseRequest(event -> event.consume());
+		reloadSettings();
+	}
+
+	public void reloadSettings() {
+		if (stage.isFullScreen())
+			stage.setFullScreen(false);
+
+		if (stage.isShowing())
+			stage.close();
+
+		if (Screen.getScreens().size() > settings.getScreenId()) {
+			Screen screen = Screen.getScreens().get(settings.getScreenId());
+
+			Rectangle2D bounds;
+			if (OS.getType() == OSType.Windows)
+				bounds = screen.getBounds();
+			else
+				bounds = screen.getVisualBounds();
+
+			stage.setX(bounds.getMinX());
+			stage.setY(bounds.getMinY());
+			stage.setWidth(bounds.getWidth());
+			stage.setHeight(bounds.getHeight());
+		}
+
+		if (settings.isOpenAtLaunch() && !stage.isShowing())
+			stage.show();
+
+		if (settings.isFullScreen() && !stage.isFullScreen())
+			stage.setFullScreen(true);
+	}
+
+	public Stage getStage() {
+		return stage;
+	}
+
+	// Media
+	public void setMediaPlayer(MediaPlayer player, Pad pad) {
+		if (currentDisplayedPad != null && currentDisplayedPad != pad)
+			this.currentDisplayedPad.setStatus(PadStatus.STOP);
+
+		mediaView.setMediaPlayer(player);
+		if (player == null) {
+			finish = true;
+			this.currentDisplayedPad = null;
+		} else {
+			finish = false;
+			this.currentDisplayedPad = pad;
+		}
+	}
+
+	public boolean isPlaying() {
+		if (mediaView.getMediaPlayer() != null) {
+			if (finish)
+				return false;
+			else
+				return mediaView.getMediaPlayer().getStatus() == Status.PLAYING;
+		} else {
+			return false;
+		}
+	}
+
+	@Override
+	public void reloadSettings(Profile old, Profile currentProfile) {
+		Platform.runLater(() -> reloadSettings());
+	}
+
+	public boolean isFinish() {
+		return finish;
+	}
+
+	// Image
+	public void setImage(String path, Pad pad) {
+		if (currentDisplayedPad != null)
+			this.currentDisplayedPad.setStatus(PadStatus.STOP);
+
+		if (path != null) {
+			this.imageView.setStyle("-fx-background-image: url(\"" + path
+					+ "\"); -fx-background-size: contain; -fx-background-repeat: no-repeat; -fx-background-position: center");
+			this.currentDisplayedPad = pad;
+		} else {
+			this.imageView.setStyle("");
+			this.currentDisplayedPad = null;
+		}
+	}
+
+	public boolean isPicutureShowing() {
+		return !imageView.getStyle().isEmpty();
+	}
+
+	// Utils
+	public Pad getCurrentDisplayedPad() {
+		return currentDisplayedPad;
+	}
+
+	public void blind(boolean blind) {
+		if (blind) {
+			this.imageView.setStyle("");
+			mediaView.setMediaPlayer(null);
+		} else {
+			if (currentDisplayedPad != null) {
+				if (currentDisplayedPad.getContent() instanceof VideoContent) {
+					VideoContent content = (VideoContent) currentDisplayedPad.getContent();
+					mediaView.setMediaPlayer(content.getPlayer());
+				} else if (currentDisplayedPad.getContent() instanceof ImageContent) {
+					ImageContent content = (ImageContent) currentDisplayedPad.getContent();
+					URI uri = content.getPath().toUri();
+					setImage(uri.toString(), currentDisplayedPad);
+				}
+			}
+		}
+	}
+}
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/Strings.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/Strings.java
new file mode 100644
index 0000000000000000000000000000000000000000..526606dfd9790c6368b4d2938a1a1ed7eee2eee4
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/main/impl/Strings.java
@@ -0,0 +1,7 @@
+package de.tobias.playpad.mediaplugin.main.impl;
+
+public class Strings {
+
+	public static final String Content_Video_Name = "Content.Video.Name";
+	public static final String Content_Image_Name = "Content.Image.Name";
+}
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/video/VideoContent.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/video/VideoContent.java
new file mode 100644
index 0000000000000000000000000000000000000000..021b6458fab9660f5c01773afb0dc049631c7eb5
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/video/VideoContent.java
@@ -0,0 +1,274 @@
+package de.tobias.playpad.mediaplugin.video;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.dom4j.Element;
+
+import de.tobias.playpad.mediaplugin.main.impl.MediaPluginImpl;
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadStatus;
+import de.tobias.playpad.pad.conntent.Durationable;
+import de.tobias.playpad.pad.conntent.PadContent;
+import de.tobias.playpad.pad.conntent.Pauseable;
+import de.tobias.playpad.project.ProjectExporter;
+import de.tobias.playpad.settings.Profile;
+import de.tobias.utils.util.ZipFile;
+import javafx.application.Platform;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.beans.value.ChangeListener;
+import javafx.scene.media.Media;
+import javafx.scene.media.MediaPlayer;
+import javafx.util.Duration;
+
+public class VideoContent extends PadContent implements Pauseable, Durationable {
+
+	private static final String TYPE = "video";
+	public static final String VIDEO_LAST_FRAME = "Video.LastFrame";
+
+	private Media media;
+	private MediaPlayer player;
+
+	private Path path;
+
+	private transient ObjectProperty<Duration> durationProperty = new SimpleObjectProperty<>();
+	private transient ObjectProperty<Duration> positionProperty = new SimpleObjectProperty<>();
+
+	private transient ChangeListener<Number> padVolumeListener;
+	private transient ChangeListener<Number> customVolumeListener;
+
+	private transient boolean holdLastFrame = false;
+
+	public VideoContent(Pad pad) {
+		super(pad);
+		padVolumeListener = (a, b, c) ->
+		{
+			player.setVolume(c.doubleValue() * Profile.currentProfile().getProfileSettings().getVolume() * getPad().getCustomVolume());
+		};
+		customVolumeListener = (a, b, c) ->
+		{
+			player.setVolume(getPad().getVolume() * Profile.currentProfile().getProfileSettings().getVolume() * c.doubleValue());
+		};
+	}
+
+	public VideoContent(Pad pad, Path path) {
+		this(pad);
+		this.path = path;
+	}
+
+	public Path getPath() {
+		return path;
+	}
+
+	public void setPath(Path path) {
+		this.path = path;
+	}
+
+	@Override
+	public void handlePath(Path path) {
+		unloadMedia();
+		setPath(path);
+		loadMedia();
+	}
+
+	@Override
+	public void setMasterVolume(double masterVolume) {
+		if (player != null) {
+			player.setVolume(getPad().getVolume() * masterVolume * getPad().getCustomVolume());
+		}
+	}
+
+	@Override
+	public String getType() {
+		return TYPE;
+	}
+
+	@Override
+	public void play() {
+		getPad().setCustomVolume(1.0);
+		getPad().setEof(false);
+		MediaPluginImpl.getInstance().getVideoViewController().setMediaPlayer(player, getPad());
+		if (holdLastFrame) {
+			holdLastFrame = false;
+			player.seek(Duration.ZERO);
+		}
+
+		player.play();
+		holdLastFrame = false;
+	}
+
+	@Override
+	public void pause() {
+		player.pause();
+	}
+
+	@Override
+	public boolean stop() {
+		if (getPad().getCustomSettings().containsKey(VIDEO_LAST_FRAME) && !holdLastFrame && getPad().isEof()) {
+			if ((boolean) getPad().getCustomSettings().get(VIDEO_LAST_FRAME)) {
+				getPad().setStatus(PadStatus.PAUSE);
+				holdLastFrame = true;
+				return false;
+			}
+		}
+		player.stop();
+		MediaPluginImpl.getInstance().getVideoViewController().setMediaPlayer(null, null);
+		return true;
+	}
+
+	@Override
+	public boolean isPadLoaded() {
+		return player != null;
+	}
+
+	@Override
+	public Duration getDuration() {
+		return durationProperty.get();
+	}
+
+	@Override
+	public ReadOnlyObjectProperty<Duration> durationProperty() {
+		return durationProperty;
+	}
+
+	@Override
+	public Duration getPosition() {
+		return positionProperty.get();
+	}
+
+	@Override
+	public ReadOnlyObjectProperty<Duration> positionProperty() {
+		return positionProperty;
+	}
+
+	public MediaPlayer getPlayer() {
+		return player;
+	}
+
+	@Override
+	public void loadMedia() {
+		if (Files.exists(path)) {
+			Platform.runLater(() ->
+			{
+				if (getPad().isPadVisible()) {
+					getPad().getController().getParent().setBusy(true);
+				}
+			});
+			media = new Media(path.toUri().toString());
+
+			// Old Player
+			if (player != null) {
+				stop();
+			}
+
+			player = new MediaPlayer(media);
+
+			// Player Listener
+			player.setOnReady(() ->
+			{
+				getPad().setStatus(PadStatus.READY);
+
+				Platform.runLater(() ->
+				{
+					if (getPad().isPadVisible()) {
+						getPad().getController().getParent().setBusy(false);
+					}
+				});
+			});
+
+			player.setOnError(() ->
+			{
+				Platform.runLater(() ->
+				{
+					if (getPad().isPadVisible()) {
+						getPad().getController().getParent().setBusy(false);
+					}
+				});
+				getPad().throwException(path, player.getError());
+			});
+			player.setOnEndOfMedia(() ->
+			{
+				if (!getPad().isLoop()) {
+					getPad().setEof(true);
+					getPad().setStatus(PadStatus.STOP);
+				} else {
+					// Loop
+					player.seek(Duration.ZERO);
+				}
+			});
+
+			durationProperty.bind(player.totalDurationProperty());
+			positionProperty.bind(player.currentTimeProperty());
+
+			getPad().volumeProperty().addListener(padVolumeListener);
+			getPad().customVolumeProperty().addListener(customVolumeListener);
+		}
+	}
+
+	@Override
+	public void unloadMedia() {
+		durationProperty.unbind();
+		positionProperty.unbind();
+
+		getPad().volumeProperty().removeListener(padVolumeListener);
+		getPad().customVolumeProperty().removeListener(customVolumeListener);
+
+		player = null;
+		media = null;
+		durationProperty.set(null);
+
+		Platform.runLater(() ->
+		{
+			if (getPad() != null) {
+				getPad().setStatus(PadStatus.EMPTY);
+			}
+		});
+	}
+
+	@Override
+	public void load(Element element) {
+		path = Paths.get(element.getStringValue());
+	}
+
+	@Override
+	public void save(Element element) {
+		element.addText(path.toString());
+	}
+
+	@Override
+	public void importMedia(Path mediaFolder, ZipFile zip, Element element) {
+		String fileName = Paths.get(element.getStringValue()).getFileName().toString();
+		Path mediaFile = Paths.get(ProjectExporter.mediaFolder, fileName);
+
+		Path desFile = mediaFolder.resolve(fileName);
+
+		try {
+			if (Files.notExists(desFile.getParent())) {
+				Files.createDirectories(desFile.getParent());
+			}
+
+			if (Files.notExists(desFile))
+				zip.getFile(mediaFile, desFile);
+
+			element.setText(desFile.toString());
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public void exportMedia(ZipFile zip, Element element) {
+		Path desPath = Paths.get(ProjectExporter.mediaFolder, path.getFileName().toString());
+		try {
+			if (Files.notExists(desPath.getParent())) {
+				Files.createDirectories(desPath.getParent());
+			}
+			zip.addFile(path, desPath);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+}
\ No newline at end of file
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/video/VideoContentConntect.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/video/VideoContentConntect.java
new file mode 100644
index 0000000000000000000000000000000000000000..65a48ac94219ed5e8bcf28e4f0d1db0da86d1f69
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/video/VideoContentConntect.java
@@ -0,0 +1,105 @@
+package de.tobias.playpad.mediaplugin.video;
+
+import de.tobias.playpad.mediaplugin.main.impl.MediaPluginImpl;
+import de.tobias.playpad.mediaplugin.main.impl.MediaSettingsTabViewController;
+import de.tobias.playpad.mediaplugin.main.impl.Strings;
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.conntent.PadContent;
+import de.tobias.playpad.pad.conntent.PadContentConnect;
+import de.tobias.playpad.pad.view.IPadContentView;
+import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
+import de.tobias.playpad.viewcontroller.SettingsTabViewController;
+import de.tobias.utils.ui.icon.FontAwesomeType;
+import de.tobias.utils.ui.icon.FontIcon;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+import javafx.scene.layout.Pane;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+import javafx.scene.text.TextAlignment;
+
+public class VideoContentConntect extends PadContentConnect {
+
+	public static final String TYPE = "video";
+	public static final String[] FILE_EXTENSION = { "*.mp4", "*.mov" };
+
+	private FontIcon icon;
+
+	public VideoContentConntect() {
+		icon = new FontIcon(FontAwesomeType.FILM);
+		icon.setSize(30);
+	}
+
+	@Override
+	public String getType() {
+		return TYPE;
+	}
+
+	@Override
+	public PadContent newInstance(Pad pad) {
+		return new VideoContent(pad);
+	}
+
+	@Override
+	public IPadContentView getPadContentPreview(Pad pad, Pane parentNode) {
+		return new VideoContentView(pad, parentNode);
+	}
+
+	@Override
+	public SettingsTabViewController getSettingsTabViewController(boolean activePlayer) {
+		MediaPluginImpl instance = MediaPluginImpl.getInstance();
+		return new MediaSettingsTabViewController(instance.getCurrentSettings());
+	}
+
+	@Override
+	public PadSettingsTabViewController getSettingsViewController(Pad pad) {
+		return new VideoPadSettingsTabViewController();
+	}
+
+	@Override
+	public String[] getSupportedTypes() {
+		return FILE_EXTENSION;
+	}
+
+	private class VideoContentView implements IPadContentView {
+
+		private Label nameLabel;
+
+		public VideoContentView(Pad pad, Pane parentNode) {
+			nameLabel = new Label();
+			nameLabel.textProperty().bind(pad.nameProperty());
+
+			nameLabel.setWrapText(true);
+			nameLabel.setAlignment(Pos.CENTER);
+			nameLabel.setTextAlignment(TextAlignment.CENTER);
+
+			nameLabel.prefWidthProperty().bind(parentNode.widthProperty());
+			nameLabel.setMaxHeight(Double.MAX_VALUE);
+			VBox.setVgrow(nameLabel, Priority.ALWAYS);
+		}
+
+		@Override
+		public Node getNode() {
+			return nameLabel;
+		}
+
+		@Override
+		public void unconnect() {
+			nameLabel.textProperty().unbind();
+		}
+	}
+
+	@Override
+	public StringProperty displayProperty() {
+		return new SimpleStringProperty(MediaPluginImpl.getInstance().getBundle().getString(Strings.Content_Video_Name));
+	}
+
+	@Override
+	public Node getGraphics() {
+		return icon;
+	}
+
+}
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/video/VideoPadSettingsTabViewController.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/video/VideoPadSettingsTabViewController.java
new file mode 100644
index 0000000000000000000000000000000000000000..b7a0f0592cc609c6b5ab25ab5697d030d431c80d
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/mediaplugin/video/VideoPadSettingsTabViewController.java
@@ -0,0 +1,33 @@
+package de.tobias.playpad.mediaplugin.video;
+
+import de.tobias.playpad.mediaplugin.main.impl.MediaPluginImpl;
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
+import javafx.fxml.FXML;
+import javafx.scene.control.CheckBox;
+
+public class VideoPadSettingsTabViewController extends PadSettingsTabViewController {
+
+	@FXML private CheckBox lastFrameCheckBox;
+
+	public VideoPadSettingsTabViewController() {
+		super("settingsPadPane", "de/tobias/playpad/mediaplugin/assets/", MediaPluginImpl.getInstance().getBundle());
+	}
+
+	@Override
+	public String getName() {
+		return MediaPluginImpl.getInstance().getBundle().getString("settings.video.tab");
+	}
+
+	@Override
+	public void loadSettings(Pad pad) {
+		if (pad.getCustomSettings().containsKey(VideoContent.VIDEO_LAST_FRAME))
+			lastFrameCheckBox.setSelected((boolean) pad.getCustomSettings().get(VideoContent.VIDEO_LAST_FRAME));
+	}
+
+	@Override
+	public void saveSettings(Pad pad) {
+		pad.getCustomSettings().put(VideoContent.VIDEO_LAST_FRAME, lastFrameCheckBox.isSelected());
+	}
+
+}
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/plugin/image/ImageContent.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/plugin/image/ImageContent.java
new file mode 100644
index 0000000000000000000000000000000000000000..92e4eb5c994c95a5e936d20664f31a555493663d
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/plugin/image/ImageContent.java
@@ -0,0 +1,133 @@
+package de.tobias.playpad.plugin.image;
+
+import java.io.FileNotFoundException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.dom4j.Element;
+
+import de.tobias.playpad.mediaplugin.main.impl.MediaPluginImpl;
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadStatus;
+import de.tobias.playpad.pad.conntent.PadContent;
+import de.tobias.playpad.project.ProjectExporter;
+import de.tobias.utils.util.ZipFile;
+import javafx.application.Platform;
+
+public class ImageContent extends PadContent {
+
+	private Path path;
+
+	public ImageContent(Pad pad) {
+		super(pad);
+	}
+
+	public ImageContent(Pad pad, Path path) {
+		this(pad);
+		this.path = path;
+	}
+
+	public Path getPath() {
+		return path;
+	}
+
+	public void setPath(Path path) {
+		this.path = path;
+	}
+
+	@Override
+	public void handlePath(Path path) {
+		unloadMedia();
+		setPath(path);
+		loadMedia();
+	}
+
+	@Override
+	public void setMasterVolume(double masterVolume) {}
+
+	@Override
+	public String getType() {
+		return ImageContentConntect.TYPE;
+	}
+
+	@Override
+	public void play() {
+		MediaPluginImpl.getInstance().getVideoViewController().setImage(path.toUri().toString(), getPad());
+	}
+
+	@Override
+	public boolean stop() {
+		MediaPluginImpl.getInstance().getVideoViewController().setImage(null, null);
+		return true;
+	}
+
+	@Override
+	public boolean isPadLoaded() {
+		return path != null;
+	}
+
+	@Override
+	public void loadMedia() {
+		if (Files.exists(path)) {
+			getPad().setStatus(PadStatus.READY);
+		} else {
+			getPad().throwException(path, new FileNotFoundException());
+		}
+	}
+
+	@Override
+	public void unloadMedia() {
+		Platform.runLater(() ->
+		{
+			if (getPad() != null) {
+				getPad().setStatus(PadStatus.EMPTY);
+			}
+		});
+	}
+
+	@Override
+	public void load(Element element) {
+		path = Paths.get(element.getStringValue());
+	}
+
+	@Override
+	public void save(Element element) {
+		element.addText(path.toString());
+	}
+
+	@Override
+	public void importMedia(Path mediaFolder, ZipFile zip, Element element) {
+		String fileName = Paths.get(element.getStringValue()).getFileName().toString();
+		Path mediaFile = Paths.get(ProjectExporter.mediaFolder, fileName);
+
+		Path desFile = mediaFolder.resolve(fileName);
+
+		try {
+			if (Files.notExists(desFile.getParent())) {
+				Files.createDirectories(desFile.getParent());
+			}
+
+			if (Files.notExists(desFile))
+				zip.getFile(mediaFile, desFile);
+
+			element.setText(desFile.toString());
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public void exportMedia(ZipFile zip, Element element) {
+		Path desPath = Paths.get(ProjectExporter.mediaFolder, path.getFileName().toString());
+		try {
+			if (Files.notExists(desPath.getParent())) {
+				Files.createDirectories(desPath.getParent());
+			}
+			zip.addFile(path, desPath);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/PlayWallPlugins/mediaplugin/de/tobias/playpad/plugin/image/ImageContentConntect.java b/PlayWallPlugins/mediaplugin/de/tobias/playpad/plugin/image/ImageContentConntect.java
new file mode 100644
index 0000000000000000000000000000000000000000..d3d80d8ecebf6d58d2eacb7181238fadb7b92e70
--- /dev/null
+++ b/PlayWallPlugins/mediaplugin/de/tobias/playpad/plugin/image/ImageContentConntect.java
@@ -0,0 +1,144 @@
+package de.tobias.playpad.plugin.image;
+
+import de.tobias.playpad.mediaplugin.main.impl.MediaPluginImpl;
+import de.tobias.playpad.mediaplugin.main.impl.Strings;
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.conntent.PadContent;
+import de.tobias.playpad.pad.conntent.PadContentConnect;
+import de.tobias.playpad.pad.view.IPadContentView;
+import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
+import de.tobias.utils.ui.icon.FontAwesomeType;
+import de.tobias.utils.ui.icon.FontIcon;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.collections.ListChangeListener;
+import javafx.collections.SetChangeListener;
+import javafx.css.PseudoClass;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+import javafx.scene.layout.Pane;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.StackPane;
+import javafx.scene.layout.VBox;
+import javafx.scene.text.TextAlignment;
+
+public class ImageContentConntect extends PadContentConnect {
+
+	public static final String TYPE = "image";
+	public static final String[] FILE_EXTENSION = { "*.png", "*.jpg", "*.jpeg", "*.bmp", "*.gif" };
+
+	private FontIcon icon;
+
+	public ImageContentConntect() {
+		icon = new FontIcon(FontAwesomeType.PICTURE_ALT);
+		icon.setSize(30);
+	}
+
+	@Override
+	public String getType() {
+		return TYPE;
+	}
+
+	@Override
+	public PadContent newInstance(Pad pad) {
+		return new ImageContent(pad);
+	}
+
+	@Override
+	public IPadContentView getPadContentPreview(Pad pad, Pane parentNode) {
+		return new ImageContentView(pad, parentNode);
+	}
+
+	@Override
+	public PadSettingsTabViewController getSettingsViewController(Pad pad) {
+		return null;
+	}
+
+	@Override
+	public String[] getSupportedTypes() {
+		return FILE_EXTENSION;
+	}
+
+	class ImageContentView implements IPadContentView {
+
+		private StackPane stackPane;
+		private Label nameLabel;
+		private Label imageLabel;
+		private Pad pad;
+
+		public ImageContentView(Pad pad, Pane parentNode) {
+			this.pad = pad;
+			nameLabel = new Label();
+			nameLabel.textProperty().bind(pad.nameProperty());
+
+			nameLabel.setWrapText(true);
+			nameLabel.setAlignment(Pos.CENTER);
+			nameLabel.setTextAlignment(TextAlignment.CENTER);
+
+			imageLabel = new Label();
+			imageLabel.setMaxHeight(Double.MAX_VALUE);
+			imageLabel.setMaxWidth(Double.MAX_VALUE);
+			setImage();
+
+			stackPane = new StackPane(imageLabel, nameLabel);
+			stackPane.prefWidthProperty().bind(parentNode.widthProperty());
+			stackPane.setMaxHeight(Double.MAX_VALUE);
+			VBox.setVgrow(stackPane, Priority.ALWAYS);
+
+			// Leitet alle StyleClasses von Parent Object an das NameLabel weiter
+			stackPane.getStyleClass().addListener(new ListChangeListener<String>() {
+
+				@Override
+				public void onChanged(javafx.collections.ListChangeListener.Change<? extends String> c) {
+					while (c.next()) {
+						for (String remitem : c.getRemoved()) {
+							nameLabel.getStyleClass().remove(remitem);
+
+						}
+						for (String additem : c.getAddedSubList()) {
+							nameLabel.getStyleClass().add(additem);
+						}
+					}
+				}
+			});
+			// Leitet alle PseudoClassStates von Parent Object an das NameLabel weiter
+			stackPane.getPseudoClassStates().addListener(new SetChangeListener<PseudoClass>() {
+
+				@Override
+				public void onChanged(javafx.collections.SetChangeListener.Change<? extends PseudoClass> c) {
+					nameLabel.pseudoClassStateChanged(c.getElementRemoved(), false);
+					nameLabel.pseudoClassStateChanged(c.getElementAdded(), true);
+				}
+			});
+		}
+
+		@Override
+		public Node getNode() {
+			return stackPane;
+		}
+
+		@Override
+		public void unconnect() {
+			nameLabel.textProperty().unbind();
+		}
+
+		void setImage() {
+			ImageContent content = (ImageContent) pad.getContent();
+
+			if (content.getPath() != null)
+				imageLabel.setStyle("-fx-background-image: url(\"" + content.getPath().toUri().toString()
+						+ "\"); -fx-background-size: contain; -fx-background-repeat: no-repeat; -fx-background-position: center; -fx-opacity: 0.3;");
+		}
+	}
+
+	@Override
+	public StringProperty displayProperty() {
+		return new SimpleStringProperty(MediaPluginImpl.getInstance().getBundle().getString(Strings.Content_Image_Name));
+	}
+
+	@Override
+	public Node getGraphics() {
+		return icon;
+	}
+}
diff --git a/PlayWallPlugins/src/de/tobias/playpad/debugplugin/DebugPlugin.java b/PlayWallPlugins/src/de/tobias/playpad/debugplugin/DebugPlugin.java
new file mode 100644
index 0000000000000000000000000000000000000000..e09806faa00912906741c31f98d76ec0f485e39b
--- /dev/null
+++ b/PlayWallPlugins/src/de/tobias/playpad/debugplugin/DebugPlugin.java
@@ -0,0 +1,7 @@
+package de.tobias.playpad.debugplugin;
+
+import net.xeoh.plugins.base.Plugin;
+
+public interface DebugPlugin extends Plugin {
+
+}
diff --git a/PlayWallPlugins/src/de/tobias/playpad/debugplugin/DebugPluginImpl.java b/PlayWallPlugins/src/de/tobias/playpad/debugplugin/DebugPluginImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c5de9d0b5bdd925e9dcfe5b6dfe0e79c12da9ec
--- /dev/null
+++ b/PlayWallPlugins/src/de/tobias/playpad/debugplugin/DebugPluginImpl.java
@@ -0,0 +1,23 @@
+package de.tobias.playpad.debugplugin;
+
+import net.xeoh.plugins.base.annotations.PluginImplementation;
+import net.xeoh.plugins.base.annotations.events.PluginLoaded;
+import net.xeoh.plugins.base.annotations.events.Shutdown;
+
+@PluginImplementation
+public class DebugPluginImpl implements DebugPlugin {
+
+	public DebugPluginImpl() {
+		
+	}
+
+	@PluginLoaded
+	public void onInit(DebugPlugin plugin) {
+		System.out.println("INIT");
+	}
+
+	@Shutdown
+	public void onShutdown() {
+		System.out.println("SHUTDOWN");
+	}
+}