diff --git a/.idea/ant.xml b/.idea/ant.xml
deleted file mode 100644
index 9ec298f22d3ea3a74fba0ee285c8b69f9aad243f..0000000000000000000000000000000000000000
--- a/.idea/ant.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="AntConfiguration">
-    <buildFile url="file://$PROJECT_DIR$/PlayWall/build.xml" />
-  </component>
-</project>
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index b1d76afb5f55573cbaa122c6cda52782e035402e..cfb629fb5ccc38ed3b8c37eff76828314cfba5c0 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -5,11 +5,14 @@
     <file url="file://$PROJECT_DIR$/PlayWall" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/PlayWallComponents" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/PlayWallCore" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/PlayWallPluginAwake" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/PlayWallPluginEqualizer" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/PlayWallPluginLaunchpad" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/PlayWallPluginMedia" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/PlayWallPluginNativeAudio" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/PlayWallPlugins" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginAwake" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginEqualizer" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginLaunchpad" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginMedia" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginNativeAudio" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginPlayoutLog" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginWebAPI" charset="UTF-8" />
     <file url="PROJECT" charset="UTF-8" />
   </component>
 </project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 588e56e88e1ef2e64de047efc9934948f56314c2..71a1574f2f6df494b2028c78bb51cb89fc3ba39e 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -6,11 +6,14 @@
       <module fileurl="file://$PROJECT_DIR$/PlayWallComponents/PlayWallComponents.iml" filepath="$PROJECT_DIR$/PlayWallComponents/PlayWallComponents.iml" />
       <module fileurl="file://$PROJECT_DIR$/PlayWallCore/PlayWallCore.iml" filepath="$PROJECT_DIR$/PlayWallCore/PlayWallCore.iml" />
       <module fileurl="file://$PROJECT_DIR$/PlayWallDesktop.iml" filepath="$PROJECT_DIR$/PlayWallDesktop.iml" />
-      <module fileurl="file://$PROJECT_DIR$/PlayWallPluginAwake/PlayWallPluginAwake.iml" filepath="$PROJECT_DIR$/PlayWallPluginAwake/PlayWallPluginAwake.iml" />
-      <module fileurl="file://$PROJECT_DIR$/PlayWallPluginEqualizer/PlayWallPluginEqualizer.iml" filepath="$PROJECT_DIR$/PlayWallPluginEqualizer/PlayWallPluginEqualizer.iml" />
-      <module fileurl="file://$PROJECT_DIR$/PlayWallPluginLaunchpad/PlayWallPluginLaunchpad.iml" filepath="$PROJECT_DIR$/PlayWallPluginLaunchpad/PlayWallPluginLaunchpad.iml" />
-      <module fileurl="file://$PROJECT_DIR$/PlayWallPluginMedia/PlayWallPluginMedia.iml" filepath="$PROJECT_DIR$/PlayWallPluginMedia/PlayWallPluginMedia.iml" />
-      <module fileurl="file://$PROJECT_DIR$/PlayWallPluginNativeAudio/PlayWallPluginNativeAudio.iml" filepath="$PROJECT_DIR$/PlayWallPluginNativeAudio/PlayWallPluginNativeAudio.iml" />
+      <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginAwake/PlayWallPluginAwake.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginAwake/PlayWallPluginAwake.iml" />
+      <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginEqualizer/PlayWallPluginEqualizer.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginEqualizer/PlayWallPluginEqualizer.iml" />
+      <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginLaunchpad/PlayWallPluginLaunchpad.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginLaunchpad/PlayWallPluginLaunchpad.iml" />
+      <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginMedia/PlayWallPluginMedia.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginMedia/PlayWallPluginMedia.iml" />
+      <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginNativeAudio/PlayWallPluginNativeAudio.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginNativeAudio/PlayWallPluginNativeAudio.iml" />
+      <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginPlayoutLog/PlayWallPluginPlayoutLog.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginPlayoutLog/PlayWallPluginPlayoutLog.iml" />
+      <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginWebAPI/PlayWallPluginWebAPI.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginWebAPI/PlayWallPluginWebAPI.iml" />
+      <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPlugins.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPlugins.iml" />
     </modules>
   </component>
 </project>
\ No newline at end of file
diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml
deleted file mode 100644
index 50861d52337869ea9f86ffcc5dc14b306d5f9013..0000000000000000000000000000000000000000
--- a/.idea/sqldialects.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="SqlDialectMappings">
-    <file url="file://$PROJECT_DIR$/PlayWallCore/src/main/java/de/tobias/playpad/log/storage/SqlLiteLogSeasonStorageHandler.java" dialect="SQLite" />
-  </component>
-</project>
\ No newline at end of file
diff --git a/PlayWall/pom.xml b/PlayWall/pom.xml
index 60dad96caaea7bc7f3a0996b0d6a63b66d87286f..cca1c6cabf4a29b2bbfd982cc044df07c2cf0f4a 100644
--- a/PlayWall/pom.xml
+++ b/PlayWall/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallDesktop</artifactId>
-        <version>6.2.0-SNAPSHOT</version>
+        <version>7.0.0</version>
     </parent>
 
     <artifactId>PlayWall</artifactId>
@@ -16,8 +16,6 @@
         <project.main>de.tobias.playpad.PlayPadMain</project.main>
         <project.iconBase>src/main/resources/icon</project.iconBase>
 
-        <itextpdf.version>5.5.13</itextpdf.version>
-
         <launch4j-maven-plugin.version>1.7.25</launch4j-maven-plugin.version>
         <appbundle-maven-plugin.version>1.2.0</appbundle-maven-plugin.version>
 
@@ -40,13 +38,6 @@
             <version>${components.version}</version>
         </dependency>
 
-        <!-- PDF-->
-        <dependency>
-            <groupId>com.itextpdf</groupId>
-            <artifactId>itextpdf</artifactId>
-            <version>${itextpdf.version}</version>
-        </dependency>
-
         <!--Template parsing-->
         <dependency>
             <groupId>org.springframework</groupId>
@@ -101,6 +92,24 @@
                 </executions>
             </plugin>
 
+            <plugin>
+                <groupId>nl.geodienstencentrum.maven</groupId>
+                <artifactId>sass-maven-plugin</artifactId>
+                <version>3.7.2</version>
+                <executions>
+                    <execution>
+                        <id>translate-css</id>
+                        <goals>
+                            <goal>update-stylesheets</goal>
+                        </goals>
+                        <phase>generate-resources</phase>
+                        <configuration>
+                            <destination>target/classes/style</destination>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
             <!--Fat Jar-->
             <plugin>
                 <artifactId>maven-assembly-plugin</artifactId>
@@ -249,19 +258,19 @@
         <repository>
             <id>release</id>
             <name>TheCodeLabs-releases</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
         </repository>
         <snapshotRepository>
             <id>snapshots</id>
             <name>TheCodeLabs-snapshots</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
         </snapshotRepository>
     </distributionManagement>
 
     <repositories>
         <repository>
             <id>release</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
             <releases>
                 <enabled>true</enabled>
             </releases>
@@ -271,7 +280,7 @@
         </repository>
         <repository>
             <id>snapshots</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
             <releases>
                 <enabled>false</enabled>
             </releases>
diff --git a/PlayWall/src/main/java/de/tobias/playpad/AppUserInfoStrings.java b/PlayWall/src/main/java/de/tobias/playpad/AppUserInfoStrings.java
index 28618084b36950495be5a7f8969882a16712e25a..0c0edf1e619ca51823fc9a409a0b4ed623707103 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/AppUserInfoStrings.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/AppUserInfoStrings.java
@@ -1,16 +1,16 @@
 package de.tobias.playpad;
 
-public class AppUserInfoStrings {
+import de.thecodelabs.utils.application.ApplicationInfo;
 
-	public static final String WEBSITE = "Website";
-	public static final String REPOSITORY = "Repository";
+public interface AppUserInfoStrings extends ApplicationInfo.CustomUserInfo {
 
-	public static final String PLUGINS_URL_STABLE = "PluginsURL.Stable";
-	public static final String PLUGINS_URL_BETA = "PluginsURL.Beta";
+	String website();
 
-	public static final String CHANGELOG_URL = "ChangelogURL";
-	public static final String UPDATER_PROGRAM = "UpdaterProgram";
+	String repository();
 
-	public static final String SERVER = "Server";
-	public static final String ACCOUNT_REGISTER = "AccountRegister";
+	String changelogURL();
+
+	String server();
+
+	String accountRegister();
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java b/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java
index dd7c4b284f2ec8552615a770415affa7f64bc2c8..f3f434f50447c73577d67fdb21460933fcb5ea93 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java
@@ -1,84 +1,78 @@
 package de.tobias.playpad;
 
-import com.neovisionaries.ws.client.WebSocketException;
-import de.thecodelabs.logger.LogLevel;
 import de.thecodelabs.logger.Logger;
-import de.thecodelabs.storage.settings.StorageTypes;
 import de.thecodelabs.utils.application.App;
 import de.thecodelabs.utils.application.ApplicationUtils;
-import de.thecodelabs.utils.application.container.PathType;
 import de.thecodelabs.utils.io.FileUtils;
 import de.thecodelabs.utils.threading.Worker;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.util.SystemUtils;
-import de.thecodelabs.versionizer.VersionizerItem;
-import de.thecodelabs.versionizer.config.Artifact;
-import de.thecodelabs.versionizer.config.Repository;
 import de.thecodelabs.versionizer.service.UpdateService;
-import de.tobias.playpad.audio.JavaFXHandlerFactory;
-import de.tobias.playpad.design.ModernDesign;
-import de.tobias.playpad.design.ModernDesignHandlerImpl;
-import de.tobias.playpad.log.LogSeasons;
-import de.tobias.playpad.log.storage.SqlLiteLogSeasonStorageHandler;
-import de.tobias.playpad.midi.PD12;
-import de.tobias.playpad.midi.device.DeviceRegistry;
+import de.tobias.playpad.design.ModernDesignHandler;
+import de.tobias.playpad.initialize.*;
 import de.tobias.playpad.plugin.*;
+import de.tobias.playpad.profile.ProfileNotFoundException;
 import de.tobias.playpad.project.Project;
-import de.tobias.playpad.server.*;
+import de.tobias.playpad.project.ProjectNotFoundException;
+import de.tobias.playpad.project.ProjectReader;
+import de.tobias.playpad.project.loader.ProjectLoader;
+import de.tobias.playpad.project.ref.ProjectReference;
+import de.tobias.playpad.server.ConnectionState;
+import de.tobias.playpad.server.Server;
+import de.tobias.playpad.server.Session;
+import de.tobias.playpad.server.SessionDelegate;
 import de.tobias.playpad.settings.GlobalSettings;
-import de.tobias.playpad.view.MapperListViewControllerImpl;
-import de.tobias.playpad.viewcontroller.BaseMapperListViewController;
+import de.tobias.playpad.viewcontroller.dialog.project.ProjectLoadDialog;
+import de.tobias.playpad.viewcontroller.dialog.project.ProjectReaderDelegateImpl;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import de.tobias.playpad.viewcontroller.main.MainViewController;
-import de.tobias.playpad.volume.GlobalVolume;
-import de.tobias.playpad.volume.PadVolume;
-import de.tobias.playpad.volume.VolumeManager;
 import javafx.application.Application;
+import javafx.application.Platform;
 import javafx.scene.image.Image;
+import javafx.stage.Window;
+import org.dom4j.DocumentException;
 
 import java.io.IOException;
 import java.nio.file.Path;
-import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Optional;
-import java.util.ResourceBundle;
 import java.util.function.Consumer;
 
 public class PlayPadImpl implements PlayPad {
 
 	private Application.Parameters parameters;
 
-	protected List<WindowListener<IMainViewController>> mainViewListeners = new ArrayList<>();
-	protected List<SettingsListener> settingsListeners = new ArrayList<>();
-	protected List<PadListener> padListeners = new ArrayList<>();
+	private List<MainWindowListener> mainViewListeners = new ArrayList<>();
+	private List<SettingsListener> settingsListeners = new ArrayList<>();
+	private List<PadListener> padListeners = new ArrayList<>();
+	private List<GlobalListener> globalListeners = new ArrayList<>();
 
 	private MainViewController mainViewController;
+	private Image stageIcon;
 	private Project currentProject;
-	private static Module module;
 
-	private UpdateService updateService;
+	private Module module;
 
+	private UpdateService updateService;
 	protected GlobalSettings globalSettings;
-	private ModernDesign modernDesign;
+	private ModernDesignHandler modernDesign;
 
-	protected Session session;
+	private Session session;
 
-	PlayPadImpl(GlobalSettings globalSettings, Application.Parameters parameters) {
+	PlayPadImpl(Application.Parameters parameters) {
 		this.parameters = parameters;
-		this.globalSettings = globalSettings;
 
 		App app = ApplicationUtils.getApplication();
-		module = new Module(app.getInfo().getName(), app.getInfo().getIdentifier());
+		this.module = new Module(app.getInfo().getName(), app.getInfo().getIdentifier());
 		ModernPluginManager.getInstance().addModule(module);
 	}
 
 	@Override
-	public void addMainViewListener(WindowListener<IMainViewController> listener) {
+	public void addMainViewListener(MainWindowListener listener) {
 		mainViewListeners.add(listener);
 	}
 
-	public List<WindowListener<IMainViewController>> getMainViewListeners() {
+	public List<MainWindowListener> getMainViewListeners() {
 		return mainViewListeners;
 	}
 
@@ -112,14 +106,29 @@ public class PlayPadImpl implements PlayPad {
 		return padListeners;
 	}
 
+	@Override
+	public void addGlobalListener(GlobalListener globalListener) {
+		globalListeners.add(globalListener);
+	}
+
+	@Override
+	public void removeGlobalListener(GlobalListener globalListener) {
+		globalListeners.remove(globalListener);
+	}
+
+	@Override
+	public List<GlobalListener> getGlobalListeners() {
+		return globalListeners;
+	}
+
 	@Override
 	public IMainViewController getMainViewController() {
 		return mainViewController;
 	}
 
 	@Override
-	public Optional<Image> getIcon() {
-		return PlayPadMain.stageIcon;
+	public GlobalSettings getGlobalSettings() {
+		return globalSettings;
 	}
 
 	@Override
@@ -131,7 +140,7 @@ public class PlayPadImpl implements PlayPad {
 				try {
 					((AutoCloseable) i).close();
 				} catch (Exception e) {
-					e.printStackTrace();
+					Logger.error(e);
 				}
 			}
 		});
@@ -141,17 +150,11 @@ public class PlayPadImpl implements PlayPad {
 			server.disconnect();
 		}
 
-		try {
-			LogSeasons.getStorageHandler().close();
-		} catch (RuntimeException e) {
-			Logger.log(LogLevel.ERROR, "Cannot close LogSeasonStorageHandler (" + e.getLocalizedMessage() + ")");
-		}
-
 		try {
 			Path applicationSupportPath = SystemUtils.getApplicationSupportDirectoryPath("de.tobias.playpad.PlayPadMain");
 			FileUtils.deleteDirectory(applicationSupportPath);
 		} catch (IOException e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 
 		ModernPluginManager.getInstance().showdown();
@@ -159,129 +162,121 @@ public class PlayPadImpl implements PlayPad {
 	}
 
 	@Override
-	public GlobalSettings getGlobalSettings() {
-		return globalSettings;
-	}
+	public void openProject(ProjectReference projectReference, Consumer<NVC> onLoaded) throws ProjectNotFoundException, ProjectReader.ProjectReaderDelegate.ProfileAbortException, ProfileNotFoundException, DocumentException, IOException {
+		if (mainViewController != null) {
+			mainViewController.closeProject();
+			globalListeners.forEach(l -> l.projectClosed(currentProject));
+		}
+
+		Window owner = mainViewController != null ? mainViewController.getContainingWindow() : null;
+
+		ProjectLoader loader = new ProjectLoader(projectReference);
+		loader.setDelegate(ProjectReaderDelegateImpl.getInstance(owner));
+		loader.setListener(new ProjectLoadDialog());
+
+		currentProject = loader.load();
 
-	public void openProject(Project project, Consumer<NVC> onLoaded) {
 		if (mainViewController == null) {
 			mainViewController = new MainViewController(e -> {
-				currentProject = project;
-				mainViewController.openProject(project);
+				mainViewController.openProject(currentProject);
+				mainViewListeners.forEach(l -> l.onInit(mainViewController));
+
 				if (onLoaded != null) {
 					onLoaded.accept(e);
 				}
-				mainViewListeners.forEach(l -> l.onInit(mainViewController));
+
+				globalListeners.forEach(l -> l.projectOpened(currentProject));
+				Platform.setImplicitExit(true);
 			});
 		} else {
-			currentProject = project;
-			mainViewController.openProject(project);
+			mainViewController.openProject(currentProject);
+			globalListeners.forEach(l -> l.projectOpened(currentProject));
 		}
 	}
 
-	@Override
-	public Project getCurrentProject() {
-		return currentProject;
-	}
+	public void startup(SessionDelegate delegate, PlayPadInitializer.Listener listener) {
+		PlayPadInitializer initializer = new PlayPadInitializer(this, listener);
 
-	void startup(ResourceBundle resourceBundle, SessionDelegate delegate) {
-		App app = ApplicationUtils.getApplication();
-		// Setup PlayoutLog
-		try {
-			Path playOutLogPath = app.getPath(PathType.DOCUMENTS, "logging.db");
-			LogSeasons.setStorageHandler(new SqlLiteLogSeasonStorageHandler(playOutLogPath));
-			Logger.info("Setup LogSeasonStorageHandler in path: " + playOutLogPath);
-		} catch (SQLException e) {
-			Logger.error("Cannot setup LogSeasonStorageHandler (" + e.getLocalizedMessage() + ")");
-		}
+		initializer.submit(new LocalizationLoadingTask());
+		initializer.submit(new GlobalSettingsLoadingTask());
+		initializer.submit(new KeyboardDefaultMappingTask());
 
-		modernDesign = new ModernDesignHandlerImpl();
+		initializer.submit(new ServiceInitializationTask());
 
-		// Register Update Service
-		Artifact playpadArtifact = app.getClasspathResource("build-app.json").deserialize(StorageTypes.JSON, Artifact.class);
-		Repository repository = app.getClasspathResource("repository.yml").deserialize(StorageTypes.YAML, Repository.class);
+		initializer.submit(new VersionizerSetupTask());
+		initializer.submit(new ComponentLoadingTask());
+		initializer.submit(new MidiActionsInitializerTask());
+		initializer.submit(new VolumeInitializerTask());
 
-		VersionizerItem versionizerItem = new VersionizerItem(repository, SystemUtils.getRunPath().toString());
-		updateService = UpdateService.startVersionizer(versionizerItem, UpdateService.Strategy.JAR, UpdateService.InteractionType.GUI);
-		updateService.addArtifact(playpadArtifact, SystemUtils.getRunPath());
-		updateService.setRepositoryType(globalSettings.getUpdateChannel());
+		initializer.submit(new ProfileLoadingTask());
 
-		registerComponents(resourceBundle);
-		configureServer(delegate);
-	}
+		initializer.submit(new ServerInitializeTask(delegate));
 
-	private void registerComponents(ResourceBundle resourceBundle) {
-		// Midi
-		DeviceRegistry.getFactoryInstance().registerDevice(PD12.NAME, PD12.class);
+		initializer.submit(new NativeAppInitializerTask());
+		initializer.submit(new PluginLoadingTask());
+		initializer.submit(new ProjectsLoadingTask());
+		initializer.submit(new KeyboardLoadingMappingTask());
 
-		try {
-			// Load Components
-			Registries registryCollection = PlayPadPlugin.getRegistries();
-
-			registryCollection.getActions().loadComponentsFromFile("components/Actions.xml", module, resourceBundle);
-			registryCollection.getAudioHandlers().loadComponentsFromFile("components/AudioHandler.xml", module, resourceBundle);
-			registryCollection.getDragModes().loadComponentsFromFile("components/DragMode.xml", module, resourceBundle);
-			registryCollection.getMappers().loadComponentsFromFile("components/Mapper.xml", module, resourceBundle);
-			registryCollection.getPadContents().loadComponentsFromFile("components/PadContent.xml", module, resourceBundle);
-			registryCollection.getTriggerItems().loadComponentsFromFile("components/Trigger.xml", module, resourceBundle);
-			registryCollection.getMainLayouts().loadComponentsFromFile("components/Layout.xml", module, resourceBundle);
-
-			// Set Default
-			// TODO Set Default
-			registryCollection.getAudioHandlers().setDefaultID(JavaFXHandlerFactory.class);
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
+		initializer.submit(new CheckUpdateTask());
 
-		// Volume Management
-		VolumeManager volumeManager = VolumeManager.getInstance();
-		volumeManager.addFilter(new GlobalVolume());
-		volumeManager.addFilter(new PadVolume());
+		initializer.submit(new OpenLastDocumentTask()); // abort if project is opened
+		initializer.submit(new ProjectParameterOpenTask()); // abort if project is opened
 
-		// Mapper
-		BaseMapperListViewController.setInstance(new MapperListViewControllerImpl());
+		initializer.start();
 	}
 
 	public Application.Parameters getParameters() {
 		return parameters;
 	}
 
-	private void configureServer(SessionDelegate delegate) {
-		// Load Server session key
-		session = Session.load();
+	public ModernDesignHandler getModernDesign() {
+		return modernDesign;
+	}
 
-		if (session == null) {
-			session = delegate.getSession();
-		}
+	void setModernDesign(ModernDesignHandler modernDesign) {
+		this.modernDesign = modernDesign;
+	}
 
-		if (session != Session.EMPTY) {
-			// Connect to Server
-			Server server = PlayPadPlugin.getServerHandler().getServer();
-			try {
-				server.connect(session.getKey());
-			} catch (IOException | WebSocketException e) {
-				Logger.error(e);
-			} catch (SessionNotExisitsException ignored) {
+	@Override
+	public UpdateService getUpdateService() {
+		return updateService;
+	}
 
-			}
-		}
+	/*
+	Getter / Setter
+	 */
+
+	@Override
+	public Project getCurrentProject() {
+		return currentProject;
 	}
 
-	public Session getSession() {
-		return session;
+	@Override
+	public Image getIcon() {
+		return stageIcon;
 	}
 
-	public ModernDesign getModernDesign() {
-		return modernDesign;
+	public void setIcon(Image icon) {
+		this.stageIcon = icon;
 	}
 
-	@Override
-	public UpdateService getUpdateService() {
-		return updateService;
+	public Module getModule() {
+		return module;
 	}
 
-	@Override
-	public ResourceBundle getUIResourceBundle() {
-		return PlayPadMain.getUiResourceBundle();
+	public void setGlobalSettings(GlobalSettings globalSettings) {
+		this.globalSettings = globalSettings;
+	}
+
+	public void setUpdateService(UpdateService updateService) {
+		this.updateService = updateService;
+	}
+
+	public Session getSession() {
+		return session;
+	}
+
+	public void setSession(Session session) {
+		this.session = session;
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/PlayPadLocalizationDelegate.java b/PlayWall/src/main/java/de/tobias/playpad/PlayPadLocalizationDelegate.java
new file mode 100644
index 0000000000000000000000000000000000000000..a30e062860f5617d297397d6106fe2ba38c6d48e
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/PlayPadLocalizationDelegate.java
@@ -0,0 +1,25 @@
+package de.tobias.playpad;
+
+import de.thecodelabs.utils.util.Localization;
+
+import java.util.Locale;
+
+public class PlayPadLocalizationDelegate implements Localization.LocalizationDelegate {
+	@Override
+	public String[] getBaseResources() {
+		return new String[]{
+				"lang/",
+				"lang/ui"
+		};
+	}
+
+	@Override
+	public boolean useMultipleResourceBundles() {
+		return true;
+	}
+
+	@Override
+	public Locale getLocale() {
+		return Locale.getDefault();
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/PlayPadMain.java b/PlayWall/src/main/java/de/tobias/playpad/PlayPadMain.java
index c61d5559d6145adc2e0e54e0a6c74e44004b39f5..47696ffe718bf872dd71584a00689ac476f8d041 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/PlayPadMain.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/PlayPadMain.java
@@ -3,270 +3,133 @@ package de.tobias.playpad;
 import de.thecodelabs.logger.FileOutputOption;
 import de.thecodelabs.logger.LogLevelFilter;
 import de.thecodelabs.logger.Logger;
+import de.thecodelabs.storage.proxy.SettingsProxy;
 import de.thecodelabs.storage.settings.UserDefaults;
 import de.thecodelabs.utils.application.App;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
-import de.thecodelabs.utils.application.system.NativeApplication;
-import de.thecodelabs.utils.threading.Worker;
 import de.thecodelabs.utils.ui.Alerts;
-import de.thecodelabs.utils.util.Localization;
-import de.thecodelabs.utils.util.Localization.LocalizationDelegate;
 import de.thecodelabs.utils.util.OS;
 import de.thecodelabs.utils.util.OS.OSType;
 import de.thecodelabs.utils.util.SystemUtils;
-import de.thecodelabs.versionizer.service.UpdateService;
+import de.tobias.playpad.design.ModernDesignHandlerImpl;
 import de.tobias.playpad.design.ModernStyleableImpl;
-import de.tobias.playpad.plugin.ModernPluginManager;
 import de.tobias.playpad.profile.ref.ProfileReferenceManager;
 import de.tobias.playpad.project.Project;
-import de.tobias.playpad.project.loader.ProjectLoader;
 import de.tobias.playpad.project.ref.ProjectReferenceManager;
-import de.tobias.playpad.server.ServerHandlerImpl;
-import de.tobias.playpad.server.sync.command.CommandExecutorHandlerImpl;
-import de.tobias.playpad.settings.GlobalSettings;
 import de.tobias.playpad.update.VersionUpdater;
 import de.tobias.playpad.util.UUIDSerializer;
-import de.tobias.playpad.viewcontroller.LaunchDialog;
-import de.tobias.playpad.viewcontroller.LoginViewController;
-import de.tobias.playpad.viewcontroller.dialog.AutoUpdateDialog;
+import de.tobias.playpad.viewcontroller.SplashScreenViewController;
 import io.github.openunirest.http.Unirest;
 import javafx.application.Application;
 import javafx.application.Platform;
-import javafx.scene.control.ButtonBar.ButtonData;
 import javafx.scene.image.Image;
 import javafx.stage.Stage;
-import javafx.stage.Window;
 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
 import org.apache.http.conn.ssl.SSLContexts;
 import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
-import org.dom4j.DocumentException;
 
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.security.cert.X509Certificate;
-import java.util.Locale;
-import java.util.Optional;
-import java.util.ResourceBundle;
 import java.util.UUID;
 
 /*
  * TODOS
  */
 // Idden
-// 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 {
+public class PlayPadMain extends Application {
 
-	private static final String iconPath = "icon_small.png";
-	public static Optional<Image> stageIcon = Optional.empty();
+	private static final String ICON_PATH = "icon_small.png";
 
-	public static final long displayTimeMillis = 1500;
+	public static final long NOTIFICATION_DISPLAY_TIME = 1500;
 
-	public static final String projectZIPType = "*.zip";
-	public static final String midiPresetType = "*.pre";
-
-	private static ResourceBundle uiResourceBundle;
+	public static final String ZIP_TYPE = "*.zip";
+	public static final String PRESET_TYPE = "*.pre";
 
 	private static PlayPadImpl impl;
-
-	public static ResourceBundle getUiResourceBundle() {
-		return uiResourceBundle;
-	}
-
 	public static SSLContext sslContext;
 
 	public static void main(String[] args) {
-		try {
-			// Verhindert einen Bug unter Windows 10 mit comboboxen
-			if (OS.getType() == OSType.Windows) {
-				System.setProperty("glass.accessible.force", "false");
-			}
+		// Verhindert einen Bug unter Windows 10 mit comboboxen
+		if (OS.getType() == OSType.Windows) {
+			System.setProperty("glass.accessible.force", "false");
+		}
 
-			// Register UserDefaults Serializer
-			UserDefaults.registerLoader(new UUIDSerializer(), UUID.class);
+		// Register UserDefaults Serializer
+		UserDefaults.registerLoader(new UUIDSerializer(), UUID.class);
 
-			App app = ApplicationUtils.registerMainApplication(PlayPadMain.class);
-			ApplicationUtils.registerUpdateSercive(new VersionUpdater());
+		ApplicationUtils.addAppListener(PlayPadMain::applicationWillStart);
+		App app = ApplicationUtils.registerMainApplication(PlayPadMain.class);
+		ApplicationUtils.registerUpdateSercive(new VersionUpdater());
 
-			Logger.init(app.getPath(PathType.LOG));
-			Logger.setLevelFilter(LogLevelFilter.DEBUG);
-			Logger.debug("Start JavaFX Application");
+		app.start(args);
+	}
 
-			app.start(args);
-		} catch (Exception e) {
-			e.printStackTrace();
+	private static void applicationWillStart(App app) {
+		Logger.init(app.getPath(PathType.LOG));
+		if (app.isDebug()) {
+			Logger.setLevelFilter(LogLevelFilter.DEBUG);
+			Logger.setFileOutput(FileOutputOption.DISABLED);
+			Logger.addFilter(message -> !message.getCaller().getClassName().contains("org.apache.commons.logging.impl.SLF4JLog"));
+		} else {
+			Logger.setFileOutput(FileOutputOption.COMBINED);
 		}
+		Logger.info("Logging initialized (Running in LogLevel: {0})", Logger.getLevelFilter().toString());
 	}
 
+
 	@Override
 	public void init() {
 		App app = ApplicationUtils.getApplication();
-
-		if (!app.isDebug()) {
-			Logger.setFileOutput(FileOutputOption.COMBINED);
-		}
+		Logger.info("Run Path: {0}", SystemUtils.getRunPath());
 
 		// Init SSLContext
 		if (app.isDebug()) {
 			disableSSL();
 		}
 
-		Logger.info("Run Path: {0}", SystemUtils.getRunPath());
-
-		// Localization
-		setupLocalization();
+		// Set Factory Implementations
+		impl = new PlayPadImpl(getParameters());
 
-		// Setup Global Settings
-		Logger.debug("Load global settings");
-		Path globalSettingsPath = app.getPath(PathType.CONFIGURATION, "GlobalSettings.xml");
-		GlobalSettings globalSettings = GlobalSettings.load(globalSettingsPath);
-		globalSettings.getKeyCollection().loadDefaultFromFile("components/Keys.xml", uiResourceBundle);
-		globalSettings.getKeyCollection().load(globalSettingsPath);
+		Image stageIcon = new Image(ICON_PATH);
+		Alerts.getInstance().setDefaultIcon(stageIcon);
+		impl.setIcon(stageIcon);
 
-		// Set Factory Implementations
-		impl = new PlayPadImpl(globalSettings, getParameters());
-		PlayPadPlugin.setInstance(impl);
 		PlayPadPlugin.setStyleable(new ModernStyleableImpl());
-		PlayPadPlugin.setRegistryCollection(new RegistryCollectionImpl());
-		PlayPadPlugin.setServerHandler(new ServerHandlerImpl());
-		PlayPadPlugin.setCommandExecutorHandler(new CommandExecutorHandlerImpl());
+		impl.setModernDesign(new ModernDesignHandlerImpl());
 
-		/*
-		 * Setup
-		 */
-
-		impl.startup(Localization.getBundle(), new LoginViewController());
+		PlayPadPlugin.setInstance(impl);
 	}
 
 	@Override
 	public void start(Stage stage) {
-		try {
-			// Assets
-			Image stageIcon = new Image(iconPath);
-			PlayPadMain.stageIcon = Optional.of(stageIcon);
-			Alerts.getInstance().setDefaultIcon(stageIcon);
-
-			// App Setup
-			NativeApplication.sharedInstance().setDockIcon(new Image("gfx/Logo-large.png"));
-			NativeApplication.sharedInstance().setAppearance(true);
-
-			try {
-				// Load Plugin Path
-				if (!getParameters().getRaw().contains("noplugins")) {
-					Path pluginFolder;
-					if (getParameters().getNamed().containsKey("plugin")) {
-						String pluginParam = getParameters().getNamed().get("plugin");
-						for (String part : pluginParam.split(":")) {
-							pluginFolder = Paths.get(part);
-							setupPlugins(pluginFolder);
-						}
-					} else {
-						pluginFolder = ApplicationUtils.getApplication().getPath(PathType.LIBRARY);
-						setupPlugins(pluginFolder);
-					}
-				}
-			} catch (Exception e) {
-				System.err.println("Cannot load plugins:");
-				e.printStackTrace();
-			}
-
-			/*
-			 * Load Data
-			 */
-			try {
-				ProfileReferenceManager.loadProfiles();
-				ProjectReferenceManager.loadProjects();
-			} catch (IOException | DocumentException e) {
-				e.printStackTrace();
-			}
-
-			if (PlayPadPlugin.getInstance().getGlobalSettings().isOpenLastDocument()) {
-				UUID value = (UUID) ApplicationUtils.getApplication().getUserDefaults().getData("project");
-				if (value != null) {
-					ProjectLoader loader = new ProjectLoader(ProjectReferenceManager.getProject(value));
-					// TODO Load indicator
-					Project project = loader.load();
-					impl.openProject(project, null);
-					return;
-				}
-			}
-
-			// Auto Open Project DEBUG
-			if (getParameters().getRaw().size() > 0) {
-				if (getParameters().getNamed().containsKey("project")) {
-					UUID uuid = UUID.fromString(getParameters().getNamed().get("project"));
-					ProjectLoader loader = new ProjectLoader(ProjectReferenceManager.getProject(uuid));
-					Project project = loader.load();
-					impl.openProject(project, null);
-					return;
-				}
-			}
-
-			// Show Launch Stage
-			new LaunchDialog(stage);
-
-			checkUpdates(impl.globalSettings, stage);
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
-	@SuppressWarnings("Duplicates")
-	private void checkUpdates(GlobalSettings globalSettings, Window owner) {
-		if (globalSettings.isAutoUpdate() && !globalSettings.isIgnoreUpdate()) {
-			Worker.runLater(() ->
-			{
-				UpdateService updateService = impl.getUpdateService();
-				updateService.fetchCurrentVersion();
-				if (updateService.isUpdateAvailable()) {
-					Platform.runLater(() ->
-					{
-						AutoUpdateDialog autoUpdateDialog = new AutoUpdateDialog(updateService, owner);
-						autoUpdateDialog.showAndWait().filter(item -> item.getButtonData() == ButtonData.APPLY).ifPresent(result ->
-						{
-							Logger.info("Install update");
-							try {
-								updateService.runVersionizerInstance(updateService.getAllLatestVersionEntries());
-							} catch (IOException e) {
-								e.printStackTrace();
-							}
-							System.exit(0);
-						});
-						if (autoUpdateDialog.isSelected()) {
-							globalSettings.setIgnoreUpdate(true);
-						}
-					});
-				}
-			});
-		}
+		SplashScreenViewController.show(impl, stage);
 	}
 
 	@Override
 	public void stop() {
 		try {
-			// Save last open project
+			// Save last opened project
 			Project project = impl.getCurrentProject();
 			if (project != null) {
-				ApplicationUtils.getApplication().getUserDefaults().setData("project", project.getProjectReference().getUuid());
+				ApplicationUtils.getApplication().getUserDefaults()
+						.setData("project", project.getProjectReference().getUuid());
 			}
 
-
 			ProfileReferenceManager.saveProfiles();
 			ProjectReferenceManager.saveProjects();
 			impl.getGlobalSettings().save();
+			SettingsProxy.saveAll();
 		} catch (Exception e) {
-			e.printStackTrace(); // Speichern Fehler
+			Logger.error(e);
 		}
 
 		impl.shutdown();
@@ -275,31 +138,6 @@ public class PlayPadMain extends Application implements LocalizationDelegate {
 		System.exit(0);
 	}
 
-	private void setupPlugins(Path pluginPath) throws IOException {
-		// Delete old plugins
-		ModernPluginManager.getInstance().deletePlugins();
-
-		// Load Plugins
-		ModernPluginManager.getInstance().loadFile(pluginPath);
-	}
-
-	private void setupLocalization() {
-		Localization.setDelegate(this);
-		Localization.load();
-
-		uiResourceBundle = Localization.loadBundle("lang/ui", getClass().getClassLoader());
-	}
-
-	@Override
-	public String getBaseResource() {
-		return "lang/";
-	}
-
-	@Override
-	public Locale getLocale() {
-		return Locale.getDefault();
-	}
-
 	/**
 	 * Gibt die Implementierung des Peers für Plugins zurück.
 	 *
@@ -338,7 +176,7 @@ public class PlayPadMain extends Application implements LocalizationDelegate {
 			CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
 			Unirest.setHttpClient(httpclient);
 		} catch (Exception e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 }
\ No newline at end of file
diff --git a/PlayWall/src/main/java/de/tobias/playpad/RegistryCollectionImpl.java b/PlayWall/src/main/java/de/tobias/playpad/RegistryCollectionImpl.java
index 283669c4d69433f36eb2ba8b4b7abeff41df3edf..d295bc188c5d73c3b030d43963c57f6d43da9343 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/RegistryCollectionImpl.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/RegistryCollectionImpl.java
@@ -1,7 +1,6 @@
 package de.tobias.playpad;
 
 import de.tobias.playpad.action.ActionProvider;
-import de.tobias.playpad.action.mapper.MapperFactory;
 import de.tobias.playpad.audio.AudioRegistry;
 import de.tobias.playpad.pad.content.PadContentRegistry;
 import de.tobias.playpad.pad.drag.PadDragMode;
@@ -17,7 +16,6 @@ public class RegistryCollectionImpl implements Registries {
 	private Registry<ActionProvider> actionRegistry;
 	private AudioRegistry audioHandlerRegistry;
 	private Registry<PadDragMode> dragModeRegistry;
-	private Registry<MapperFactory> mapperRegistry;
 	private PadContentRegistry padContentRegistry;
 	private Registry<TriggerItemFactory> triggerItemRegistry;
 	private DefaultRegistry<MainLayoutFactory> mainLayoutRegistry;
@@ -26,7 +24,6 @@ public class RegistryCollectionImpl implements Registries {
 		actionRegistry = new ComponentRegistry<>("Action");
 		audioHandlerRegistry = new AudioRegistry();
 		dragModeRegistry = new ComponentRegistry<>("DragMode");
-		mapperRegistry = new ComponentRegistry<>("Mapper");
 		padContentRegistry = new PadContentRegistry("PadContent");
 		triggerItemRegistry = new ComponentRegistry<>("Trigger");
 		mainLayoutRegistry = new DefaultComponentRegistry<>("MainLayout");
@@ -47,11 +44,6 @@ public class RegistryCollectionImpl implements Registries {
 		return dragModeRegistry;
 	}
 
-	@Override
-	public Registry<MapperFactory> getMappers() {
-		return mapperRegistry;
-	}
-
 	@Override
 	public PadContentRegistry getPadContents() {
 		return padContentRegistry;
diff --git a/PlayWall/src/main/java/de/tobias/playpad/Strings.java b/PlayWall/src/main/java/de/tobias/playpad/Strings.java
index 51456bd94b3575ecfe0804b4da1ca646b2dd3814..b0dd8185e643922d87e0a59c4be70b0778a2cbb8 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/Strings.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/Strings.java
@@ -2,284 +2,272 @@ package de.tobias.playpad;
 
 public class Strings {
 
+	private Strings() {
+	}
+
 	// Standard - File
-	public static final String Standard_File_Save = "Standard.File.Save";
-	public static final String Standard_Copy = "Standard.Copy";
-	public static final String Standard_Time_Seconds = "Standard.Time.Seconds";
-	public static final String Standard_Time_Volume = "Standard.Time.Volume";
+	public static final String STANDARD_FILE_SAVE = "Standard.File.Save";
+	public static final String STANDARD_COPY = "Standard.Copy";
+	public static final String STANDARD_TIME_SECONDS = "Standard.Time.Seconds";
+	public static final String STANDARD_TIME_VOLUME = "Standard.Time.Volume";
 
 	// File - Filter
-	public static final String File_Filter_ZIP = "File.Filter.ZIP";
-	public static final String File_Filter_Media = "File.Filter.Media";
-	public static final String File_Filter_Preset = "File.Filter.Preset";
+	public static final String FILE_FILTER_ZIP = "File.Filter.ZIP";
+	public static final String FILE_FILTER_MEDIA = "File.Filter.Media";
+	public static final String FILE_FILTER_PRESET = "File.Filter.Preset";
 
 	// Timemode - Enum
-	public static final String Pad_TimeMode_BaseName = "Pad.TimeMode.";
+	public static final String PAD_TIME_MODE = "Pad.TimeMode.";
 
 	// UI - Window - Titles
-	public static final String UI_Dialog_Launch_Title = "UI.Dialog.Launch.Title";
-	public static final String UI_Dialog_Login_Title = "UI.Dialog.Login.Title";
-	public static final String UI_Window_Main_Title = "UI.Window.Main.Title";
-	public static final String UI_Window_Settings_Title = "UI.Window.Settings.Title";
-	public static final String UI_Window_ProjectSettings_Title = "UI.Window.ProjectSettings.Title";
-	public static final String UI_Window_GlobalSettings_Title = "UI.Window.GlobalSettings.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_ProjectExport_Title = "UI.Dialog.ProjectExport.Title";
-	public static final String UI_Dialog_ProjectImport_Title = "UI.Dialog.ProjectImport.Title";
-	public static final String UI_Dialog_NotFound_Title = "UI.Dialog.NotFound.Title";
-	public static final String UI_Dialog_NewProfile_Title = "UI.Dialog.NewProfile.Title";
-	public static final String UI_Dialog_NewProject_Title = "UI.Dialog.NewProject.Title";
-	public static final String UI_Dialog_ChooseProfile_Title = "UI.Dialog.ChooseProfile.Title";
-	public static final String UI_Dialog_ProjectManager_Title = "UI.Dialog.ProjectManager.Title";
-	public static final String UI_Dialog_Plugins_Title = "UI.Dialog.Plugins.Title";
-	public static final String UI_Dialog_Print_Title = "UI.Dialog.Print.Title";
-	public static final String UI_Dialog_Profile_Title = "UI.Dialog.Profile.Title";
-	public static final String UI_Dialog_PlayoutLog_Title = "UI.Dialog.PlayoutLog.Title";
+	public static final String UI_DIALOG_LAUNCH_TITLE = "UI.Dialog.Launch.Title";
+	public static final String UI_DIALOG_LOGIN_TITLE = "UI.Dialog.Login.Title";
+	public static final String UI_WINDOW_MAIN_TITLE = "UI.Window.Main.Title";
+	public static final String UI_WINDOW_SETTINGS_TITLE = "UI.Window.Settings.Title";
+	public static final String UI_WINDOW_PROJECT_SETTINGS_TITLE = "UI.Window.ProjectSettings.Title";
+	public static final String UI_WINDOW_GLOBAL_SETTINGS_TITLE = "UI.Window.GlobalSettings.Title";
+	public static final String UI_WINDOW_PAD_SETTINGS_TITLE = "UI.Window.PadSettings.Title";
+	public static final String UI_WINDOW_PAD_SETTINGS_TITLE_EMPTY = "UI.Window.PadSettings.Title.Empty";
+	public static final String UI_DIALOG_PROJECT_EXPORT_TITLE = "UI.Dialog.ProjectExport.Title";
+	public static final String UI_DIALOG_PROJECT_IMPORT_TITLE = "UI.Dialog.ProjectImport.Title";
+	public static final String UI_DIALOG_NOT_FOUND_TITLE = "UI.Dialog.NotFound.Title";
+	public static final String UI_DIALOG_NEW_PROFILE_TITLE = "UI.Dialog.NewProfile.Title";
+	public static final String UI_DIALOG_NEW_PROJECT_TITLE = "UI.Dialog.NewProject.Title";
+	public static final String UI_DIALOG_CHOOSE_PROFILE_TITLE = "UI.Dialog.ChooseProfile.Title";
+	public static final String UI_DIALOG_PROJECT_MANAGER_TITLE = "UI.Dialog.ProjectManager.Title";
+	public static final String UI_DIALOG_PLUGINS_TITLE = "UI.Dialog.Plugins.Title";
+	public static final String UI_DIALOG_PRINT_TITLE = "UI.Dialog.Print.Title";
+	public static final String UI_DIALOG_PROFILE_TITLE = "UI.Dialog.Profile.Title";
 
 	// UI - Window - Main
-	public static final String UI_Window_Main_CloseRequest = "UI.Window.Main.CloseRequest";
-	public static final String UI_Window_Main_PageButton = "UI.Window.Main.PageButton";
+	public static final String UI_WINDOW_MAIN_CLOSE_REQUEST = "UI.Window.Main.CloseRequest";
+	public static final String UI_WINDOW_MAIN_PAGE_BUTTON = "UI.Window.Main.PageButton";
 
 	// UI - Dialog - Launch
-	public static final String UI_Dialog_Launch_Info = "UI.Dialog.Launch.Info";
+	public static final String UI_DIALOG_LAUNCH_INFO = "UI.Dialog.Launch.Info";
 
 	// UI - Dialog - ProjectLoad
-	public static final String UI_Dialog_ProjectLoad_StartProject = "UI.Dialof.ProjectLoad.StartProject";
-	public static final String UI_Dialog_ProjectLoad_StartPad = "UI.Dialof.ProjectLoad.StartPad";
+	public static final String UI_DIALOG_PROJECT_LOAD_START_PROJECT = "UI.Dialog.ProjectLoad.StartProject";
+	public static final String UI_DIALOG_PROJECT_LOAD_START_PAD = "UI.Dialog.ProjectLoad.StartPad";
 
 	// UI - Window - Settings
-	public static final String UI_Window_Settings_Gen_Title = "UI.Window.Settings.Gen.Title";
-	public static final String UI_Window_Settings_Gen_CacheSize = "UI.Window.Settings.Gen.CacheSize";
-	public static final String UI_Window_Settings_Gen_Wait = "UI.Window.Settings.Gen.Wait";
-	public static final String UI_Window_Settings_Mapping_Title = "UI.Window.Settings.Mapping.Title";
-	public static final String UI_Window_Settings_Midi_Title = "UI.Window.Settings.Midi.Title";
-	public static final String UI_Window_Settings_Layout_Title = "UI.Window.Settings.Layout.Title";
-	public static final String UI_Window_Settings_Player_Title = "UI.Window.Settings.Player.Title";
-	public static final String UI_Window_Settings_Audio_Title = "UI.Window.Settings.Audio.Title";
-	public static final String UI_Window_Settings_Updates_Title = "UI.Window.Settings.Updates.Title";
-	public static final String UI_Window_Settings_Keys_Title = "UI.Window.Settings.Keys.Title";
-	public static final String UI_Window_Settings_Paths_Title = "UI.Window.Settings.Paths.Title";
+	public static final String UI_WINDOW_SETTINGS_GEN_TITLE = "UI.Window.Settings.Gen.Title";
+	public static final String UI_WINDOW_SETTINGS_GEN_CACHE_SIZE = "UI.Window.Settings.Gen.CacheSize";
+	public static final String UI_WINDOW_SETTINGS_MAPPING_TITLE = "UI.Window.Settings.Mapping.Title";
+	public static final String UI_WINDOW_SETTINGS_LAYOUT_TITLE = "UI.Window.Settings.Layout.Title";
+	public static final String UI_WINDOW_SETTINGS_PLAYER_TITLE = "UI.Window.Settings.Player.Title";
+	public static final String UI_WINDOW_SETTINGS_AUDIO_TITLE = "UI.Window.Settings.Audio.Title";
+	public static final String UI_WINDOW_SETTINGS_UPDATES_TITLE = "UI.Window.Settings.Updates.Title";
+	public static final String UI_WINDOW_SETTINGS_KEYS_TITLE = "UI.Window.Settings.Keys.Title";
+	public static final String UI_WINDOW_SETTINGS_PATHS_TITLE = "UI.Window.Settings.Paths.Title";
 
 	// UI - Settings - Keys
-	public static final String UI_Settings_Keys_Conflict_Header = "UI.Settings.Keys.Conflict.Header";
-	public static final String UI_Settings_Keys_Conflict_Content = "UI.Settings.Keys.Conflict.Content";
+	public static final String UI_SETTINGS_KEYS_CONFLICT_HEADER = "UI.Settings.Keys.Conflict.Header";
+	public static final String UI_SETTINGS_KEYS_CONFLICT_CONTENT = "UI.Settings.Keys.Conflict.Content";
 
 	// UI - Dialog - NewProfile
-	public static final String UI_Dialog_NewProfile_Content = "UI.Dialog.NewProfile.Content";
+	public static final String UI_DIALOG_NEW_PROFILE_CONTENT = "UI.Dialog.NewProfile.Content";
 
 	// UI - Dialog - NewProject
-	public static final String UI_Dialog_NewProject_Content = "UI.Dialog.NewProject.Content"; // Duplicate Project
-	public static final String UI_Dialog_NewProject_Media = "UI.Dialog.NewProject.MediaPath"; // Create Project
+	public static final String UI_DIALOG_NEW_PROJECT_CONTENT = "UI.Dialog.NewProject.Content"; // Duplicate Project
+	public static final String UI_DIALOG_NEW_PROJECT_MEDIA_PATH = "UI.Dialog.NewProject.MediaPath"; // Create Project
 
 
 	// UI - Dialog - ProjectManager
-	public static final String UI_Dialog_ProjectManager_Delete_Header = "UI.Dialog.ProjectManager.Delete.Header";
-	public static final String UI_Dialog_ProjectManager_Delete_Content = "UI.Dialog.ProjectManager.Delete.Content";
+	public static final String UI_DIALOG_PROJECT_MANAGER_DELETE_HEADER = "UI.Dialog.ProjectManager.Delete.Header";
+	public static final String UI_DIALOG_PROJECT_MANAGER_DELETE_CONTENT = "UI.Dialog.ProjectManager.Delete.Content";
 
 	// UI - Dialog - Project Convert
-	public static final String UI_Dialog_Project_Convert_Header = "UI.Dialog.Project.Convert.Header";
-	public static final String UI_Dialog_Project_Convert_Content = "UI.Dialog.Project.Convert.Content";
+	public static final String UI_DIALOG_PROJECT_CONVERT_HEADER = "UI.Dialog.Project.Convert.Header";
+	public static final String UI_DIALOG_PROJECT_CONVERT_CONTENT = "UI.Dialog.Project.Convert.Content";
 
 	// UI - Dialog - Profile
-	public static final String UI_Dialog_Profile_Delete_Content = "UI.Dialog.Profile.Delete.Content";
+	public static final String UI_DIALOG_PROFILE_DELETE_CONTENT = "UI.Dialog.Profile.Delete.Content";
 
 	// UI - Dialog - About
-	public static final String UI_Dialog_About_Graphics = "UI.Dialog.About.Graphics";
-	public static final String UI_Dialog_About_Libraries = "UI.Dialog.About.Libraries";
-	public static final String UI_Dialog_About_Website = "UI.Dialog.About.Website";
-	public static final String UI_Dialog_About_Code = "UI.Dialog.About.Code";
-
-	// UI - Dialog - Feedback
-	public static final String UI_Dialog_Feedback_Content = "UI.Dialog.Feedback.Content";
+	public static final String UI_DIALOG_ABOUT_GRAPHICS = "UI.Dialog.About.Graphics";
+	public static final String UI_DIALOG_ABOUT_LIBRARIES = "UI.Dialog.About.Libraries";
+	public static final String UI_DIALOG_ABOUT_WEBSITE = "UI.Dialog.About.Website";
+	public static final String UI_DIALOG_ABOUT_CODE = "UI.Dialog.About.Code";
 
 	// UI - Placeholder
-	public static final String UI_Placeholder_Project = "UI.Placeholder.Project";
-	public static final String UI_Placeholder_Preset = "UI.Placeholder.Preset";
-	public static final String UI_Placeholder_Plugins = "UI.Placeholder.Plugins";
-	public static final String UI_Placeholder_Updates = "UI.Placeholder.Updates";
+	public static final String UI_PLACEHOLDER_PROJECT = "UI.Placeholder.Project";
+	public static final String UI_PLACEHOLDER_PRESET = "UI.Placeholder.Preset";
+	public static final String UI_PLACEHOLDER_PLUGINS = "UI.Placeholder.Plugins";
+	public static final String UI_PLACEHOLDER_UPDATES = "UI.Placeholder.Updates";
 
 	// Info - MIDI
-	public static final String Info_Midi_Device_Connected = "Info.Midi.Device.Connected";
+	public static final String INFO_MIDI_DEVICE_CONNECTED = "Info.Midi.Device.Connected";
 
 	// Info - Settings
-	public static final String Info_Settings_ResetWarning = "Info.Settings.ResetWarning";
-	public static final String Info_Settings_CacheDelete = "Info.Settings.CacheDelete";
+	public static final String INFO_SETTINGS_RESET_WARNING = "Info.Settings.ResetWarning";
+	public static final String INFO_SETTINGS_CACHE_DELETE = "Info.Settings.CacheDelete";
 
 	// Info - Print
-	public static final String Info_Print_Header = "Info.Print.Header";
+	public static final String INFO_PRINT_HEADER = "Info.Print.Header";
 
 	// Error - Standard
-	public static final String Error_Standard_Gen = "Error.Standard.Gen";
-	public static final String Error_Standard_NameInUse = "Error.Standard.NameInUse";
+	public static final String ERROR_STANDARD_GEN = "Error.Standard.Gen";
+	public static final String ERROR_STANDARD_NAME_IN_USE = "Error.Standard.NameInUse";
 
 	// Error - Settings
-	public static final String Error_Settings_CacheSize = "Error.Settings.CacheSize";
-	public static final String Error_Settings_CacheClear = "Error.Settings.CacheClear";
+	public static final String ERROR_SETTINGS_CACHE_SIZE = "Error.Settings.CacheSize";
+	public static final String ERROR_SETTINGS_CACHE_CLEAR = "Error.Settings.CacheClear";
 
 	// Error - Profile
-	public static final String Error_Profile_Create = "Error.Profile.Create";
-	public static final String Error_Profile_NotFound = "Error.Profile.NotFound";
-	public static final String Error_Profile_Save = "Error.Profile.Save";
-	public static final String Error_Profile_Delete = "Error.Profile.Delete";
+	public static final String ERROR_PROFILE_CREATE = "Error.Profile.Create";
+	public static final String ERROR_PROFILE_NOT_FOUND = "Error.Profile.NotFound";
+	public static final String ERROR_PROFILE_SAVE = "Error.Profile.Save";
+	public static final String ERROR_PROFILE_DELETE = "Error.Profile.Delete";
 
 	// Error - Preset
-	public static final String Error_Preset_Import = "Error.Preset.Import";
-	public static final String Error_Preset_Export = "Error.Preset.Export";
+	public static final String ERROR_PRESET_IMPORT = "Error.Preset.Import";
+	public static final String ERROR_PRESET_EXPORT = "Error.Preset.Export";
 
 	// Error - Project
-	public static final String Error_Project_Create = "Error.Project.Create";
-	public static final String Error_Project_Convert = "Error.Project.Convert";
-	public static final String Error_Project_NotFound = "Error.Project.NotFound";
-	public static final String Error_Project_Open = "Error.Project.Open";
-	public static final String Error_Project_Save = "Error.Project.Save";
-	public static final String Error_Project_Rename = "Error.Project.Rename";
-	public static final String Error_Project_Delete = "Error.Project.Delete";
-	public static final String Error_Project_Export = "Error.Project.Export";
-	public static final String Error_Project_Import = "Error.Project.Import";
-	public static final String Error_Project_MediaPath = "Error.Project.MediaPath";
-	public static final String Error_Project_PageCount = "Error.Project.PageCount";
-	public static final String Error_Project_Sync_Change = "Error.Project.Sync.Change";
+	public static final String ERROR_PROJECT_CREATE = "Error.Project.Create";
+	public static final String ERROR_PROJECT_CONVERT = "Error.Project.Convert";
+	public static final String ERROR_PROJECT_NOT_FOUND = "Error.Project.NotFound";
+	public static final String ERROR_PROJECT_OPEN = "Error.Project.Open";
+	public static final String ERROR_PROJECT_SAVE = "Error.Project.Save";
+	public static final String ERROR_PROJECT_RENAME = "Error.Project.Rename";
+	public static final String ERROR_PROJECT_DELETE = "Error.Project.Delete";
+	public static final String ERROR_PROJECT_EXPORT = "Error.Project.Export";
+	public static final String ERROR_PROJECT_IMPORT = "Error.Project.Import";
+	public static final String ERROR_PROJECT_MEDIA_PATH = "Error.Project.MediaPath";
+	public static final String ERROR_PROJECT_PAGE_COUNT = "Error.Project.PageCount";
+	public static final String ERROR_PROJECT_SYNC_CHANGE = "Error.Project.Sync.Change";
 
 	// Error - Pad
-	public static final String Error_Pad_BaseName = "Error.Pad.";
+	public static final String ERROR_PAD = "Error.Pad.";
 
 	// Error - Midi
-	public static final String Error_Midi_Settings_Unkown = "Error.Midi.Settings.Unknown";
-	public static final String Error_Midi_Device_Busy = "Error.Midi.Device.Busy";
-	public static final String Error_Midi_Device_Unavailible = "Error.Midi.Device.Unavailable";
-	public static final String Error_Midi_Record_Fail = "Error.Midi.Record.Fail";
-	public static final String Error_Midi_Send = "Error.Midi.Send";
+	public static final String ERROR_MIDI_SETTINGS_UNKNOWN = "Error.Midi.Settings.Unknown";
+	public static final String ERROR_MIDI_DEVICE_BUSY = "Error.Midi.Device.Busy";
+	public static final String ERROR_MIDI_DEVICE_UNAVAILABLE = "Error.Midi.Device.Unavailable";
+	public static final String ERROR_MIDI_RECORD_FAIL = "Error.Midi.Record.Fail";
+	public static final String ERROR_MIDI_SEND = "Error.Midi.Send";
 
 	// Error - Plugins
-	public static final String Error_Plugins_Missing = "Error.Plugins.Missing";
+	public static final String ERROR_PLUGINS_HEADER = "Error.Plugins.Header";
+	public static final String ERROR_PLUGINS_MISSING = "Error.Plugins.Missing";
+	public static final String ERROR_PLUGINS_LOADING = "Error.Plugins.Loading";
+	public static final String ERROR_PLUGINS_INSTALL = "Error.Plugins.Install";
 
 	// Error - Screen
-	public static final String Error_Screen_TooMuch = "Error.Screen.TooMuch";
-	public static final String Error_Screen_TooLess = "Error.Screen.TooLess";
+	public static final String ERROR_SCREEN_TOO_MUCH = "Error.Screen.TooMuch";
+	public static final String ERROR_SCREEN_TOO_LESS = "Error.Screen.TooLess";
 
 	// Mapper
-	public static final String Mapper_Keyboard_Name = "Mapper.Keyboard.Name";
-	public static final String Mapper_Midi_Name = "Mapper.Midi.Name";
-	public static final String Mapper_Keyboard_toString = "Mapper.Keyboard.toString";
-	public static final String Mapper_Midi_toString = "Mapper.Midi.toString";
+	public static final String MAPPER_KEYBOARD_NAME = "Mapper.Keyboard.Name";
+	public static final String MAPPER_MIDI_NAME = "Mapper.Midi.Name";
+	public static final String MAPPER_KEYBOARD_TO_STRING = "Mapper.Keyboard.toString";
+	public static final String MAPPER_MIDI_TO_STRING = "Mapper.Midi.toString";
 
 	// Info - Mapper
-	public static final String Info_Mapper_PressKey = "Info.Mapper.PressKey";
+	public static final String INFO_MAPPER_PRESS_KEY = "Info.Mapper.PressKey";
 
-	// UI - Settings - Aler
+	// UI - Settings - Alert
 
-	public static final String UI_Settings_Alert_NewKeyShortcut_Text = "UI.Settings.Alert.NewKeyShortcut.Text";
+	public static final String UI_SETTINGS_ALERT_NEW_KEY_SHORTCUT_TEXT = "UI.Settings.Alert.NewKeyShortcut.Text";
 
 	// UI - Window - PadSettings
-	public static final String UI_Window_PadSettings_General_Title = "UI.Window.PadSettings.General.Title";
-	public static final String UI_Window_PadSettings_Player_Title = "UI.Window.PadSettings.Player.Title";
-	public static final String UI_Window_PadSettings_Layout_Title = "UI.Window.PadSettings.Layout.Title";
-	public static final String UI_Window_PadSettings_Trigger_Title = "UI.Window.PadSettings.Trigger.Title";
+	public static final String UI_WINDOW_PAD_SETTINGS_GENERAL_TITLE = "UI.Window.PadSettings.General.Title";
+	public static final String UI_WINDOW_PAD_SETTINGS_PLAYER_TITLE = "UI.Window.PadSettings.Player.Title";
+	public static final String UI_WINDOW_PAD_SETTINGS_LAYOUT_TITLE = "UI.Window.PadSettings.Layout.Title";
+	public static final String UI_WINDOW_PAD_SETTINGS_TRIGGER_TITLE = "UI.Window.PadSettings.Trigger.Title";
 
 	// Actions
-	public static final String Action_Cart_toString = "Action.Cart.toString";
-	public static final String Action_Page_toString = "Action.Page.toString";
-	public static final String Action_Navigate_toString = "Action.Navigate.toString";
-	public static final String Action_Cart_Name = "Action.Cart.Name";
-	public static final String Action_Stop_Name = "Action.Stop.Name";
-	public static final String Action_Page_Name = "Action.Page.Name";
-	public static final String Action_Navigate_Name = "Action.Navigate.Name";
+	public static final String ACTION_CART_TO_STRING = "Action.Cart.toString";
+	public static final String ACTION_PAGE_TO_STRING = "Action.Page.toString";
+	public static final String ACTION_NAVIGATE_TO_STRING = "Action.Navigate.toString";
+	public static final String ACTION_CART_NAME = "Action.Cart.Name";
+	public static final String ACTION_STOP_NAME = "Action.Stop.Name";
+	public static final String ACTION_PAGE_NAME = "Action.Page.Name";
+	public static final String ACTION_NAVIGATE_NAME = "Action.Navigate.Name";
 
 	// Content
-	public static final String Content_Empty = "Content.Empty";
-	public static final String Content_Audio_Name = "Content.Audio.Name";
+	public static final String CONTENT_EMPTY = "Content.Empty";
+	public static final String CONTENT_AUDIO_NAME = "Content.Audio.Name";
 
 	// NavigationType - Enum
-	public static final String NavigationType_BaseName = "NavigationType.";
+	public static final String NAVIGATION_TYPE = "NavigationType.";
 
 	// CartActionMode - Enum
-	public static final String CartAction_Mode_BaseName = "CartAction.Mode.";
+	public static final String CART_ACTION_MODE = "CartAction.Mode.";
 
 	// UI - Dialog - AutoUpdate
-	public static final String UI_Dialog_AutoUpdate_Header = "UI.Dialog.AutoUpdate.Header";
-	public static final String UI_Dialog_AutoUpdate_Content = "UI.Dialog.AutoUpdate.Content";
-	public static final String UI_Dialog_AutoUpdate_Checkbox = "UI.Dialog.AutoUpdate.Checkbox";
-	public static final String UI_Dialog_AutoUpdate_Title = "UI.Dialog.AutoUpdate.Title";
-	public static final String UI_Dialog_AutoUpdate_Button_Update = "UI.Dialog.AutoUpdate.Button.Update";
-	public static final String UI_Dialog_AutoUpdate_Button_Cancel = "UI.Dialog.AutoUpdate.Button.Cancel";
+	public static final String UI_DIALOG_AUTO_UPDATE_HEADER = "UI.Dialog.AutoUpdate.Header";
+	public static final String UI_DIALOG_AUTO_UPDATE_CONTENT = "UI.Dialog.AutoUpdate.Content";
+	public static final String UI_DIALOG_AUTO_UPDATE_CHECKBOX = "UI.Dialog.AutoUpdate.Checkbox";
+	public static final String UI_DIALOG_AUTO_UPDATE_TITLE = "UI.Dialog.AutoUpdate.Title";
+	public static final String UI_DIALOG_AUTO_UPDATE_BUTTON_UPDATE = "UI.Dialog.AutoUpdate.Button.Update";
+	public static final String UI_DIALOG_AUTO_UPDATE_BUTTON_CANCEL = "UI.Dialog.AutoUpdate.Button.Cancel";
 
 	// UI - Dialog - Save
-	public static final String UI_Dialog_Save_Header = "UI.Dialog.Save.Header";
-	public static final String UI_Dialog_Save_Content = "UI.Dialog.Save.Content";
-	public static final String UI_Dialog_Save_Checkbox = "UI.Dialog.Save.Checkbox";
-	public static final String UI_Dialog_Save_Title = "UI.Dialog.Save.Title";
-	public static final String UI_Dialog_Save_Button_Yes = "UI.Dialog.Save.Button.Yes";
-	public static final String UI_Dialog_Save_Button_No = "UI.Dialog.Save.Button.No";
-	public static final String UI_Dialog_Save_Button_Cancel = "UI.Dialog.Save.Button.Cancel";
+	public static final String UI_DIALOG_SAVE_HEADER = "UI.Dialog.Save.Header";
+	public static final String UI_DIALOG_SAVE_CONTENT = "UI.Dialog.Save.Content";
+	public static final String UI_DIALOG_SAVE_CHECKBOX = "UI.Dialog.Save.Checkbox";
+	public static final String UI_DIALOG_SAVE_TITLE = "UI.Dialog.Save.Title";
+	public static final String UI_DIALOG_SAVE_BUTTON_YES = "UI.Dialog.Save.Button.Yes";
+	public static final String UI_DIALOG_SAVE_BUTTON_NO = "UI.Dialog.Save.Button.No";
+	public static final String UI_DIALOG_SAVE_BUTTON_CANCEL = "UI.Dialog.Save.Button.Cancel";
 
 	// Update Channel - Basename
-	public static final String Update_Channel_BaseName = "UpdateChannel.";
+	public static final String UPDATE_CHANNEL = "UpdateChannel.";
 
 	// Error - Layout
-	public static final String Error_Layout_Load = "Error.Layout.Load";
+	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_Dialog_Update_Info = "UI.Dialog.Update.Info";
-	public static final String UI_Window_Settings_Updates_CurrentVersion = "UI.Window.Settings.Updates.CurrentVersion";
-
-	// Layout
-	public static final String Layout_Modern_Name = "Layout.Modern.Name";
-	public static final String Layout_Classic_Name = "Layout.Classic.Name";
+	public static final String UI_DIALOG_UPDATE_CELL = "UI.Dialog.Update.Cell";
+	public static final String UI_DIALOG_UPDATE_INFO = "UI.Dialog.Update.Info";
+	public static final String UI_WINDOW_SETTINGS_UPDATES_CURRENT_VERSION = "UI.Window.Settings.Updates.CurrentVersion";
 
 	// Trigger
-	public static final String TriggerPoint_toString = "TriggerPoint.toString";
-	public static final String Trigger_Cart_Name = "Trigger.Cart.Name";
-	public static final String Trigger_Volume_Name = "Trigger.Volume.Name";
+	public static final String TRIGGER_POINT_TO_STRING = "TriggerPoint.toString";
+	public static final String TRIGGER_CART_NAME = "Trigger.Cart.Name";
+	public static final String TRIGGER_VOLUME_NAME = "Trigger.Volume.Name";
 
 	// 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_Duplicate = "DnDMode.Duplicate";
-	public static final String DnDMode_Replace = "DnDMode.Replace";
+	public static final String TRIGGER_POINT = "TriggerPoint.";
 
 	// Main Layout
-	public static final String MainLayout_Desktop = "MainLayout.Desktop";
-	public static final String MainLayout_Touch = "MainLayout.Touch";
+	public static final String MAIN_LAYOUT_DESKTOP = "MainLayout.Desktop";
+	public static final String MAIN_LAYOUT_TOUCH = "MainLayout.Touch";
 
 	// Search
-	public static final String Search_Button = "Search.Button";
-	public static final String Search_Placeholder = "Search.Placeholder";
-	public static final String Search_Alert_NoMatches = "Search.Alert.NoMatches";
+	public static final String SEARCH_BUTTON = "Search.Button";
+	public static final String SEARCH_PLACEHOLDER = "Search.Placeholder";
+	public static final String SEARCH_ALERT_NO_MATCHES_HEADER = "Search.Alert.NoMatches.Header";
+	public static final String SEARCH_ALERT_NO_MATCHES_CONTENT = "Search.Alert.NoMatches.Content";
 
 	// UI - Dialog - Page - Delete
-	public static final String UI_Dialog_Page_Delete_Header = "UI.Dialog.Page.Delete.Header";
-	public static final String UI_Dialog_Page_Delete_Content = "UI.Dialog.Page.Delete.Content";
+	public static final String UI_DIALOG_PAGE_DELETE_HEADER = "UI.Dialog.Page.Delete.Header";
+	public static final String UI_DIALOG_PAGE_DELETE_CONTENT = "UI.Dialog.Page.Delete.Content";
 
 	// UI - Dialog - Page - Name
-	public static final String UI_Dialog_Page_Name_Header = "UI.Dialog.Page.Name.Header";
-	public static final String UI_Dialog_Page_Name_Content = "UI.Dialog.Page.Name.Content";
+	public static final String UI_DIALOG_PAGE_NAME_HEADER = "UI.Dialog.Page.Name.Header";
+	public static final String UI_DIALOG_PAGE_NAME_CONTENT = "UI.Dialog.Page.Name.Content";
 
 	// UI - Dialog - PathMatch
-	public static final String UI_Dialog_PathMatch_Status = "UI.Dialog.PathMatch.Status";
+	public static final String UI_DIALOG_PATH_MATCH_STATUS = "UI.Dialog.PathMatch.Status";
 
 	// Tooltip
-	public static final String Tooltip_PlayButton = "Tooltip.PlayButton";
-	public static final String Tooltip_DragButton = "Tooltip.DragButton";
-	public static final String Tooltip_PageButton = "Tooltip.PageButton";
-	public static final String Tooltip_ColorButton = "Tooltip.ColorButton";
-
-	public static final String Tooltip_Page_LeftMove = "Tooltip.Page.LeftMove";
-	public static final String Tooltip_Page_RightMove = "Tooltip.Page.RightMove";
-	public static final String Tooltip_Page_Rename = "Tooltip.Page.Rename";
-	public static final String Tooltip_Page_Clone = "Tooltip.Page.Clone";
-	public static final String Tooltip_Page_Delete = "Tooltip.Page.Delete";
+	public static final String TOOLTIP_PLAY_BUTTON = "Tooltip.PlayButton";
+	public static final String TOOLTIP_DRAG_BUTTON = "Tooltip.DragButton";
+	public static final String TOOLTIP_PAGE_BUTTON = "Tooltip.PageButton";
+	public static final String TOOLTIP_COLOR_BUTTON = "Tooltip.ColorButton";
 
-	// AudioHandler
-	public static final String AudioHandler_JavaFX = "AudioHandler.JavaFX";
-	public static final String AudioHandler_TinySound = "AudioHandler.TinySound";
+	public static final String TOOLTIP_PAGE_LEFT_MOVE = "Tooltip.Page.LeftMove";
+	public static final String TOOLTIP_PAGE_RIGHT_MOVE = "Tooltip.Page.RightMove";
+	public static final String TOOLTIP_PAGE_RENAME = "Tooltip.Page.Rename";
+	public static final String TOOLTIP_PAGE_CLONE = "Tooltip.Page.Clone";
+	public static final String TOOLTIP_PAGE_DELETE = "Tooltip.Page.Delete";
 
 	// Server
-	public static final String Server_Connected = "Server.Connected";
-	public static final String Server_Connection_Lost = "Server.Connection_Lost";
-	public static final String Server_Disconnected = "Server.Disconnected";
-	public static final String Auth_Logout = "Auth.Logout";
+	public static final String SERVER_CONNECTED = "Server.Connected";
+	public static final String SERVER_CONNECTION_LOST = "Server.Connection_Lost";
+	public static final String SERVER_DISCONNECTED = "Server.Disconnected";
+	public static final String AUTH_LOGOUT = "Auth.Logout";
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/MappingUtils.java b/PlayWall/src/main/java/de/tobias/playpad/action/MappingUtils.java
deleted file mode 100644
index 5d3393884f10b12aa72f2c4818cb7d8f2e1e60a4..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/MappingUtils.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package de.tobias.playpad.action;
-
-import de.tobias.playpad.action.mapper.KeyboardMapper;
-import de.tobias.playpad.action.mapper.Mapper;
-import de.tobias.playpad.action.mapper.MidiMapper;
-import javafx.scene.input.KeyCode;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class MappingUtils {
-
-	public static List<Action> getActionsForKey(KeyCode code, Mapping mapping) {
-		List<Action> actions = new ArrayList<>();
-		for (Action action : mapping.keySet()) {
-			for (Mapper mapper : mapping.get(action)) {
-				if (mapper instanceof KeyboardMapper) {
-					KeyboardMapper keyMapper = (KeyboardMapper) mapper;
-					if (keyMapper.getCode() == code) {
-						actions.add(action);
-					}
-				}
-			}
-		}
-		return actions;
-	}
-
-	public static List<Action> getActionsForMidi(int cmd, int key, Mapping mapping) {
-		List<Action> actions = new ArrayList<>();
-		for (Action action : mapping.keySet()) {
-			for (Mapper mapper : mapping.get(action)) {
-				if (mapper instanceof MidiMapper) {
-					MidiMapper midiMapper = (MidiMapper) mapper;
-					if (midiMapper.getCommand() == cmd && midiMapper.getKey() == key) {
-						actions.add(action);
-					}
-				}
-			}
-		}
-		return actions;
-	}
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/actions/CartAction.java b/PlayWall/src/main/java/de/tobias/playpad/action/actions/CartAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..276ad3ff80d19b38e4b8058db375bc66376dec39
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/actions/CartAction.java
@@ -0,0 +1,200 @@
+package de.tobias.playpad.action.actions;
+
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.event.KeyEvent;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.mapping.MidiKey;
+import de.thecodelabs.midi.midi.Midi;
+import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.action.actions.cart.handler.CartActionHandlerFactory;
+import de.tobias.playpad.action.feedback.ActionFeedbackSuggester;
+import de.tobias.playpad.action.feedback.ColorAdjuster;
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadSettings;
+import de.tobias.playpad.pad.content.play.Durationable;
+import de.tobias.playpad.project.Project;
+import de.tobias.playpad.project.page.PageCoordinate;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+import javafx.util.Duration;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+public class CartAction extends ActionHandler implements ActionFeedbackSuggester {
+
+	public static final String TYPE = "CartAction";
+	public static final String PAYLOAD_X = "x";
+	public static final String PAYLOAD_Y = "y";
+	public static final String PAYLOAD_MODE = "mode";
+	public static final String PAYLOAD_AUTO_FEEDBACK = "autoFeedback";
+
+	public enum CartActionMode {
+		PLAY_PAUSE,
+		PLAY_STOP,
+		PLAY_HOLD,
+		PLAY_PLAY;
+
+		public static CartActionMode valueOf(Action action) {
+			return valueOf(action.getPayload(PAYLOAD_MODE));
+		}
+	}
+
+	@Override
+	public String actionType() {
+		return TYPE;
+	}
+
+	@Override
+	public FeedbackType handle(KeyEvent keyEvent, Action action) {
+		Pad pad = getPad(action);
+		CartActionMode mode = getMode(action);
+
+		if (pad == null) {
+			return FeedbackType.NONE;
+		}
+
+		if (pad.hasVisibleContent()) {
+			CartActionHandlerFactory.getInstance(mode).performAction(keyEvent.getKeyEventType(), this, pad);
+		}
+		return getCurrentFeedbackType(action);
+	}
+
+	@SuppressWarnings("DuplicateBranchesInSwitch")
+	@Override
+	public FeedbackType getCurrentFeedbackType(Action action) {
+		Project project = PlayPadPlugin.getInstance().getCurrentProject();
+		IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController();
+
+		Pad pad = project.getPad(getX(action), getY(action), mainViewController.getPage());
+
+		if (pad == null) {
+			return FeedbackType.NONE;
+		}
+
+		switch (pad.getStatus()) {
+			case EMPTY:
+			case ERROR:
+				return FeedbackType.NONE;
+			case PLAY:
+				if (isWarningState(pad)) {
+					return FeedbackType.WARNING;
+				}
+				return FeedbackType.EVENT;
+			case PAUSE:
+			case READY:
+			case STOP:
+				return FeedbackType.DEFAULT;
+			default:
+				return FeedbackType.NONE;
+		}
+	}
+
+	private boolean isWarningState(Pad pad) {
+		if (pad.getContent() instanceof Durationable) {
+			Durationable durationable = (Durationable) pad.getContent();
+			PadSettings padSettings = pad.getPadSettings();
+
+			if (!padSettings.isLoop()) {
+				Duration warning = padSettings.getWarning();
+				Duration rest = durationable.getRemaining(padSettings);
+				if (rest != null) {
+					double seconds = rest.toSeconds();
+					return warning.toSeconds() > seconds;
+				}
+			}
+		}
+		return false;
+	}
+
+	public static void refreshFeedback(Pad pad) {
+		final Mapping mapping = Mapping.getCurrentMapping();
+		final PageCoordinate coordinate = pad.getPageCoordinate();
+
+		Map<String, String> payload = new HashMap<>();
+		payload.put(CartAction.PAYLOAD_X, String.valueOf(coordinate.getX()));
+		payload.put(CartAction.PAYLOAD_Y, String.valueOf(coordinate.getY()));
+
+		final Optional<Action> action = mapping.getActionForTypeWithPayload(CartAction.TYPE, payload);
+		action.ifPresent(value -> Midi.getInstance().showFeedback(value));
+	}
+
+	/*
+	Color Adjustable
+	 */
+
+	@Override
+	public boolean isAutoFeedbackColors(Action action) {
+		return isAutoFeedback(action);
+	}
+
+	@Override
+	public void suggestFeedback(Action action) {
+		for (MidiKey midiKey : action.getKeysForType(MidiKey.class)) {
+			ColorAdjuster.setSuggestedFeedbackColors(this, action, midiKey);
+		}
+	}
+
+	@Override
+	public byte suggestFeedbackChannel(FeedbackType type) {
+		switch (type) {
+			case DEFAULT:
+				return 0;
+			case EVENT:
+				return 2;
+			case WARNING:
+				return 1;
+			default:
+				throw new UnsupportedOperationException("No suggested channel supported for the feedback type: " + type);
+		}
+	}
+
+	@Override
+	public Pad getPad(Action action) {
+		Project project = PlayPadPlugin.getInstance().getCurrentProject();
+		IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController();
+
+		int x = getX(action);
+		int y = getY(action);
+		final int page = mainViewController.getPage();
+
+		return project.getPad(x, y, page);
+	}
+
+	/*
+
+	 */
+	public static CartActionMode getMode(Action action) {
+		return CartActionMode.valueOf(action);
+	}
+
+	public static int getY(Action action) {
+		return Integer.parseInt(action.getPayload(PAYLOAD_Y));
+	}
+
+	public static int getX(Action action) {
+		return Integer.parseInt(action.getPayload(PAYLOAD_X));
+	}
+
+	public static boolean isAutoFeedback(Action action) {
+		return Boolean.parseBoolean(action.getPayload(PAYLOAD_AUTO_FEEDBACK));
+	}
+
+	public static void setMode(Action action, CartActionMode mode) {
+		action.addPayloadEntry(CartAction.PAYLOAD_MODE, mode.name());
+	}
+
+	public static void setX(Action action, int x) {
+		action.addPayloadEntry(CartAction.PAYLOAD_X, String.valueOf(x));
+	}
+
+	public static void setY(Action action, int y) {
+		action.addPayloadEntry(CartAction.PAYLOAD_Y, String.valueOf(y));
+	}
+
+	public static void setAutoFeedback(Action action, boolean enable) {
+		action.addPayloadEntry(CartAction.PAYLOAD_AUTO_FEEDBACK, String.valueOf(enable));
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/actions/NavigateAction.java b/PlayWall/src/main/java/de/tobias/playpad/action/actions/NavigateAction.java
index b9ec12d43502e991608bc90652217baa7bc77adc..33e833f7a3f64d502858d3db8bb45777e9904910 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/action/actions/NavigateAction.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/actions/NavigateAction.java
@@ -1,73 +1,45 @@
 package de.tobias.playpad.action.actions;
 
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.event.KeyEvent;
+import de.thecodelabs.midi.event.KeyEventType;
+import de.thecodelabs.midi.feedback.FeedbackType;
 import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
-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.project.Project;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import javafx.application.Platform;
-import javafx.beans.property.SimpleStringProperty;
-import javafx.beans.property.StringProperty;
-import org.dom4j.Element;
 
-public class NavigateAction extends Action {
+public class NavigateAction extends ActionHandler {
+
+	public static final String TYPE = "NavigateAction";
+	public static final String PAYLOAD_TYPE = "type";
 
 	public enum NavigationType {
 		PREVIOUS,
 		NEXT;
 
+		public static NavigationType valueOf(Action action) {
+			return valueOf(action.getPayload(PAYLOAD_TYPE));
+		}
+
 		@Override
 		public String toString() {
-			return Localization.getString(Strings.NavigationType_BaseName + name());
+			return Localization.getString(Strings.NAVIGATION_TYPE + name());
 		}
 	}
 
-	private NavigationType action;
-	private String type; // reference from NavigateActionFactory
-
-	public NavigateAction(String type) {
-		this(type, NavigationType.NEXT);
-	}
-
-	public NavigateAction(String type, NavigationType action) {
-		this.action = action;
-		this.type = type;
-	}
-
-	public NavigationType getAction() {
-		return action;
-	}
-
-	public void setAction(NavigationType action) {
-		this.action = action;
-	}
-
-	@Override
-	public String getType() {
-		return type;
-	}
-
 	@Override
-	public void init(Project project, IMainViewController controller) {
+	public String actionType() {
+		return TYPE;
 	}
 
 	@Override
-	public void showFeedback(Project project, IMainViewController controller) {
-		handleFeedback(FeedbackMessage.STANDARD);
-	}
-
-	@Override
-	public void clearFeedback() {
-		handleFeedback(FeedbackMessage.OFF);
-	}
-
-	@Override
-	public void performAction(InputType type, Project project, IMainViewController mainViewController) {
-		if (type == InputType.PRESSED) {
-			switch (this.action) {
+	public FeedbackType handle(KeyEvent keyEvent, Action action) {
+		if (keyEvent.getKeyEventType() == KeyEventType.DOWN) {
+			IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController();
+			switch (NavigationType.valueOf(action)) {
 				case PREVIOUS:
 					Platform.runLater(() -> mainViewController.showPage(mainViewController.getPage() - 1));
 					break;
@@ -78,50 +50,11 @@ public class NavigateAction extends Action {
 					break;
 			}
 		}
+		return FeedbackType.DEFAULT;
 	}
 
 	@Override
-	public FeedbackType geFeedbackType() {
-		return FeedbackType.SINGLE;
-	}
-
-	// Serialization
-	private static final String TYPE = "action";
-
-	@Override
-	public void load(Element root) {
-		action = NavigationType.valueOf(root.attributeValue(TYPE));
-	}
-
-	@Override
-	public void save(Element root) {
-		root.addAttribute(TYPE, action.name());
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (obj instanceof NavigateAction) {
-			return ((NavigateAction) obj).getAction() == action;
-		}
-		return super.equals(obj);
-	}
-
-	@Override
-	public String toString() {
-		return Localization.getString(Strings.Action_Navigate_toString, action.toString());
-	}
-
-	@Override
-	public StringProperty displayProperty() {
-		return new SimpleStringProperty(toString());
-	}
-
-	@Override
-	public Action cloneAction() throws CloneNotSupportedException {
-		NavigateAction actionClone = (NavigateAction) super.clone();
-
-		actionClone.action = this.action;
-
-		return actionClone;
+	public FeedbackType getCurrentFeedbackType(Action action) {
+		return FeedbackType.DEFAULT;
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/actions/PageAction.java b/PlayWall/src/main/java/de/tobias/playpad/action/actions/PageAction.java
index 3b69aaa55c975e12dd67e5a9321570b1077c00f7..23954783012e365a80d0b4c8b7f7497d19d351e4 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/action/actions/PageAction.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/actions/PageAction.java
@@ -1,114 +1,52 @@
 package de.tobias.playpad.action.actions;
 
-import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.Strings;
-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.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.event.KeyEvent;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import javafx.application.Platform;
-import javafx.beans.property.SimpleStringProperty;
-import javafx.beans.property.StringProperty;
-import org.dom4j.Element;
 
-public class PageAction extends Action {
+public class PageAction extends ActionHandler {
 
-	private final String type;
-
-	private int page;
-
-	public PageAction(String type) {
-		this(type, 0);
-	}
-
-	public PageAction(String type, int page) {
-		this.type = type;
-		this.page = page;
-	}
-
-	public int getPage() {
-		return page;
-	}
-
-	public void setPage(int page) {
-		this.page = page;
-	}
+	public static final String TYPE = "PageAction";
+	public static final String PAYLOAD_PAGE = "page";
 
 	@Override
-	public String getType() {
-		return type;
-	}
-
-	@Override
-	public void init(Project project, IMainViewController controller) {
-
-	}
-
-	@Override
-	public void showFeedback(Project project, IMainViewController controller) {
-		int page = controller.getPage();
-		if (page == this.page) {
-			handleFeedback(FeedbackMessage.EVENT);
-		} else {
-			handleFeedback(FeedbackMessage.STANDARD);
-		}
+	public String actionType() {
+		return TYPE;
 	}
 
 	@Override
-	public void clearFeedback() {
-		handleFeedback(FeedbackMessage.OFF);
-	}
+	public FeedbackType handle(KeyEvent keyEvent, Action action) {
+		Project project = PlayPadPlugin.getInstance().getCurrentProject();
+		IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController();
+		int targetPage = getPageForAction(action);
 
-	@Override
-	public void performAction(InputType type, Project project, IMainViewController mainViewController) {
-		if (type == InputType.PRESSED) {
-			Platform.runLater(() -> mainViewController.showPage(page));
+		if (targetPage < 0 || targetPage >= project.getPages().size()) {
+			return FeedbackType.DEFAULT;
 		}
-	}
 
-	@Override
-	public FeedbackType geFeedbackType() {
-		return FeedbackType.DOUBLE;
-	}
+		Platform.runLater(() -> mainViewController.showPage(targetPage));
 
-	private static final String PAGE = "page";
-
-	@Override
-	public void load(Element root) {
-		page = Integer.valueOf(root.attributeValue(PAGE));
+		return FeedbackType.EVENT;
 	}
 
 	@Override
-	public void save(Element root) {
-		root.addAttribute(PAGE, String.valueOf(page));
-	}
+	public FeedbackType getCurrentFeedbackType(Action action) {
+		IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController();
+		int targetPage = getPageForAction(action);
 
-	@Override
-	public boolean equals(Object obj) {
-		if (obj instanceof PageAction) {
-			return ((PageAction) obj).getPage() == page;
+		if (mainViewController.getPage() == targetPage) {
+			return FeedbackType.EVENT;
 		}
-		return super.equals(obj);
-	}
-
-	@Override
-	public String toString() {
-		return Localization.getString(Strings.Action_Page_toString, String.valueOf(page + 1));
-	}
 
-	@Override
-	public StringProperty displayProperty() {
-		return new SimpleStringProperty(toString());
+		return FeedbackType.DEFAULT;
 	}
 
-	@Override
-	public Action cloneAction() throws CloneNotSupportedException {
-		PageAction action = (PageAction) super.clone();
-
-		action.page = page;
-
-		return action;
+	public static int getPageForAction(Action action) {
+		return Integer.parseInt(action.getPayload(PAYLOAD_PAGE));
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/actions/StopAction.java b/PlayWall/src/main/java/de/tobias/playpad/action/actions/StopAction.java
index 017ab524f0c3e44fcea1e54466c1c2b45fb932e1..88356e24d0f421fcb075a5bcb09fe19ad84d5b53 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/action/actions/StopAction.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/actions/StopAction.java
@@ -1,93 +1,37 @@
 package de.tobias.playpad.action.actions;
 
-import de.thecodelabs.utils.ui.icon.FontAwesomeType;
-import de.thecodelabs.utils.ui.icon.FontIcon;
-import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.Strings;
-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.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.event.KeyEvent;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.tobias.playpad.PlayPadPlugin;
 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 javafx.beans.property.SimpleStringProperty;
-import javafx.beans.property.StringProperty;
-import javafx.scene.Node;
-import javafx.scene.control.Label;
-import org.dom4j.Element;
 
-public class StopAction extends Action {
+public class StopAction extends ActionHandler {
 
-	private String type;
-
-	public StopAction(String type) {
-		this.type = type;
-	}
+	public static final String TYPE = "StopAction";
 
 	@Override
-	public String getType() {
-		return type;
+	public String actionType() {
+		return TYPE;
 	}
 
 	@Override
-	public void performAction(InputType type, Project project, IMainViewController mainViewController) {
+	public FeedbackType handle(KeyEvent keyEvent, Action action) {
+		final Project project = PlayPadPlugin.getInstance().getCurrentProject();
+
 		for (Pad pad : project.getPads()) {
 			if (pad.getStatus() == PadStatus.PLAY || pad.getStatus() == PadStatus.PAUSE)
 				pad.setStatus(PadStatus.STOP, true);
 		}
-	}
-
-	@Override
-	public void init(Project project, IMainViewController controller) {
-
-	}
-
-	@Override
-	public void showFeedback(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(Localization.getString(Strings.Action_Stop_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);
+		return FeedbackType.DEFAULT;
 	}
 
 	@Override
-	public Action cloneAction() throws CloneNotSupportedException {
-		return (Action) super.clone();
+	public FeedbackType getCurrentFeedbackType(Action action) {
+		return FeedbackType.DEFAULT;
 	}
-
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/actions/cart/CartAction.java b/PlayWall/src/main/java/de/tobias/playpad/action/actions/cart/CartAction.java
deleted file mode 100644
index e82cfa59339af244c5531a7ab2f798211c9870c9..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/actions/cart/CartAction.java
+++ /dev/null
@@ -1,249 +0,0 @@
-package de.tobias.playpad.action.actions.cart;
-
-import de.thecodelabs.utils.ui.NVC;
-import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.Strings;
-import de.tobias.playpad.action.Action;
-import de.tobias.playpad.action.InputType;
-import de.tobias.playpad.action.actions.cart.handler.CartActionHandler;
-import de.tobias.playpad.action.actions.cart.handler.CartActionHandlerFactory;
-import de.tobias.playpad.action.feedback.ColorAdjustable;
-import de.tobias.playpad.action.feedback.FeedbackType;
-import de.tobias.playpad.pad.Pad;
-import de.tobias.playpad.pad.content.play.Durationable;
-import de.tobias.playpad.project.Project;
-import de.tobias.playpad.viewcontroller.actions.CartActionViewController;
-import de.tobias.playpad.viewcontroller.main.IMainViewController;
-import javafx.beans.property.SimpleStringProperty;
-import javafx.beans.property.StringProperty;
-import org.dom4j.Element;
-
-public class CartAction extends Action implements ColorAdjustable {
-
-	public enum CartActionMode {
-		PLAY_PAUSE,
-		PLAY_STOP,
-		PLAY_HOLD,
-		PLAY_PLAY
-	}
-
-	private final String type;
-
-	private int x;
-	private int y;
-
-	private CartActionMode mode;
-	private CartActionHandler handler;
-	private boolean autoFeedbackColors;
-
-	private transient Pad pad;
-	private transient PadContentFeedbackListener padContentFeedbackListener = new PadContentFeedbackListener();
-	private transient PadStatusFeedbackListener padStatusFeedbackListener = new PadStatusFeedbackListener();
-	private transient PadPositionWarningListener padPositionListener = new PadPositionWarningListener(this);
-
-	public CartAction(String type) {
-		this(type, 0, 0, CartActionMode.PLAY_STOP);
-		this.autoFeedbackColors = true;
-	}
-
-	public CartAction(String type, int x, int y, CartActionMode mode) {
-		this.type = type;
-		this.x = x;
-		this.y = y;
-
-		setMode(mode);
-		this.autoFeedbackColors = true;
-	}
-
-	public int getX() {
-		return x;
-	}
-
-	public int getY() {
-		return y;
-	}
-
-	public CartActionMode getMode() {
-		return mode;
-	}
-
-	public void setMode(CartActionMode mode) {
-		this.mode = mode;
-		this.handler = CartActionHandlerFactory.getInstance(mode);
-	}
-
-	@Override
-	public boolean isAutoFeedbackColors() {
-		return autoFeedbackColors;
-	}
-
-	public void setAutoFeedbackColors(boolean autoFeedbackColors) {
-		this.autoFeedbackColors = autoFeedbackColors;
-	}
-
-	// Helper
-	@Override
-	public Pad getPad() {
-		return pad;
-	}
-
-	@Override
-	public void init(Project project, IMainViewController controller) {
-		Pad pad = project.getPad(x, y, controller.getPage());
-		if (pad != null) {
-			setPad(pad);
-		}
-	}
-
-	@Override
-	public void showFeedback(Project project, IMainViewController controller) {
-		if (pad != null) {
-			// init first feedback
-			padStatusFeedbackListener.changed(null, null, pad.getStatus());
-		}
-	}
-
-	@Override
-	public void clearFeedback() {
-		setPad(null);
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (obj instanceof CartAction) {
-			CartAction action2 = (CartAction) obj;
-			if (action2.x == x && action2.y == y) {
-				return true;
-			}
-		}
-		return super.equals(obj);
-	}
-
-	@Override
-	public String getType() {
-		return type;
-	}
-
-	@Override
-	public void performAction(InputType type, Project project, IMainViewController mainViewController) {
-		setPad(project.getPad(x, y, mainViewController.getPage()));
-
-		if (pad == null) {
-			return;
-		}
-
-		if (pad.hasVisibleContent()) {
-			handler.performAction(type, this, pad);
-		}
-	}
-
-	@Override
-	public FeedbackType geFeedbackType() {
-		return FeedbackType.DOUBLE;
-	}
-
-	private void setPad(Pad newPad) {
-		Pad oldPad = this.pad;
-		if (newPad == null || !newPad.equals(oldPad)) {
-			removeOldListener(oldPad);
-			this.pad = newPad;
-			addNewListener(newPad);
-		}
-	}
-
-	private void removeOldListener(Pad oldPad) {
-		if (oldPad != null) {
-			if (oldPad.getContent() != null) {
-				if (oldPad.getContent() instanceof Durationable) {
-					Durationable durationable = (Durationable) oldPad.getContent();
-					durationable.positionProperty().removeListener(padPositionListener);
-				}
-			}
-			oldPad.contentProperty().removeListener(padContentFeedbackListener);
-			oldPad.statusProperty().removeListener(padStatusFeedbackListener);
-		}
-	}
-
-	private void addNewListener(Pad newPad) {
-		padPositionListener.setPad(newPad);
-		padStatusFeedbackListener.setAction(this);
-		padContentFeedbackListener.setAction(this);
-
-		if (newPad != null) {
-			// Add new listener
-			if (newPad.getContent() != null) {
-				if (newPad.getContent() instanceof Durationable) {
-					Durationable durationable = (Durationable) newPad.getContent();
-					durationable.positionProperty().addListener(padPositionListener);
-				}
-			}
-
-			newPad.statusProperty().addListener(padStatusFeedbackListener);
-			newPad.contentProperty().addListener(padContentFeedbackListener);
-		}
-	}
-
-	public PadPositionWarningListener getPadPositionListener() {
-		return padPositionListener;
-	}
-
-	// Helper
-	@Override
-	public Action cloneAction() throws CloneNotSupportedException {
-		CartAction action = (CartAction) super.clone();
-
-		action.autoFeedbackColors = autoFeedbackColors;
-		action.x = x;
-		action.y = y;
-		action.setMode(mode);
-
-		return action;
-	}
-
-	// UI Helper
-	@Override
-	public String toString() {
-		return Localization.getString(Strings.Action_Cart_toString, x + ", " + y);
-	}
-
-	@Override
-	public StringProperty displayProperty() {
-		return new SimpleStringProperty(toString());
-	}
-
-	private static CartActionViewController cartActionViewController;
-
-	@Override
-	public NVC getSettingsViewController() {
-		if (cartActionViewController == null) {
-			CartAction.cartActionViewController = new CartActionViewController();
-		}
-		CartAction.cartActionViewController.setCartAction(this);
-		return cartActionViewController;
-	}
-
-	// Serialization
-	private static final String X_ATTR = "x";
-	private static final String Y_ATTR = "y";
-	private static final String CONTROL_MODE = "mode";
-	private static final String AUTO_FEEDBACK_COLORS = "autoColor";
-
-	@Override
-	public void load(Element root) {
-		if (root.attributeValue(X_ATTR) != null)
-			x = Integer.parseInt(root.attributeValue(X_ATTR));
-		if (root.attributeValue(Y_ATTR) != null)
-			y = Integer.parseInt(root.attributeValue(Y_ATTR));
-		setMode(CartActionMode.valueOf(root.attributeValue(CONTROL_MODE)));
-		autoFeedbackColors = Boolean.parseBoolean(root.attributeValue(AUTO_FEEDBACK_COLORS));
-	}
-
-	@Override
-	public void save(Element root) {
-		root.addAttribute(X_ATTR, String.valueOf(x));
-		root.addAttribute(Y_ATTR, String.valueOf(y));
-		root.addAttribute(CONTROL_MODE, mode.name());
-		root.addAttribute(AUTO_FEEDBACK_COLORS, String.valueOf(autoFeedbackColors));
-	}
-
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/actions/cart/PadContentFeedbackListener.java b/PlayWall/src/main/java/de/tobias/playpad/action/actions/cart/PadContentFeedbackListener.java
deleted file mode 100644
index 906d41c4f261193f30d85c0c5cf9a313bebef219..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/actions/cart/PadContentFeedbackListener.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package de.tobias.playpad.action.actions.cart;
-
-import de.tobias.playpad.pad.content.PadContent;
-import de.tobias.playpad.pad.content.play.Durationable;
-import javafx.beans.value.ChangeListener;
-import javafx.beans.value.ObservableValue;
-
-public class PadContentFeedbackListener implements ChangeListener<PadContent> {
-
-	private CartAction action;
-
-	public void setAction(CartAction action) {
-		this.action = action;
-	}
-
-	@Override
-	public void changed(ObservableValue<? extends PadContent> observable, PadContent oldValue, PadContent newValue) {
-		if (oldValue != null) {
-			if (oldValue instanceof Durationable) {
-				Durationable durationable = (Durationable) oldValue;
-				durationable.positionProperty().addListener(action.getPadPositionListener());
-			}
-		}
-
-		if (newValue != null) {
-			if (newValue instanceof Durationable) {
-				Durationable durationable = (Durationable) newValue;
-				durationable.positionProperty().addListener(action.getPadPositionListener());
-			}
-		}
-	}
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/actions/cart/PadPositionWarningListener.java b/PlayWall/src/main/java/de/tobias/playpad/action/actions/cart/PadPositionWarningListener.java
deleted file mode 100644
index e1475c64c7316f30ce87e796bad3ab53692f3ac3..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/actions/cart/PadPositionWarningListener.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package de.tobias.playpad.action.actions.cart;
-
-import de.tobias.playpad.action.feedback.FeedbackMessage;
-import de.tobias.playpad.pad.Pad;
-import de.tobias.playpad.pad.PadSettings;
-import de.tobias.playpad.pad.content.play.Durationable;
-import javafx.beans.value.ChangeListener;
-import javafx.beans.value.ObservableValue;
-import javafx.util.Duration;
-
-public class PadPositionWarningListener implements ChangeListener<Duration> {
-
-	private Pad pad;
-	private CartAction action;
-
-	boolean send = false;
-
-	public PadPositionWarningListener(CartAction action) {
-		this.action = action;
-	}
-
-	public void setPad(Pad pad) {
-		this.pad = pad;
-	}
-
-	@Override
-	public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
-		// Nur wenn Pad Sichtbar ist
-		if (pad != null && pad.isPadVisible()) {
-			if (pad.getContent() instanceof Durationable) {
-				Durationable durationable = (Durationable) pad.getContent();
-				PadSettings padSettings = pad.getPadSettings();
-
-				// Warning nur wenn kein Loop
-				if (!padSettings.isLoop()) {
-					// Warning
-					Duration warning = padSettings.getWarning();
-					Duration totalDuration = durationable.getDuration();
-					if (totalDuration != null) {
-						Duration rest = totalDuration.subtract(newValue);
-						double seconds = rest.toSeconds();
-
-						if (warning.toSeconds() > seconds && !send) {
-							action.handleFeedback(FeedbackMessage.WARNING);
-							send = true;
-						}
-					}
-				}
-			}
-		}
-	}
-
-	public void setSend(boolean send) {
-		this.send = send;
-	}
-
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/actions/cart/PadStatusFeedbackListener.java b/PlayWall/src/main/java/de/tobias/playpad/action/actions/cart/PadStatusFeedbackListener.java
deleted file mode 100644
index 97737ce8472cd7bd173cd4f6bba07c53e3dc46c6..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/actions/cart/PadStatusFeedbackListener.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package de.tobias.playpad.action.actions.cart;
-
-import de.tobias.playpad.action.feedback.FeedbackMessage;
-import de.tobias.playpad.pad.Pad;
-import de.tobias.playpad.pad.PadSettings;
-import de.tobias.playpad.pad.PadStatus;
-import de.tobias.playpad.pad.content.play.Durationable;
-import javafx.beans.value.ChangeListener;
-import javafx.beans.value.ObservableValue;
-import javafx.util.Duration;
-
-public class PadStatusFeedbackListener implements ChangeListener<PadStatus> {
-
-	private CartAction action;
-
-	public void setAction(CartAction action) {
-		this.action = action;
-	}
-
-	@Override
-	public void changed(ObservableValue<? extends PadStatus> observable, PadStatus oldValue, PadStatus newValue) {
-		if (action != null) {
-			Pad pad = action.getPad();
-			if (pad.isPadVisible()) {
-				switch (newValue) {
-					case EMPTY:
-					case ERROR:
-						action.handleFeedback(FeedbackMessage.OFF);
-						break;
-					case PAUSE:
-						action.handleFeedback(FeedbackMessage.STANDARD);
-						break;
-					case PLAY:
-						action.handleFeedback(FeedbackMessage.EVENT);
-
-						// Wenn Cart in Warning Zeitbereich und vomn Pause zu Play wechselt
-						try {
-							if (pad.getContent() instanceof Durationable) {
-								Durationable durationable = (Durationable) pad.getContent();
-								PadSettings padSettings = pad.getPadSettings();
-
-								if (!padSettings.isLoop()) {
-									Duration warning = padSettings.getWarning();
-									Duration rest = durationable.getDuration().subtract(durationable.getPosition());
-									double seconds = rest.toSeconds();
-
-									if (warning.toSeconds() > seconds) {
-										action.handleFeedback(FeedbackMessage.WARNING);
-									}
-								}
-							}
-						} catch (Exception ignored) {
-						}
-						break;
-					case READY:
-						action.handleFeedback(FeedbackMessage.STANDARD);
-						break;
-					case STOP:
-						action.handleFeedback(FeedbackMessage.STANDARD);
-						break;
-					default:
-						break;
-
-				}
-			}
-		}
-	}
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/factory/CartActionProvider.java b/PlayWall/src/main/java/de/tobias/playpad/action/factory/CartActionProvider.java
index 0d9402c5f5aba4182df272111b1b8bb1ac014eeb..7b078335255b168e0d61f42051ea0ab5cea69afd 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/action/factory/CartActionProvider.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/factory/CartActionProvider.java
@@ -1,51 +1,80 @@
 package de.tobias.playpad.action.factory;
 
-import de.thecodelabs.utils.ui.NVC;
-import de.tobias.playpad.action.*;
-import de.tobias.playpad.action.actions.cart.CartAction;
-import de.tobias.playpad.action.actions.cart.CartAction.CartActionMode;
-import de.tobias.playpad.profile.Profile;
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.mapping.KeyType;
+import de.tobias.playpad.action.ActionProvider;
+import de.tobias.playpad.action.ActionType;
+import de.tobias.playpad.action.actions.CartAction;
+import de.tobias.playpad.action.actions.CartAction.*;
+import de.tobias.playpad.action.settings.ActionSettingsEntry;
+import de.tobias.playpad.action.settings.CartActionSettingsEntry;
 import de.tobias.playpad.project.ProjectSettings;
-import de.tobias.playpad.viewcontroller.IMappingTabViewController;
-import de.tobias.playpad.viewcontroller.actions.CartActionTypeViewController;
 import javafx.scene.control.TreeItem;
 
 import java.util.List;
 
-public class CartActionProvider extends ActionProvider implements ActionDisplayable {
+import static de.tobias.playpad.action.actions.CartAction.*;
+
+public class CartActionProvider extends ActionProvider {
 
 	public CartActionProvider(String type) {
-		super(type);
+		super(TYPE);
 	}
 
 	@Override
-	public TreeItem<ActionDisplayable> getTreeViewForActions(List<Action> actions, Mapping mapping) {
-		return new TreeItem<>(this);
+	public String getType() {
+		return TYPE;
 	}
 
 	@Override
-	public void initActionType(Mapping mapping, Profile profile) {
+	public void createDefaultActions(Mapping mapping) {
 		for (int x = 0; x < ProjectSettings.MAX_COLUMNS; x++) {
 			for (int y = 0; y < ProjectSettings.MAX_ROWS; y++) {
-				CartAction action = new CartAction(getType(), x, y, CartActionMode.PLAY_STOP);
-				mapping.addActionIfNotContains(action);
+				Action action = newInstance(x, y);
+				mapping.addUniqueAction(action);
 			}
 		}
 	}
 
+	private Action newInstance(int x, int y) {
+		Action action = new Action(getType());
+		action.addPayloadEntry(PAYLOAD_X, String.valueOf(x));
+		action.addPayloadEntry(PAYLOAD_Y, String.valueOf(y));
+		action.addPayloadEntry(PAYLOAD_MODE, CartActionMode.PLAY_STOP.name());
+		action.addPayloadEntry(PAYLOAD_AUTO_FEEDBACK, String.valueOf(true));
+		return action;
+	}
+
 	@Override
-	public NVC getActionSettingsViewController(Mapping mapping, IMappingTabViewController controller) {
-		return new CartActionTypeViewController(mapping, controller);
+	public ActionHandler getActionHandler() {
+		return new CartAction();
 	}
 
 	@Override
-	public Action newInstance() {
-		return new CartAction(getType());
+	public FeedbackType[] supportedFeedbackOptions(Action action, KeyType keyType) {
+		switch (keyType) {
+			case KEYBOARD:
+				return new FeedbackType[0];
+			case MIDI:
+				return new FeedbackType[]{FeedbackType.DEFAULT, FeedbackType.EVENT, FeedbackType.WARNING};
+		}
+		return new FeedbackType[0];
 	}
 
+	/*
+
+	 */
+
 	@Override
-	public ActionType geActionType() {
+	public ActionType getActionType() {
 		return ActionType.CONTROL;
 	}
 
+	@Override
+	public TreeItem<ActionSettingsEntry> getTreeItemForActions(List<Action> actions, Mapping mapping) {
+		return new TreeItem<>(new CartActionSettingsEntry());
+	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/factory/NavigateActionProvider.java b/PlayWall/src/main/java/de/tobias/playpad/action/factory/NavigateActionProvider.java
index 676c88f74bc1ae0bb2e58b568c7e6734133b74da..541d648b5d5fcb610ce4ee5203c079f16db9d2ca 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/action/factory/NavigateActionProvider.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/factory/NavigateActionProvider.java
@@ -1,61 +1,86 @@
 package de.tobias.playpad.action.factory;
 
-import de.thecodelabs.utils.ui.NVC;
-import de.tobias.playpad.action.*;
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.mapping.KeyType;
+import de.tobias.playpad.action.ActionProvider;
+import de.tobias.playpad.action.ActionType;
 import de.tobias.playpad.action.actions.NavigateAction;
 import de.tobias.playpad.action.actions.NavigateAction.NavigationType;
-import de.tobias.playpad.profile.Profile;
+import de.tobias.playpad.action.settings.ActionSettingsEntry;
+import de.tobias.playpad.action.settings.NavigateActionSettingsEntry;
+import de.tobias.playpad.action.settings.NavigateActionTypeSettingsEntry;
 import javafx.scene.control.TreeItem;
 
 import java.util.List;
 
-public class NavigateActionProvider extends ActionProvider implements ActionDisplayable {
+import static de.tobias.playpad.action.actions.NavigateAction.TYPE;
+
+public class NavigateActionProvider extends ActionProvider {
 
 	public NavigateActionProvider(String type) {
-		super(type);
+		super(TYPE);
 	}
 
 	@Override
-	public TreeItem<ActionDisplayable> getTreeViewForActions(List<Action> actions, Mapping mapping) {
-		TreeItem<ActionDisplayable> rootItem = new TreeItem<>(this);
-
-		actions.sort((o1, o2) ->
-		{
-			if (o1 instanceof NavigateAction && o2 instanceof NavigateAction) {
-				NavigateAction c1 = (NavigateAction) o1;
-				NavigateAction c2 = (NavigateAction) o2;
-				return Long.compare(c1.getAction().ordinal(), c2.getAction().ordinal());
-			} else {
-				return -1;
-			}
-		});
-
-		for (Action action : actions) {
-			TreeItem<ActionDisplayable> actionItem = new TreeItem<>(action);
-			rootItem.getChildren().add(actionItem);
-		}
-		return rootItem;
+	public String getType() {
+		return TYPE;
 	}
 
 	@Override
-	public void initActionType(Mapping mapping, Profile profile) {
-		mapping.addActionIfNotContains(new NavigateAction(getType(), NavigationType.PREVIOUS));
-		mapping.addActionIfNotContains(new NavigateAction(getType(), NavigationType.NEXT));
+	public void createDefaultActions(Mapping mapping) {
+		mapping.addUniqueAction(newInstance(NavigationType.PREVIOUS));
+		mapping.addUniqueAction(newInstance(NavigationType.NEXT));
+	}
+
+	private Action newInstance(NavigationType navigationType) {
+		Action action = new Action(getType());
+		action.addPayloadEntry(NavigateAction.PAYLOAD_TYPE, navigationType.name());
+		return action;
 	}
 
 	@Override
-	public NVC getSettingsViewController() {
-		return null;
+	public ActionHandler getActionHandler() {
+		return new NavigateAction();
 	}
 
 	@Override
-	public Action newInstance() {
-		return new NavigateAction(getType());
+	public FeedbackType[] supportedFeedbackOptions(Action action, KeyType keyType) {
+		switch (keyType) {
+			case KEYBOARD:
+				return new FeedbackType[0];
+			case MIDI:
+				return new FeedbackType[]{FeedbackType.DEFAULT};
+		}
+		return new FeedbackType[0];
 	}
 
+	/*
+
+	 */
+
 	@Override
-	public ActionType geActionType() {
+	public ActionType getActionType() {
 		return ActionType.CONTROL;
 	}
 
+	@Override
+	public TreeItem<ActionSettingsEntry> getTreeItemForActions(List<Action> actions, Mapping mapping) {
+		TreeItem<ActionSettingsEntry> rootItem = new TreeItem<>(new NavigateActionTypeSettingsEntry());
+
+		actions.sort((o1, o2) ->
+		{
+			final NavigationType value1 = NavigationType.valueOf(o1);
+			final NavigationType value2 = NavigationType.valueOf(o2);
+			return Long.compare(value1.ordinal(), value2.ordinal());
+		});
+
+		for (Action action : actions) {
+			TreeItem<ActionSettingsEntry> actionItem = new TreeItem<>(new NavigateActionSettingsEntry(action));
+			rootItem.getChildren().add(actionItem);
+		}
+		return rootItem;
+	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/factory/PageActionProvider.java b/PlayWall/src/main/java/de/tobias/playpad/action/factory/PageActionProvider.java
index fe37595082f827044c2f39b3095daee653907d57..2f75bf00ec8536450c028664169f63939b1a5c38 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/action/factory/PageActionProvider.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/factory/PageActionProvider.java
@@ -1,65 +1,89 @@
 package de.tobias.playpad.action.factory;
 
-import de.thecodelabs.utils.ui.NVC;
-import de.tobias.playpad.action.*;
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.mapping.KeyType;
+import de.tobias.playpad.action.ActionProvider;
+import de.tobias.playpad.action.ActionType;
 import de.tobias.playpad.action.actions.PageAction;
-import de.tobias.playpad.profile.Profile;
+import de.tobias.playpad.action.settings.ActionSettingsEntry;
+import de.tobias.playpad.action.settings.PageActionSettingsEntry;
+import de.tobias.playpad.action.settings.PageActionTypeSettingsEntry;
 import de.tobias.playpad.project.ProjectSettings;
 import javafx.scene.control.TreeItem;
 
-import java.util.Collections;
 import java.util.List;
 
-public class PageActionProvider extends ActionProvider implements ActionDisplayable {
+import static de.tobias.playpad.action.actions.PageAction.TYPE;
+
+public class PageActionProvider extends ActionProvider {
 
 	public PageActionProvider(String type) {
-		super(type);
+		super(TYPE);
 	}
 
 	@Override
-	public TreeItem<ActionDisplayable> getTreeViewForActions(List<Action> actions, Mapping mapping) {
-		TreeItem<ActionDisplayable> rootItem = new TreeItem<>(this);
-
-		Collections.sort(actions, (o1, o2) ->
-		{
-			if (o1 instanceof PageAction && o2 instanceof PageAction) {
-				PageAction c1 = (PageAction) o1;
-				PageAction c2 = (PageAction) o2;
-				return Long.compare(c1.getPage(), c2.getPage());
-			} else {
-				return -1;
-			}
-		});
-
-		for (Action action : actions) {
-			TreeItem<ActionDisplayable> actionItem = new TreeItem<>(action);
-			rootItem.getChildren().add(actionItem);
-		}
-
-		return rootItem;
+	public String getType() {
+		return TYPE;
 	}
 
 	@Override
-	public void initActionType(Mapping mapping, Profile profile) {
+	public void createDefaultActions(Mapping mapping) {
 		for (int i = 0; i < ProjectSettings.MAX_PAGES; i++) {
-			PageAction action = new PageAction(getType(), i);
-			mapping.addActionIfNotContains(action);
+			Action action = newInstance(i);
+			mapping.addUniqueAction(action);
 		}
 	}
 
+	private Action newInstance(int i) {
+		Action action = new Action(getType());
+		action.addPayloadEntry(PageAction.PAYLOAD_PAGE, String.valueOf(i));
+		return action;
+	}
+
 	@Override
-	public NVC getSettingsViewController() {
-		return null;
+	public ActionHandler getActionHandler() {
+		return new PageAction();
 	}
 
 	@Override
-	public Action newInstance() {
-		return new PageAction(getType());
+	public FeedbackType[] supportedFeedbackOptions(Action action, KeyType keyType) {
+		switch (keyType) {
+			case KEYBOARD:
+				return new FeedbackType[0];
+			case MIDI:
+				return new FeedbackType[]{FeedbackType.DEFAULT, FeedbackType.EVENT};
+		}
+		return new FeedbackType[0];
 	}
 
+	/*
+
+	 */
+
 	@Override
-	public ActionType geActionType() {
+	public ActionType getActionType() {
 		return ActionType.CONTROL;
 	}
 
+	@Override
+	public TreeItem<ActionSettingsEntry> getTreeItemForActions(List<Action> actions, Mapping mapping) {
+		TreeItem<ActionSettingsEntry> rootItem = new TreeItem<>(new PageActionTypeSettingsEntry());
+
+		actions.sort((o1, o2) ->
+		{
+			int page1 = PageAction.getPageForAction(o1);
+			int page2 = PageAction.getPageForAction(o2);
+			return Long.compare(page1, page2);
+		});
+
+		for (Action action : actions) {
+			TreeItem<ActionSettingsEntry> actionItem = new TreeItem<>(new PageActionSettingsEntry(action));
+			rootItem.getChildren().add(actionItem);
+		}
+
+		return rootItem;
+	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/factory/StopActionProvider.java b/PlayWall/src/main/java/de/tobias/playpad/action/factory/StopActionProvider.java
index fb873eefcd63c6b0d9b55fff7683e7ad1f64618d..e73d17919e4af7bde9909ff4f08b5804c71b37d5 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/action/factory/StopActionProvider.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/factory/StopActionProvider.java
@@ -1,36 +1,65 @@
 package de.tobias.playpad.action.factory;
 
-import de.tobias.playpad.action.*;
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.mapping.KeyType;
+import de.tobias.playpad.action.ActionProvider;
+import de.tobias.playpad.action.ActionType;
 import de.tobias.playpad.action.actions.StopAction;
-import de.tobias.playpad.profile.Profile;
+import de.tobias.playpad.action.settings.ActionSettingsEntry;
+import de.tobias.playpad.action.settings.StopActionTypeSettingsEntry;
 import javafx.scene.control.TreeItem;
 
 import java.util.List;
 
+import static de.tobias.playpad.action.actions.StopAction.TYPE;
+
 public class StopActionProvider extends ActionProvider {
 
 	public StopActionProvider(String type) {
-		super(type);
+		super(TYPE);
 	}
 
 	@Override
-	public TreeItem<ActionDisplayable> getTreeViewForActions(List<Action> actions, Mapping mapping) {
-		return new TreeItem<>(actions.get(0));
+	public String getType() {
+		return TYPE;
+	}
+
+	@Override
+	public void createDefaultActions(Mapping mapping) {
+		mapping.addUniqueAction(newInstance());
+	}
+
+	private Action newInstance() {
+		return new Action(getType());
 	}
 
 	@Override
-	public void initActionType(Mapping mapping, Profile profile) {
-		mapping.addActionIfNotContains(newInstance());
+	public ActionHandler getActionHandler() {
+		return new StopAction();
 	}
 
 	@Override
-	public Action newInstance() {
-		return new StopAction(getType());
+	public FeedbackType[] supportedFeedbackOptions(Action action, KeyType keyType) {
+		if (keyType == KeyType.MIDI) {
+			return new FeedbackType[]{FeedbackType.DEFAULT};
+		}
+		return new FeedbackType[0];
 	}
 
+	/*
+
+	 */
+
 	@Override
-	public ActionType geActionType() {
+	public ActionType getActionType() {
 		return ActionType.CONTROL;
 	}
 
+	@Override
+	public TreeItem<ActionSettingsEntry> getTreeItemForActions(List<Action> actions, Mapping mapping) {
+		return new TreeItem<>(new StopActionTypeSettingsEntry(actions.stream().findFirst().orElse(null)));
+	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/KeyboardMapper.java b/PlayWall/src/main/java/de/tobias/playpad/action/mapper/KeyboardMapper.java
deleted file mode 100644
index 801b2ed05be27b52a52cc9fc89e23c4951accbce..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/KeyboardMapper.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package de.tobias.playpad.action.mapper;
-
-import de.thecodelabs.utils.ui.NVC;
-import de.thecodelabs.utils.util.Localization;
-import de.thecodelabs.utils.util.StringUtils;
-import de.tobias.playpad.Strings;
-import de.tobias.playpad.action.Action;
-import de.tobias.playpad.viewcontroller.mapper.KeyboardMapperViewController;
-import javafx.beans.property.SimpleStringProperty;
-import javafx.beans.property.StringProperty;
-import javafx.scene.input.KeyCode;
-import org.dom4j.Element;
-
-public class KeyboardMapper extends Mapper {
-
-	private final String type;
-
-	private KeyCode code;
-	private String key;
-
-	public KeyboardMapper(String type) {
-		this(type, KeyCode.A, "A");
-	}
-
-	public KeyboardMapper(String type, KeyCode code, String key) {
-		this.type = type;
-		this.code = code;
-		this.key = key;
-		updateDisplayProperty();
-	}
-
-	public KeyCode getCode() {
-		return code;
-	}
-
-	public void setCode(KeyCode code) {
-		this.code = code;
-		updateDisplayProperty();
-	}
-
-	public String getKey() {
-		return key;
-	}
-
-	public void setKey(String key) {
-		this.key = key;
-		updateDisplayProperty();
-	}
-
-	@Override
-	public String getType() {
-		return type;
-	}
-
-	public String getReadableName() {
-		if (!StringUtils.isStringNotVisable(getKey())) {
-			return getKey();
-		} else {
-			return getCode().getName();
-		}
-	}
-
-	private static final String KEY = "key";
-	private static final String CODE = "code";
-
-	@Override
-	public void load(Element element, Action action) {
-		key = element.attributeValue(KEY);
-		code = KeyCode.valueOf(element.attributeValue(CODE));
-	}
-
-	@Override
-	public void save(Element element) {
-		element.addAttribute(KEY, key);
-		element.addAttribute(CODE, code.name());
-	}
-
-	@Override
-	public String toString() {
-		return Localization.getString(Strings.Mapper_Keyboard_toString, getReadableName());
-	}
-
-	private StringProperty displayProperty = new SimpleStringProperty();
-
-	@Override
-	public StringProperty displayProperty() {
-		updateDisplayProperty();
-		return displayProperty;
-	}
-
-	private void updateDisplayProperty() {
-		displayProperty.set(toString());
-	}
-
-	private KeyboardMapperViewController settingsViewController;
-
-	@Override
-	public NVC getSettingsViewController() {
-		if (settingsViewController == null) {
-			settingsViewController = new KeyboardMapperViewController();
-		}
-		settingsViewController.setMapper(this);
-		return settingsViewController;
-	}
-
-	@Override
-	public Mapper cloneMapper() throws CloneNotSupportedException {
-		KeyboardMapper mapper = (KeyboardMapper) super.clone();
-
-		mapper.code = code;
-		mapper.key = key;
-		mapper.displayProperty = new SimpleStringProperty();
-
-		return mapper;
-	}
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/KeyboardMapperFactory.java b/PlayWall/src/main/java/de/tobias/playpad/action/mapper/KeyboardMapperFactory.java
deleted file mode 100644
index ba591c17b004916c669b4ce4658ae11239119b0a..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/KeyboardMapperFactory.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package de.tobias.playpad.action.mapper;
-
-import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.Strings;
-
-public class KeyboardMapperFactory extends MapperFactory {
-
-	public KeyboardMapperFactory(String type) {
-		super(type);
-	}
-
-	@Override
-	public MapperViewController getQuickSettingsViewController(Mapper mapper) {
-		return null;
-	}
-
-	@Override
-	public Mapper createNewMapper() {
-		return new KeyboardMapper(getType());
-	}
-
-	// TODO Remove
-	@Override
-	public String toString() {
-		return Localization.getString(Strings.Mapper_Keyboard_Name);
-	}
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/MidiMapper.java b/PlayWall/src/main/java/de/tobias/playpad/action/mapper/MidiMapper.java
deleted file mode 100644
index 495ea269618bffdab337ce43a26ff1c08f2ddb4f..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/MidiMapper.java
+++ /dev/null
@@ -1,231 +0,0 @@
-package de.tobias.playpad.action.mapper;
-
-import de.thecodelabs.utils.ui.NVC;
-import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.Strings;
-import de.tobias.playpad.action.Action;
-import de.tobias.playpad.action.feedback.*;
-import de.tobias.playpad.action.mapper.feedback.DoubleMidiFeedback;
-import de.tobias.playpad.action.mapper.feedback.SingleMidiFeedback;
-import de.tobias.playpad.action.mididevice.DeviceColorAssociatorConnector;
-import de.tobias.playpad.action.mididevice.MidiDeviceImpl;
-import de.tobias.playpad.midi.Midi;
-import de.tobias.playpad.viewcontroller.mapper.MidiMapperViewController;
-import javafx.beans.property.SimpleStringProperty;
-import javafx.beans.property.StringProperty;
-import javafx.scene.paint.Color;
-import org.dom4j.Element;
-
-public class MidiMapper extends Mapper implements ColorAssociator, MapperFeedbackable {
-
-	private String type;
-
-	private int command;
-	private int key;
-
-	private Feedback feedback;
-	private FeedbackType feedbackType;
-
-	MidiMapper(String type) {
-		this(type, 0, 0);
-	}
-
-	MidiMapper(String type, int command, int key) {
-		this.type = type;
-		this.command = command;
-		this.key = key;
-		updateDisplayProperty();
-	}
-
-	public int getCommand() {
-		return command;
-	}
-
-	public void setCommand(int command) {
-		this.command = command;
-		updateDisplayProperty();
-	}
-
-	public int getKey() {
-		return key;
-	}
-
-	public void setKey(int key) {
-		this.key = key;
-		updateDisplayProperty();
-	}
-
-	@Override
-	public void initFeedback() {
-		if (feedback == null || this.feedbackType != super.feedbackType) {
-			if (super.feedbackType == FeedbackType.SINGLE) {
-				feedback = new SingleMidiFeedback();
-			} else if (super.feedbackType == FeedbackType.DOUBLE) {
-				feedback = new DoubleMidiFeedback();
-			}
-		}
-		this.feedbackType = super.feedbackType;
-	}
-
-	public Feedback getFeedback() {
-		return feedback;
-	}
-
-	@Deprecated
-	public void setFeedback(Feedback feedback) {
-		this.feedback = feedback;
-	}
-
-	@Override
-	public void handleFeedback(FeedbackMessage message) {
-		MidiDeviceImpl midiDeviceImpl = Midi.getInstance().getMidiDevice();
-		if (midiDeviceImpl != null) {
-			midiDeviceImpl.handleFeedback(message, key, feedback);
-		}
-	}
-
-	@Override
-	public String getType() {
-		return type;
-	}
-
-	// Feedback, depends on MidiDeviceImpl
-	@Override
-	public boolean supportFeedback() {
-		MidiDeviceImpl midiMidiDeviceImpl = Midi.getInstance().getMidiDevice();
-		if (midiMidiDeviceImpl != null) {
-			return midiMidiDeviceImpl.supportFeedback();
-		}
-		return false;
-	}
-
-	@Override
-	public void setColor(FeedbackMessage feedbackMessage, DisplayableFeedbackColor color) {
-		if (feedbackMessage == FeedbackMessage.STANDARD || feedbackMessage == FeedbackMessage.EVENT) {
-			feedback.setFeedback(feedbackMessage, color.mapperFeedbackValue());
-		} else {
-			throw new IllegalArgumentException("Unexpected Message Type.");
-		}
-	}
-
-	@Override
-	public DisplayableFeedbackColor[] getColors() {
-		MidiDeviceImpl midiDeviceImpl = Midi.getInstance().getMidiDevice();
-		if (midiDeviceImpl != null) {
-			if (midiDeviceImpl instanceof DeviceColorAssociatorConnector) {
-				return ((DeviceColorAssociatorConnector) midiDeviceImpl).getColors();
-			}
-		}
-		return null;
-	}
-
-	@Override
-	public DisplayableFeedbackColor getDefaultEventColor() {
-		MidiDeviceImpl midiDeviceImpl = Midi.getInstance().getMidiDevice();
-		if (midiDeviceImpl != null) {
-			if (midiDeviceImpl instanceof DeviceColorAssociatorConnector) {
-				return ((DeviceColorAssociatorConnector) midiDeviceImpl).getDefaultEventColor();
-			}
-		}
-		return null;
-	}
-
-	@Override
-	public DisplayableFeedbackColor getDefaultStandardColor() {
-		MidiDeviceImpl midiDeviceImpl = Midi.getInstance().getMidiDevice();
-		if (midiDeviceImpl != null) {
-			if (midiDeviceImpl instanceof DeviceColorAssociatorConnector) {
-				return ((DeviceColorAssociatorConnector) midiDeviceImpl).getDefaultStandardColor();
-			}
-		}
-		return null;
-	}
-
-	@Override
-	public DisplayableFeedbackColor map(Color color) {
-		MidiDeviceImpl midiDeviceImpl = Midi.getInstance().getMidiDevice();
-		if (midiDeviceImpl != null) {
-			if (midiDeviceImpl instanceof DeviceColorAssociatorConnector) {
-				return ((DeviceColorAssociatorConnector) midiDeviceImpl).getPreferColorMapping(color);
-			}
-		}
-		return null;
-	}
-
-	private static final String MIDI_COMMAND = "command";
-	private static final String MIDI_KEY = "key";
-	private static final String FEEDBACK = "Feedback";
-
-	@Override
-	public void load(Element element, Action action) {
-		String commandValue = element.attributeValue(MIDI_COMMAND);
-		String keyValue = element.attributeValue(MIDI_KEY);
-
-		if (commandValue != null) {
-			command = Integer.valueOf(commandValue);
-		}
-		if (keyValue != null) {
-			key = Integer.valueOf(keyValue);
-		}
-
-		Element feedbackElement = element.element(FEEDBACK);
-		setFeedbackType(action.geFeedbackType());
-		if (feedback != null) {
-			feedback.load(feedbackElement);
-		} else {
-			initFeedback();
-		}
-	}
-
-	@Override
-	public void save(Element element) {
-		element.addAttribute(MIDI_COMMAND, String.valueOf(command));
-		element.addAttribute(MIDI_KEY, String.valueOf(key));
-
-		Element feedbackElement = element.addElement(FEEDBACK);
-		if (feedback != null) {
-			feedback.save(feedbackElement);
-		}
-	}
-
-	@Override
-	public String toString() {
-		return Localization.getString(Strings.Mapper_Midi_toString, key);
-	}
-
-	private StringProperty displayProperty = new SimpleStringProperty();
-
-	@Override
-	public StringProperty displayProperty() {
-		updateDisplayProperty();
-		return displayProperty;
-	}
-
-	private MidiMapperViewController settingsViewController;
-
-	@Override
-	public NVC getSettingsViewController() {
-		if (settingsViewController == null) {
-			settingsViewController = new MidiMapperViewController();
-		}
-		settingsViewController.setMapper(this);
-		return settingsViewController;
-	}
-
-	private void updateDisplayProperty() {
-		displayProperty.set(toString());
-	}
-
-	@Override
-	public Mapper cloneMapper() throws CloneNotSupportedException {
-		MidiMapper mapper = (MidiMapper) super.clone();
-
-		mapper.command = command;
-		mapper.feedback = feedback.cloneFeedback();
-		mapper.key = key;
-
-		mapper.displayProperty = new SimpleStringProperty();
-
-		return mapper;
-	}
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/MidiMapperFactory.java b/PlayWall/src/main/java/de/tobias/playpad/action/mapper/MidiMapperFactory.java
deleted file mode 100644
index e026a12e65ecc27234558a8081ac756e1be5e4cd..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/MidiMapperFactory.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package de.tobias.playpad.action.mapper;
-
-import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.Strings;
-import de.tobias.playpad.action.mididevice.MidiDeviceImpl;
-import de.tobias.playpad.midi.Midi;
-
-public class MidiMapperFactory extends MapperFactory implements MapperConnectFeedbackable {
-
-	public MidiMapperFactory(String type) {
-		super(type);
-	}
-
-	@Override
-	public MapperViewController getQuickSettingsViewController(Mapper mapper) {
-		return null;
-	}
-
-	@Override
-	public Mapper createNewMapper() {
-		return new MidiMapper(getType());
-	}
-
-	@Override
-	public void initFeedbackType() {
-		MidiDeviceImpl midiDeviceImpl = Midi.getInstance().getMidiDevice();
-		if (midiDeviceImpl != null) {
-			midiDeviceImpl.initDevice();
-		}
-	}
-
-	@Override
-	public void clearFeedbackType() {
-		MidiDeviceImpl midiDeviceImpl = Midi.getInstance().getMidiDevice();
-		if (midiDeviceImpl != null) {
-			midiDeviceImpl.clearFeedback();
-		}
-	}
-
-	// TODO Remove
-	@Override
-	public String toString() {
-		return Localization.getString(Strings.Mapper_Midi_Name);
-	}
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/feedback/DoubleMidiFeedback.java b/PlayWall/src/main/java/de/tobias/playpad/action/mapper/feedback/DoubleMidiFeedback.java
deleted file mode 100644
index 9e930fc25266650f6b1eb8c16c88325e1d07e188..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/feedback/DoubleMidiFeedback.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package de.tobias.playpad.action.mapper.feedback;
-
-import de.tobias.playpad.action.feedback.Feedback;
-import de.tobias.playpad.action.feedback.FeedbackMessage;
-import org.dom4j.Element;
-
-/**
- * Implementierung eines 2 State Feedbacks für MIDI Geräte.
- *
- * @author tobias
- * @since 5.0.0
- */
-public class DoubleMidiFeedback extends Feedback {
-
-	private static final int INIT_FEEDBACK_VALUE = 0;
-
-	private int feedbackDefaultValue; // e.g. Color on an LaunchPad
-	private int feedbackEventValue; // e.g. Color on an LaunchPad
-
-	public DoubleMidiFeedback() {
-		this.feedbackDefaultValue = INIT_FEEDBACK_VALUE;
-		this.feedbackEventValue = INIT_FEEDBACK_VALUE;
-	}
-
-	public DoubleMidiFeedback(int feedbackDefaultValue, int feedbackEventValue) {
-		this.feedbackDefaultValue = feedbackDefaultValue;
-		this.feedbackEventValue = feedbackEventValue;
-	}
-
-	public int getFeedbackDefaultValue() {
-		return feedbackDefaultValue;
-	}
-
-	public int getFeedbackEventValue() {
-		return feedbackEventValue;
-	}
-
-	public void setFeedbackDefaultValue(int feedbackDefaultValue) {
-		this.feedbackDefaultValue = feedbackDefaultValue;
-	}
-
-	public void setFeedbackEventValue(int feedbackEventValue) {
-		this.feedbackEventValue = feedbackEventValue;
-	}
-
-	@Override
-	public int getValueForFeedbackMessage(FeedbackMessage message) {
-		if (message == FeedbackMessage.EVENT) {
-			return feedbackEventValue;
-		} else if (message == FeedbackMessage.OFF) {
-			return 0;
-		} else if (message == FeedbackMessage.STANDARD) {
-			return feedbackDefaultValue;
-		} else {
-			return 0;
-		}
-	}
-
-	@Override
-	public void setFeedback(FeedbackMessage message, int value) {
-		if (message == FeedbackMessage.EVENT) {
-			feedbackEventValue = value;
-		} else if (message == FeedbackMessage.STANDARD) {
-			feedbackDefaultValue = value;
-		}
-	}
-
-	private static final String FEEDBACK_DEFAULT_VALUE = "default";
-	private static final String FEEDBACK_EVENT_VALUE = "event";
-
-	@Override
-	public void load(Element root) {
-		String defaultValue = root.attributeValue(FEEDBACK_DEFAULT_VALUE);
-		if (defaultValue != null) {
-			this.feedbackDefaultValue = Integer.valueOf(defaultValue);
-		}
-		String eventValue = root.attributeValue(FEEDBACK_EVENT_VALUE);
-		if (eventValue != null) {
-			this.feedbackEventValue = Integer.valueOf(eventValue);
-		}
-	}
-
-	@Override
-	public void save(Element root) {
-		root.addAttribute(FEEDBACK_DEFAULT_VALUE, String.valueOf(feedbackDefaultValue));
-		root.addAttribute(FEEDBACK_EVENT_VALUE, String.valueOf(feedbackEventValue));
-	}
-
-	@Override
-	public Feedback cloneFeedback() throws CloneNotSupportedException {
-		DoubleMidiFeedback feedback = (DoubleMidiFeedback) super.clone();
-
-		feedback.feedbackDefaultValue = feedbackDefaultValue;
-		feedback.feedbackEventValue = feedbackEventValue;
-
-		return feedback;
-	}
-
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/feedback/SingleMidiFeedback.java b/PlayWall/src/main/java/de/tobias/playpad/action/mapper/feedback/SingleMidiFeedback.java
deleted file mode 100644
index e637347b1c4dc5eabceaaf163237761e26c18eaa..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/feedback/SingleMidiFeedback.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package de.tobias.playpad.action.mapper.feedback;
-
-import de.tobias.playpad.action.feedback.Feedback;
-import de.tobias.playpad.action.feedback.FeedbackMessage;
-import org.dom4j.Element;
-
-/**
- * Implementierung eines 1 State Feedbacks für MIDI Geräte.
- *
- * @author tobias
- * @since 5.0.0
- */
-public class SingleMidiFeedback extends Feedback {
-
-	private static final int INIT_FEEDBACK_VALUE = 0;
-
-	private int feedbackValue; // e.g. Color on an LaunchPad
-
-	public SingleMidiFeedback() {
-		this.feedbackValue = INIT_FEEDBACK_VALUE;
-	}
-
-	public SingleMidiFeedback(int feedbackValue) {
-		this.feedbackValue = feedbackValue;
-	}
-
-	public int getFeedbackValue() {
-		return feedbackValue;
-	}
-
-	public void setFeedbackValue(int feedbackValue) {
-		this.feedbackValue = feedbackValue;
-	}
-
-	@Override
-	public int getValueForFeedbackMessage(FeedbackMessage message) {
-		switch (message) {
-			case EVENT:
-				return feedbackValue;
-			case OFF:
-				return 0;
-			case STANDARD:
-				return feedbackValue;
-			default:
-				break;
-		}
-		return 0;
-	}
-
-	@Override
-	public void setFeedback(FeedbackMessage message, int value) {
-		if (message == FeedbackMessage.STANDARD) {
-			feedbackValue = value;
-		}
-	}
-
-	private static final String FEEDBACK_VALUE = "default";
-
-	@Override
-	public void load(Element root) {
-		String value = root.attributeValue(FEEDBACK_VALUE);
-		if (value != null) {
-			this.feedbackValue = Integer.valueOf(value);
-		}
-	}
-
-	@Override
-	public void save(Element root) {
-		root.addAttribute(FEEDBACK_VALUE, String.valueOf(feedbackValue));
-	}
-
-	@Override
-	public Feedback cloneFeedback() throws CloneNotSupportedException {
-		SingleMidiFeedback feedback = (SingleMidiFeedback) super.clone();
-
-		feedback.feedbackValue = feedbackValue;
-
-		return feedback;
-	}
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/listener/KeyboardHandler.java b/PlayWall/src/main/java/de/tobias/playpad/action/mapper/listener/KeyboardHandler.java
deleted file mode 100644
index 3dce4167c1d34a7dc145bd4bac3fb00f78296e00..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/listener/KeyboardHandler.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package de.tobias.playpad.action.mapper.listener;
-
-import de.tobias.playpad.action.Action;
-import de.tobias.playpad.action.InputType;
-import de.tobias.playpad.action.MappingUtils;
-import de.tobias.playpad.profile.Profile;
-import de.tobias.playpad.project.Project;
-import de.tobias.playpad.viewcontroller.main.IMainViewController;
-import javafx.event.EventHandler;
-import javafx.scene.input.KeyCode;
-import javafx.scene.input.KeyEvent;
-
-import java.util.List;
-
-public class KeyboardHandler implements EventHandler<KeyEvent> {
-
-	private Project project;
-	private IMainViewController mainViewController;
-
-	public KeyboardHandler(Project project, IMainViewController mainViewController) {
-		this.project = project;
-		this.mainViewController = mainViewController;
-
-		mainViewController.registerKeyboardListener(KeyEvent.ANY, this);
-	}
-
-	// KeyType ist nicht unterstützt.
-	@Override
-	public void handle(KeyEvent event) {
-		if (event.getTarget() == mainViewController.getParent()) {
-			if (!event.isShortcutDown()) {
-				KeyCode code = null;
-				InputType type = null;
-
-				if (event.getEventType() == KeyEvent.KEY_PRESSED) {
-					code = event.getCode();
-					type = InputType.PRESSED;
-
-				} else if (event.getEventType() == KeyEvent.KEY_RELEASED) {
-					code = event.getCode();
-					type = InputType.RELEASED;
-
-				}
-
-				// Only execute this, then the right event is triggered and this var is set
-				if (code != null) {
-					List<Action> actions = MappingUtils.getActionsForKey(code, Profile.currentProfile().getMappings().getActiveMapping());
-
-					executeActions(type, actions);
-				}
-			}
-		}
-	}
-
-	private void executeActions(InputType type, List<Action> actions) {
-		for (Action action : actions) {
-			try {
-				action.performAction(type, project, mainViewController);
-			} catch (Exception e) {
-				e.printStackTrace();
-				// TODO Exception Hadling
-			}
-		}
-	}
-
-	public void setProject(Project project) {
-		this.project = project;
-	}
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/listener/MidiHandler.java b/PlayWall/src/main/java/de/tobias/playpad/action/mapper/listener/MidiHandler.java
deleted file mode 100644
index 7e4d42884c8020e4edd9d4a2c3ba19525eed624b..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/action/mapper/listener/MidiHandler.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package de.tobias.playpad.action.mapper.listener;
-
-import de.tobias.playpad.action.Action;
-import de.tobias.playpad.action.InputType;
-import de.tobias.playpad.action.MappingUtils;
-import de.tobias.playpad.action.mididevice.MidiDeviceImpl;
-import de.tobias.playpad.midi.Midi;
-import de.tobias.playpad.midi.MidiListener;
-import de.tobias.playpad.profile.Profile;
-import de.tobias.playpad.project.Project;
-import de.tobias.playpad.viewcontroller.main.IMainViewController;
-import javafx.application.Platform;
-
-import javax.sound.midi.MidiMessage;
-import java.util.List;
-
-/**
- * Diese Klasse Verwaltet den MIDI Input und führt die Actions aus.
- *
- * @author tobias
- */
-public class MidiHandler implements MidiListener {
-
-	private final Midi midi;
-
-	private IMainViewController mainView;
-	private Project project;
-
-	public MidiHandler(Midi midi, IMainViewController mainView, Project project) {
-		this.midi = midi;
-		this.mainView = mainView;
-		this.project = project;
-	}
-
-	/**
-	 * Midi Input Listener
-	 */
-	@Override
-	public void onMidiAction(MidiMessage message) {
-		int cmd = message.getMessage()[0];
-		int key = message.getMessage()[1];
-
-		// Custom Midi Listener
-		MidiDeviceImpl midiDeviceImpl = midi.getMidiDevice();
-		midiDeviceImpl.onMidiMessage(message);
-
-		InputType type;
-		if (message.getMessage()[2] != 0) {
-			type = InputType.PRESSED;
-		} else {
-			type = InputType.RELEASED;
-		}
-
-		Platform.runLater(() ->
-		{
-			List<Action> actions = MappingUtils.getActionsForMidi(cmd, key, Profile.currentProfile().getMappings().getActiveMapping());
-			for (Action action : actions) {
-				action.performAction(type, project, mainView);
-			}
-		});
-	}
-
-	public void setProject(Project project) {
-		this.project = project;
-	}
-}
\ No newline at end of file
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/settings/CartActionSettingsEntry.java b/PlayWall/src/main/java/de/tobias/playpad/action/settings/CartActionSettingsEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea3451324c18430407d74b4a7ab10b698748057a
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/settings/CartActionSettingsEntry.java
@@ -0,0 +1,27 @@
+package de.tobias.playpad.action.settings;
+
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.Strings;
+import de.tobias.playpad.viewcontroller.IMappingTabViewController;
+import de.tobias.playpad.viewcontroller.actions.CartActionTypeViewController;
+
+public class CartActionSettingsEntry implements ActionSettingsEntry {
+
+	@Override
+	public String getName() {
+		return Localization.getString(Strings.ACTION_CART_NAME);
+	}
+
+	@Override
+	public FontIcon getIcon() {
+		return null;
+	}
+
+	@Override
+	public NVC getDetailSettingsController(Mapping mapping, IMappingTabViewController controller) {
+		return new CartActionTypeViewController(mapping, controller);
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/settings/NavigateActionSettingsEntry.java b/PlayWall/src/main/java/de/tobias/playpad/action/settings/NavigateActionSettingsEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f74877509356efcb842fabcbaa8f9f964ce7efa
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/settings/NavigateActionSettingsEntry.java
@@ -0,0 +1,39 @@
+package de.tobias.playpad.action.settings;
+
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.Strings;
+import de.tobias.playpad.action.actions.NavigateAction;
+import de.tobias.playpad.viewcontroller.IMappingTabViewController;
+
+public class NavigateActionSettingsEntry implements ActionSettingsEntry, ActionSettingsMappable {
+
+	private Action action;
+
+	public NavigateActionSettingsEntry(Action action) {
+		this.action = action;
+	}
+
+	@Override
+	public Action getAction() {
+		return action;
+	}
+
+	@Override
+	public String getName() {
+		return Localization.getString(Strings.ACTION_NAVIGATE_TO_STRING, NavigateAction.NavigationType.valueOf(action).toString());
+	}
+
+	@Override
+	public FontIcon getIcon() {
+		return null;
+	}
+
+	@Override
+	public NVC getDetailSettingsController(Mapping mapping, IMappingTabViewController controller) {
+		return null;
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/settings/NavigateActionTypeSettingsEntry.java b/PlayWall/src/main/java/de/tobias/playpad/action/settings/NavigateActionTypeSettingsEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..34cabea2aafda7327dcea57b0e3848ec077c9137
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/settings/NavigateActionTypeSettingsEntry.java
@@ -0,0 +1,25 @@
+package de.tobias.playpad.action.settings;
+
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.Strings;
+import de.tobias.playpad.viewcontroller.IMappingTabViewController;
+
+public class NavigateActionTypeSettingsEntry implements ActionSettingsEntry {
+	@Override
+	public String getName() {
+		return Localization.getString(Strings.ACTION_NAVIGATE_NAME);
+	}
+
+	@Override
+	public FontIcon getIcon() {
+		return null;
+	}
+
+	@Override
+	public NVC getDetailSettingsController(Mapping mapping, IMappingTabViewController controller) {
+		return null;
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/settings/PageActionSettingsEntry.java b/PlayWall/src/main/java/de/tobias/playpad/action/settings/PageActionSettingsEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..1dcc33f67f6cfe30f42754991c189d6684677b91
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/settings/PageActionSettingsEntry.java
@@ -0,0 +1,39 @@
+package de.tobias.playpad.action.settings;
+
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.Strings;
+import de.tobias.playpad.action.actions.PageAction;
+import de.tobias.playpad.viewcontroller.IMappingTabViewController;
+
+public class PageActionSettingsEntry implements ActionSettingsEntry, ActionSettingsMappable {
+
+	private Action action;
+
+	public PageActionSettingsEntry(Action action) {
+		this.action = action;
+	}
+
+	@Override
+	public Action getAction() {
+		return action;
+	}
+
+	@Override
+	public String getName() {
+		return Localization.getString(Strings.ACTION_PAGE_TO_STRING, String.valueOf(PageAction.getPageForAction(action) + 1));
+	}
+
+	@Override
+	public FontIcon getIcon() {
+		return null;
+	}
+
+	@Override
+	public NVC getDetailSettingsController(Mapping mapping, IMappingTabViewController controller) {
+		return null;
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/settings/PageActionTypeSettingsEntry.java b/PlayWall/src/main/java/de/tobias/playpad/action/settings/PageActionTypeSettingsEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..feab771f8213b5284f50a71b41d08ebcacac8367
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/settings/PageActionTypeSettingsEntry.java
@@ -0,0 +1,25 @@
+package de.tobias.playpad.action.settings;
+
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.Strings;
+import de.tobias.playpad.viewcontroller.IMappingTabViewController;
+
+public class PageActionTypeSettingsEntry implements ActionSettingsEntry {
+	@Override
+	public String getName() {
+		return Localization.getString(Strings.ACTION_PAGE_NAME);
+	}
+
+	@Override
+	public FontIcon getIcon() {
+		return null;
+	}
+
+	@Override
+	public NVC getDetailSettingsController(Mapping mapping, IMappingTabViewController controller) {
+		return null;
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/settings/StopActionTypeSettingsEntry.java b/PlayWall/src/main/java/de/tobias/playpad/action/settings/StopActionTypeSettingsEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..96a7d74a73a91a1f835768b6f46ab2deff581f29
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/settings/StopActionTypeSettingsEntry.java
@@ -0,0 +1,38 @@
+package de.tobias.playpad.action.settings;
+
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.Strings;
+import de.tobias.playpad.viewcontroller.IMappingTabViewController;
+
+public class StopActionTypeSettingsEntry implements ActionSettingsEntry, ActionSettingsMappable {
+
+	private Action action;
+
+	public StopActionTypeSettingsEntry(Action action) {
+		this.action = action;
+	}
+
+	@Override
+	public Action getAction() {
+		return action;
+	}
+
+	@Override
+	public String getName() {
+		return Localization.getString(Strings.ACTION_STOP_NAME);
+	}
+
+	@Override
+	public FontIcon getIcon() {
+		return null;
+	}
+
+	@Override
+	public NVC getDetailSettingsController(Mapping mapping, IMappingTabViewController controller) {
+		return null;
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignHandlerImpl.java b/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignHandlerImpl.java
index eefbc82f5715ba3408603c70318154bd8a88c3d4..4d14df99a3f684c79a02dbfa75b37b259b20a9ff 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignHandlerImpl.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignHandlerImpl.java
@@ -3,7 +3,7 @@ package de.tobias.playpad.design;
 import de.tobias.playpad.design.modern.ModernCartDesignHandler;
 import de.tobias.playpad.design.modern.ModernGlobalDesignHandler;
 
-public class ModernDesignHandlerImpl implements ModernDesign {
+public class ModernDesignHandlerImpl implements ModernDesignHandler {
 
 	private ModernCartDesignHandler cartDesignHandler;
 	private ModernGlobalDesignHandler globalDesignHandler;
diff --git a/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java b/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java
index 551f0097b56d2a2eb1838a561f528ac924dfee68..d06dbc7a7c6619d5dedb9389c9124e680fe0bb53 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java
@@ -2,22 +2,25 @@ package de.tobias.playpad.design;
 
 public class ModernDesignSizeHelper {
 
-	public static final double minWidth = 165;
-	public static final double minHeight = 115;
+	private static final double MIN_WIDTH = 165;
+	private static final double MIN_HEIGHT = 115;
+
+	private ModernDesignSizeHelper() {
+	}
 
 	public static double getMinHeight(int rows) {
-		return rows * minHeight;
+		return rows * MIN_HEIGHT;
 	}
 
 	public static double getMinWidth(int columns) {
-		return columns * minWidth;
+		return columns * MIN_WIDTH;
 	}
 
 	public static double getPadHeight() {
-		return minHeight;
+		return MIN_HEIGHT;
 	}
 
 	public static double getPadWidth() {
-		return minWidth;
+		return MIN_WIDTH;
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/initialize/PlayPadInitializeAbortException.java b/PlayWall/src/main/java/de/tobias/playpad/initialize/PlayPadInitializeAbortException.java
new file mode 100644
index 0000000000000000000000000000000000000000..36fbbd2e7ddff2bea26b6a9d77fc98f842e385c5
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/initialize/PlayPadInitializeAbortException.java
@@ -0,0 +1,14 @@
+package de.tobias.playpad.initialize;
+
+public class PlayPadInitializeAbortException extends RuntimeException {
+
+	private PlayPadInitializeTask task;
+
+	public PlayPadInitializeAbortException(PlayPadInitializeTask task) {
+		this.task = task;
+	}
+
+	public PlayPadInitializeTask getTask() {
+		return task;
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/initialize/PlayPadInitializeTask.java b/PlayWall/src/main/java/de/tobias/playpad/initialize/PlayPadInitializeTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..c979364d11375530570ee5ae60705a9c9e89e194
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/initialize/PlayPadInitializeTask.java
@@ -0,0 +1,9 @@
+package de.tobias.playpad.initialize;
+
+import de.thecodelabs.utils.application.App;
+import de.tobias.playpad.PlayPadImpl;
+
+public interface PlayPadInitializeTask {
+	String name();
+	void run(App app, PlayPadImpl instance);
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/initialize/PlayPadInitializer.java b/PlayWall/src/main/java/de/tobias/playpad/initialize/PlayPadInitializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc4c726337a65c963cd0760b377d329191e662ec
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/initialize/PlayPadInitializer.java
@@ -0,0 +1,72 @@
+package de.tobias.playpad.initialize;
+
+import de.thecodelabs.logger.Logger;
+import de.thecodelabs.utils.application.App;
+import de.thecodelabs.utils.application.ApplicationUtils;
+import de.tobias.playpad.PlayPadImpl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PlayPadInitializer implements Runnable {
+
+	public interface Listener {
+		void startLoading(int count);
+
+		void startTask(PlayPadInitializeTask task);
+
+		void finishTask(PlayPadInitializeTask task);
+
+		void finishLoading();
+
+		void abortedLoading();
+
+		void errorLoading(PlayPadInitializeTask task, Exception e);
+	}
+
+	private List<PlayPadInitializeTask> tasks;
+
+	private PlayPadImpl instance;
+	private Listener listener;
+
+	public PlayPadInitializer(PlayPadImpl instance, Listener listener) {
+		tasks = new ArrayList<>();
+		this.instance = instance;
+		this.listener = listener;
+	}
+
+	public void submit(PlayPadInitializeTask task) {
+		tasks.add(task);
+	}
+
+	public void start() {
+		Thread thread = new Thread(this);
+		thread.setName("PlayPad Initializer Thread");
+		thread.start();
+	}
+
+	@Override
+	public void run() {
+		PlayPadInitializeTask currentTask = null;
+		try {
+			App app = ApplicationUtils.getApplication();
+
+			listener.startLoading(tasks.size());
+
+			for (PlayPadInitializeTask task : tasks) {
+				currentTask = task;
+				listener.startTask(task);
+				task.run(app, instance);
+				listener.finishTask(task);
+			}
+
+			listener.finishLoading();
+		} catch (PlayPadInitializeAbortException e) {
+			listener.abortedLoading();
+			Logger.debug("Initialization aborted at task: " + e.getTask().name());
+		} catch (Exception e) {
+			listener.errorLoading(currentTask, e);
+			Logger.error(e);
+		}
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopEditMode.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopEditMode.java
index 437580d81d1bc8f0fdc563994c68f3683f9d8a5b..50bd255c1a79cf91a35c5a4c1913a9a766943aaf 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopEditMode.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopEditMode.java
@@ -2,5 +2,8 @@ package de.tobias.playpad.layout.desktop;
 
 public enum DesktopEditMode {
 
-	PLAY, DRAG, PAGE, COLOR
+	PLAY,
+	DRAG,
+	PAGE,
+	COLOR
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMainLayoutFactory.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMainLayoutFactory.java
index 35efd1e7c59548761c5cd98faaaedf98eb940cbf..ef01fa96ae6a41cef3f5c94a11d706aa28e51410 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMainLayoutFactory.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMainLayoutFactory.java
@@ -9,7 +9,8 @@ import de.tobias.playpad.viewcontroller.main.MenuToolbarViewController;
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.SimpleObjectProperty;
 
-import java.util.Stack;
+import java.util.ArrayDeque;
+import java.util.Deque;
 
 /**
  * Desktop Implmentierung des Main Layouts.
@@ -22,11 +23,11 @@ public class DesktopMainLayoutFactory extends MainLayoutFactory {
 	private DesktopMenuToolbarViewController desktopMenuToolbarViewController;
 	private ObjectProperty<DesktopEditMode> editMode = new SimpleObjectProperty<>(DesktopEditMode.PLAY);
 
-	private Stack<IPadView> recyclingStack;
+	private Deque<IPadView> recyclingStack;
 
 	public DesktopMainLayoutFactory(String type) {
 		super(type);
-		recyclingStack = new Stack<>();
+		recyclingStack = new ArrayDeque<>();
 	}
 
 	@Override
diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMenuToolbarViewController.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMenuToolbarViewController.java
index c0f010aec5a3c5a4b55e237dc27b8e375c3eb9e2..6c5477e33d821002801d566770e8e6771e5f765e 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMenuToolbarViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMenuToolbarViewController.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.layout.desktop;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
@@ -15,29 +16,31 @@ import de.tobias.playpad.design.modern.ModernGlobalDesignHandler;
 import de.tobias.playpad.layout.desktop.listener.DesktopSearchController;
 import de.tobias.playpad.layout.desktop.listener.PadRemoveMouseListener;
 import de.tobias.playpad.layout.desktop.listener.PageButtonDragHandler;
-import de.tobias.playpad.midi.Midi;
 import de.tobias.playpad.pad.view.IPadView;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.profile.ProfileNotFoundException;
 import de.tobias.playpad.profile.ProfileSettings;
 import de.tobias.playpad.profile.ref.ProfileReference;
+import de.tobias.playpad.profile.ref.ProfileReferenceManager;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.ProjectNotFoundException;
-import de.tobias.playpad.project.ProjectReader;
-import de.tobias.playpad.project.loader.ProjectLoader;
+import de.tobias.playpad.project.ProjectReader.ProjectReaderDelegate.ProfileAbortException;
+import de.tobias.playpad.project.ProjectSettings;
 import de.tobias.playpad.project.page.Page;
 import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.project.ref.ProjectReferenceManager;
 import de.tobias.playpad.registry.Registry;
 import de.tobias.playpad.server.Session;
-import de.tobias.playpad.server.SessionNotExisitsException;
+import de.tobias.playpad.server.SessionNotExistsException;
 import de.tobias.playpad.settings.GlobalSettings;
 import de.tobias.playpad.settings.keys.KeyCollection;
 import de.tobias.playpad.view.main.MainLayoutFactory;
 import de.tobias.playpad.view.main.MenuType;
 import de.tobias.playpad.viewcontroller.AuthViewController;
-import de.tobias.playpad.viewcontroller.dialog.*;
-import de.tobias.playpad.viewcontroller.dialog.project.ProjectLoadDialog;
+import de.tobias.playpad.viewcontroller.dialog.AboutDialog;
+import de.tobias.playpad.viewcontroller.dialog.ModernPluginViewController;
+import de.tobias.playpad.viewcontroller.dialog.PrintDialog;
+import de.tobias.playpad.viewcontroller.dialog.ProfileViewController;
 import de.tobias.playpad.viewcontroller.dialog.project.ProjectManagerDialog;
 import de.tobias.playpad.viewcontroller.dialog.project.ProjectNewDialog;
 import de.tobias.playpad.viewcontroller.dialog.project.ProjectReaderDelegateImpl;
@@ -48,7 +51,6 @@ import de.tobias.playpad.viewcontroller.option.profile.ProfileSettingsViewContro
 import de.tobias.playpad.viewcontroller.option.project.ProjectSettingsViewController;
 import javafx.application.Platform;
 import javafx.beans.binding.Bindings;
-import javafx.beans.binding.StringBinding;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 import javafx.event.ActionEvent;
@@ -80,9 +82,6 @@ import java.util.Optional;
 public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewController
 		implements EventHandler<ActionEvent>, ChangeListener<DesktopEditMode> {
 
-	// TODO Page Buttons gleicher Margin wie pads
-
-	// meuBar
 	@FXML
 	private MenuBar menuBar;
 
@@ -108,8 +107,6 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 	@FXML
 	private MenuItem colorMenu;
 
-	@FXML
-	private MenuItem logMenuItem;
 	@FXML
 	private MenuItem notFoundMenu;
 	@FXML
@@ -159,12 +156,11 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 	private DesktopMainLayoutFactory connect;
 
 	DesktopMenuToolbarViewController(IMainViewController controller, DesktopMainLayoutFactory connect) {
-		super("Header", "view/main/desktop", PlayPadMain.getUiResourceBundle());
+		super("Header", "view/main/desktop", Localization.getBundle());
 		this.mainViewController = controller;
 		this.connect = connect;
 		this.connect.editModeProperty().addListener(this);
 
-		// Ist Zustand herstellen, indem Listener mit dem Initialen Wert bekannt gemacht wird.
 		changed(connect.editModeProperty(), null, connect.getEditMode());
 
 		initLayoutMenu();
@@ -180,16 +176,16 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 		// Edit Mode Buttons
 		editButtons = new SegmentedButton();
 		playButton = new ToggleButton("", new FontIcon(FontAwesomeType.PLAY));
-		playButton.setTooltip(new Tooltip(Localization.getString(Strings.Tooltip_PlayButton)));
+		playButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PLAY_BUTTON)));
 		playButton.setFocusTraversable(false);
 		dragButton = new ToggleButton("", new FontIcon(FontAwesomeType.ARROWS));
-		dragButton.setTooltip(new Tooltip(Localization.getString(Strings.Tooltip_DragButton)));
+		dragButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_DRAG_BUTTON)));
 		dragButton.setFocusTraversable(false);
 		pageButton = new ToggleButton("", new FontIcon(FontAwesomeType.FILES_ALT));
-		pageButton.setTooltip(new Tooltip(Localization.getString(Strings.Tooltip_PageButton)));
+		pageButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_BUTTON)));
 		pageButton.setFocusTraversable(false);
 		colorButton = new ToggleButton("", new FontIcon(FontAwesomeType.PENCIL));
-		colorButton.setTooltip(new Tooltip(Localization.getString(Strings.Tooltip_ColorButton)));
+		colorButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_COLOR_BUTTON)));
 		colorButton.setFocusTraversable(false);
 		editButtons.getButtons().addAll(playButton, dragButton, pageButton, colorButton);
 		editButtons.getToggleGroup().selectedToggleProperty().addListener((a, b, c) ->
@@ -222,7 +218,7 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 				initPageButtons();
 				highlightPageButton(mainViewController.getPage());
 			} else {
-				showErrorMessage(Localization.getString(Strings.Error_Project_PageCount));
+				showErrorMessage(Localization.getString(Strings.ERROR_PROJECT_PAGE_COUNT, ProjectSettings.MAX_PAGES));
 			}
 		});
 
@@ -344,16 +340,9 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 
 		for (int i = 0; i < openProject.getPages().size(); i++) {
 			Page page = openProject.getPage(i);
-			Button button = new Button();
 
-			StringBinding nameBinding = Bindings.when(page.nameProperty().isEmpty())
-					.then(Localization.getString(Strings.UI_Window_Main_PageButton, (i + 1)))
-					.otherwise(page.nameProperty());
-			button.textProperty().bind(nameBinding);
-			button.setUserData(i);
+			Button button = createPageButton(page, i);
 			button.setOnDragOver(new PageButtonDragHandler(mainViewController, i));
-			button.setFocusTraversable(false);
-			button.setOnAction(this);
 			pageHBox.getChildren().add(button);
 		}
 	}
@@ -486,7 +475,7 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 
 				if (newNode instanceof Button && connect.getEditMode() == DesktopEditMode.PAGE) { // Nur bei Drag And Drop mode
 					Button button = (Button) newNode;
-					DesktopPageEditButtonView editBox = new DesktopPageEditButtonView(this, openProject.getPage(index), button);
+					DesktopPageEditButtonView editBox = new DesktopPageEditButtonView(this, mainViewController, openProject.getPage(index));
 					button.setGraphic(editBox);
 				}
 			}
@@ -501,11 +490,9 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 			ProjectNewDialog dialog = new ProjectNewDialog(mainViewController.getStage());
 			dialog.showAndWait().ifPresent(projectReference -> {
 				try {
-					ProjectLoader loader = new ProjectLoader(projectReference);
-					Project project = loader.load();
-					PlayPadMain.getProgramInstance().openProject(project, null);
-				} catch (DocumentException | IOException | ProjectNotFoundException | ProfileNotFoundException | ProjectReader.ProjectReaderDelegate.ProfileAbortException e) {
-					e.printStackTrace();
+					PlayPadMain.getProgramInstance().openProject(projectReference, null);
+				} catch (DocumentException | IOException | ProjectNotFoundException | ProfileNotFoundException | ProfileAbortException e) {
+					Logger.error(e);
 				}
 			});
 		});
@@ -523,36 +510,31 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 			if (result.isPresent()) {
 				ProjectReference ref = result.get();
 
-				ProjectReader.ProjectReaderDelegate delegate = ProjectReaderDelegateImpl.getInstance(stage);
 				try {
-					ProjectLoader loader = new ProjectLoader(result.get());
-					loader.setDelegate(delegate);
-					loader.setListener(new ProjectLoadDialog());
-					Project project = loader.load();
-					PlayPadMain.getProgramInstance().openProject(project, null);
+					PlayPadMain.getProgramInstance().openProject(ref, null);
 
 					createRecentDocumentMenuItems();
 				} catch (ProfileNotFoundException e) {
-					e.printStackTrace();
+					Logger.error(e);
 
 					// Error Message
-					String errorMessage = Localization.getString(Strings.Error_Profile_NotFound, ref.getProfileReference(),
+					String errorMessage = Localization.getString(Strings.ERROR_PROFILE_NOT_FOUND, ref.getProfileReference(),
 							e.getLocalizedMessage());
 					mainViewController.showError(errorMessage);
 
 					// Neues Profile wählen
 					ProfileReference profile = null;
 					try {
-						profile = delegate.getProfileReference();
-					} catch (ProjectReader.ProjectReaderDelegate.ProfileAbortException ignored) {
+						profile = ProjectReaderDelegateImpl.getInstance(stage).getProfileReference();
+					} catch (ProfileAbortException ignored) {
 					}
 					ref.setProfileReference(profile);
 				} catch (ProjectNotFoundException e) {
-					e.printStackTrace();
-					mainViewController.showError(Localization.getString(Strings.Error_Project_NotFound, ref, e.getLocalizedMessage()));
+					Logger.error(e);
+					mainViewController.showError(Localization.getString(Strings.ERROR_PROJECT_NOT_FOUND, ref, e.getLocalizedMessage()));
 				} catch (Exception e) {
-					e.printStackTrace();
-					mainViewController.showError(Localization.getString(Strings.Error_Project_Open, ref, e.getLocalizedMessage()));
+					Logger.error(e);
+					mainViewController.showError(Localization.getString(Strings.ERROR_PROJECT_OPEN, ref, e.getLocalizedMessage()));
 				}
 			}
 		});
@@ -561,11 +543,16 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 	@FXML
 	void saveMenuHandler(ActionEvent event) {
 		try {
-			ProjectReferenceManager.saveProject(openProject);
-			mainViewController.notify(Localization.getString(Strings.Standard_File_Save), PlayPadMain.displayTimeMillis);
+			ProjectReferenceManager.saveProjects();
+			ProjectReferenceManager.saveSingleProject(openProject);
+			ProfileReferenceManager.saveProfiles();
+			Profile.currentProfile().save();
+			PlayPadPlugin.getInstance().getGlobalSettings().save();
+
+			mainViewController.notify(Localization.getString(Strings.STANDARD_FILE_SAVE), PlayPadMain.NOTIFICATION_DISPLAY_TIME);
 		} catch (IOException e) {
-			mainViewController.showError(Localization.getString(Strings.Error_Project_Save));
-			e.printStackTrace();
+			mainViewController.showError(Localization.getString(Strings.ERROR_PROJECT_SAVE));
+			Logger.error(e);
 		}
 	}
 
@@ -587,17 +574,18 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 
 	@FXML
 	void logoutMenuHandler(ActionEvent event) {
-		AuthViewController authViewController = new AuthViewController(Localization.getString(Strings.Auth_Logout), (username, password) -> {
-			Session session = Session.load();
-			try {
-				PlayPadPlugin.getServerHandler().getServer().logout(username, password, session.getKey());
-				session.delete();
-				Platform.exit();
-				return true;
-			} catch (SessionNotExisitsException e) {
-				return false;
-			}
-		});
+		AuthViewController authViewController = new AuthViewController(getContainingWindow(), Localization.getString(Strings.AUTH_LOGOUT),
+				(username, password) -> {
+					Session session = Session.load();
+					try {
+						PlayPadPlugin.getServerHandler().getServer().logout(username, password, session.getKey());
+						session.delete();
+						Platform.exit();
+						return true;
+					} catch (SessionNotExistsException e) {
+						return false;
+					}
+				});
 		authViewController.showStage();
 	}
 
@@ -621,16 +609,9 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 		connect.setEditMode(DesktopEditMode.COLOR);
 	}
 
-	@FXML
-	void logMenuItemHandler(ActionEvent event) {
-		PlayoutLogViewController playoutLogViewController = new PlayoutLogViewController(mainViewController.getStage());
-		playoutLogViewController.getStageContainer().ifPresent(NVCStage::showAndWait);
-	}
-
 	@FXML
 	void notFoundMenuHandler(ActionEvent event) {
-		PathMatchDialog dialog = new PathMatchDialog(openProject, mainViewController.getStage());
-		dialog.showAndWait();
+		showNotMediaFoundDialog();
 	}
 
 	@FXML
@@ -650,16 +631,18 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 			Runnable onFinish = () -> projectSettingsViewController = null;
 
 			projectSettingsViewController = new ProjectSettingsViewController(mainViewController.getScreen(), mainStage, openProject, onFinish);
-
-			projectSettingsViewController.getStageContainer().ifPresent(NVCStage::show);
-		} else if (projectSettingsViewController.getStageContainer().isPresent() && projectSettingsViewController.getStageContainer().get().getStage().isShowing()) {
-			projectSettingsViewController.getStageContainer().get().getStage().toFront();
+			projectSettingsViewController.showStage();
+		} else {
+			projectSettingsViewController.getStageContainer().ifPresent(stage -> {
+				if (stage.getStage().isShowing()) {
+					stage.getStage().toFront();
+				}
+			});
 		}
 	}
 
 	@FXML
 	void profileSettingsHandler(ActionEvent event) {
-		Midi midi = Midi.getInstance();
 		Project currentProject = PlayPadMain.getProgramInstance().getCurrentProject();
 		GlobalSettings settings = PlayPadPlugin.getInstance().getGlobalSettings();
 		if (settings.isLiveMode() && settings.isLiveModeSettings() && currentProject.getActivePlayers() > 0) {
@@ -669,19 +652,19 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 		if (profileSettingsViewController == null) {
 			Stage mainStage = mainViewController.getStage();
 
-			Runnable onFinish = () ->
-			{
-				midi.setListener(mainViewController.getMidiHandler());
-
+			Runnable onFinish = () -> {
 				profileSettingsViewController = null;
 				mainStage.toFront();
 			};
 
 			profileSettingsViewController = new ProfileSettingsViewController(mainStage, openProject, onFinish);
-
-			profileSettingsViewController.getStageContainer().ifPresent(NVCStage::show);
-		} else if (profileSettingsViewController.getStageContainer().isPresent() && profileSettingsViewController.getStageContainer().get().getStage().isShowing()) {
-			profileSettingsViewController.getStageContainer().get().getStage().toFront();
+			profileSettingsViewController.showStage();
+		} else {
+			profileSettingsViewController.getStageContainer().ifPresent(stage -> {
+				if (stage.getStage().isShowing()) {
+					stage.getStage().toFront();
+				}
+			});
 		}
 	}
 
@@ -690,8 +673,7 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 		if (globalSettingsViewController == null) {
 
 			Stage mainStage = mainViewController.getStage();
-			Runnable onFinish = () ->
-			{
+			Runnable onFinish = () -> {
 				globalSettingsViewController = null;
 				mainStage.toFront();
 			};
@@ -699,7 +681,11 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 			globalSettingsViewController = new GlobalSettingsViewController(mainStage, onFinish);
 			globalSettingsViewController.getStageContainer().ifPresent(NVCStage::show);
 		} else {
-			globalSettingsViewController.getStageContainer().ifPresent(e -> e.getStage().toFront());
+			globalSettingsViewController.getStageContainer().ifPresent(stage -> {
+				if (stage.getStage().isShowing()) {
+					stage.getStage().toFront();
+				}
+			});
 		}
 	}
 
@@ -718,18 +704,19 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 
 	@FXML
 	void searchPadHandler(ActionEvent event) {
-		TextField field = TextFields.createClearableTextField();
-		field.setPromptText(Localization.getString(Strings.Search_Placeholder));
+		TextField searchField = TextFields.createClearableTextField();
+		searchField.setPromptText(Localization.getString(Strings.SEARCH_PLACEHOLDER));
 
-		Button button = new Button(Localization.getString(Strings.Search_Button));
+		Button button = new Button(Localization.getString(Strings.SEARCH_BUTTON));
 		button.setDefaultButton(true);
 		Project project = PlayPadMain.getProgramInstance().getCurrentProject();
-		button.setOnAction(new DesktopSearchController(project, field, mainViewController));
+		button.setOnAction(new DesktopSearchController(project, searchField, mainViewController));
 
-		HBox box = new HBox(14, field, button);
+		HBox box = new HBox(14, searchField, button);
 		box.setAlignment(Pos.CENTER_LEFT);
 
 		NotificationPane pane = mainViewController.getNotificationPane();
+		pane.setOnShown(e -> searchField.requestFocus());
 		pane.show("", box);
 	}
 
@@ -742,21 +729,21 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 
 	@FXML
 	void showChangelogMenuHandler(ActionEvent event) {
-		String website = ApplicationUtils.getApplication().getInfo().getUserInfo().getString(AppUserInfoStrings.CHANGELOG_URL);
+		String website = ApplicationUtils.getApplication().getUserInfo(AppUserInfoStrings.class).changelogURL();
 		try {
 			Desktop.getDesktop().browse(new URI(website));
 		} catch (IOException | URISyntaxException e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 
 	@FXML
-	void visiteWebsiteMenuHandler(ActionEvent event) {
-		String website = ApplicationUtils.getApplication().getInfo().getUserInfo().getString(AppUserInfoStrings.WEBSITE);
+	void visitWebsiteMenuHandler(ActionEvent event) {
+		String website = ApplicationUtils.getApplication().getUserInfo(AppUserInfoStrings.class).website();
 		try {
 			Desktop.getDesktop().browse(new URI(website));
 		} catch (IOException | URISyntaxException e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 
@@ -779,45 +766,47 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 	@Override
 	public void handle(ActionEvent event) {
 		if (event.getSource() instanceof Button) {
-			Button button = (Button) event.getSource();
-			int page = (int) button.getUserData();
-			mainViewController.showPage(page);
+			handlePageButton(event);
 		} else if (event.getSource() instanceof MenuItem) {
-			// Zuletzt verwendete Projects
-			doAction(() ->
-			{
-				// TODO Rewrite mit openProject von BasicMenuToolbarViewController
-				MenuItem item = (MenuItem) event.getSource();
-				ProjectReference ref = (ProjectReference) item.getUserData();
-
-				ProjectReader.ProjectReaderDelegate delegate = ProjectReaderDelegateImpl.getInstance(getContainingWindow());
-				try {
-					// Speichern das alte Project in mvc.setProject(Project)
-					ProjectLoader loader = new ProjectLoader(ref);
-					loader.setDelegate(delegate);
-					loader.setListener(new ProjectLoadDialog());
-					Project project = loader.load();
-					PlayPadMain.getProgramInstance().openProject(project, null);
-				} catch (ProfileNotFoundException e) {
-					e.printStackTrace();
-					mainViewController.showError(
-							Localization.getString(Strings.Error_Profile_NotFound, ref.getProfileReference(), e.getLocalizedMessage()));
+			handleLastOpenProjectMenuItems(event);
+		}
+	}
 
-					// Neues Profile wählen
-					ProfileReference profile = null;
-					try {
-						profile = delegate.getProfileReference();
-					} catch (ProjectReader.ProjectReaderDelegate.ProfileAbortException ignored) {
-					}
-					ref.setProfileReference(profile);
-				} catch (ProjectNotFoundException e) {
-					e.printStackTrace();
-					mainViewController.showError(Localization.getString(Strings.Error_Project_NotFound, ref, e.getLocalizedMessage()));
-				} catch (Exception e) {
-					e.printStackTrace();
-					mainViewController.showError(Localization.getString(Strings.Error_Project_Open, ref, e.getLocalizedMessage()));
+	private void handleLastOpenProjectMenuItems(ActionEvent event) {
+		doAction(() ->
+		{
+			// TODO Rewrite mit openProject von BasicMenuToolbarViewController
+			MenuItem item = (MenuItem) event.getSource();
+			ProjectReference ref = (ProjectReference) item.getUserData();
+
+			try {
+				// Speichern das alte Project in mvc.setProject(Project)
+				PlayPadMain.getProgramInstance().openProject(ref, null);
+			} catch (ProfileNotFoundException e) {
+				Logger.error(e);
+				mainViewController.showError(
+						Localization.getString(Strings.ERROR_PROFILE_NOT_FOUND, ref.getProfileReference(), e.getLocalizedMessage()));
+
+				// Neues Profile wählen
+				ProfileReference profile = null;
+				try {
+					profile = ProjectReaderDelegateImpl.getInstance(getContainingWindow()).getProfileReference();
+				} catch (ProfileAbortException ignored) {
 				}
-			});
-		}
+				ref.setProfileReference(profile);
+			} catch (ProjectNotFoundException e) {
+				Logger.error(e);
+				mainViewController.showError(Localization.getString(Strings.ERROR_PROJECT_NOT_FOUND, ref, e.getLocalizedMessage()));
+			} catch (Exception e) {
+				Logger.error(e);
+				mainViewController.showError(Localization.getString(Strings.ERROR_PROJECT_OPEN, ref, e.getLocalizedMessage()));
+			}
+		});
+	}
+
+	private void handlePageButton(ActionEvent event) {
+		Button button = (Button) event.getSource();
+		int page = (int) button.getUserData();
+		mainViewController.showPage(page);
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopPageEditButtonView.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopPageEditButtonView.java
index afaf1bd51e2f0ce6204ccea7b63f882e80b99493..94c9d6cb155705a2eb67eb7b6bcef255ef71517f 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopPageEditButtonView.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopPageEditButtonView.java
@@ -29,37 +29,38 @@ public class DesktopPageEditButtonView extends HBox implements EventHandler<Acti
 	private Button cloneButton;
 	private Button deleteButton;
 
-	private transient Button pageButton;
 	private transient MenuToolbarViewController controller;
+	private transient IMainViewController mainViewController;
 
-	DesktopPageEditButtonView(MenuToolbarViewController controller, Page page, Button pageButton) {
+	DesktopPageEditButtonView(MenuToolbarViewController controller, IMainViewController mainViewController, Page page) {
 		this.page = page;
-		this.pageButton = pageButton;
+
 		this.controller = controller;
+		this.mainViewController = mainViewController;
 
 		leftMoveButton = new Button("", new FontIcon(FontAwesomeType.ARROW_LEFT));
 		leftMoveButton.setOnAction(this);
-		leftMoveButton.setTooltip(new Tooltip(Localization.getString(Strings.Tooltip_Page_LeftMove)));
+		leftMoveButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_LEFT_MOVE)));
 		leftMoveButton.setFocusTraversable(false);
 
 		rightMoveButton = new Button("", new FontIcon(FontAwesomeType.ARROW_RIGHT));
 		rightMoveButton.setOnAction(this);
-		rightMoveButton.setTooltip(new Tooltip(Localization.getString(Strings.Tooltip_Page_RightMove)));
+		rightMoveButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_RIGHT_MOVE)));
 		rightMoveButton.setFocusTraversable(false);
 
 		editTextButton = new Button("", new FontIcon(FontAwesomeType.EDIT));
 		editTextButton.setOnAction(this);
-		editTextButton.setTooltip(new Tooltip(Localization.getString(Strings.Tooltip_Page_Rename)));
+		editTextButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_RENAME)));
 		editTextButton.setFocusTraversable(false);
 
 		cloneButton = new Button("", new FontIcon(FontAwesomeType.COPY));
 		cloneButton.setOnAction(this);
-		cloneButton.setTooltip(new Tooltip(Localization.getString(Strings.Tooltip_Page_Clone)));
+		cloneButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_CLONE)));
 		cloneButton.setFocusTraversable(false);
 
 		deleteButton = new Button("", new FontIcon(FontAwesomeType.TRASH));
 		deleteButton.setOnAction(this);
-		deleteButton.setTooltip(new Tooltip(Localization.getString(Strings.Tooltip_Page_Delete)));
+		deleteButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_DELETE)));
 		deleteButton.setFocusTraversable(false);
 
 		getChildren().addAll(leftMoveButton, rightMoveButton, editTextButton, cloneButton, deleteButton);
@@ -107,35 +108,30 @@ public class DesktopPageEditButtonView extends HBox implements EventHandler<Acti
 
 			event.consume();
 		} else if (event.getSource() == cloneButton) {
-			try {
-				Page clone = page.clone();
+			Page clone = page.copy();
 
-				// Show Rename dialog for cloned page
-				boolean success = showPageNameDialog(clone);
+			// Show Rename dialog for cloned page
+			boolean success = showPageNameDialog(clone);
 
-				if (!success) {
-					return;
-				}
+			if (!success) {
+				return;
+			}
 
-				Project project = page.getProject();
-				project.addPage(clone);
+			Project project = page.getProject();
+			project.addPage(clone);
 
-				controller.initPageButtons();
-				controller.highlightPageButton(page.getPosition());
-				event.consume();
-			} catch (CloneNotSupportedException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			}
+			controller.initPageButtons();
+			mainViewController.showPage(clone);
+			event.consume();
 		} else if (event.getSource() == deleteButton) {
 			Alert alert = new Alert(AlertType.CONFIRMATION);
 
-			alert.setHeaderText(Localization.getString(Strings.UI_Dialog_Page_Delete_Header));
-			alert.setContentText(Localization.getString(Strings.UI_Dialog_Page_Delete_Content));
+			alert.setHeaderText(Localization.getString(Strings.UI_DIALOG_PAGE_DELETE_HEADER));
+			alert.setContentText(Localization.getString(Strings.UI_DIALOG_PAGE_DELETE_CONTENT));
 			alert.initOwner(controller.getContainingWindow());
 			alert.initModality(Modality.WINDOW_MODAL);
 			Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
-			PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+			stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 			Optional<ButtonType> result = alert.showAndWait();
 			result.filter(r -> r == ButtonType.OK).ifPresent(r ->
@@ -153,12 +149,12 @@ public class DesktopPageEditButtonView extends HBox implements EventHandler<Acti
 	private boolean showPageNameDialog(Page page) {
 		TextInputDialog dialog = new TextInputDialog(page.getName());
 
-		dialog.setHeaderText(Localization.getString(Strings.UI_Dialog_Page_Name_Header));
-		dialog.setContentText(Localization.getString(Strings.UI_Dialog_Page_Name_Content));
+		dialog.setHeaderText(Localization.getString(Strings.UI_DIALOG_PAGE_NAME_HEADER));
+		dialog.setContentText(Localization.getString(Strings.UI_DIALOG_PAGE_NAME_CONTENT));
 		dialog.initOwner(controller.getContainingWindow());
 		dialog.initModality(Modality.WINDOW_MODAL);
 		Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		Optional<String> result = dialog.showAndWait();
 		result.ifPresent(page::setName);
diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/listener/DesktopSearchController.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/listener/DesktopSearchController.java
index 9bc3402d4be3d2d5109fce90c7dd9dc66e689fe5..a00f2083d8c9c74070412de447ddfc6212d9da17 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/listener/DesktopSearchController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/listener/DesktopSearchController.java
@@ -1,5 +1,7 @@
 package de.tobias.playpad.layout.desktop.listener;
 
+import de.thecodelabs.utils.application.ApplicationUtils;
+import de.thecodelabs.utils.ui.Alerts;
 import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.pad.Pad;
@@ -7,6 +9,7 @@ import de.tobias.playpad.project.Project;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
+import javafx.scene.control.Alert;
 import javafx.scene.control.TextField;
 
 import java.util.List;
@@ -47,7 +50,12 @@ public class DesktopSearchController implements EventHandler<ActionEvent> {
 		}
 
 		if (searchResult.isEmpty()) {
-			mainView.showInfoMessage(Localization.getString(Strings.Search_Alert_NoMatches));
+			Alerts.getInstance().createAlert(
+					Alert.AlertType.INFORMATION, ApplicationUtils.getApplication().getInfo().getName(),
+					Localization.getString(Strings.SEARCH_ALERT_NO_MATCHES_HEADER),
+					Localization.getString(Strings.SEARCH_ALERT_NO_MATCHES_CONTENT, currentSearchTerm),
+					mainView.getStage()
+			).showAndWait();
 			return;
 		}
 
@@ -58,7 +66,12 @@ public class DesktopSearchController implements EventHandler<ActionEvent> {
 				result.getController().getView().highlightView(HIGHLIGHT_DURATION);
 			}
 		} else {
-			mainView.showInfoMessage(Localization.getString(Strings.Search_Alert_NoMatches));
+			Alerts.getInstance().createAlert(
+					Alert.AlertType.INFORMATION, ApplicationUtils.getApplication().getInfo().getName(),
+					Localization.getString(Strings.SEARCH_ALERT_NO_MATCHES_HEADER),
+					Localization.getString(Strings.SEARCH_ALERT_NO_MATCHES_CONTENT, currentSearchTerm),
+					mainView.getStage()
+			).showAndWait();
 			currentIndex = 0;
 		}
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadDragListener.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadDragListener.java
index eac9e7add5a6e0b5bab06f7157663d96145b06d4..86347f6aa5f964cc26359dbbe7d49bbfdc102ad5 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadDragListener.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadDragListener.java
@@ -4,6 +4,7 @@ import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.layout.desktop.DesktopEditMode;
 import de.tobias.playpad.layout.desktop.DesktopMainLayoutFactory;
 import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.pad.content.PadContentFactory;
 import de.tobias.playpad.pad.content.PadContentRegistry;
 import de.tobias.playpad.pad.drag.PadDragMode;
@@ -11,7 +12,6 @@ import de.tobias.playpad.pad.view.IPadView;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.page.PadIndex;
-import de.tobias.playpad.registry.NoSuchComponentException;
 import de.tobias.playpad.server.sync.command.CommandManager;
 import de.tobias.playpad.server.sync.command.Commands;
 import de.tobias.playpad.settings.GlobalSettings;
@@ -38,7 +38,6 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> {
 	private final Pane padView; // Node der PadView
 
 	private DesktopMainLayoutFactory connect;
-	private static Project project;
 
 	private PadDragOptionView padHud;
 	private FileDragOptionView fileHud;
@@ -89,28 +88,24 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> {
 				}
 
 				// Build In Filesupport
-				try {
-					PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents();
-					Set<PadContentFactory> connects = registry.getPadContentConnectsForFile(file.toPath());
-
-					if (!connects.isEmpty()) {
-						if (fileHud == null) {
-							fileHud = new FileDragOptionView(padView);
-						}
-						fileHud.showDropOptions(connects);
-
-						event.acceptTransferModes(TransferMode.LINK);
-						return;
+				PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents();
+				Set<PadContentFactory> connects = registry.getPadContentConnectsForFile(file.toPath());
+
+				if (!connects.isEmpty()) {
+					if (fileHud == null) {
+						fileHud = new FileDragOptionView(padView);
 					}
-				} catch (NoSuchComponentException e) {
-					e.printStackTrace();
+					fileHud.showDropOptions(connects);
+
+					event.acceptTransferModes(TransferMode.LINK);
+					return;
 				}
 			}
 		}
 
 		// Drag and Drop von Pads
 		if (event.getDragboard().hasContent(dataFormat)) {
-			PadIndex index = (PadIndex) event.getDragboard().getContent(dataFormat); // TODO Check cast
+			PadIndex index = (PadIndex) event.getDragboard().getContent(dataFormat);
 			if (!currentPad.getPadIndex().equals(index)) {
 
 				Collection<PadDragMode> connects = PlayPadPlugin.getRegistries().getDragModes().getComponents();
@@ -139,6 +134,8 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> {
 
 	// Drag Content ist los gelassen am Ziel
 	private void dragDropped(DragEvent event) {
+		Project project = PlayPadPlugin.getInstance().getCurrentProject();
+
 		Dragboard db = event.getDragboard();
 		boolean success = false;
 
@@ -148,6 +145,12 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> {
 
 			PadContentFactory connect = fileHud.getSelectedConnect();
 			if (connect != null) {
+				// stop pad if playing
+				if(currentPad.getContent() != null && currentPad.getStatus().equals(PadStatus.PLAY)) {
+					currentPad.getContent().stop();
+					currentPad.stop();
+				}
+
 				if (currentPad.getContent() == null || !currentPad.getContent().getType().equals(connect.getType())) {
 					currentPad.setContentType(connect.getType());
 				}
@@ -232,9 +235,4 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> {
 		}
 		return false;
 	}
-
-	public static void setProject(Project project) {
-		DesktopPadDragListener.project = project;
-	}
-
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadView.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadView.java
index e3e4b776c8ac0d96d8d07d89b76bded206b095d0..6d0b659e2464756bf60529e5533697aa164c9611 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadView.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadView.java
@@ -1,11 +1,13 @@
 package de.tobias.playpad.layout.desktop.pad;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.ui.animation.PulseTranslation;
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
 import de.thecodelabs.utils.ui.scene.BusyView;
+import de.thecodelabs.utils.util.ColorUtils;
 import de.tobias.playpad.PlayPadPlugin;
-import de.tobias.playpad.design.DesignColorAssociator;
+import de.tobias.playpad.design.FeedbackDesignColorSuggester;
 import de.tobias.playpad.layout.desktop.DesktopMainLayoutFactory;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadStatus;
@@ -19,7 +21,6 @@ import de.tobias.playpad.pad.viewcontroller.IPadViewController;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.project.page.PadIndex;
 import de.tobias.playpad.registry.NoSuchComponentException;
-import de.tobias.playpad.util.ColorUtils;
 import de.tobias.playpad.view.EmptyPadView;
 import de.tobias.playpad.view.PseudoClasses;
 import javafx.beans.property.Property;
@@ -59,6 +60,9 @@ public class DesktopPadView implements IPadView {
 	private VBox root;
 	private BusyView busyView;
 
+	private VBox cueInContainer;
+	private Label cueInLayer;
+
 	private transient DesktopPadViewController controller; // Reference to its controller
 
 	public DesktopPadView(DesktopMainLayoutFactory connect) {
@@ -71,6 +75,10 @@ public class DesktopPadView implements IPadView {
 		root = new VBox();
 		busyView = new BusyView(superRoot);
 
+		cueInLayer = new Label();
+		cueInLayer.prefHeightProperty().bind(root.heightProperty());
+		cueInContainer = new VBox(cueInLayer);
+
 		indexLabel = new Label();
 
 		loopLabel = new Label(); // Active über Visible
@@ -128,7 +136,7 @@ public class DesktopPadView implements IPadView {
 		buttonBox = new HBox(); // childern in addDefaultButton()
 
 		root.getChildren().addAll(infoBox, preview, playBar, buttonBox);
-		superRoot.getChildren().addAll(root, notFoundLabel);
+		superRoot.getChildren().addAll(cueInContainer, root, notFoundLabel);
 	}
 
 	@Override
@@ -141,7 +149,7 @@ public class DesktopPadView implements IPadView {
 		superRoot.setUserData(pad);
 
 		if (previewContent != null) {
-			previewContent.deinit();
+			previewContent.deInit();
 		}
 
 		if (pad != null) {
@@ -164,8 +172,7 @@ public class DesktopPadView implements IPadView {
 					preview.getChildren().setAll(node);
 					return;
 				} catch (NoSuchComponentException e) {
-					// TODO Auto-generated catch block
-					e.printStackTrace();
+					Logger.error(e);
 				}
 			}
 		}
@@ -209,6 +216,7 @@ public class DesktopPadView implements IPadView {
 	@Override
 	public void pseudoClassState(PseudoClass pseudoClass, boolean active) {
 		superRoot.pseudoClassStateChanged(pseudoClass, active);
+		cueInLayer.pseudoClassStateChanged(pseudoClass, active);
 		indexLabel.pseudoClassStateChanged(pseudoClass, active);
 		timeLabel.pseudoClassStateChanged(pseudoClass, active);
 		loopLabel.getGraphic().pseudoClassStateChanged(pseudoClass, active);
@@ -231,7 +239,6 @@ public class DesktopPadView implements IPadView {
 	@Override
 	public void setStyle(String string) {
 		superRoot.setStyle(string);
-
 	}
 
 	@Override
@@ -271,7 +278,8 @@ public class DesktopPadView implements IPadView {
 		triggerLabel.setVisible(hasTriggerItems);
 	}
 
-	void setTime(String time) {
+	void
+	setTime(String time) {
 		if (time == null) {
 			timeLabel.setText("");
 		} else {
@@ -318,6 +326,7 @@ public class DesktopPadView implements IPadView {
 	@Override
 	public void applyStyleClasses(PadIndex index) {
 		superRoot.getStyleClass().addAll("pad", "pad" + index);
+		cueInLayer.getStyleClass().addAll("pad-cue-in", "pad" + index + "-cue-in");
 
 		indexLabel.getStyleClass().addAll("pad-index", "pad" + index + "-index", "pad-info", "pad" + index + "-info");
 		timeLabel.getStyleClass().addAll("pad-time", "pad" + index + "-time", "pad-info", "pad" + index + "-info");
@@ -348,6 +357,7 @@ public class DesktopPadView implements IPadView {
 	@Override
 	public void removeStyleClasses() {
 		superRoot.getStyleClass().removeIf(c -> c.startsWith("pad"));
+		cueInLayer.getStyleClass().removeIf(c -> c.startsWith("pad"));
 
 		indexLabel.getStyleClass().removeIf(c -> c.startsWith("pad"));
 		timeLabel.getStyleClass().removeIf(c -> c.startsWith("pad"));
@@ -391,7 +401,7 @@ public class DesktopPadView implements IPadView {
 
 	void clearPreviewContentView() {
 		if (previewContent != null) {
-			previewContent.deinit();
+			previewContent.deInit();
 		}
 		setContentView(null);
 	}
@@ -406,10 +416,15 @@ public class DesktopPadView implements IPadView {
 		playBar.setProgress(value);
 	}
 
+	@Override
+	public void setCueInProgress(double milliSeconds) {
+		cueInLayer.setPrefWidth(root.getWidth() * milliSeconds);
+	}
+
 	@Override
 	public void showNotFoundIcon(Pad pad, boolean show) {
 		if (show) {
-			DesignColorAssociator associator;
+			FeedbackDesignColorSuggester associator;
 			if (pad.getPadSettings().isCustomDesign()) {
 				associator = pad.getPadSettings().getDesign();
 			} else {
@@ -417,8 +432,8 @@ public class DesktopPadView implements IPadView {
 			}
 
 			if (associator != null) {
-				Color color = associator.getAssociatedStandardColor();
-				notFoundLabel.setColor(ColorUtils.getWarningSignColor(color));
+				Color color = associator.getDesignDefaultColor();
+				notFoundLabel.setColor(ColorUtils.getAppropriateTextColor(color));
 			} else {
 				notFoundLabel.setColor(Color.RED);
 			}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadViewController.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadViewController.java
index b66827b8fd353ec0ceb51452cbac26407dae9d27..21700d33e55e8d33b0dd52bc5e10075c6f48b331 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadViewController.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.layout.desktop.pad;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.util.Localization;
@@ -110,7 +111,7 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 			padDragListener = new DesktopPadDragListener(pad, padView, connect);
 			padDragListener.addListener();
 		} catch (Exception e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 
 		padView.applyStyleClasses(pad.getPadIndex());
@@ -169,7 +170,7 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 					onNew(event);
 				} catch (NoSuchComponentException e) {
 					// TODO Error Handling
-					e.printStackTrace();
+					Logger.error(e);
 				}
 			} else if (event.getSource() == padView.getSettingsButton()) {
 				onSettings();
@@ -207,7 +208,7 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 		PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents();
 
 		// File Extension
-		ExtensionFilter extensionFilter = new ExtensionFilter(Localization.getString(Strings.File_Filter_Media),
+		ExtensionFilter extensionFilter = new ExtensionFilter(Localization.getString(Strings.FILE_FILTER_MEDIA),
 				registry.getSupportedFileTypes());
 		chooser.getExtensionFilters().add(extensionFilter);
 
@@ -215,7 +216,9 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 		Object openFolder = ApplicationUtils.getApplication().getUserDefaults().getData(OPEN_FOLDER);
 		if (openFolder != null) {
 			File folder = new File(openFolder.toString());
-			chooser.setInitialDirectory(folder);
+			if (folder.exists()) {
+				chooser.setInitialDirectory(folder);
+			}
 		}
 
 		File file = chooser.showOpenDialog(((Node) event.getTarget()).getScene().getWindow());
@@ -293,7 +296,8 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 					if (pad.getStatus() == PadStatus.READY || position == null) {
 						String time = durationToString(duration);
 						padView.setTime(time);
-						padView.getPlayBar().setProgress(0);
+						padView.setPlayBarProgress(0);
+						padView.setCueInProgress(0);
 					} else {
 						// Play/Gesamtzeit anzeigen
 						TimeMode timeMode = pad.getPadSettings().getTimeMode();
@@ -315,7 +319,8 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 				return;
 			}
 		}
-		padView.getPlayBar().setProgress(0);
+		padView.setPlayBarProgress(0);
+		padView.setCueInProgress(0);
 		padView.setTime(null);
 	}
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/touch/TouchMenuToolbarViewController.java b/PlayWall/src/main/java/de/tobias/playpad/layout/touch/TouchMenuToolbarViewController.java
index c44b098a4719ef34447050472486d75735f74747..0ebc97bc89a32ff3bc2a1e7a4038b685970b1f4e 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/layout/touch/TouchMenuToolbarViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/layout/touch/TouchMenuToolbarViewController.java
@@ -2,9 +2,7 @@ package de.tobias.playpad.layout.touch;
 
 import de.thecodelabs.utils.ui.icon.FontIcon;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
-import de.tobias.playpad.Strings;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.page.Page;
@@ -13,8 +11,6 @@ import de.tobias.playpad.view.main.MainLayoutFactory;
 import de.tobias.playpad.view.main.MenuType;
 import de.tobias.playpad.viewcontroller.main.BasicMenuToolbarViewController;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
-import javafx.beans.binding.Bindings;
-import javafx.beans.binding.StringBinding;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.scene.Node;
@@ -35,7 +31,7 @@ public class TouchMenuToolbarViewController extends BasicMenuToolbarViewControll
 	private IMainViewController mainViewController;
 
 	TouchMenuToolbarViewController(IMainViewController mainViewController) {
-		super("Header", "view/main/touch", PlayPadMain.getUiResourceBundle());
+		super("Header", "view/main/touch", Localization.getBundle());
 		this.mainViewController = mainViewController;
 
 		// Schriftgröße Icons
@@ -66,14 +62,7 @@ public class TouchMenuToolbarViewController extends BasicMenuToolbarViewControll
 		for (int i = 0; i < openProject.getPages().size(); i++) {
 			Page page = openProject.getPage(i);
 
-			Button button = new Button();
-			StringBinding nameBinding = Bindings.when(page.nameProperty().isEmpty())
-					.then(Localization.getString(Strings.UI_Window_Main_PageButton, (i + 1)))
-					.otherwise(page.nameProperty());
-			button.textProperty().bind(nameBinding);
-			button.setUserData(i);
-			button.setFocusTraversable(false);
-			button.setOnAction(this);
+			Button button = createPageButton(page, i);
 			pageHBox.getChildren().add(button);
 		}
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadView.java b/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadView.java
index f5cbbefc49e1929d32d1510316713b77713eff9f..c094f0df8c0058df0096424b0d132f1bfdd4f122 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadView.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadView.java
@@ -1,12 +1,14 @@
 package de.tobias.playpad.layout.touch.pad;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
 import de.thecodelabs.utils.ui.scene.BusyView;
+import de.thecodelabs.utils.util.ColorUtils;
 import de.thecodelabs.utils.util.OS;
 import de.thecodelabs.utils.util.win.User32X;
 import de.tobias.playpad.PlayPadPlugin;
-import de.tobias.playpad.design.DesignColorAssociator;
+import de.tobias.playpad.design.FeedbackDesignColorSuggester;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.content.PadContent;
 import de.tobias.playpad.pad.content.PadContentFactory;
@@ -16,7 +18,6 @@ import de.tobias.playpad.pad.viewcontroller.IPadViewController;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.project.page.PadIndex;
 import de.tobias.playpad.registry.NoSuchComponentException;
-import de.tobias.playpad.util.ColorUtils;
 import de.tobias.playpad.view.EmptyPadView;
 import de.tobias.playpad.view.PseudoClasses;
 import javafx.beans.property.Property;
@@ -49,6 +50,9 @@ public class TouchPadView implements IPadView {
 	private VBox root;
 	private BusyView busyView;
 
+	private VBox cueInContainer;
+	private Label cueInLayer;
+
 	private transient TouchPadViewController controller; // Reference to its controller
 
 	public TouchPadView() {
@@ -61,6 +65,10 @@ public class TouchPadView implements IPadView {
 		root = new VBox();
 		busyView = new BusyView(superRoot);
 
+		cueInLayer = new Label();
+		cueInLayer.prefHeightProperty().bind(root.heightProperty());
+		cueInContainer = new VBox(cueInLayer);
+
 		indexLabel = new Label();
 
 		loopLabel = new Label(); // Active über Visible
@@ -98,7 +106,7 @@ public class TouchPadView implements IPadView {
 		notFoundLabel.setVisible(false);
 
 		root.getChildren().addAll(infoBox, preview, playBar);
-		superRoot.getChildren().addAll(root, notFoundLabel);
+		superRoot.getChildren().addAll(cueInContainer, root, notFoundLabel);
 
 		if (OS.isWindows() && User32X.isTouchAvailable()) {
 			superRoot.setOnTouchPressed(controller);
@@ -116,7 +124,7 @@ public class TouchPadView implements IPadView {
 	@Override
 	public void setContentView(Pad pad) {
 		if (previewContent != null) {
-			previewContent.deinit();
+			previewContent.deInit();
 		}
 
 		if (pad != null) {
@@ -137,8 +145,7 @@ public class TouchPadView implements IPadView {
 					preview.getChildren().setAll(node);
 					return;
 				} catch (NoSuchComponentException e) {
-					// TODO Auto-generated catch block
-					e.printStackTrace();
+					Logger.error(e);
 				}
 			}
 		}
@@ -182,6 +189,7 @@ public class TouchPadView implements IPadView {
 	@Override
 	public void pseudoClassState(PseudoClass pseudoClass, boolean active) {
 		superRoot.pseudoClassStateChanged(pseudoClass, active);
+		cueInLayer.pseudoClassStateChanged(pseudoClass, active);
 		indexLabel.pseudoClassStateChanged(pseudoClass, active);
 		timeLabel.pseudoClassStateChanged(pseudoClass, active);
 		loopLabel.getGraphic().pseudoClassStateChanged(pseudoClass, active);
@@ -240,6 +248,7 @@ public class TouchPadView implements IPadView {
 	@Override
 	public void applyStyleClasses(PadIndex index) {
 		superRoot.getStyleClass().addAll("pad", "pad" + index);
+		cueInLayer.getStyleClass().addAll("pad-cue-in", "pad" + index + "-cue-in");
 
 		indexLabel.getStyleClass().addAll("pad-index", "pad" + index + "-index", "pad-info", "pad" + index + "-info");
 		timeLabel.getStyleClass().addAll("pad-time", "pad" + index + "-time", "pad-info", "pad" + index + "-info");
@@ -257,6 +266,7 @@ public class TouchPadView implements IPadView {
 	@Override
 	public void removeStyleClasses() {
 		superRoot.getStyleClass().removeIf(c -> c.startsWith("pad"));
+		cueInLayer.getStyleClass().removeIf(c -> c.startsWith("pad"));
 
 		indexLabel.getStyleClass().removeIf(c -> c.startsWith("pad"));
 		timeLabel.getStyleClass().removeIf(c -> c.startsWith("pad"));
@@ -272,8 +282,8 @@ public class TouchPadView implements IPadView {
 	}
 
 	@Override
-	public void highlightView(int milliSecounds) {
-
+	public void highlightView(int milliSeconds) {
+		cueInLayer.setPrefWidth(root.getWidth() * milliSeconds);
 	}
 
 	void clearIndex() {
@@ -286,7 +296,7 @@ public class TouchPadView implements IPadView {
 
 	void clearPreviewContent() {
 		if (previewContent != null) {
-			previewContent.deinit();
+			previewContent.deInit();
 		}
 		setContentView(null);
 	}
@@ -301,10 +311,15 @@ public class TouchPadView implements IPadView {
 		playBar.setProgress(value);
 	}
 
+	@Override
+	public void setCueInProgress(double value) {
+		cueInLayer.setPrefWidth(root.getWidth() * value);
+	}
+
 	@Override
 	public void showNotFoundIcon(Pad pad, boolean show) {
 		if (show) {
-			DesignColorAssociator associator = null;
+			FeedbackDesignColorSuggester associator = null;
 			if (pad.getPadSettings().isCustomDesign()) {
 				associator = pad.getPadSettings().getDesign();
 			} else {
@@ -312,8 +327,8 @@ public class TouchPadView implements IPadView {
 			}
 
 			if (associator != null) {
-				Color color = associator.getAssociatedStandardColor();
-				notFoundLabel.setColor(ColorUtils.getWarningSignColor(color));
+				Color color = associator.getDesignDefaultColor();
+				notFoundLabel.setColor(ColorUtils.getAppropriateTextColor(color));
 			} else {
 				notFoundLabel.setColor(Color.RED);
 			}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadViewController.java b/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadViewController.java
index 58bfb48aa548bfb28955001ee2c95aadc8006e05..d6a75430cb0063cd1191e25e9a2499c2f7080f92 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadViewController.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.layout.touch.pad;
 
+import de.thecodelabs.logger.Logger;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.pad.TimeMode;
@@ -82,7 +83,7 @@ public class TouchPadViewController implements IPadViewController, EventHandler<
 			padContentListener.changed(null, null, pad.getContent()); // Add Duration listener
 			padStatusListener.changed(null, null, pad.getStatus());
 		} catch (Exception e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 
 		padView.applyStyleClasses(pad.getPadIndex());
diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java b/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java
index 7d1066bc7e41eb7d5c3c8339ad65c7c18bcdb6c5..426d058b27de8b181450cc7727dbf0e3c7a0335d 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java
@@ -228,8 +228,8 @@ public class AudioContent extends PadContent implements Pauseable, Durationable,
 	}
 
 	@Override
-	public PadContent clone() throws CloneNotSupportedException {
-		AudioContent clone = (AudioContent) super.clone();
+	public PadContent copy(Pad pad) {
+		AudioContent clone = new AudioContent(getType(), pad);
 
 		AudioRegistry audioRegistry = PlayPadPlugin.getRegistries().getAudioHandlers();
 		clone.audioHandler = audioRegistry.getCurrentAudioHandler().createAudioHandler(this);
diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioPadContentFactory.java b/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioPadContentFactory.java
index c4720f3bf7b6af1ccdd9b132b39df386934056a1..d60a59d949a82adbb94f117600f4d9e6fd95da51 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioPadContentFactory.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioPadContentFactory.java
@@ -14,7 +14,7 @@ import javafx.scene.text.TextAlignment;
 
 public class AudioPadContentFactory extends PadContentFactory {
 
-	public static final String[] FILE_EXTENSION = {"*.mp3", "*.wav"};
+	private static final String[] FILE_EXTENSION = {"*.mp3", "*.wav"};
 
 	public AudioPadContentFactory(String type) {
 		super(type);
@@ -44,7 +44,7 @@ public class AudioPadContentFactory extends PadContentFactory {
 		return new AudioTabViewController(activePlayer);
 	}
 
-	private class AudioContentView implements IPadContentView {
+	private static class AudioContentView implements IPadContentView {
 
 		private Label nameLabel;
 
@@ -67,7 +67,7 @@ public class AudioPadContentFactory extends PadContentFactory {
 		}
 
 		@Override
-		public void deinit() {
+		public void deInit() {
 			nameLabel.textProperty().unbind();
 		}
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/drag/DuplicateDragMode.java b/PlayWall/src/main/java/de/tobias/playpad/pad/drag/DuplicateDragMode.java
index 6de2cb25d7c4f4c75cf5ea1cab3a0dd134f27f05..c945a85fd56735fa7627b13d2d63ec0d8be77058 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/pad/drag/DuplicateDragMode.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/pad/drag/DuplicateDragMode.java
@@ -15,15 +15,10 @@ public class DuplicateDragMode extends PadDragMode {
 		Pad oldPad = project.getPad(oldIndex);
 		Pad newPad = project.getPad(newIndex);
 
-		try {
-			Pad copyPad = oldPad.clone(oldPad.getPage());
+		Pad copyPad = oldPad.copy(oldPad.getPage());
 
-			project.removePad(newPad.getUuid());
-			project.setPad(newIndex, copyPad);
-			return true;
-		} catch (CloneNotSupportedException e) {
-			e.printStackTrace();
-		}
-		return false;
+		project.removePad(newPad.getUuid());
+		project.setPad(newIndex, copyPad);
+		return true;
 	}
 }
\ No newline at end of file
diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadPositionListener.java b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadPositionListener.java
index b428b46194b7bdf9629a7a43801a6038d3cf39d3..579fe5a9dfb6fbac7a207b2f67b09cfce5c74800 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadPositionListener.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadPositionListener.java
@@ -1,7 +1,8 @@
 package de.tobias.playpad.pad.listener;
 
 import de.tobias.playpad.PlayPadMain;
-import de.tobias.playpad.design.ModernDesign;
+import de.tobias.playpad.action.actions.CartAction;
+import de.tobias.playpad.design.ModernDesignHandler;
 import de.tobias.playpad.design.modern.ModernCartDesignHandler;
 import de.tobias.playpad.design.modern.ModernGlobalDesignHandler;
 import de.tobias.playpad.design.modern.model.ModernCartDesign;
@@ -55,6 +56,7 @@ public class PadPositionListener implements Runnable, IPadPositionListener {
 
 				if (totalDuration != null) {
 					updateDuration(newValue, durationable, totalDuration);
+					CartAction.refreshFeedback(pad);
 				}
 			}
 		}
@@ -64,6 +66,16 @@ public class PadPositionListener implements Runnable, IPadPositionListener {
 		double value = newValue.toMillis() / totalDuration.toMillis();
 		controller.getView().setPlayBarProgress(value);
 
+		Duration cueInDuration = pad.getPadSettings().getCueIn();
+		if (cueInDuration != null) {
+			if (cueInDuration.greaterThan(newValue)) {
+				double cueInProgress = newValue.toMillis() / cueInDuration.toMillis();
+				controller.getView().setCueInProgress(cueInProgress);
+			} else {
+				controller.getView().setCueInProgress(0);
+			}
+		}
+
 		// Label (Restlaufzeit)
 		controller.updateTimeLabel();
 
@@ -96,7 +108,7 @@ public class PadPositionListener implements Runnable, IPadPositionListener {
 		Duration warning = padSettings.getWarning();
 
 		ModernGlobalDesign globalDesign = Profile.currentProfile().getProfileSettings().getDesign();
-		final ModernDesign modernDesign = PlayPadMain.getProgramInstance().getModernDesign();
+		final ModernDesignHandler modernDesign = PlayPadMain.getProgramInstance().getModernDesign();
 
 		if (padSettings.isCustomDesign()) {
 			ModernCartDesignHandler handler = modernDesign.cart();
@@ -125,7 +137,7 @@ public class PadPositionListener implements Runnable, IPadPositionListener {
 		}
 
 		PadSettings padSettings = pad.getPadSettings();
-		final ModernDesign modernDesign = PlayPadMain.getProgramInstance().getModernDesign();
+		final ModernDesignHandler modernDesign = PlayPadMain.getProgramInstance().getModernDesign();
 
 		if (padSettings.isCustomDesign()) {
 			ModernCartDesignHandler handler = modernDesign.cart();
diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadStatusListener.java b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadStatusListener.java
index afdda7ebf792cb228328e024f0989c5eff1fe67a..bda5270de706c8c4ecfece808faaa2780eb11170 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadStatusListener.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadStatusListener.java
@@ -1,5 +1,7 @@
 package de.tobias.playpad.pad.listener;
 
+import de.thecodelabs.midi.Mapping;
+import de.tobias.playpad.action.actions.CartAction;
 import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.pad.viewcontroller.IPadViewController;
 import de.tobias.playpad.view.PseudoClasses;
@@ -19,6 +21,11 @@ public class PadStatusListener implements ChangeListener<PadStatus> {
 		controller.updateButtonDisable();
 		controller.updateTimeLabel();
 
+		// Show Feedback on Midi
+		if (Mapping.getCurrentMapping() != null) {
+			CartAction.refreshFeedback(controller.getPad());
+		}
+
 		// Reset
 		controller.getView().setErrorLabelActive(false);
 		controller.getView().showNotFoundIcon(controller.getPad(), false);
@@ -40,19 +47,13 @@ public class PadStatusListener implements ChangeListener<PadStatus> {
 				break;
 
 			case STOP:
-				controller.getPadPositionListener().stopWaning();
-				controller.getView().pseudoClassState(PseudoClasses.PLAY_CLASS, false);
-				controller.getView().pseudoClassState(PseudoClasses.FADE_CLASS, false);
-				controller.getView().pseudoClassState(PseudoClasses.WARN_CLASS, false);
-				controller.getView().setStyle("");
-				break;
-
 			case READY:
+			case EMPTY:
 				controller.getPadPositionListener().stopWaning();
 				controller.getView().pseudoClassState(PseudoClasses.PLAY_CLASS, false);
 				controller.getView().pseudoClassState(PseudoClasses.FADE_CLASS, false);
 				controller.getView().pseudoClassState(PseudoClasses.WARN_CLASS, false);
-				controller.getView().setStyle(""); // Cleanup from warning UI
+				controller.getView().setStyle("");
 				break;
 
 			case ERROR:
@@ -75,13 +76,6 @@ public class PadStatusListener implements ChangeListener<PadStatus> {
 				controller.getView().setStyle(""); // Cleanup from warning UI
 				break;
 
-			case EMPTY:
-				controller.getPadPositionListener().stopWaning();
-				controller.getView().pseudoClassState(PseudoClasses.PLAY_CLASS, false);
-				controller.getView().pseudoClassState(PseudoClasses.FADE_CLASS, false);
-				controller.getView().pseudoClassState(PseudoClasses.WARN_CLASS, false);
-				controller.getView().setStyle(""); // Cleanup from warning UI
-				break;
 			default:
 				break;
 		}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/project/ProjectJsonReader.java b/PlayWall/src/main/java/de/tobias/playpad/project/ProjectJsonReader.java
index 5ff65ecc0da37eaccdd4771a6b8c341c275deb89..6f33e38af123e5c80346b484ffed63211fee6171 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/project/ProjectJsonReader.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/project/ProjectJsonReader.java
@@ -70,7 +70,7 @@ public class ProjectJsonReader {
 			pad.getPaths().add(path); // TODO Use addPath Method in right scope
 		}
 
-		if (pad.getPaths().size() != 0) {
+		if (!pad.getPaths().isEmpty()) {
 			pad.setStatus(PadStatus.READY);
 		}
 
@@ -101,7 +101,7 @@ public class ProjectJsonReader {
 			ModernColor backgroundColor = ModernColor.valueOf(object.getString("background_color"));
 			ModernColor playColor = ModernColor.valueOf(object.getString("play_color"));
 
-			return new ModernCartDesign(pad, id, backgroundColor, playColor);
+			return new ModernCartDesign(pad, id, backgroundColor, playColor, ModernColor.RED2); // TODO Fix Cue In Color
 		}
 		return null;
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/server/ServerHandlerImpl.java b/PlayWall/src/main/java/de/tobias/playpad/server/ServerHandlerImpl.java
index 2adfc1041bb582c0e12a6c79fade32c8966eee0e..76f4be2cfcaef8e0ff4e502cd1023de109e43244 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/server/ServerHandlerImpl.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/server/ServerHandlerImpl.java
@@ -19,7 +19,7 @@ public class ServerHandlerImpl implements ServerHandler {
 
 	public Server getServer() {
 		if (server == null) {
-			String url = ApplicationUtils.getApplication().getInfo().getUserInfo().get(AppUserInfoStrings.SERVER).toString();
+			String url = ApplicationUtils.getApplication().getUserInfo(AppUserInfoStrings.class).server();
 
 			PlayPadImpl impl = PlayPadMain.getProgramInstance();
 			Application.Parameters parameters = impl.getParameters();
diff --git a/PlayWall/src/main/java/de/tobias/playpad/server/ServerImpl.java b/PlayWall/src/main/java/de/tobias/playpad/server/ServerImpl.java
index 98a132c61773e260ffb4c23e67a77a70cb8ce201..7920226aec329f3beaa502e701fb055778ceef76 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/server/ServerImpl.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/server/ServerImpl.java
@@ -53,11 +53,8 @@ import java.io.InputStreamReader;
 import java.io.Reader;
 import java.lang.reflect.Type;
 import java.net.URL;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.nio.file.StandardOpenOption;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.*;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -71,6 +68,8 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 
 	private static final String OK = "OK";
 	private static final String CACHE_FOLDER = "Cache";
+	private static final String PROTOCOL = "https";
+	private static final String WS_PROTOCOL = "wss";
 
 	private String host;
 	private WebSocket websocket;
@@ -84,7 +83,7 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 		try {
 			loadStoredFiles();
 		} catch (IOException e) {
-			e.printStackTrace(); // TODO Error Handling
+			Logger.error(e);
 		}
 		registerCommands();
 	}
@@ -121,8 +120,8 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 
 	@Override
 	public List<ModernPlugin> getPlugins() throws IOException {
-		URL url = new URL("https://" + host + "/plugins");
-		Reader reader = new InputStreamReader(url.openStream(), Charset.forName("UTF-8"));
+		URL url = new URL(PROTOCOL + "://" + host + "/plugins");
+		Reader reader = new InputStreamReader(url.openStream(), StandardCharsets.UTF_8);
 		Type listType = new TypeToken<List<ModernPlugin>>() {
 		}.getType();
 
@@ -131,22 +130,19 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 	}
 
 	@Override
-	public ModernPlugin getPlugin(String name) throws IOException {
-		URL url = new URL("https://" + host + "/plugin/" + name);
-		Reader reader = new InputStreamReader(url.openStream(), Charset.forName("UTF-8"));
+	public ModernPlugin getPlugin(String id) throws IOException {
+		URL url = new URL(PROTOCOL + "://" + host + "/plugins/" + id);
+		Reader reader = new InputStreamReader(url.openStream(), StandardCharsets.UTF_8);
 		Gson gson = new Gson();
 		return gson.fromJson(reader, ModernPlugin.class);
 	}
 
 	@Override
 	public void loadPlugin(ModernPlugin plugin, UpdateService.RepositoryType channel) throws IOException {
-		Path path = ApplicationUtils.getApplication().getPath(PathType.LIBRARY, plugin.getFileName());
-		loadSource(plugin.getPath(), channel, path);
-	}
+		Path destination = ApplicationUtils.getApplication().getPath(PathType.LIBRARY, plugin.getFileName());
 
-	private void loadSource(String path, UpdateService.RepositoryType channel, Path destination) throws IOException {
-		String url = "https://" + host + "/" + channel + path;
-		Logger.debug("Load server resource: {0}", path);
+		String url = PROTOCOL + "://" + host + "/plugins/raw/" + plugin.getId();
+		Logger.debug("Load server resource: {0}", destination);
 		try {
 			HttpResponse<InputStream> response = Unirest.get(url).asBinary();
 			Files.copy(response.getBody(), destination, StandardCopyOption.REPLACE_EXISTING);
@@ -157,7 +153,7 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 
 	@Override
 	public String getSession(String username, String password) throws IOException, LoginException {
-		String url = "https://" + host + "/sessions";
+		String url = PROTOCOL + "://" + host + "/sessions";
 		try {
 			HttpResponse<JsonNode> response = Unirest.post(url)
 					.queryString("username", username)
@@ -178,7 +174,7 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 
 	@Override
 	public void logout(String username, String password, String key) throws IOException {
-		String url = "https://" + host + "/sessions";
+		String url = PROTOCOL + "://" + host + "/sessions";
 		try {
 			Unirest.post(url)
 					.queryString("username", username)
@@ -192,7 +188,7 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 
 	@Override
 	public List<ProjectReference> getSyncedProjects() throws IOException, LoginException {
-		String url = "https://" + host + "/projects";
+		String url = PROTOCOL + "://" + host + "/projects";
 		try {
 			Session session = PlayPadMain.getProgramInstance().getSession();
 			HttpResponse<JsonNode> request = Unirest.get(url)
@@ -218,14 +214,14 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 			}
 		} catch (UnirestException e) {
 			throw new IOException(e.getMessage());
-		} catch (SessionNotExisitsException ignored) {
+		} catch (SessionNotExistsException ignored) {
 			return new ArrayList<>();
 		}
 	}
 
 	@Override
 	public Project getProject(ProjectReference ref) throws IOException {
-		String url = "https://" + host + "/projects/" + ref.getUuid();
+		String url = PROTOCOL + "://" + host + "/projects/" + ref.getUuid();
 		Session session = PlayPadMain.getProgramInstance().getSession();
 		try {
 			HttpResponse<JsonNode> response = Unirest.get(url)
@@ -237,20 +233,19 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 			return reader.read(ref);
 		} catch (UnirestException e) {
 			throw new IOException(e.getMessage());
-		} catch (SessionNotExisitsException ignored) {
+		} catch (SessionNotExistsException ignored) {
 			return null;
 		}
 	}
 
 	@Override
 	public void postProject(Project project) throws IOException {
-		String url = "https://" + host + "/projects";
+		String url = PROTOCOL + "://" + host + "/projects";
 		Session session = PlayPadMain.getProgramInstance().getSession();
 		try {
 			ProjectJsonWriter writer = new ProjectJsonWriter();
 
 			String value = writer.write(project).toString();
-			System.out.println(value);
 
 			Unirest.post(url)
 					.queryString("session", session.getKey())
@@ -258,13 +253,13 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 					.asJson();
 		} catch (UnirestException e) {
 			throw new IOException(e.getMessage(), e);
-		} catch (SessionNotExisitsException ignored) {
+		} catch (SessionNotExistsException ignored) {
 		}
 	}
 
 	@Override
 	public Version getLastServerModification(ProjectReference ref) throws IOException {
-		String url = "https://" + host + "/projects/modification/" + ref.getUuid();
+		String url = PROTOCOL + "://" + host + "/projects/modification/" + ref.getUuid();
 		Session session = PlayPadMain.getProgramInstance().getSession();
 		try {
 			HttpResponse<JsonNode> response = Unirest.get(url)
@@ -277,7 +272,7 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 			return new Version(time, remoteSession, false);
 		} catch (UnirestException e) {
 			throw new IOException(e.getMessage());
-		} catch (SessionNotExisitsException ignored) {
+		} catch (SessionNotExistsException ignored) {
 			return null;
 		}
 	}
@@ -289,25 +284,25 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 			if (PlayPadMain.sslContext != null) {
 				webSocketFactory.setSSLContext(PlayPadMain.sslContext);
 			}
-			websocket = webSocketFactory.createSocket("wss://" + host + "/project");
+			websocket = webSocketFactory.createSocket(WS_PROTOCOL + "://" + host + "/project");
 			websocket.addHeader("key", key);
 
 			websocket.addListener(syncListener);
 			websocket.connect();
 		} catch (WebSocketException | IOException e) {
-			System.err.println("Failed to connect to server: " + e.getMessage());
+			Logger.error("Failed to connect to server: " + e.getMessage());
 		}
 	}
 
 	@Override
 	public void disconnect() {
-		System.out.println("Disconnect from Server");
+		Logger.info("Disconnect from Server");
 		websocket.disconnect();
 
 		try {
 			saveStoredCommands();
 		} catch (IOException e) {
-			e.printStackTrace(); // TODO Error Handling
+			Logger.error(e);
 		}
 	}
 
@@ -315,7 +310,7 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 	public boolean push(String data) {
 		if (websocket.isOpen()) {
 			if (ApplicationUtils.getApplication().isDebug()) {
-				System.out.println("Send: " + data);
+				Logger.debug("Send: " + data);
 			}
 			// Send to Server
 			websocket.sendText(data);
@@ -350,8 +345,10 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 	private void loadStoredFiles() throws IOException {
 		Path path = ApplicationUtils.getApplication().getPath(PathType.DOCUMENTS, CACHE_FOLDER);
 		if (Files.exists(path)) {
-			for (Path file : Files.newDirectoryStream(path)) {
-				loadStoredFile(file);
+			try (final DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path)) {
+				for (Path file : directoryStream) {
+					loadStoredFile(file);
+				}
 			}
 		}
 	}
@@ -375,9 +372,9 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 
 		CommandStore executor = (CommandStore) PlayPadPlugin.getCommandExecutorHandler().getCommandExecutor();
 		Map<UUID, List<JsonObject>> storedCommands = executor.getStoredCommands();
-		for (UUID key : storedCommands.keySet()) {
-			Path file = folder.resolve(key.toString());
-			List<String> lines = storedCommands.get(key).stream().map(JsonElement::toString).collect(Collectors.toList());
+		for (Map.Entry<UUID, List<JsonObject>> entry : storedCommands.entrySet()) {
+			Path file = folder.resolve(entry.getKey().toString());
+			List<String> lines = entry.getValue().stream().map(JsonElement::toString).collect(Collectors.toList());
 			Files.write(file, lines, StandardOpenOption.CREATE);
 		}
 	}
@@ -390,9 +387,8 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 			try {
 				websocket = websocket.recreate().connect();
 				connected = true;
-				Thread.sleep(30 * 1000);
+				Thread.sleep(30 * 1000L);
 			} catch (InterruptedException e) {
-				e.printStackTrace();
 				break;
 			} catch (WebSocketException | IOException ignored) {
 			}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/server/ServerSyncListener.java b/PlayWall/src/main/java/de/tobias/playpad/server/ServerSyncListener.java
index 599eb0f4422757773f7269abd9bd218b5cd1ae16..5d94243b37a09505c791862f26b734a51f007dd2 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/server/ServerSyncListener.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/server/ServerSyncListener.java
@@ -6,6 +6,7 @@ import com.google.gson.JsonParser;
 import com.neovisionaries.ws.client.WebSocket;
 import com.neovisionaries.ws.client.WebSocketAdapter;
 import com.neovisionaries.ws.client.WebSocketFrame;
+import de.thecodelabs.logger.Logger;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.project.ref.ProjectReferenceManager;
@@ -78,7 +79,7 @@ public class ServerSyncListener extends WebSocketAdapter {
 
 	@Override
 	public void onConnected(WebSocket websocket, Map<String, List<String>> headers) throws Exception {
-		System.out.println("Connected");
+		Logger.info("Connected");
 		connectionStateProperty.set(ConnectionState.CONNECTED);
 
 
@@ -92,7 +93,7 @@ public class ServerSyncListener extends WebSocketAdapter {
 		// Find new conflicts
 		for (ProjectReference reference : ProjectReferenceManager.getProjects()) {
 			ConflictType conflictType = solver.checkConflict(commandExecutor, reference);
-			if (conflictType != ConflictType.NON) {
+			if (conflictType != ConflictType.NONE) {
 				List<Version> versions = solver.getVersions(reference);
 
 				Conflict conflict = new Conflict(reference, conflictType, versions);
@@ -103,7 +104,7 @@ public class ServerSyncListener extends WebSocketAdapter {
 
 	@Override
 	public void onDisconnected(WebSocket websocket, WebSocketFrame serverCloseFrame, WebSocketFrame clientCloseFrame, boolean closedByServer) throws Exception {
-		System.out.println("Disconnected: " + clientCloseFrame.getCloseReason());
+		Logger.info("Disconnected: " + clientCloseFrame.getCloseReason());
 		if (clientCloseFrame.getCloseCode() == CONNECTION_CLOSED) {
 			connectionStateProperty.set(ConnectionState.CONNECTION_LOST);
 		} else if (clientCloseFrame.getCloseCode() == DISCONNECTED) {
diff --git a/PlayWall/src/main/java/de/tobias/playpad/server/Session.java b/PlayWall/src/main/java/de/tobias/playpad/server/Session.java
index 305808a7a70bba2b1886c4857c44c5b6202933ff..26f15824a4467708c5d426ca39a03a83e4b3a0d4 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/server/Session.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/server/Session.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.server;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
 
@@ -22,9 +23,9 @@ public class Session {
 		this.key = key;
 	}
 
-	public String getKey() throws SessionNotExisitsException {
+	public String getKey() throws SessionNotExistsException {
 		if (key == null) {
-			throw new SessionNotExisitsException();
+			throw new SessionNotExistsException();
 		}
 		return key;
 	}
@@ -52,7 +53,7 @@ public class Session {
 			}
 			Files.write(path, key.getBytes());
 		} catch (IOException e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/server/sync/command/CommandExecutorImpl.java b/PlayWall/src/main/java/de/tobias/playpad/server/sync/command/CommandExecutorImpl.java
index f18723763c1da1c7ff1440daab060e769347c24a..65c1db5438deb0ba5fc2eb8b49ec6eafe05db54f 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/server/sync/command/CommandExecutorImpl.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/server/sync/command/CommandExecutorImpl.java
@@ -55,7 +55,7 @@ public class CommandExecutorImpl implements CommandExecutor, CommandStore {
 		Command command = commandMap.get(name);
 		JsonObject sendData = command.execute(data);
 
-		// Handle Last midication date
+		// Handle Last modification date
 		long lastModified = System.currentTimeMillis();
 		sendData.addProperty(PropertyDef.TIME, lastModified);
 		sendData.addProperty(PropertyDef.PROJECT_REF, projectReference.getUuid().toString());
diff --git a/PlayWall/src/main/java/de/tobias/playpad/server/sync/conflict/ConflictSolverImpl.java b/PlayWall/src/main/java/de/tobias/playpad/server/sync/conflict/ConflictSolverImpl.java
index c42ffa68cb2b88fa8ec28554a17472876914b83d..112d432f919c32fe3451f5ca77746ebbb092147a 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/server/sync/conflict/ConflictSolverImpl.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/server/sync/conflict/ConflictSolverImpl.java
@@ -52,7 +52,7 @@ public class ConflictSolverImpl implements ConflictSolver {
 				return ConflictType.LOCAL_CHANGES;
 			}
 		}
-		return ConflictType.NON;
+		return ConflictType.NONE;
 	}
 
 	@Override
diff --git a/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItem.java b/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItem.java
index c03558c0a8c1308e25e0f9df3d8eabcd36f12455..7bb7597bec88d5a0f72cfae7fb6d7f75e62c5ebe 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItem.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItem.java
@@ -9,6 +9,7 @@ import de.tobias.playpad.tigger.TriggerItem;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import org.dom4j.Element;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
 
@@ -20,7 +21,7 @@ public class CartTriggerItem extends TriggerItem {
 
 	private String type;
 
-	public CartTriggerItem(String type) {
+	CartTriggerItem(String type) {
 		super();
 		this.type = type;
 		newStatus = PadStatus.PLAY;
@@ -72,6 +73,18 @@ public class CartTriggerItem extends TriggerItem {
 		}
 	}
 
+	@Override
+	public TriggerItem copy() {
+		CartTriggerItem clone = new CartTriggerItem(getType());
+
+		clone.uuids = new ArrayList<>();
+		clone.uuids.addAll(uuids);
+		clone.allCarts = allCarts;
+		clone.newStatus = newStatus;
+
+		return clone;
+	}
+
 	private static final String CART_ELEMENT = "Cart";
 	private static final String STATUS_ATTR = "Status";
 	private static final String ALLCARTS_ATTR = "all";
@@ -83,13 +96,10 @@ public class CartTriggerItem extends TriggerItem {
 		if (element.attributeValue(STATUS_ATTR) != null)
 			setNewStatus(PadStatus.valueOf(element.attributeValue(STATUS_ATTR)));
 		if (element.attributeValue(ALLCARTS_ATTR) != null)
-			setAllCarts(Boolean.valueOf(element.attributeValue(ALLCARTS_ATTR)));
+			setAllCarts(Boolean.parseBoolean(element.attributeValue(ALLCARTS_ATTR)));
 
-		for (Object cartObj : element.elements(CART_ELEMENT)) {
-			if (cartObj instanceof Element) {
-				Element cartElement = (Element) cartObj;
-				uuids.add(UUID.fromString(cartElement.getStringValue()));
-			}
+		for (Element cartElement : element.elements(CART_ELEMENT)) {
+			uuids.add(UUID.fromString(cartElement.getStringValue()));
 		}
 	}
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItemFactory.java b/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItemFactory.java
index 00d1b72e34f828798812ed68a26b7ba54b21e28e..98290adbcd0df99adf16698fe28258999e072a94 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItemFactory.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItemFactory.java
@@ -26,6 +26,6 @@ public class CartTriggerItemFactory extends TriggerItemFactory {
 
 	@Override
 	public String toString() {
-		return Localization.getString(Strings.Trigger_Cart_Name);
+		return Localization.getString(Strings.TRIGGER_CART_NAME);
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/trigger/TriggerDisplayable.java b/PlayWall/src/main/java/de/tobias/playpad/trigger/TriggerDisplayable.java
index 30ea31687aa488a7d2eec34fbf2120146a1d6096..434a17a2577ee8aee5a27b1a2850134362e350d0 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/trigger/TriggerDisplayable.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/TriggerDisplayable.java
@@ -44,7 +44,7 @@ public class TriggerDisplayable implements Displayable {
 
 	@Override
 	public String toString() {
-		String triggerPointName = Localization.getString(Strings.TriggerPoint_BaseName + trigger.getTriggerPoint().name());
-		return Localization.getString(Strings.TriggerPoint_toString, triggerPointName, trigger.getItems().size());
+		String triggerPointName = Localization.getString(Strings.TRIGGER_POINT + trigger.getTriggerPoint().name());
+		return Localization.getString(Strings.TRIGGER_POINT_TO_STRING, triggerPointName, trigger.getItems().size());
 	}
 }
\ No newline at end of file
diff --git a/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItem.java b/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItem.java
index 4255118cd3239612c588d954eb90da17cb1a89de..667c4aa90b0cb045c1655a0ccea97a897061979a 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItem.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItem.java
@@ -7,13 +7,13 @@ import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.tigger.TriggerItem;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
+import de.tobias.playpad.volume.VolumeManager;
 import javafx.util.Duration;
 import org.dom4j.Element;
 
-import java.util.HashMap;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
-import java.util.stream.Collectors;
 
 public class VolumeTriggerItem extends TriggerItem {
 
@@ -21,11 +21,9 @@ public class VolumeTriggerItem extends TriggerItem {
 	private Duration duration = new Duration(2000);
 	private List<UUID> uuids;
 
-	private static HashMap<Integer, Double> volumeCache = new HashMap<>();
-
 	private String type;
 
-	public VolumeTriggerItem(String type) {
+	VolumeTriggerItem(String type) {
 		super();
 		this.type = type;
 		this.uuids = new UniqList<>();
@@ -58,22 +56,26 @@ public class VolumeTriggerItem extends TriggerItem {
 
 	@Override
 	public void performAction(Pad pad, Project project, IMainViewController controller, Profile profile) {
-		for (Pad destination : uuids.stream().map(project::getPad).collect(Collectors.toList())) {
-			if (destination.getContent() instanceof Fadeable) {
+		uuids.stream().map(project::getPad)
+				.filter(i -> i.getContent() instanceof Fadeable)
+				.forEach(destination -> {
+			Fadeable fadeable = (Fadeable) destination.getContent();
+
+			final double start = VolumeManager.getInstance().computeVolume(destination);
+			fadeable.fade(start, volume, duration, null);
+		});
+	}
 
-				final int id = destination.getPadIndex().getId();
-				if (!volumeCache.containsKey(id)) {
-					volumeCache.put(id, destination.getPadSettings().getVolume());
-				}
-				double start = volumeCache.get(id);
+	@Override
+	public TriggerItem copy() {
+		VolumeTriggerItem clone = new VolumeTriggerItem(getType());
 
+		clone.uuids = new ArrayList<>();
+		clone.uuids.addAll(uuids);
+		clone.volume = volume;
+		clone.duration = new Duration(duration.toMillis());
 
-				Fadeable fadeable = (Fadeable) destination.getContent();
-				fadeable.fade(start, volume, duration, () -> {
-					volumeCache.put(id, volume);
-				});
-			}
-		}
+		return clone;
 	}
 
 	private static final String CART_ELEMENT = "Cart";
@@ -84,15 +86,12 @@ public class VolumeTriggerItem extends TriggerItem {
 	public void load(Element element) {
 		super.load(element);
 		if (element.attributeValue(VOLUME_ATTR) != null)
-			volume = Double.valueOf(element.attributeValue(VOLUME_ATTR));
+			volume = Double.parseDouble(element.attributeValue(VOLUME_ATTR));
 		if (element.attributeValue(DURATION_ATTR) != null)
-			duration = Duration.millis(Double.valueOf(element.attributeValue(DURATION_ATTR)));
+			duration = Duration.millis(Double.parseDouble(element.attributeValue(DURATION_ATTR)));
 
-		for (Object cartObj : element.elements(CART_ELEMENT)) {
-			if (cartObj instanceof Element) {
-				Element cartElement = (Element) cartObj;
-				uuids.add(UUID.fromString(cartElement.getStringValue()));
-			}
+		for (Element cartElement : element.elements(CART_ELEMENT)) {
+			uuids.add(UUID.fromString(cartElement.getStringValue()));
 		}
 	}
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItemFactory.java b/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItemFactory.java
index dc29fe38460872b533995187f1fd7ef091a74f7f..73d2447a29858d8ba7ea630749aa89d8cec357dc 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItemFactory.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItemFactory.java
@@ -26,6 +26,6 @@ public class VolumeTriggerItemFactory extends TriggerItemFactory {
 
 	@Override
 	public String toString() {
-		return Localization.getString(Strings.Trigger_Volume_Name);
+		return Localization.getString(Strings.TRIGGER_VOLUME_NAME);
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/util/ColorUtils.java b/PlayWall/src/main/java/de/tobias/playpad/util/ColorUtils.java
deleted file mode 100644
index 5bafd226c947eb9b251341028d28e21de8ada24e..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/util/ColorUtils.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package de.tobias.playpad.util;
-
-import com.itextpdf.text.BaseColor;
-import javafx.scene.paint.Color;
-
-/**
- * Created by tobias on 26.03.17.
- */
-public class ColorUtils {
-	/**
-	 * Get the color for the not found warning sign in a pad view.
-	 *
-	 * @param color background color
-	 * @return sign color
-	 */
-	public static Color getWarningSignColor(Color color) {
-		// Counting the perceptive luminance - human eye favors green color...
-		double a = 1 - (0.299 * (int) (color.getRed() * 255) + 0.587 * (int) (color.getGreen() * 255) + 0.114 * (int) (color.getBlue() * 255)) / 255;
-
-		if (a < 0.5) {
-			return Color.BLACK;
-		} else {
-			return Color.WHITE;
-		}
-	}
-
-	public static BaseColor toBaseColor(String hexCode) {
-		hexCode = hexCode.replace("#", "");
-		return new BaseColor(
-				Integer.valueOf(hexCode.substring(0, 2), 16),
-				Integer.valueOf(hexCode.substring(2, 4), 16),
-				Integer.valueOf(hexCode.substring(4, 6), 16)
-		);
-	}
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/ColorPickerView.java b/PlayWall/src/main/java/de/tobias/playpad/view/ColorPickerView.java
index b71d1e661e8553516d51c054c9ab465e58a2fbb1..82aac320145e82df920ece326834ba45aa53ac75 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/view/ColorPickerView.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/ColorPickerView.java
@@ -31,12 +31,12 @@ public class ColorPickerView extends GridPane {
 
 					// Style in CSS
 					Rectangle rectangle = new Rectangle(40, 40);
-					rectangle.setFill(color.getPaint());
+					rectangle.setFill(color.getColor());
 
 					rectangle.getStyleClass().add("color-view-item");
 
 					// Gestrichelte Linie
-					if (color == startColor) {
+					if (color.equals(startColor)) {
 						rectangle.getStrokeDashArray().addAll(3.0);
 					}
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/EmptyPadView.java b/PlayWall/src/main/java/de/tobias/playpad/view/EmptyPadView.java
index d88ba03b4a99b28d6f3309e107b4bcfc2d88c4f2..5a97cd55644c7b8e05b77a90bd51b0350e497a93 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/view/EmptyPadView.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/EmptyPadView.java
@@ -12,7 +12,7 @@ import javafx.scene.text.TextAlignment;
 public class EmptyPadView extends Label {
 
 	public EmptyPadView(Pane parent) {
-		super(Localization.getString(Strings.Content_Empty));
+		super(Localization.getString(Strings.CONTENT_EMPTY));
 		setWrapText(true);
 		setAlignment(Pos.CENTER);
 		setTextAlignment(TextAlignment.CENTER);
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/FeedbackColorPickerView.java b/PlayWall/src/main/java/de/tobias/playpad/view/FeedbackColorPickerView.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5e544a21abea36f0190c66ed793808841f84e15
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/FeedbackColorPickerView.java
@@ -0,0 +1,59 @@
+package de.tobias.playpad.view;
+
+import de.thecodelabs.midi.feedback.FeedbackColor;
+import javafx.geometry.Insets;
+import javafx.scene.layout.GridPane;
+import javafx.scene.shape.Rectangle;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+public class FeedbackColorPickerView extends GridPane {
+
+	private Rectangle currentSelected;
+
+	public FeedbackColorPickerView(FeedbackColor startColor, List<? extends FeedbackColor> colors, Consumer<FeedbackColor> finish) {
+		double size = Math.sqrt(colors.size());
+		int iSize = (int) size;
+		if (size != iSize) {
+			iSize++;
+		}
+
+		setVgap(5);
+		setHgap(5);
+
+		setPadding(new Insets(5));
+
+		int index = 0;
+		for (int y = 0; y < iSize; y++) {
+			for (int x = 0; x < iSize; x++) {
+				if (index < colors.size()) {
+					FeedbackColor color = colors.get(index++);
+
+					// Style in CSS
+					Rectangle rectangle = new Rectangle(40, 40);
+					rectangle.setFill(color.getColor());
+
+					rectangle.getStyleClass().add("color-view-item");
+
+					// Gestrichelte Linie
+					if (color.equals(startColor)) {
+						rectangle.getStrokeDashArray().addAll(3.0);
+					}
+
+					// EventHandler
+					rectangle.setOnMouseReleased(event ->
+					{
+						if (currentSelected != null) {
+							currentSelected.getStrokeDashArray().clear();
+						}
+						rectangle.getStrokeDashArray().addAll(3.0);
+						currentSelected = rectangle;
+						finish.accept(color);
+					});
+					add(rectangle, x, y);
+				}
+			}
+		}
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/FileDragOptionView.java b/PlayWall/src/main/java/de/tobias/playpad/view/FileDragOptionView.java
index 2a1afb6756d878d29a1e708c8e88cd0b5b466d7b..e04e34fbe511be49ef008abbdd6963f1219026db 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/view/FileDragOptionView.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/FileDragOptionView.java
@@ -68,7 +68,7 @@ public class FileDragOptionView {
 
 		ParallelTransition parallelTransition = new ParallelTransition(fadeTransition, scaleTransition);
 
-		parallelTransition.setOnFinished((e) ->
+		parallelTransition.setOnFinished(event ->
 		{
 			if (!in)
 				parent.getChildren().remove(optionPane);
@@ -132,17 +132,11 @@ public class FileDragOptionView {
 			if (node instanceof Label) {
 				Label label = (Label) node;
 				label.setOnMouseClicked(ev ->
-				{
-					onFinish.accept((PadContentFactory) label.getUserData());
-				});
+						onFinish.accept((PadContentFactory) label.getUserData()));
 				label.setOnMouseEntered(e ->
-				{
-					label.pseudoClassStateChanged(PseudoClasses.HOVER_CLASS, true);
-				});
+						label.pseudoClassStateChanged(PseudoClasses.HOVER_CLASS, true));
 				label.setOnMouseExited(e ->
-				{
-					label.pseudoClassStateChanged(PseudoClasses.HOVER_CLASS, false);
-				});
+						label.pseudoClassStateChanged(PseudoClasses.HOVER_CLASS, false));
 			}
 		}
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/MapperListViewControllerImpl.java b/PlayWall/src/main/java/de/tobias/playpad/view/MapperListViewControllerImpl.java
index 6cea7473ee2828b8f6112751bf87883f35674970..5216a30d8083ca9d6480f57d49eb2f09106bd45e 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/view/MapperListViewControllerImpl.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/MapperListViewControllerImpl.java
@@ -1,16 +1,22 @@
 package de.tobias.playpad.view;
 
+import de.thecodelabs.logger.Logger;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.mapping.Key;
+import de.thecodelabs.midi.mapping.KeyRegistry;
+import de.thecodelabs.midi.mapping.KeyType;
+import de.thecodelabs.midi.midi.Midi;
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
-import de.tobias.playpad.PlayPadMain;
+import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.PlayPadPlugin;
-import de.tobias.playpad.action.Action;
-import de.tobias.playpad.action.mapper.Mapper;
-import de.tobias.playpad.action.mapper.MapperFactory;
+import de.tobias.playpad.Strings;
+import de.tobias.playpad.action.ActionProvider;
 import de.tobias.playpad.action.mapper.MapperViewController;
 import de.tobias.playpad.registry.NoSuchComponentException;
-import de.tobias.playpad.registry.Registry;
 import de.tobias.playpad.viewcontroller.BaseMapperListViewController;
+import de.tobias.playpad.viewcontroller.mapper.KeyboardMapperViewController;
+import de.tobias.playpad.viewcontroller.mapper.MidiMapperViewController;
 import javafx.scene.Parent;
 import javafx.scene.control.Button;
 import javafx.scene.control.ContentDisplay;
@@ -22,7 +28,7 @@ import javafx.scene.layout.VBox;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Set;
+import java.util.stream.Stream;
 
 // Diese Klasse zeigt die Mapper zu einer Action an
 public class MapperListViewControllerImpl extends BaseMapperListViewController {
@@ -54,22 +60,23 @@ public class MapperListViewControllerImpl extends BaseMapperListViewController {
 
 		addMappingBox = new HBox(14);
 
-		Label headline = new Label(PlayPadMain.getUiResourceBundle().getString("action.mapper.headline"));
+		Label headline = new Label(Localization.getString("action.mapper.headline"));
 		headline.setUnderline(true);
 		root.getChildren().addAll(headline, mappingView, addMappingBox);
 
-		Registry<MapperFactory> registry = PlayPadPlugin.getRegistries().getMappers();
-		Set<String> types = registry.getTypes();
-		types.stream().sorted().forEach(item ->
+		final KeyType[] keys = KeyType.values();
+		Stream.of(keys).forEach(item ->
 		{
-			String name = item;
-			try {
-				MapperFactory connect = registry.getFactory(item);
-				name = connect.toString();
-			} catch (NoSuchComponentException e) {
-				// TODO Error Handling
-				e.printStackTrace();
+			String name = "";
+			switch (item) {
+				case MIDI:
+					name = Localization.getString(Strings.MAPPER_MIDI_NAME);
+					break;
+				case KEYBOARD:
+					name = Localization.getString(Strings.MAPPER_KEYBOARD_NAME);
+					break;
 			}
+
 			Button button = new Button(name, new FontIcon(FontAwesomeType.PLUS_CIRCLE));
 			button.setContentDisplay(ContentDisplay.TOP);
 			button.setPrefWidth(150);
@@ -78,17 +85,17 @@ public class MapperListViewControllerImpl extends BaseMapperListViewController {
 			{
 				// Adds a mapper to the action
 				try {
-					MapperViewController controller = onAddMapper(item);
+					ActionProvider provider = PlayPadPlugin.getRegistries().getActions().getFactory(action.getActionType());
+					MapperViewController controller = onAddMapper(item, action, provider);
 					boolean result = controller.showInputMapperUI();
 
 					// Delete Mapper wenn Eingabe abgebrochen wurde
 					if (!result) {
 						mappingView.getChildren().removeAll(controller.getParent().getParent());
-						action.removeMapper(controller.getMapper());
+						action.removeKey(controller.getKey());
 					}
 				} catch (NoSuchComponentException ex) {
-					// TODO Error Handling
-					ex.printStackTrace();
+					Logger.error(e);
 				}
 
 			});
@@ -96,32 +103,51 @@ public class MapperListViewControllerImpl extends BaseMapperListViewController {
 		});
 	}
 
-	private MapperViewController onAddMapper(String type) throws NoSuchComponentException {
-		Registry<MapperFactory> registry = PlayPadPlugin.getRegistries().getMappers();
-
-		Mapper mapper = registry.getFactory(type).createNewMapper();
-		action.addMapper(mapper);
-		return addMapperView(type, mapper);
+	private MapperViewController onAddMapper(KeyType type, Action action, ActionProvider provider) throws NoSuchComponentException {
+		try {
+			KeyRegistry registry = KeyRegistry.getInstance();
+			Key mapper = registry.createInstance(type, provider.supportedFeedbackOptions(action, type));
+			action.addKey(mapper);
+			return addMapperView(type, mapper);
+		} catch (Exception e) {
+			throw new NoSuchComponentException(e);
+		}
 	}
 
-	private MapperViewController addMapperView(String type, Mapper mapper) {
-		MapperViewController controller = (MapperViewController) mapper.getSettingsViewController();
-		if (controller != null) {
-			Button deleteButton = new Button("", new FontIcon(FontAwesomeType.TRASH));
+	private MapperViewController addMapperView(KeyType type, Key key) {
+		MapperViewController controller = null;
+
+		switch (type) {
+			case MIDI:
+				controller = new MidiMapperViewController();
+				break;
+			case KEYBOARD:
+				controller = new KeyboardMapperViewController();
+				break;
+			default:
+				return null;
+		}
 
-			HBox hbox = new HBox(controller.getParent(), deleteButton);
-			hbox.setSpacing(14);
+		controller.setKey(key);
+		Button deleteButton = new Button("", new FontIcon(FontAwesomeType.TRASH));
 
-			mappingView.getChildren().addAll(hbox);
+		HBox hbox = new HBox(controller.getParent(), deleteButton);
+		hbox.setSpacing(14);
+
+		mappingView.getChildren().addAll(hbox);
+
+		deleteButton.setOnAction(e ->
+		{
+			action.removeKey(key);
+			mappingView.getChildren().removeAll(hbox);
+
+			// disable highlight for current button on device
+			Midi.getInstance().clearFeedback();
+		});
 
-			deleteButton.setOnAction((e) ->
-			{
-				action.removeMapper(mapper);
-				mappingView.getChildren().removeAll(hbox);
-			});
-		}
 		controllers.add(controller);
-		addListeners.forEach(i -> i.onAdd(mapper, controller));
+		MapperViewController finalController = controller;
+		addListeners.forEach(i -> i.onAdd(key, finalController));
 		return controller;
 	}
 
@@ -144,21 +170,22 @@ public class MapperListViewControllerImpl extends BaseMapperListViewController {
 		controllers.clear();
 		mappingView.getChildren().clear();
 
-		List<Mapper> mapperSorted = action.getMapperSorted();
+		List<Key> mapperSorted = action.getKeys();
 		for (int i = 0; i < mapperSorted.size(); i++) {
-			Mapper mapper = mapperSorted.get(i);
+			Key mapper = mapperSorted.get(i);
 			addMapperView(mapper.getType(), mapper);
 		}
 	}
 
 	@Override
 	public void showAction(Action action, Pane parent) {
+		this.addListeners.clear();
 		this.action = action;
 
 		createSubViews(action);
 
 		if (this.parent != null) {
-			this.parent.getChildren().remove(getParent()); // Rmeove from old Parent
+			this.parent.getChildren().remove(getParent()); // Remove from old Parent
 		}
 		if (this.scrollPane != null) {
 			this.scrollPane.setContent(null);
@@ -175,7 +202,7 @@ public class MapperListViewControllerImpl extends BaseMapperListViewController {
 		createSubViews(action);
 
 		if (this.parent != null) {
-			this.parent.getChildren().remove(getParent()); // Rmeove from old Parent
+			this.parent.getChildren().remove(getParent()); // Remove from old Parent
 		}
 		if (this.scrollPane != null) {
 			this.scrollPane.setContent(null);
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/PseudoClasses.java b/PlayWall/src/main/java/de/tobias/playpad/view/PseudoClasses.java
index 625a1a9480771f75b2d7aa2e5b8d2a5566f2e410..3af53dd3a98de27a9bde11cfeceb946b627c57f1 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/view/PseudoClasses.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/PseudoClasses.java
@@ -4,10 +4,17 @@ import javafx.css.PseudoClass;
 
 public class PseudoClasses {
 
+	private PseudoClasses() {
+	}
+
 	public static final PseudoClass ERROR_CLASS = PseudoClass.getPseudoClass("error");
 	public static final PseudoClass PLAY_CLASS = PseudoClass.getPseudoClass("play");
 	public static final PseudoClass FADE_CLASS = PseudoClass.getPseudoClass("fade");
 	public static final PseudoClass WARN_CLASS = PseudoClass.getPseudoClass("warn");
 	public static final PseudoClass HOVER_CLASS = PseudoClass.getPseudoClass("drag");
 	public static final PseudoClass DRAG_CLASS = PseudoClass.getPseudoClass("drag");
+
+	public static final PseudoClass DEACTIVATED_CLASS = PseudoClass.getPseudoClass("deactivated");
+
+
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/AuthViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/AuthViewController.java
index 7bd7fa21fd9f019d9e558c679ea742a15faee824..fea41877d080d699740941a325ef0d8b3fbb4a2c 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/AuthViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/AuthViewController.java
@@ -1,11 +1,11 @@
 package de.tobias.playpad.viewcontroller;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.server.Session;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.scene.control.Button;
@@ -13,6 +13,7 @@ import javafx.scene.control.Label;
 import javafx.scene.control.PasswordField;
 import javafx.scene.control.TextField;
 import javafx.stage.Stage;
+import javafx.stage.Window;
 
 import java.io.IOException;
 
@@ -34,28 +35,27 @@ public class AuthViewController extends NVC {
 	@FXML
 	private Label infoLabel;
 
-	private Session session;
-
 	private AuthBasedRunnable authBasedRunnable;
 
-	public AuthViewController(String info, AuthBasedRunnable authBasedRunnable) {
-		load("view/dialog", "AuthDialog", PlayPadMain.getUiResourceBundle());
+	public AuthViewController(Window owner, String info, AuthBasedRunnable authBasedRunnable) {
+		load("view/dialog", "AuthDialog", Localization.getBundle());
 		infoLabel.setText(info);
 
-		applyViewControllerToStage();
+		final NVCStage nvcStage = applyViewControllerToStage();
+		nvcStage.initOwner(owner);
 
 		this.authBasedRunnable = authBasedRunnable;
 	}
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		stage.setMinWidth(500);
 		stage.setMinHeight(250);
 		stage.setWidth(500);
 		stage.setHeight(250);
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_Login_Title));
+		stage.setTitle(Localization.getString(Strings.UI_DIALOG_LOGIN_TITLE));
 
 		PlayPadPlugin.styleable().applyStyle(stage);
 	}
@@ -71,7 +71,7 @@ public class AuthViewController extends NVC {
 				closeStage();
 			}
 		} catch (IOException e) {
-			e.printStackTrace();
+			Logger.error(e);
 			showErrorMessage(e.getMessage());
 		}
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/LaunchDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/LaunchDialog.java
index a0af515d98d066291f7fab3b8269e5993779236d..ef0c65d94162cd5221379f41fe0cdb97ad135820 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/LaunchDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/LaunchDialog.java
@@ -14,18 +14,15 @@ import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.profile.ProfileNotFoundException;
 import de.tobias.playpad.profile.ref.ProfileReference;
-import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.ProjectNotFoundException;
 import de.tobias.playpad.project.ProjectReader;
-import de.tobias.playpad.project.importer.ConverterV6;
-import de.tobias.playpad.project.loader.ProjectLoader;
+import de.tobias.playpad.project.importer.ProjectImporter;
 import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.project.ref.ProjectReferenceManager;
 import de.tobias.playpad.server.*;
 import de.tobias.playpad.viewcontroller.cell.ProjectCell;
 import de.tobias.playpad.viewcontroller.dialog.ModernPluginViewController;
 import de.tobias.playpad.viewcontroller.dialog.project.ProjectImportDialog;
-import de.tobias.playpad.viewcontroller.dialog.project.ProjectLoadDialog;
 import de.tobias.playpad.viewcontroller.dialog.project.ProjectNewDialog;
 import de.tobias.playpad.viewcontroller.dialog.project.ProjectReaderDelegateImpl;
 import javafx.application.Platform;
@@ -43,7 +40,6 @@ import javafx.scene.paint.Color;
 import javafx.stage.FileChooser;
 import javafx.stage.Modality;
 import javafx.stage.Stage;
-import org.dom4j.DocumentException;
 
 import java.io.File;
 import java.io.IOException;
@@ -57,31 +53,31 @@ public class LaunchDialog extends NVC implements ChangeListener<ConnectionState>
 	static final String IMAGE = "gfx/Logo-large.png";
 
 	@FXML
-	Label infoLabel;
+	private Label infoLabel;
 	@FXML
-	ImageView imageView;
+	private ImageView imageView;
 
 	@FXML
-	ListView<ProjectReference> projectListView;
+	private ListView<ProjectReference> projectListView;
 
 	@FXML
-	Button newProjectButton;
+	private Button newProjectButton;
 	@FXML
-	Button importProjectButton;
+	private Button importProjectButton;
 	@FXML
-	Button convertProjectButton;
+	private Button convertProjectButton;
 
 	@FXML
-	Button openButton;
+	private Button openButton;
 	@FXML
-	Button deleteButton;
+	private Button deleteButton;
 
 	@FXML
-	Label cloudLabel;
-	FontIcon cloudIcon;
+	private Label cloudLabel;
+	private FontIcon cloudIcon;
 
 	public LaunchDialog(Stage stage) {
-		load("view/dialog", "LaunchDialog", PlayPadMain.getUiResourceBundle());
+		load("view/dialog", "LaunchDialog", Localization.getBundle());
 		setProjectListValues();
 
 		applyViewControllerToStage(stage);
@@ -97,14 +93,14 @@ public class LaunchDialog extends NVC implements ChangeListener<ConnectionState>
 		App app = ApplicationUtils.getApplication();
 
 		// Setup launchscreen labels and image
-		infoLabel.setText(getString(Strings.UI_Dialog_Launch_Info, app.getInfo().getName(), app.getInfo().getVersion()));
+		infoLabel.setText(getString(Strings.UI_DIALOG_LAUNCH_INFO, app.getInfo().getName(), app.getInfo().getVersion()));
 		imageView.setImage(new Image(IMAGE));
 
 		openButton.setDisable(true);
 		deleteButton.setDisable(true);
 
 		// Load project to list
-		projectListView.setPlaceholder(new Label(getString(Strings.UI_Placeholder_Project)));
+		projectListView.setPlaceholder(new Label(getString(Strings.UI_PLACEHOLDER_PROJECT)));
 		projectListView.setId("list");
 		projectListView.setCellFactory(list -> new ProjectCell(true));
 
@@ -116,12 +112,10 @@ public class LaunchDialog extends NVC implements ChangeListener<ConnectionState>
 
 		// Mouse Double Click on list
 		projectListView.setOnMouseClicked(mouseEvent -> {
-			if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {
-				if (mouseEvent.getClickCount() == 2) {
-					if (!projectListView.getSelectionModel().isEmpty()) {
-						launchProject(getSelectedProject());
-					}
-				}
+			if (mouseEvent.getButton().equals(MouseButton.PRIMARY) &&
+					mouseEvent.getClickCount() == 2 &&
+					!projectListView.getSelectionModel().isEmpty()) {
+				launchProject(getSelectedProject());
 			}
 		});
 
@@ -138,8 +132,8 @@ public class LaunchDialog extends NVC implements ChangeListener<ConnectionState>
 	public void initStage(Stage stage) {
 		PlayPadPlugin.styleable().applyStyle(stage);
 
-		stage.setTitle(getString(Strings.UI_Dialog_Launch_Title));
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.setTitle(getString(Strings.UI_DIALOG_LAUNCH_TITLE));
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		stage.setResizable(false);
 		stage.setWidth(650);
@@ -158,22 +152,21 @@ public class LaunchDialog extends NVC implements ChangeListener<ConnectionState>
 		switch (server.getConnectionState()) {
 			case CONNECTED:
 				cloudIcon.setColor(Color.BLACK);
-				cloudLabel.setText(Localization.getString(Strings.Server_Connected));
+				cloudLabel.setText(Localization.getString(Strings.SERVER_CONNECTED));
 				break;
 			case CONNECTION_LOST:
 				cloudIcon.setColor(Color.GRAY);
-				cloudLabel.setText(Localization.getString(Strings.Server_Connection_Lost));
+				cloudLabel.setText(Localization.getString(Strings.SERVER_CONNECTION_LOST));
 				break;
 			case DISCONNECTED:
 				cloudIcon.setColor(Color.RED);
-				cloudLabel.setText(Localization.getString(Strings.Server_Disconnected));
+				cloudLabel.setText(Localization.getString(Strings.SERVER_DISCONNECTED));
 				break;
 		}
 	}
 
 	@FXML
 	void newProjectButtonHandler(ActionEvent event) {
-		Logger.info("einfo");
 		ProjectNewDialog dialog = new ProjectNewDialog(getContainingWindow());
 		dialog.showAndWait().ifPresent(this::launchProject);
 	}
@@ -182,8 +175,8 @@ public class LaunchDialog extends NVC implements ChangeListener<ConnectionState>
 	void importProjectButtonHandler(ActionEvent event) {
 		FileChooser chooser = new FileChooser();
 
-		String extensionName = Localization.getString(Strings.File_Filter_ZIP);
-		FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter(extensionName, PlayPadMain.projectZIPType);
+		String extensionName = Localization.getString(Strings.FILE_FILTER_ZIP);
+		FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter(extensionName, PlayPadMain.ZIP_TYPE);
 		chooser.getExtensionFilters().add(extensionFilter);
 
 		File file = chooser.showOpenDialog(getContainingWindow());
@@ -193,43 +186,12 @@ public class LaunchDialog extends NVC implements ChangeListener<ConnectionState>
 				ProjectImportDialog dialog = new ProjectImportDialog(file.toPath(), getContainingWindow());
 				Optional<ProjectReference> importedProject = dialog.showAndWait();
 				importedProject.ifPresent(projectListView.getItems()::add);
-			} catch (IOException | DocumentException e) {
-				e.printStackTrace();
+			} catch (IOException | ProjectImporter.ProjectImportCorruptedException e) {
+				Logger.error(e);
 			}
 		}
 	}
 
-	@FXML
-	void convertProjectButtonHandler(ActionEvent event) {
-		try {
-			List<ProjectReference> projects = ConverterV6.loadProjectReferences();
-			ChoiceDialog<ProjectReference> dialog = new ChoiceDialog<>(null, projects);
-
-			dialog.setHeaderText(Localization.getString(Strings.UI_Dialog_Project_Convert_Header));
-			dialog.setContentText(Localization.getString(Strings.UI_Dialog_Project_Convert_Content));
-
-			dialog.initOwner(getContainingWindow());
-			dialog.initModality(Modality.WINDOW_MODAL);
-			Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
-			PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
-
-			Optional<ProjectReference> result = dialog.showAndWait();
-			result.ifPresent((ref) -> {
-				try {
-					ConverterV6.convert(ref.getUuid(), ref.getName());
-					ProjectReferenceManager.addProjectReference(ref);
-					setProjectListValues();
-				} catch (IOException | DocumentException e) {
-					e.printStackTrace();
-					showErrorMessage(Localization.getString(Strings.Error_Project_Convert));
-				}
-			});
-		} catch (IOException | DocumentException e) {
-			e.printStackTrace();
-			showErrorMessage(Localization.getString(Strings.Error_Standard_Gen));
-		}
-	}
-
 	@FXML
 	void openButtonHandler(ActionEvent event) {
 		launchProject(getSelectedProject());
@@ -241,10 +203,10 @@ public class LaunchDialog extends NVC implements ChangeListener<ConnectionState>
 			ProjectReference ref = getSelectedProject();
 
 			Alert alert = new Alert(AlertType.CONFIRMATION);
-			alert.setContentText(getString(Strings.UI_Dialog_ProjectManager_Delete_Content, ref));
+			alert.setContentText(getString(Strings.UI_DIALOG_PROJECT_MANAGER_DELETE_CONTENT, ref));
 
 			Stage dialog = (Stage) alert.getDialogPane().getScene().getWindow();
-			PlayPadMain.stageIcon.ifPresent(dialog.getIcons()::add);
+			dialog.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 			alert.initOwner(getContainingWindow());
 			alert.initModality(Modality.WINDOW_MODAL);
 
@@ -254,7 +216,7 @@ public class LaunchDialog extends NVC implements ChangeListener<ConnectionState>
 					ProjectReferenceManager.removeProject(ref);
 					projectListView.getItems().remove(ref); // VIEW
 				} catch (IOException e) {
-					showErrorMessage(getString(Strings.Error_Project_Delete, e.getLocalizedMessage()));
+					showErrorMessage(getString(Strings.ERROR_PROJECT_DELETE, e.getLocalizedMessage()));
 				}
 			});
 		}
@@ -270,7 +232,7 @@ public class LaunchDialog extends NVC implements ChangeListener<ConnectionState>
 				server.connect(session.getKey());
 			} catch (IOException | WebSocketException e) {
 				Logger.error(e);
-			} catch (SessionNotExisitsException ignored) {
+			} catch (SessionNotExistsException ignored) {
 				Logger.warning("Session not exists");
 			}
 		}
@@ -294,40 +256,33 @@ public class LaunchDialog extends NVC implements ChangeListener<ConnectionState>
 		Server server = PlayPadPlugin.getServerHandler().getServer();
 		server.connectionStateProperty().removeListener(this);
 
-		// Es fehlen Module
+		// Modules missing
 		if (!ref.getMissedModules().isEmpty()) {
-			showInfoMessage(Localization.getString(Strings.Error_Plugins_Missing));
+			showInfoMessage(Localization.getString(Strings.ERROR_PLUGINS_MISSING));
 
 			ModernPluginViewController pluginViewController = new ModernPluginViewController(getContainingWindow(), ref.getMissedModules());
 			pluginViewController.getStageContainer().ifPresent(NVCStage::showAndWait);
 		}
 
-		ProjectReader.ProjectReaderDelegate delegate = ProjectReaderDelegateImpl.getInstance(getContainingWindow());
 		try {
-			ProjectLoader loader = new ProjectLoader(ref);
-			loader.setDelegate(delegate);
-			loader.setListener(new ProjectLoadDialog());
-
-			Project project = loader.load();
-			PlayPadMain.getProgramInstance().openProject(project, e -> getStageContainer().ifPresent(NVCStage::close));
+			PlayPadMain.getProgramInstance().openProject(ref, e -> getStageContainer().ifPresent(NVCStage::close));
 		} catch (ProfileNotFoundException e) {
 			Logger.error(e);
-			showErrorMessage(getString(Strings.Error_Profile_NotFound, ref.getProfileReference(), e.getLocalizedMessage()));
+			showErrorMessage(getString(Strings.ERROR_PROFILE_NOT_FOUND, ref.getProfileReference(), e.getLocalizedMessage()));
 
 			// Choose new profile
 			ProfileReference profile = null;
 			try {
-				profile = delegate.getProfileReference();
+				profile = ProjectReaderDelegateImpl.getInstance(getContainingWindow()).getProfileReference();
 			} catch (ProjectReader.ProjectReaderDelegate.ProfileAbortException ignored) {
 			}
 			ref.setProfileReference(profile);
-		} catch (ProjectReader.ProjectReaderDelegate.ProfileAbortException ignored) {
 		} catch (ProjectNotFoundException e) {
 			Logger.error(e);
-			showErrorMessage(getString(Strings.Error_Project_NotFound, ref, e.getLocalizedMessage()));
+			showErrorMessage(getString(Strings.ERROR_PROJECT_NOT_FOUND, ref, e.getMessage()));
 		} catch (Exception e) {
 			Logger.error(e);
-			showErrorMessage(getString(Strings.Error_Project_Open, ref, e.getLocalizedMessage()));
+			showErrorMessage(getString(Strings.ERROR_PROJECT_OPEN, ref, e.getMessage()));
 		}
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/LoginViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/LoginViewController.java
index 8166cb3f1d2a690a4b2c87e3f04b1b2839c284cb..12613d9378c90d996c6b977cf1198edc93da328b 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/LoginViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/LoginViewController.java
@@ -1,24 +1,33 @@
 package de.tobias.playpad.viewcontroller;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.App;
 import de.thecodelabs.utils.application.ApplicationUtils;
+import de.thecodelabs.utils.threading.Worker;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
+import de.thecodelabs.utils.ui.scene.HUD;
+import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.AppUserInfoStrings;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.server.LoginException;
 import de.tobias.playpad.server.Server;
 import de.tobias.playpad.server.Session;
 import de.tobias.playpad.server.SessionDelegate;
+import javafx.application.Platform;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
 import javafx.scene.control.Label;
 import javafx.scene.control.PasswordField;
+import javafx.scene.control.ProgressIndicator;
 import javafx.scene.control.TextField;
 import javafx.scene.image.Image;
 import javafx.scene.image.ImageView;
+import javafx.scene.layout.Pane;
+import javafx.stage.Modality;
 import javafx.stage.Stage;
 
 import java.awt.*;
@@ -54,23 +63,29 @@ public class LoginViewController extends NVC implements SessionDelegate {
 		App app = ApplicationUtils.getApplication();
 
 		// Setup launchscreen labels and image
-		infoLabel.setText(getString(Strings.UI_Dialog_Launch_Info, app.getInfo().getName(), app.getInfo().getVersion()));
+		infoLabel.setText(getString(Strings.UI_DIALOG_LAUNCH_INFO, app.getInfo().getName(), app.getInfo().getVersion()));
 		try {
 			imageView.setImage(new Image(LaunchDialog.IMAGE));
 		} catch (Exception e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 
 	@Override
 	public void initStage(Stage stage) {
-		stage.setTitle(getString(Strings.UI_Dialog_Login_Title));
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		PlayPadPlugin.styleable().applyStyle(stage);
+
+		stage.setTitle(getString(Strings.UI_DIALOG_LOGIN_TITLE));
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
+
+		stage.initModality(Modality.APPLICATION_MODAL);
 
 		stage.setResizable(false);
 		stage.setWidth(650);
 		stage.setHeight(350);
 		stage.centerOnScreen();
+
+		usernameTextField.requestFocus();
 	}
 
 	@FXML
@@ -80,24 +95,37 @@ public class LoginViewController extends NVC implements SessionDelegate {
 		String username = usernameTextField.getText();
 		String password = passwordTextField.getText();
 
-		try {
-			String key = server.getSession(username, password);
-			session = new Session(key);
-			session.save();
-			getStageContainer().ifPresent(NVCStage::close);
-		} catch (IOException | LoginException e) {
-			e.printStackTrace();
-			showErrorMessage(e.getMessage());
-		}
+		final ProgressIndicator progressIndicator = new ProgressIndicator(-1);
+		progressIndicator.setMinSize(100, 100);
+		HUD hud = new HUD(progressIndicator);
+		hud.setPadding(new Insets(14));
+		hud.setPosition(Pos.CENTER);
+		hud.addToParent((Pane) getParent());
+
+		Worker.runLater(() -> {
+			try {
+				String key = server.getSession(username, password);
+				session = new Session(key);
+				session.save();
+				Platform.runLater(() -> getStageContainer().ifPresent(NVCStage::close));
+			} catch (IOException e) {
+				Logger.error(e);
+				showErrorMessage(Localization.getString("Server.Error.IO"));
+			} catch (LoginException e) {
+				Logger.error(e);
+				showErrorMessage(Localization.getString("Server.Error.Login"));
+			}
+			Platform.runLater(hud::removeFromParent);
+		});
 	}
 
 	@FXML
 	private void registerHandler(ActionEvent event) {
-		URI uri = URI.create(ApplicationUtils.getApplication().getInfo().getUserInfo().get(AppUserInfoStrings.ACCOUNT_REGISTER).toString());
+		URI uri = URI.create(ApplicationUtils.getApplication().getUserInfo(AppUserInfoStrings.class).accountRegister());
 		try {
 			Desktop.getDesktop().browse(uri);
 		} catch (IOException e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 
@@ -108,7 +136,7 @@ public class LoginViewController extends NVC implements SessionDelegate {
 
 	@Override
 	public Session getSession() {
-		load("view/dialog", "LoginDialog", PlayPadMain.getUiResourceBundle());
+		load("view/dialog", "LoginDialog", Localization.getBundle());
 		applyViewControllerToStage();
 
 		Optional<NVCStage> stage = getStageContainer();
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/SplashScreenViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/SplashScreenViewController.java
new file mode 100644
index 0000000000000000000000000000000000000000..d41b191e451ffc61c673273506a86ae9e5aa2753
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/SplashScreenViewController.java
@@ -0,0 +1,96 @@
+package de.tobias.playpad.viewcontroller;
+
+import de.thecodelabs.utils.application.App;
+import de.thecodelabs.utils.application.ApplicationUtils;
+import de.thecodelabs.utils.ui.NVC;
+import de.tobias.playpad.PlayPadImpl;
+import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.initialize.PlayPadInitializeTask;
+import de.tobias.playpad.initialize.PlayPadInitializer;
+import javafx.application.Platform;
+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+import javafx.scene.control.ProgressBar;
+import javafx.stage.Stage;
+import javafx.stage.StageStyle;
+import org.controlsfx.dialog.ExceptionDialog;
+
+public class SplashScreenViewController extends NVC implements PlayPadInitializer.Listener {
+
+	@FXML
+	private Label titleLabel;
+	@FXML
+	private Label versionLabel;
+	@FXML
+	private ProgressBar progressBar;
+	@FXML
+	private Label loadingLabel;
+
+	private int maxValue;
+	private int currentValue;
+
+	public static void show(PlayPadImpl instance, Stage primaryStage) {
+		new SplashScreenViewController(instance, primaryStage);
+	}
+
+	private SplashScreenViewController(PlayPadImpl instance, Stage primaryStage) {
+		load("view", "SplashScreen", controller -> {
+			controller.applyViewControllerToStage(primaryStage).show();
+			instance.startup(new LoginViewController(), this);
+		});
+	}
+
+	@Override
+	public void init() {
+		App app = ApplicationUtils.getApplication();
+		titleLabel.setText(app.getInfo().getName());
+		versionLabel.setText(app.getInfo().getVersion());
+	}
+
+	@Override
+	public void initStage(Stage stage) {
+		stage.initStyle(StageStyle.UNDECORATED);
+		PlayPadPlugin.styleable().applyStyle(stage);
+	}
+
+	@Override
+	public void startLoading(int count) {
+		this.maxValue = count;
+	}
+
+	@Override
+	public void startTask(PlayPadInitializeTask task) {
+		Platform.runLater(() -> loadingLabel.setText(task.name()));
+	}
+
+	@Override
+	public void finishTask(PlayPadInitializeTask task) {
+		currentValue++;
+		Platform.runLater(() -> progressBar.setProgress(currentValue / (double) maxValue));
+	}
+
+	@Override
+	public void finishLoading() {
+		Platform.runLater(() -> {
+			closeStage();
+			new LaunchDialog(new Stage()); // Show Launch Stage
+		});
+	}
+
+	@Override
+	public void abortedLoading() {
+		Platform.setImplicitExit(false);
+		Platform.runLater(this::closeStage);
+	}
+
+	@Override
+	public void errorLoading(PlayPadInitializeTask task, Exception e) {
+		Platform.runLater(() -> {
+			ExceptionDialog dialog = new ExceptionDialog(e);
+			dialog.setHeaderText("Error while loading PlayWall (" + task.name() + ")");
+			dialog.initOwner(getContainingWindow());
+			dialog.showAndWait();
+			Platform.exit();
+		});
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionTypeViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionTypeViewController.java
index 5d3f52673eae254cf32b1f26d1a2a5844fddd321..8573b914f06060b1e035a45d13907bb55378f629 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionTypeViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionTypeViewController.java
@@ -1,12 +1,12 @@
 package de.tobias.playpad.viewcontroller.actions;
 
+import de.thecodelabs.logger.Logger;
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
 import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.PlayPadMain;
-import de.tobias.playpad.PlayPadPlugin;
-import de.tobias.playpad.action.ActionProvider;
-import de.tobias.playpad.action.Mapping;
-import de.tobias.playpad.action.actions.cart.CartAction;
-import de.tobias.playpad.action.factory.CartActionProvider;
+import de.tobias.playpad.action.actions.CartAction;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.ProjectSettings;
 import de.tobias.playpad.registry.NoSuchComponentException;
@@ -36,14 +36,18 @@ public class CartActionTypeViewController extends NVC {
 	@FXML
 	private VBox cartActionContainer;
 
+	private CartActionViewController cartActionViewController;
+
 	private Mapping mapping;
 	private IMappingTabViewController parentController;
 
 	public CartActionTypeViewController(Mapping mapping, IMappingTabViewController parentController) {
-		load("view/actions", "CartActions", PlayPadMain.getUiResourceBundle());
+		load("view/actions", "CartActions", Localization.getBundle());
 		this.mapping = mapping;
 		this.parentController = parentController;
 
+		cartActionViewController = new CartActionViewController();
+
 		Project currentProject = PlayPadMain.getProgramInstance().getCurrentProject();
 		ProjectSettings settings = currentProject.getSettings();
 
@@ -56,6 +60,7 @@ public class CartActionTypeViewController extends NVC {
 		buttonVbox.minHeightProperty().bind(buttonVbox.heightProperty());
 	}
 
+	@SuppressWarnings("Duplicates")
 	private void showCartButtons(ProjectSettings settings) {
 		gridPane.getChildren().clear();
 
@@ -87,36 +92,35 @@ public class CartActionTypeViewController extends NVC {
 				button.getStyleClass().add(SegmentedButton.STYLE_CLASS_DARK);
 
 				// Show the right cart settings
-				button.selectedProperty().addListener((a, b, c) ->
-				{
-					if (c) {
-						int[] data = (int[]) button.getUserData();
-						int currentX = data[0];
-						int currentY = data[1];
-
-						try {
-							ActionProvider actionFactory = PlayPadPlugin.getRegistries().getActions().getFactory(CartActionProvider.class);
-
-							List<CartAction> cartActions = mapping.getActions(actionFactory);
-							for (CartAction action : cartActions) {
-								if (action.getX() == currentX && action.getY() == currentY) {
-									NVC actionViewController = action.getSettingsViewController();
-									cartActionContainer.getChildren().setAll(actionViewController.getParent());
-									cartActionContainer.setVisible(true);
-									parentController.showMapperFor(action);
-								}
-							}
-						} catch (NoSuchComponentException e) {
-							e.printStackTrace();
-						}
-					} else {
-						cartActionContainer.setVisible(false);
-						parentController.showMapperFor(null);
-					}
-				});
+				button.selectedProperty().addListener((observable, oldValue, newValue) -> toggleButtonHandler(button, newValue));
 				gridPane.add(button, x, y);
 				cartsToggle.getToggles().add(button);
 			}
 		}
 	}
+
+	private void toggleButtonHandler(ToggleButton button, Boolean newValue) {
+		if (newValue) {
+			int[] data = (int[]) button.getUserData();
+			int currentX = data[0];
+			int currentY = data[1];
+
+			try {
+				List<Action> cartActions = mapping.getActionsForType(CartAction.TYPE);
+				for (Action action : cartActions) {
+					if (CartAction.getX(action) == currentX && CartAction.getY(action) == currentY) {
+						cartActionContainer.getChildren().setAll(cartActionViewController.getParent());
+						cartActionContainer.setVisible(true);
+						cartActionViewController.setCartAction(action);
+						parentController.showMapperFor(action);
+					}
+				}
+			} catch (NoSuchComponentException e) {
+				Logger.error(e);
+			}
+		} else {
+			cartActionContainer.setVisible(false);
+			parentController.showMapperFor(null);
+		}
+	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionViewController.java
index 114f61f4fe4a1d51e35179d8254efc0fbb0e7e95..b43977c2420ae78ac8bb1ca86e4585a88e847088 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionViewController.java
@@ -1,12 +1,11 @@
 package de.tobias.playpad.viewcontroller.actions;
 
+import de.thecodelabs.midi.action.Action;
 import de.thecodelabs.utils.ui.NVC;
-import de.tobias.playpad.PlayPadMain;
+import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.action.actions.cart.CartAction;
-import de.tobias.playpad.action.actions.cart.CartAction.CartActionMode;
-import de.tobias.playpad.action.mapper.MapperViewController;
-import de.tobias.playpad.viewcontroller.BaseMapperListViewController;
+import de.tobias.playpad.action.actions.CartAction;
+import de.tobias.playpad.action.actions.CartAction.CartActionMode;
 import de.tobias.playpad.viewcontroller.cell.EnumCell;
 import javafx.fxml.FXML;
 import javafx.scene.control.CheckBox;
@@ -23,54 +22,29 @@ public class CartActionViewController extends NVC {
 
 	@FXML
 	private VBox rootContainer;
-	private BaseMapperListViewController baseMapperListViewController;
 
-	private CartAction action;
+	private Action action;
 
 	public CartActionViewController() {
-		load("view/actions", "CartAction", PlayPadMain.getUiResourceBundle());
+		load("view/actions", "CartAction", Localization.getBundle());
 	}
 
 	@Override
 	public void init() {
 		controlMode.getItems().setAll(CartActionMode.values());
-		controlMode.setCellFactory(list -> new EnumCell<>(Strings.CartAction_Mode_BaseName));
-		controlMode.setButtonCell(new EnumCell<>(Strings.CartAction_Mode_BaseName));
-		controlMode.valueProperty().addListener((a, b, c) ->
-		{
-			action.setMode(c);
-		});
+		controlMode.setCellFactory(list -> new EnumCell<>(Strings.CART_ACTION_MODE));
+		controlMode.setButtonCell(new EnumCell<>(Strings.CART_ACTION_MODE));
+		controlMode.valueProperty().addListener((observable, oldValue, newValue) -> CartAction.setMode(action, newValue));
 
-		autoColorCheckbox.selectedProperty().addListener((a, b, c) ->
-		{
-			action.setAutoFeedbackColors(c);
-			// Disable Feedback Controls bei Automatischen Feedback für VORHANDENE MAPPER
-			if (baseMapperListViewController != null) {
-				baseMapperListViewController.getControllers().forEach(this::toggleFeedbackVisibility);
-			}
-		});
-		VBox.setVgrow(rootContainer, Priority.ALWAYS);
+		autoColorCheckbox.selectedProperty().addListener((observable, oldValue, newValue) -> CartAction.setAutoFeedback(action, newValue));
 
-		baseMapperListViewController = BaseMapperListViewController.getInstance();
-		baseMapperListViewController.addNewMapperListener((mapper, controller) ->
-		{
-			// Show/Hide Feedback settings, depending on the cart action settings
-			toggleFeedbackVisibility(controller);
-		});
+		VBox.setVgrow(rootContainer, Priority.ALWAYS);
 	}
 
-	public void setCartAction(CartAction action) {
+	public void setCartAction(Action action) {
 		this.action = action;
 
-		controlMode.setValue(action.getMode());
-		autoColorCheckbox.setSelected(action.isAutoFeedbackColors());
-	}
-
-	private void toggleFeedbackVisibility(MapperViewController controller) {
-		if (action.isAutoFeedbackColors()) {
-			controller.hideFeedback();
-		} else {
-			controller.showFeedback();
-		}
+		controlMode.setValue(CartAction.getMode(action));
+		autoColorCheckbox.setSelected(CartAction.isAutoFeedback(action));
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/MappingListCell.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/MappingListCell.java
new file mode 100644
index 0000000000000000000000000000000000000000..59a9fbb7d2bc5724b40ebe8042fcc444eb02ebb8
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/MappingListCell.java
@@ -0,0 +1,17 @@
+package de.tobias.playpad.viewcontroller.cell;
+
+import de.thecodelabs.midi.Mapping;
+import javafx.scene.control.ListCell;
+
+public final class MappingListCell extends ListCell<Mapping> {
+
+	@Override
+	protected void updateItem(Mapping item, boolean empty) {
+		super.updateItem(item, empty);
+		if (!empty) {
+			setText(item.getName());
+		} else {
+			setText("");
+		}
+	}
+}
\ No newline at end of file
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/PageNameListCell.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/PageNameListCell.java
index bab6c8085930724e90f1fb4dda828c682d73119e..8b65ac23f31d77320a68307d8a8e4a792d5a626d 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/PageNameListCell.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/PageNameListCell.java
@@ -15,7 +15,7 @@ public final class PageNameListCell extends ListCell<Integer> {
 			Page page = PlayPadMain.getProgramInstance().getCurrentProject().getPage(item);
 			String name = page.getName();
 			if (name.isEmpty()) {
-				name = Localization.getString(Strings.UI_Window_Main_PageButton, (item));
+				name = Localization.getString(Strings.UI_WINDOW_MAIN_PAGE_BUTTON, (item));
 			}
 			setText(name);
 		} else {
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/UpdateCell.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/UpdateCell.java
index bbd59831f28dbd1f3ba63c549774555af84c4f6d..10b320887a0b194bb9dc69017aa52f9171c61eb8 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/UpdateCell.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/UpdateCell.java
@@ -11,7 +11,7 @@ public class UpdateCell extends ListCell<Version> {
 	protected void updateItem(Version item, boolean empty) {
 		super.updateItem(item, empty);
 		if (!empty) {
-			setText(Localization.getString(Strings.UI_Dialog_Update_Cell,
+			setText(Localization.getString(Strings.UI_DIALOG_UPDATE_CELL,
 					item.getArtifact().getArtifactId(),
 					item.getArtifact().getVersion(),
 					item.toVersionString()));
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/PathMatchActionCell.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/path/PathMatchActionCell.java
similarity index 90%
rename from PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/PathMatchActionCell.java
rename to PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/path/PathMatchActionCell.java
index dd0fb88c6c2dfcf6f4d57654735e7741436de899..a53be0baf16b211a57999dc5241eea1581bdd129 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/PathMatchActionCell.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/path/PathMatchActionCell.java
@@ -1,4 +1,4 @@
-package de.tobias.playpad.viewcontroller.cell;
+package de.tobias.playpad.viewcontroller.cell.path;
 
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
@@ -17,6 +17,8 @@ import javafx.scene.media.MediaPlayer;
  */
 public class PathMatchActionCell extends TableCell<PathMatchDialog.TempMediaPath, PathMatchDialog.TempMediaPath> implements EventHandler<MouseEvent> {
 
+	private static final String FONTICON_NOTFOUND = "fonticon-notfound";
+
 	private PathMatchDialog parentDialog;
 	private PathMatchDialog.TempMediaPath currentItem;
 
@@ -40,9 +42,9 @@ public class PathMatchActionCell extends TableCell<PathMatchDialog.TempMediaPath
 		folderIcon.setOnMouseClicked(this);
 		playButton.setOnMouseClicked(this);
 
-		folderIcon.getStyleClass().add("fonticon-notfound");
-		playIcon.getStyleClass().add("fonticon-notfound");
-		stopIcon.getStyleClass().add("fonticon-notfound");
+		folderIcon.getStyleClass().add(FONTICON_NOTFOUND);
+		playIcon.getStyleClass().add(FONTICON_NOTFOUND);
+		stopIcon.getStyleClass().add(FONTICON_NOTFOUND);
 
 		playButton.getStyleClass().clear();
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/path/PathMatchPathCell.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/path/PathMatchPathCell.java
new file mode 100644
index 0000000000000000000000000000000000000000..b7617a56064b2287cc7c3fa2eeb6496544512004
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/cell/path/PathMatchPathCell.java
@@ -0,0 +1,28 @@
+package de.tobias.playpad.viewcontroller.cell.path;
+
+import de.tobias.playpad.view.PseudoClasses;
+import de.tobias.playpad.viewcontroller.dialog.PathMatchDialog;
+import javafx.scene.control.TableCell;
+
+import java.nio.file.Path;
+
+public class PathMatchPathCell extends TableCell<PathMatchDialog.TempMediaPath, PathMatchDialog.TempMediaPath> {
+
+	@Override
+	protected void updateItem(PathMatchDialog.TempMediaPath item, boolean empty) {
+		super.updateItem(item, empty);
+		if (!empty) {
+			pseudoClassStateChanged(PseudoClasses.DEACTIVATED_CLASS, !item.isMatched());
+			if (item.isMatched()) {
+				setText(item.getLocalPath().toString());
+			} else {
+				Path path = item.getMediaPath().getPath();
+				if (path != null) {
+					setText(path.toString());
+				}
+			}
+		} else {
+			setText(null);
+		}
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/design/IColorButton.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/design/IColorButton.java
new file mode 100644
index 0000000000000000000000000000000000000000..c1a7a5ba5815ff0f33396565cf2a0238b960b60c
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/design/IColorButton.java
@@ -0,0 +1,17 @@
+package de.tobias.playpad.viewcontroller.design;
+
+import de.thecodelabs.utils.ui.icon.FontAwesomeType;
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import javafx.geometry.Pos;
+import javafx.scene.control.Labeled;
+
+public interface IColorButton {
+
+	default void addIconToButton(Labeled button) {
+		FontIcon iconDefault = new FontIcon(FontAwesomeType.ARROW_CIRCLE_DOWN);
+		iconDefault.getStyleClass().remove(FontIcon.STYLE_CLASS);
+		button.setGraphic(iconDefault);
+		button.setAlignment(Pos.CENTER_RIGHT);
+	}
+
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/design/ModernCartDesignViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/design/ModernCartDesignViewController.java
index f2ad517c39a62c3774b83c0ef2a8f0eb89236960..fbf39d6b0e6d113d1b5d08bcf1852194f17f2e02 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/design/ModernCartDesignViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/design/ModernCartDesignViewController.java
@@ -1,11 +1,9 @@
 package de.tobias.playpad.viewcontroller.design;
 
 import de.thecodelabs.utils.ui.NVC;
-import de.tobias.playpad.DisplayableColor;
-import de.tobias.playpad.PlayPadMain;
+import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.design.modern.ModernColor;
 import de.tobias.playpad.design.modern.model.ModernCartDesign;
-import de.tobias.playpad.design.modern.model.ModernGlobalDesign;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.view.ColorPickerView;
 import javafx.event.ActionEvent;
@@ -17,13 +15,15 @@ import org.controlsfx.control.PopOver.ArrowLocation;
 
 import java.util.function.Consumer;
 
-public class ModernCartDesignViewController extends NVC {
+public class ModernCartDesignViewController extends NVC implements IColorButton {
 
 	@FXML
 	private Button backgroundColorButton;
 	@FXML
 	private Button playColorButton;
 	@FXML
+	private Button cueInColorButton;
+	@FXML
 	private CheckBox warnAnimationCheckBox;
 
 	@FXML
@@ -34,7 +34,7 @@ public class ModernCartDesignViewController extends NVC {
 	private PopOver colorChooser;
 
 	public ModernCartDesignViewController(ModernCartDesign layout) {
-		load("view/option/layout", "ModernLayoutCart", PlayPadMain.getUiResourceBundle());
+		load("view/option/layout", "ModernLayoutCart", Localization.getBundle());
 
 		this.design = layout;
 		setLayout();
@@ -43,10 +43,14 @@ public class ModernCartDesignViewController extends NVC {
 	private void setLayout() {
 		backgroundColorButton.setStyle(getLinearGradientCss(design.getBackgroundColor()));
 		playColorButton.setStyle(getLinearGradientCss(design.getPlayColor()));
+		cueInColorButton.setStyle(getLinearGradientCss(design.getCueInColor()));
 	}
 
 	@Override
 	public void init() {
+		addIconToButton(backgroundColorButton);
+		addIconToButton(playColorButton);
+		addIconToButton(cueInColorButton);
 	}
 
 	@FXML
@@ -57,21 +61,26 @@ public class ModernCartDesignViewController extends NVC {
 
 	@FXML
 	private void backgroundColorButtonHandler(ActionEvent event) {
-		colorChooser(backgroundColorButton, design.getBackgroundColor(), (color) -> design.setBackgroundColor(color));
+		colorChooser(backgroundColorButton, design.getBackgroundColor(), color -> design.setBackgroundColor(color));
 	}
 
 	@FXML
 	private void playColorButtonHandler(ActionEvent event) {
-		colorChooser(playColorButton, design.getPlayColor(), (color) -> design.setPlayColor(color));
+		colorChooser(playColorButton, design.getPlayColor(), color -> design.setPlayColor(color));
+	}
+
+	@FXML
+	private void cueInColorButtonHandler(ActionEvent event) {
+		colorChooser(cueInColorButton, design.getPlayColor(), color -> design.setCueInColor(color));
 	}
 
 	private void colorChooser(Button anchorNode, ModernColor startColor, Consumer<ModernColor> onFinish) {
-		ColorPickerView view = new ColorPickerView(startColor, ModernColor.values(), (DisplayableColor t) ->
+		ColorPickerView view = new ColorPickerView(startColor, ModernColor.values(), newValue ->
 		{
 			colorChooser.hide();
 
-			if (t instanceof ModernColor) {
-				ModernColor color = (ModernColor) t;
+			if (newValue instanceof ModernColor) {
+				ModernColor color = (ModernColor) newValue;
 				onFinish.accept(color);
 				anchorNode.setStyle(getLinearGradientCss(color));
 			}
@@ -86,8 +95,7 @@ public class ModernCartDesignViewController extends NVC {
 	}
 
 	private String getLinearGradientCss(ModernColor color) {
-		final ModernGlobalDesign design = Profile.currentProfile().getProfileSettings().getDesign();
-		if (design.isFlatDesign()) {
+		if (Profile.currentProfile().getProfileSettings().getDesign().isFlatDesign()) {
 			return "-fx-background-color: " + color.paint() + ";";
 		} else {
 			return "-fx-background-color: " + color.linearGradient() + ";";
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/design/ModernGlobalDesignViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/design/ModernGlobalDesignViewController.java
index f25aa4ae6034f34fe0cae511a5f1a29854052476..08a667c809c0404e8d7a68c64c6b7f9cc6c682fe 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/design/ModernGlobalDesignViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/design/ModernGlobalDesignViewController.java
@@ -1,8 +1,7 @@
 package de.tobias.playpad.viewcontroller.design;
 
 import de.thecodelabs.utils.ui.NVC;
-import de.tobias.playpad.DisplayableColor;
-import de.tobias.playpad.PlayPadMain;
+import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.design.modern.ModernColor;
 import de.tobias.playpad.design.modern.model.ModernGlobalDesign;
 import de.tobias.playpad.view.ColorPickerView;
@@ -17,12 +16,14 @@ import org.controlsfx.control.PopOver.ArrowLocation;
 
 import java.util.function.Consumer;
 
-public class ModernGlobalDesignViewController extends NVC {
+public class ModernGlobalDesignViewController extends NVC implements IColorButton {
 
 	@FXML
 	private Button backgroundColorButton;
 	@FXML
 	private Button playColorButton;
+	@FXML
+	private Button cueInColorButton;
 
 	@FXML
 	private CheckBox warnAnimationCheckBox;
@@ -43,7 +44,7 @@ public class ModernGlobalDesignViewController extends NVC {
 	private PopOver colorChooser;
 
 	public ModernGlobalDesignViewController(ModernGlobalDesign design) {
-		load("view/option/layout", "ModernLayoutGlobal", PlayPadMain.getUiResourceBundle());
+		load("view/option/layout", "ModernLayoutGlobal", Localization.getBundle());
 
 		this.design = design;
 		setLayout();
@@ -52,6 +53,7 @@ public class ModernGlobalDesignViewController extends NVC {
 	private void setLayout() {
 		backgroundColorButton.setStyle(getLinearGradientCss(design.getBackgroundColor()));
 		playColorButton.setStyle(getLinearGradientCss(design.getPlayColor()));
+		cueInColorButton.setStyle(getLinearGradientCss(design.getCueInColor()));
 
 		warnAnimationCheckBox.setSelected(design.isWarnAnimation());
 		flatDesignCheckbox.setSelected(design.isFlatDesign());
@@ -62,32 +64,29 @@ public class ModernGlobalDesignViewController extends NVC {
 
 	@Override
 	public void init() {
-		warnAnimationCheckBox.selectedProperty().addListener((a, b, c) ->
-		{
-			design.setWarnAnimation(c);
-		});
-		flatDesignCheckbox.selectedProperty().addListener((a, b, c) ->
+		warnAnimationCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> design.setWarnAnimation(newValue));
+
+		flatDesignCheckbox.selectedProperty().addListener((observable, oldValue, newValue) ->
 		{
-			design.setFlatDesign(c);
+			design.setFlatDesign(newValue);
 
 			// Update button preview
 			backgroundColorButton.setStyle(getLinearGradientCss(design.getBackgroundColor()));
 			playColorButton.setStyle(getLinearGradientCss(design.getPlayColor()));
+			cueInColorButton.setStyle(getLinearGradientCss(design.getCueInColor()));
 		});
 
 		infoLabelFontSizeComboBox.getItems().addAll(9, 10, 12, 13, 14, 16, 18, 20, 24, 28);
-		infoLabelFontSizeComboBox.valueProperty().addListener((a, b, c) ->
-		{
-			design.setInfoFontSize(c);
-		});
+		infoLabelFontSizeComboBox.valueProperty().addListener((observable, oldValue, newValue) -> design.setInfoFontSize(newValue));
 		infoLabelFontSizeComboBox.setConverter(new IntegerStringConverter());
 
 		titleLabelFontSizeComboBox.getItems().addAll(9, 10, 12, 13, 14, 16, 18, 20, 24, 28);
-		titleLabelFontSizeComboBox.valueProperty().addListener((a, b, c) ->
-		{
-			design.setTitleFontSize(c);
-		});
+		titleLabelFontSizeComboBox.valueProperty().addListener((observable, oldValue, newValue) -> design.setTitleFontSize(newValue));
 		titleLabelFontSizeComboBox.setConverter(new IntegerStringConverter());
+
+		addIconToButton(backgroundColorButton);
+		addIconToButton(playColorButton);
+		addIconToButton(cueInColorButton);
 	}
 
 	@FXML
@@ -98,21 +97,26 @@ public class ModernGlobalDesignViewController extends NVC {
 
 	@FXML
 	private void backgroundColorButtonHandler(ActionEvent event) {
-		colorChooser(backgroundColorButton, design.getBackgroundColor(), (color) -> design.setBackgroundColor(color));
+		colorChooser(backgroundColorButton, design.getBackgroundColor(), color -> design.setBackgroundColor(color));
 	}
 
 	@FXML
 	private void playColorButtonHandler(ActionEvent event) {
-		colorChooser(playColorButton, design.getPlayColor(), (color) -> design.setPlayColor(color));
+		colorChooser(playColorButton, design.getPlayColor(), color -> design.setPlayColor(color));
+	}
+
+	@FXML
+	private void cueInColorButtonHandler(ActionEvent event) {
+		colorChooser(cueInColorButton, design.getPlayColor(), color -> design.setCueInColor(color));
 	}
 
 	private void colorChooser(Button anchorNode, ModernColor startColor, Consumer<ModernColor> onFinish) {
-		ColorPickerView view = new ColorPickerView(startColor, ModernColor.values(), (DisplayableColor t) ->
+		ColorPickerView view = new ColorPickerView(startColor, ModernColor.values(), newValue ->
 		{
 			colorChooser.hide();
 
-			if (t instanceof ModernColor) {
-				ModernColor color = (ModernColor) t;
+			if (newValue instanceof ModernColor) {
+				ModernColor color = (ModernColor) newValue;
 				onFinish.accept(color);
 				anchorNode.setStyle(getLinearGradientCss(color));
 			}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/AboutDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/AboutDialog.java
index 5665283946bea060a552e92c0426b9b79dcdc54c..7c47592784002e01ae7bf9afed070ee0b959ec4f 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/AboutDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/AboutDialog.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.viewcontroller.dialog;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.ApplicationInfo;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.ui.NVC;
@@ -8,7 +9,6 @@ import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
 import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.AppUserInfoStrings;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import javafx.fxml.FXML;
@@ -56,7 +56,7 @@ public class AboutDialog extends NVC {
 
 	public AboutDialog(Window owner) {
 		this.owner = owner;
-		load("view/dialog", "About", PlayPadMain.getUiResourceBundle());
+		load("view/dialog", "About", Localization.getBundle());
 		NVCStage stage = applyViewControllerToStage().initOwner(owner).initModality(Modality.WINDOW_MODAL);
 		addCloseKeyShortcut(stage::close);
 	}
@@ -73,23 +73,23 @@ public class AboutDialog extends NVC {
 		ApplicationInfo info = ApplicationUtils.getApplication().getInfo();
 		versionLabel.setText(info.getVersion());
 		authorLabel.setText(info.getAuthor());
-		graphicsLabel.setText(Localization.getString(Strings.UI_Dialog_About_Graphics));
-		libsLabel.setText(Localization.getString(Strings.UI_Dialog_About_Libraries));
+		graphicsLabel.setText(Localization.getString(Strings.UI_DIALOG_ABOUT_GRAPHICS));
+		libsLabel.setText(Localization.getString(Strings.UI_DIALOG_ABOUT_LIBRARIES));
 
-		Hyperlink websiteLink = new Hyperlink(Localization.getString(Strings.UI_Dialog_About_Website));
+		Hyperlink websiteLink = new Hyperlink(Localization.getString(Strings.UI_DIALOG_ABOUT_WEBSITE));
 		websiteLink.setPadding(Insets.EMPTY);
 		websiteLink.setFocusTraversable(false);
 		websiteLink.setOnAction(e -> {
-			String url = info.getUserInfo().get(AppUserInfoStrings.WEBSITE).toString();
+			String url = ApplicationUtils.getApplication().getUserInfo(AppUserInfoStrings.class).website();
 			openWebsite(url);
 		});
 		websiteContainer.getChildren().add(websiteLink);
 
-		Hyperlink codeLink = new Hyperlink(Localization.getString(Strings.UI_Dialog_About_Code));
+		Hyperlink codeLink = new Hyperlink(Localization.getString(Strings.UI_DIALOG_ABOUT_CODE));
 		codeLink.setPadding(Insets.EMPTY);
 		codeLink.setFocusTraversable(false);
 		codeLink.setOnAction(e -> {
-			String url = info.getUserInfo().get(AppUserInfoStrings.REPOSITORY).toString();
+			String url = ApplicationUtils.getApplication().getUserInfo(AppUserInfoStrings.class).repository();
 			openWebsite(url);
 		});
 		codeContainer.getChildren().add(codeLink);
@@ -99,15 +99,15 @@ public class AboutDialog extends NVC {
 		if (Desktop.isDesktopSupported()) {
 			try {
 				Desktop.getDesktop().browse(new URI(url));
-			} catch (IOException | URISyntaxException e1) {
-				e1.printStackTrace();
+			} catch (IOException | URISyntaxException e) {
+				Logger.error(e);
 			}
 		}
 	}
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 		stage.setResizable(false);
 		stage.initStyle(StageStyle.TRANSPARENT);
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/AutoUpdateDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/AutoUpdateDialog.java
index e34ba034980f7d3d35c8ce71a2439aafffa12aae..08f3c5610afc01de3ef819082d82b3086511c29c 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/AutoUpdateDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/AutoUpdateDialog.java
@@ -5,10 +5,11 @@ import de.thecodelabs.utils.util.Localization;
 import de.thecodelabs.versionizer.config.Artifact;
 import de.thecodelabs.versionizer.model.Version;
 import de.thecodelabs.versionizer.service.UpdateService;
-import de.tobias.playpad.PlayPadMain;
+import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import javafx.scene.control.ButtonBar.ButtonData;
 import javafx.scene.control.ButtonType;
+import javafx.stage.Stage;
 import javafx.stage.Window;
 
 import java.util.Map;
@@ -27,17 +28,19 @@ public class AutoUpdateDialog extends AdvancedDialog {
 			builder.append("\n");
 		}
 
-		setTitle(Localization.getString(Strings.UI_Dialog_AutoUpdate_Title));
-		setContent(Localization.getString(Strings.UI_Dialog_AutoUpdate_Content, builder.toString()));
-		setHeaderText(Localization.getString(Strings.UI_Dialog_AutoUpdate_Header));
-		setCheckboxText(Localization.getString(Strings.UI_Dialog_AutoUpdate_Checkbox));
+		setTitle(Localization.getString(Strings.UI_DIALOG_AUTO_UPDATE_TITLE));
+		setContent(Localization.getString(Strings.UI_DIALOG_AUTO_UPDATE_CONTENT, builder.toString()));
+		setHeaderText(Localization.getString(Strings.UI_DIALOG_AUTO_UPDATE_HEADER));
+		setCheckboxText(Localization.getString(Strings.UI_DIALOG_AUTO_UPDATE_CHECKBOX));
 
-		setIcon(PlayPadMain.stageIcon);
+		setIcon(PlayPadPlugin.getInstance().getIcon());
 
-		ButtonType updateButton = new ButtonType(Localization.getString(Strings.UI_Dialog_AutoUpdate_Button_Update), ButtonData.APPLY);
-		ButtonType cancelButton = new ButtonType(Localization.getString(Strings.UI_Dialog_AutoUpdate_Button_Cancel), ButtonData.CANCEL_CLOSE);
+		ButtonType updateButton = new ButtonType(Localization.getString(Strings.UI_DIALOG_AUTO_UPDATE_BUTTON_UPDATE), ButtonData.APPLY);
+		ButtonType cancelButton = new ButtonType(Localization.getString(Strings.UI_DIALOG_AUTO_UPDATE_BUTTON_CANCEL), ButtonData.CANCEL_CLOSE);
 
 		addButtonType(updateButton);
 		addButtonType(cancelButton);
+
+		PlayPadPlugin.styleable().applyStyle((Stage) getDialogPane().getScene().getWindow());
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/ModernPluginViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/ModernPluginViewController.java
index f30ec1112baf53fa35bcc515dba8b4c857feb125..63e4ba8a4d673f84251840133cde64e92b98eab3 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/ModernPluginViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/ModernPluginViewController.java
@@ -1,10 +1,11 @@
 package de.tobias.playpad.viewcontroller.dialog;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.threading.Worker;
+import de.thecodelabs.utils.ui.Alerts;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.plugin.ModernPlugin;
@@ -15,12 +16,12 @@ import de.tobias.playpad.settings.GlobalSettings;
 import javafx.application.Platform;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.collections.transformation.FilteredList;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
-import javafx.scene.control.Button;
-import javafx.scene.control.Label;
-import javafx.scene.control.ListView;
-import javafx.scene.control.TextField;
+import javafx.scene.control.*;
 import javafx.stage.Modality;
 import javafx.stage.Stage;
 import javafx.stage.Window;
@@ -49,14 +50,30 @@ public class ModernPluginViewController extends NVC implements ChangeListener<Mo
 	@FXML
 	private ListView<ModernPlugin> pluginList;
 
+	private ObservableList<ModernPlugin> data = FXCollections.observableArrayList();
+	private FilteredList<ModernPlugin> filteredData = new FilteredList<>(data, s -> true);
+
+
 	public ModernPluginViewController(Window owner) {
 		loadView(owner);
 		Worker.runLater(() -> {
 			try {
 				List<ModernPlugin> plugins = PlayPadPlugin.getServerHandler().getServer().getPlugins();
-				Platform.runLater(() -> pluginList.getItems().setAll(plugins));
+				Platform.runLater(() -> {
+					data.addAll(plugins);
+					pluginList.getSelectionModel().selectFirst();
+				});
 			} catch (IOException e) {
-				e.printStackTrace();
+				Logger.error(e);
+				Platform.runLater(() -> {
+					Alerts.getInstance()
+							.createAlert(Alert.AlertType.ERROR,
+									Localization.getString(Strings.ERROR_PLUGINS_HEADER),
+									Localization.getString(Strings.ERROR_PLUGINS_LOADING),
+									getContainingWindow()
+							).showAndWait();
+					closeStage();
+				});
 			}
 		});
 	}
@@ -69,34 +86,55 @@ public class ModernPluginViewController extends NVC implements ChangeListener<Mo
 						.filter(p -> missedModules.parallelStream().anyMatch(m -> m.identifier.equals(p.getName())))
 						.collect(Collectors.toList());
 
-				Platform.runLater(() -> pluginList.getItems().setAll(plugins));
+				Platform.runLater(() -> {
+					data.addAll(plugins);
+					pluginList.getSelectionModel().selectFirst();
+				});
 			} catch (IOException e) {
-				e.printStackTrace();
+				Logger.error(e);
+				Platform.runLater(() -> {
+					Alerts.getInstance()
+							.createAlert(Alert.AlertType.ERROR,
+									Localization.getString(Strings.ERROR_PLUGINS_HEADER),
+									Localization.getString(Strings.ERROR_PLUGINS_LOADING),
+									getContainingWindow()
+							).showAndWait();
+					closeStage();
+				});
 			}
 		});
 	}
 
 	private void loadView(Window owner) {
-		load("view/dialog", "PluginDialog", PlayPadMain.getUiResourceBundle());
+		load("view/dialog", "PluginDialog", Localization.getBundle());
 		NVCStage stage = applyViewControllerToStage();
 		stage.initOwner(owner);
 		stage.initModality(Modality.WINDOW_MODAL);
 		addCloseKeyShortcut(stage::close);
-
 	}
 
 	@Override
 	public void init() {
+		pluginList.setItems(filteredData);
 		pluginList.getSelectionModel().selectedItemProperty().addListener(this);
+
+		searchField.textProperty().addListener((observable, oldValue, newValue) -> {
+			if(newValue == null || newValue.length() == 0) {
+				filteredData.setPredicate(s -> true);
+			}
+			else {
+				filteredData.setPredicate(p -> p.getDisplayName().contains(newValue));
+			}
+		});
 	}
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		stage.setMinWidth(600);
 		stage.setMinHeight(400);
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_Plugins_Title));
+		stage.setTitle(Localization.getString(Strings.UI_DIALOG_PLUGINS_TITLE));
 
 		if (Profile.currentProfile() != null) {
 			PlayPadPlugin.styleable().applyStyle(stage);
@@ -108,9 +146,18 @@ public class ModernPluginViewController extends NVC implements ChangeListener<Mo
 
 	@Override
 	public void changed(ObservableValue<? extends ModernPlugin> observable, ModernPlugin oldValue, ModernPlugin newValue) {
-		pluginHeadlineLabel.setText(newValue.getDisplayName());
-		pluginInfoLabel.setText(newValue.getDescription());
-		pluginVersionLabel.setText(newValue.getVersion());
+		if (newValue != null) {
+			pluginInstallButton.setText(ModernPluginManager.getInstance().isActive(newValue) ?
+					Localization.getString("plugins.button.uninstall") :
+					Localization.getString("plugins.button.install"));
+			pluginHeadlineLabel.setText(newValue.getDisplayName());
+			pluginInfoLabel.setText(newValue.getDescription());
+			pluginVersionLabel.setText(newValue.getVersion());
+		} else {
+			pluginHeadlineLabel.setText("");
+			pluginInfoLabel.setText("");
+			pluginVersionLabel.setText("");
+		}
 	}
 
 	@FXML
@@ -123,7 +170,13 @@ public class ModernPluginViewController extends NVC implements ChangeListener<Mo
 					PlayPadPlugin.getServerHandler().getServer().loadPlugin(plugin, settings.getUpdateChannel());
 					ModernPluginManager.getInstance().loadPlugin(plugin);
 				} catch (IOException e) {
-					e.printStackTrace(); // TODO Error handling
+					Logger.error(e);
+					Alerts.getInstance()
+							.createAlert(Alert.AlertType.ERROR,
+									Localization.getString(Strings.ERROR_PLUGINS_HEADER),
+									Localization.getString(Strings.ERROR_PLUGINS_INSTALL, e.getMessage()),
+									getContainingWindow()
+							).showAndWait();
 				}
 			} else {
 				ModernPluginManager.getInstance().unloadPlugin(plugin);
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/PathMatchDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/PathMatchDialog.java
index 870eb78548549f57dc6d4e9615e9dfc4a693501a..028c1a91917ff8800ce82c2473af0832308cfe6b 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/PathMatchDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/PathMatchDialog.java
@@ -1,21 +1,21 @@
 package de.tobias.playpad.viewcontroller.dialog;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.threading.Worker;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.layout.desktop.pad.DesktopPadViewController;
-import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.pad.content.PadContentRegistry;
 import de.tobias.playpad.pad.mediapath.MediaPath;
 import de.tobias.playpad.pad.mediapath.MediaPool;
 import de.tobias.playpad.project.Project;
-import de.tobias.playpad.viewcontroller.cell.PathMatchActionCell;
+import de.tobias.playpad.viewcontroller.cell.path.PathMatchActionCell;
+import de.tobias.playpad.viewcontroller.cell.path.PathMatchPathCell;
 import javafx.application.Platform;
 import javafx.beans.property.*;
 import javafx.event.ActionEvent;
@@ -32,7 +32,8 @@ import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.*;
+import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -59,7 +60,7 @@ public class PathMatchDialog extends NVC {
 			});
 		}
 
-		MediaPath getMediaPath() {
+		public MediaPath getMediaPath() {
 			return mediaPath;
 		}
 
@@ -72,7 +73,7 @@ public class PathMatchDialog extends NVC {
 			setStatusLabel();
 		}
 
-		ReadOnlyObjectProperty<Path> localPathProperty() {
+		public ReadOnlyObjectProperty<Path> localPathProperty() {
 			return localPath;
 		}
 
@@ -116,7 +117,7 @@ public class PathMatchDialog extends NVC {
 	@FXML
 	private TableColumn<TempMediaPath, String> filenameColumn;
 	@FXML
-	private TableColumn<TempMediaPath, Path> localPathColumn;
+	private TableColumn<TempMediaPath, TempMediaPath> localPathColumn;
 	@FXML
 	private TableColumn<TempMediaPath, TempMediaPath> actionColumn;
 
@@ -129,10 +130,10 @@ public class PathMatchDialog extends NVC {
 	private Button finishButton;
 
 	private Project project;
-	private List<TempMediaPath> mediaPaths;
+	private List<TempMediaPath> missingMediaPaths;
 
 	public PathMatchDialog(Project project, Window owner) {
-		load("view/dialog", "NotFoundDialog", PlayPadMain.getUiResourceBundle());
+		load("view/dialog", "PathMatchDialog", Localization.getBundle());
 
 		NVCStage stage = applyViewControllerToStage();
 		stage.initOwner(owner);
@@ -140,24 +141,21 @@ public class PathMatchDialog extends NVC {
 
 		this.project = project;
 
-		List<MediaPath> missingMediaPaths = new ArrayList<>();
-		project.getPads(p -> p.getStatus() == PadStatus.NOT_FOUND)
-				.stream()
-				.map(Pad::getPaths)
-				.forEach(missingMediaPaths::addAll);
-		mediaPaths = missingMediaPaths.stream()
+		missingMediaPaths = project.getPads(p -> p.getStatus() == PadStatus.NOT_FOUND)
+				.parallelStream()
+				.flatMap(pad -> pad.getPaths().stream())
 				.map(TempMediaPath::new)
 				.collect(Collectors.toList());
 
 		find(false);
 
-		table.getItems().setAll(mediaPaths);
+		table.getItems().setAll(missingMediaPaths);
 		setStatusLabel();
 	}
 
 	@Override
 	public void init() {
-		table.setRowFactory(table -> {
+		table.setRowFactory(param -> {
 			TableRow<TempMediaPath> row = new TableRow<>();
 			row.setOnMouseClicked(e -> {
 				if (e.getClickCount() == 2 && e.getButton() == MouseButton.PRIMARY) {
@@ -172,23 +170,24 @@ public class PathMatchDialog extends NVC {
 
 		table.setPlaceholder(new Label());
 
-		selectColumn.setCellFactory(table -> new CheckBoxTableCell<>());
-		actionColumn.setCellFactory(table -> new PathMatchActionCell(this));
+		selectColumn.setCellFactory(param -> new CheckBoxTableCell<>());
+		localPathColumn.setCellFactory(param -> new PathMatchPathCell());
+		actionColumn.setCellFactory(param -> new PathMatchActionCell(this));
 
 		selectColumn.setCellValueFactory(param -> param.getValue().selectedProperty());
 		filenameColumn.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().getMediaPath().getFileName()));
-		localPathColumn.setCellValueFactory(param -> param.getValue().localPathProperty());
+		localPathColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue()));
 		actionColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue()));
 	}
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
-		stage.setMinWidth(700);
+		stage.setMinWidth(900);
 		stage.setMinHeight(400);
 		stage.setMaxHeight(600);
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_NotFound_Title));
+		stage.setTitle(Localization.getString(Strings.UI_DIALOG_NOT_FOUND_TITLE));
 
 		PlayPadPlugin.styleable().applyStyle(stage);
 	}
@@ -204,18 +203,18 @@ public class PathMatchDialog extends NVC {
 
 	@FXML
 	void finishHandler(ActionEvent event) {
-		mediaPaths.stream()
+		missingMediaPaths.stream()
 				.filter(TempMediaPath::isSelected)
 				.forEach(p -> p.getMediaPath().setPath(p.getLocalPath(), true));
 		getStageContainer().ifPresent(NVCStage::close);
 	}
 
-	private int getUnmatchedTracks() {
-		return (int) mediaPaths.stream().filter(p -> !p.isMatched()).count();
+	private int getUnmatchedTracksCount() {
+		return (int) missingMediaPaths.stream().filter(p -> !p.isMatched()).count();
 	}
 
 	private void setStatusLabel() {
-		Platform.runLater(() -> statusLabel.setText(Localization.getString(Strings.UI_Dialog_PathMatch_Status, getUnmatchedTracks())));
+		Platform.runLater(() -> statusLabel.setText(Localization.getString(Strings.UI_DIALOG_PATH_MATCH_STATUS, getUnmatchedTracksCount())));
 	}
 
 	public void showFileChooser(TempMediaPath item) {
@@ -223,15 +222,18 @@ public class PathMatchDialog extends NVC {
 		PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents();
 
 		// File Extension
-		FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter(Localization.getString(Strings.File_Filter_Media),
+		FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter(Localization.getString(Strings.FILE_FILTER_MEDIA),
 				registry.getSupportedFileTypes());
 		chooser.getExtensionFilters().add(extensionFilter);
 
 		// Last Folder
 		Object openFolder = ApplicationUtils.getApplication().getUserDefaults().getData(DesktopPadViewController.OPEN_FOLDER);
 		if (openFolder != null) {
+			Logger.info("Restore last file chooser location: {0}", openFolder);
 			File folder = new File(openFolder.toString());
-			chooser.setInitialDirectory(folder);
+			if (folder.exists()) {
+				chooser.setInitialDirectory(folder);
+			}
 		}
 
 		File file = chooser.showOpenDialog(getContainingWindow());
@@ -240,56 +242,60 @@ public class PathMatchDialog extends NVC {
 			item.setLocalPath(path);
 			item.setSelected(true);
 
+			String lastFolder = file.getParent();
+			ApplicationUtils.getApplication().getUserDefaults().setData(DesktopPadViewController.OPEN_FOLDER, lastFolder);
+			Logger.info("Saved {0} as last file chooser location", lastFolder);
+
 			// Search for new local paths
 			find(true);
 		}
 	}
 
-	private List<Path> searchHistory = new ArrayList<>();
-
-	private void find(boolean subdirs) {
+	private void find(boolean subdirectories) {
 		// Check Project
 		Worker.runLater(() -> {
-			if (!mediaPaths.isEmpty()) {
-				Set<MediaPath> legalPaths = new HashSet<>();
-				project.getPads(p -> p.getStatus() == PadStatus.READY)
-						.stream()
-						.map(Pad::getPaths)
-						.forEach(legalPaths::addAll);
-
-				Collection<Path> folders = legalPaths.stream()
-						.filter(mediaPath -> mediaPath.getPath() != null)
-						.filter(mediaPath -> Files.exists(mediaPath.getPath()))
-						.map(mediaPath -> mediaPath.getPath().getParent())
-						.filter(path -> !searchHistory.contains(path))
-						.collect(Collectors.toSet());
-
-				// New Client Folders
-				mediaPaths.stream()
-						.filter(TempMediaPath::isMatched)
-						.filter(mediaPath -> Files.exists(mediaPath.getLocalPath()))
-						.map(mediaPath -> mediaPath.getLocalPath().getParent())
-						.filter(path -> !searchHistory.contains(path))
-						.forEach(folders::add);
-
-				for (Path folder : folders) {
-					searchHistory.add(folder);
-					System.out.println("Search in: " + folder);
-					for (TempMediaPath mediaPath : this.mediaPaths) {
-						if (!mediaPath.isMatched()) {
-							try {
-								Path result = MediaPool.find(mediaPath.getMediaPath().getFileName(), folder, subdirs);
-								Platform.runLater(() -> mediaPath.setLocalPath(result));
-								if (result != null) {
-									mediaPath.setSelected(true);
+			if (!missingMediaPaths.isEmpty()) {
+				Set<Path> searchFolders = calculateSearchPaths();
+
+				searchFolders.forEach(folder -> {
+					Logger.info("Search in: " + folder);
+					this.missingMediaPaths.parallelStream()
+							.filter(entry -> !entry.isMatched())
+							.forEach(entry -> {
+								try {
+									Path result = MediaPool.find(entry.getMediaPath().getFileName(), folder, subdirectories);
+									if (result != null) {
+										Platform.runLater(() -> {
+											entry.setLocalPath(result);
+											entry.setSelected(true);
+										});
+									}
+								} catch (IOException e) {
+									Logger.error(e);
 								}
-							} catch (IOException e) {
-								e.printStackTrace();
-							}
-						}
-					}
-				}
+							});
+				});
+				Platform.runLater(() -> table.getItems().setAll(missingMediaPaths));
 			}
 		});
 	}
+
+	private Set<Path> calculateSearchPaths() {
+		Set<Path> searchFolders = project.getPads(p -> p.getStatus() == PadStatus.READY)
+				.stream()
+				.flatMap(pad -> pad.getPaths().stream())
+
+				.filter(mediaPath -> Files.exists(mediaPath.getPath()))
+				.map(mediaPath -> mediaPath.getPath().getParent())
+
+				.collect(Collectors.toSet());
+
+		missingMediaPaths.stream()
+				.filter(TempMediaPath::isMatched)
+				.filter(mediaPath -> Files.exists(mediaPath.getLocalPath()))
+				.map(mediaPath -> mediaPath.getLocalPath().getParent())
+				.forEach(searchFolders::add);
+
+		return searchFolders;
+	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/PlayoutLogViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/PlayoutLogViewController.java
deleted file mode 100644
index e43d028a3caf5928a0e3e46f278c60697ee16cbf..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/PlayoutLogViewController.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package de.tobias.playpad.viewcontroller.dialog;
-
-import com.itextpdf.text.DocumentException;
-import de.thecodelabs.utils.ui.NVC;
-import de.thecodelabs.utils.ui.NVCStage;
-import de.thecodelabs.utils.ui.icon.FontAwesomeType;
-import de.thecodelabs.utils.ui.icon.FontIcon;
-import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
-import de.tobias.playpad.PlayPadPlugin;
-import de.tobias.playpad.Strings;
-import de.tobias.playpad.log.LogSeason;
-import de.tobias.playpad.log.LogSeasons;
-import de.tobias.playpad.log.PlayoutLogPdfExport;
-import de.tobias.playpad.project.Project;
-import de.tobias.playpad.project.ProjectSettings;
-import de.tobias.playpad.viewcontroller.main.MenuToolbarViewController;
-import javafx.event.ActionEvent;
-import javafx.fxml.FXML;
-import javafx.scene.control.Button;
-import javafx.scene.control.ListView;
-import javafx.scene.control.TextField;
-import javafx.stage.FileChooser;
-import javafx.stage.Modality;
-import javafx.stage.Stage;
-import javafx.stage.Window;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Optional;
-
-public class PlayoutLogViewController extends NVC {
-
-	@FXML
-	private TextField nameTextField;
-	@FXML
-	private ListView<LogSeason> logList;
-	@FXML
-	private Button startButton;
-	@FXML
-	private Button exportButton;
-	@FXML
-	private Button deleteButton;
-	@FXML
-	private Button finishButton;
-
-	private FontIcon logIcon;
-
-	// TODO l10n
-	public PlayoutLogViewController(Window owner) {
-		load("view/dialog", "PlayoutLogDialog", PlayPadMain.getUiResourceBundle());
-
-		NVCStage stage = applyViewControllerToStage();
-		stage.initOwner(owner);
-		stage.initModality(Modality.WINDOW_MODAL);
-		addCloseKeyShortcut(stage::close);
-	}
-
-	@Override
-	public void init() {
-		logList.getItems().setAll(LogSeasons.getAllLogSeasonsLazy());
-
-		// LogIcon
-		logIcon = new FontIcon(FontAwesomeType.LIST);
-
-		if (LogSeasons.getInstance() != null) { // Running
-			startButton.setText("Stop"); // TODO l10n
-			nameTextField.setDisable(true);
-			nameTextField.setText(LogSeasons.getInstance().getName());
-		} else {
-			startButton.setText("Start"); // TODO l10n
-			nameTextField.setDisable(false);
-		}
-	}
-
-	@Override
-	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
-
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_PlayoutLog_Title));
-		stage.setMinWidth(375);
-		stage.setMinHeight(400);
-
-		stage.initModality(Modality.WINDOW_MODAL);
-
-		PlayPadPlugin.styleable().applyStyle(stage);
-	}
-
-	@FXML
-	private void startButtonHandler(ActionEvent event) {
-		final MenuToolbarViewController controller = PlayPadPlugin.getInstance().getMainViewController().getMenuToolbarController();
-
-		if (LogSeasons.getInstance() == null) { // Start
-			if (nameTextField.getText().isEmpty()) {
-				return;
-			}
-
-			final Project currentProject = PlayPadPlugin.getInstance().getCurrentProject();
-			final ProjectSettings settings = currentProject.getSettings();
-
-			LogSeason logSeason = LogSeasons.createLogSeason(nameTextField.getText(), settings.getColumns(), settings.getRows());
-			logSeason.createProjectSnapshot(currentProject);
-
-			controller.addToolbarItem(logIcon);
-			startButton.setText("Stop"); // TODO l10n
-			nameTextField.setDisable(false);
-		} else { // Stop
-			LogSeasons.stop();
-			controller.removeToolbarItem(logIcon);
-			startButton.setText("Start"); // TODO l10n
-			nameTextField.setDisable(false);
-		}
-	}
-
-	@FXML
-	private void exportButtonHandler(ActionEvent event) {
-		getSelectedLogSeason().ifPresent(season -> { // Lazy Season
-			FileChooser fileChooser = new FileChooser();
-			FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter("PDF", "*.pdf");
-			fileChooser.getExtensionFilters().add(extensionFilter);
-
-			File file = fileChooser.showSaveDialog(getContainingWindow());
-			if (file != null) {
-				try {
-					PlayoutLogPdfExport.createPdfFile(file.toPath(), LogSeasons.getLogSeason(season.getId()));
-				} catch (IOException | DocumentException e) {
-					e.printStackTrace();
-				}
-			}
-		});
-	}
-
-	@FXML
-	private void deleteButtonHandler(ActionEvent event) {
-
-	}
-
-	@FXML
-	private void finishButtonHandler(ActionEvent event) {
-		getStageContainer().ifPresent(NVCStage::close);
-	}
-
-	private Optional<LogSeason> getSelectedLogSeason() {
-		return Optional.ofNullable(logList.getSelectionModel().getSelectedItem());
-	}
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/PrintDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/PrintDialog.java
index 89726f98a930d594c2e393dea5e501a942217bc0..cce215184211438f4b174acc3adb8238f289eb90 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/PrintDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/PrintDialog.java
@@ -5,7 +5,6 @@ import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.pad.Pad;
@@ -39,7 +38,7 @@ public class PrintDialog extends NVC {
 	private Project project;
 
 	public PrintDialog(Project project, Window owner) {
-		load("view/dialog/project", "PrintDialog", PlayPadMain.getUiResourceBundle());
+		load("view/dialog/project", "PrintDialog", Localization.getBundle());
 		this.project = project;
 
 		int pages = project.getPages().size();
@@ -65,11 +64,11 @@ public class PrintDialog extends NVC {
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		stage.setMinWidth(600);
 		stage.setMinHeight(400);
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_Print_Title));
+		stage.setTitle(Localization.getString(Strings.UI_DIALOG_PRINT_TITLE));
 
 		PlayPadPlugin.styleable().applyStyle(stage);
 	}
@@ -85,10 +84,10 @@ public class PrintDialog extends NVC {
 		Page page = project.getPage(pageIndex);
 		String pageName = page.getName();
 		if (pageName.isEmpty()) {
-			pageName = Localization.getString(Strings.UI_Window_Main_PageButton, (pageIndex + 1));
+			pageName = Localization.getString(Strings.UI_WINDOW_MAIN_PAGE_BUTTON, (pageIndex + 1));
 		}
 
-		String headerString = Localization.getString(Strings.Info_Print_Header, project.getProjectReference().getName(), pageName);
+		String headerString = Localization.getString(Strings.INFO_PRINT_HEADER, project.getProjectReference().getName(), pageName);
 		header.appendText(headerString);
 		header.setStyle("text-align: center;");
 		body.appendChild(header);
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/ProfileViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/ProfileViewController.java
index 2aa80127b626bf2f622a42033fbc5388b300d73a..8c3e2eb676c5d95ede2e9fac0e50ba48176efdb9 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/ProfileViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/ProfileViewController.java
@@ -4,7 +4,6 @@ import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.profile.Profile;
@@ -49,7 +48,7 @@ public class ProfileViewController extends NVC implements ChangeListener<Profile
 	private Project project;
 
 	public ProfileViewController(Window owner, Project project) {
-		load("view/dialog", "ProfileSettingsView", PlayPadMain.getUiResourceBundle());
+		load("view/dialog", "ProfileSettingsView", Localization.getBundle());
 		profileList.getSelectionModel().select(Profile.currentProfile().getRef());
 		this.project = project;
 
@@ -93,9 +92,9 @@ public class ProfileViewController extends NVC implements ChangeListener<Profile
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_Profile_Title));
+		stage.setTitle(Localization.getString(Strings.UI_DIALOG_PROFILE_TITLE));
 		stage.setMinWidth(375);
 		stage.setMinHeight(400);
 
@@ -147,18 +146,18 @@ public class ProfileViewController extends NVC implements ChangeListener<Profile
 		alert.initOwner(getContainingWindow());
 		alert.initModality(Modality.WINDOW_MODAL);
 		Stage dialog = (Stage) alert.getDialogPane().getScene().getWindow();
-		PlayPadMain.stageIcon.ifPresent(dialog.getIcons()::add);
+		dialog.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		ProfileReference ref = profileList.getSelectionModel().getSelectedItem();
 
-		alert.setContentText(Localization.getString(Strings.UI_Dialog_Profile_Delete_Content, ref));
+		alert.setContentText(Localization.getString(Strings.UI_DIALOG_PROFILE_DELETE_CONTENT, ref));
 		alert.showAndWait().filter(button -> button == ButtonType.OK).ifPresent(button ->
 		{
 			try {
 				ProfileReferenceManager.removeProfile(ref);
 				profileList.getItems().remove(ref);
 			} catch (Exception e) {
-				showErrorMessage(Localization.getString(Strings.Error_Profile_Delete, e.getMessage()));
+				showErrorMessage(Localization.getString(Strings.ERROR_PROFILE_DELETE, e.getMessage()));
 				Logger.error(e);
 			}
 		});
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/SaveDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/SaveDialog.java
index 9e00364424a1fb69b0973bde7b6087118c098e83..247e857a99137a1abdd0ab4ff6b64a97733b48f9 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/SaveDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/SaveDialog.java
@@ -2,7 +2,7 @@ package de.tobias.playpad.viewcontroller.dialog;
 
 import de.thecodelabs.utils.ui.AdvancedDialog;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
+import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import javafx.scene.control.ButtonBar.ButtonData;
 import javafx.scene.control.ButtonType;
@@ -13,15 +13,15 @@ public class SaveDialog extends AdvancedDialog {
 	public SaveDialog(Window owner) {
 		super(owner);
 
-		setTitle(Localization.getString(Strings.UI_Dialog_Save_Title));
-		setContent(Localization.getString(Strings.UI_Dialog_Save_Content));
-		setHeaderText(Localization.getString(Strings.UI_Dialog_Save_Header));
-		setCheckboxText(Localization.getString(Strings.UI_Dialog_Save_Checkbox));
-		setIcon(PlayPadMain.stageIcon);
+		setTitle(Localization.getString(Strings.UI_DIALOG_SAVE_TITLE));
+		setContent(Localization.getString(Strings.UI_DIALOG_SAVE_CONTENT));
+		setHeaderText(Localization.getString(Strings.UI_DIALOG_SAVE_HEADER));
+		setCheckboxText(Localization.getString(Strings.UI_DIALOG_SAVE_CHECKBOX));
+		setIcon(PlayPadPlugin.getInstance().getIcon());
 
-		ButtonType saveButton = new ButtonType(Localization.getString(Strings.UI_Dialog_Save_Button_Yes), ButtonData.YES);
-		ButtonType notSaveButton = new ButtonType(Localization.getString(Strings.UI_Dialog_Save_Button_No), ButtonData.NO);
-		ButtonType cancelButton = new ButtonType(Localization.getString(Strings.UI_Dialog_Save_Button_Cancel), ButtonData.CANCEL_CLOSE);
+		ButtonType saveButton = new ButtonType(Localization.getString(Strings.UI_DIALOG_SAVE_BUTTON_YES), ButtonData.YES);
+		ButtonType notSaveButton = new ButtonType(Localization.getString(Strings.UI_DIALOG_SAVE_BUTTON_NO), ButtonData.NO);
+		ButtonType cancelButton = new ButtonType(Localization.getString(Strings.UI_DIALOG_SAVE_BUTTON_CANCEL), ButtonData.CANCEL_CLOSE);
 
 		addButtonType(saveButton);
 		addButtonType(notSaveButton);
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/UpdaterDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/UpdaterDialog.java
index 4706a94ec502aff195f92aac0b1d144ae06a8ffd..ebaa807acb57bba73811f09b91dbcd5eedc63aab 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/UpdaterDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/UpdaterDialog.java
@@ -1,7 +1,7 @@
 package de.tobias.playpad.viewcontroller.dialog;
 
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
+import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import javafx.scene.control.Dialog;
 import javafx.scene.control.Label;
@@ -15,7 +15,7 @@ public class UpdaterDialog extends Dialog<Void> {
 	public UpdaterDialog(Window owner) {
 		setGraphic(new ImageView("org/controlsfx/dialog/dialog-information.png"));
 
-		Label textLabel = new Label(Localization.getString(Strings.UI_Dialog_Update_Info));
+		Label textLabel = new Label(Localization.getString(Strings.UI_DIALOG_UPDATE_INFO));
 		textLabel.setWrapText(true);
 		textLabel.setMaxWidth(450);
 		getDialogPane().setContent(textLabel);
@@ -23,6 +23,6 @@ public class UpdaterDialog extends Dialog<Void> {
 		initOwner(owner);
 		initModality(Modality.WINDOW_MODAL);
 		Stage dialogStage = (Stage) getDialogPane().getScene().getWindow();
-		PlayPadMain.stageIcon.ifPresent(dialogStage.getIcons()::add);
+		dialogStage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 	}
 }
\ No newline at end of file
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/profile/NewProfileDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/profile/NewProfileDialog.java
index 356581a74365457dd33c561792b69a2086563c2b..3c7539ecc5d8ee6389a365a380ab2e740ea4561d 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/profile/NewProfileDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/profile/NewProfileDialog.java
@@ -1,9 +1,9 @@
 package de.tobias.playpad.viewcontroller.dialog.profile;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.profile.Profile;
@@ -32,7 +32,7 @@ public class NewProfileDialog extends NVC {
 	private Profile profile;
 
 	public NewProfileDialog(Window owner) {
-		load("view/dialog", "NewProfileDialog", PlayPadMain.getUiResourceBundle());
+		load("view/dialog", "NewProfileDialog", Localization.getBundle());
 
 		NVCStage nvcStage = applyViewControllerToStage();
 		nvcStage.initOwner(owner);
@@ -64,11 +64,11 @@ public class NewProfileDialog extends NVC {
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 		PlayPadPlugin.styleable().applyStyle(stage);
 		stage.initModality(Modality.WINDOW_MODAL);
 
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_NewProfile_Title));
+		stage.setTitle(Localization.getString(Strings.UI_DIALOG_NEW_PROFILE_TITLE));
 		stage.setWidth(400);
 		stage.setHeight(200);
 
@@ -86,7 +86,7 @@ public class NewProfileDialog extends NVC {
 			List<ProfileReference> profiles = ProfileReferenceManager.getProfiles();
 
 			if (profiles.contains(name)) {
-				showErrorMessage(Localization.getString(Strings.Error_Standard_NameInUse, name));
+				showErrorMessage(Localization.getString(Strings.ERROR_STANDARD_NAME_IN_USE, name));
 				return;
 			}
 
@@ -94,8 +94,8 @@ public class NewProfileDialog extends NVC {
 			profile.save();
 			getStageContainer().ifPresent(NVCStage::close);
 		} catch (Exception e) {
-			e.printStackTrace();
-			showErrorMessage(Localization.getString(Strings.Error_Profile_Create, e.getMessage()));
+			Logger.error(e);
+			showErrorMessage(Localization.getString(Strings.ERROR_PROFILE_CREATE, e.getMessage()));
 		}
 	}
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/profile/ProfileChooseDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/profile/ProfileChooseDialog.java
index 82cef96dc6ebe71ea10cb03ad9fa6eb47082127a..4bbd9f2fe052d42fa8274906872585d5f84575b0 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/profile/ProfileChooseDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/profile/ProfileChooseDialog.java
@@ -4,7 +4,6 @@ import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.profile.Profile;
@@ -38,7 +37,7 @@ public class ProfileChooseDialog extends NVC {
 	private Profile profile;
 
 	public ProfileChooseDialog(Window owner) {
-		load("view/dialog", "ProfileChooseDialog", PlayPadMain.getUiResourceBundle());
+		load("view/dialog", "ProfileChooseDialog", Localization.getBundle());
 
 		NVCStage nvcStage = applyViewControllerToStage();
 		nvcStage.initOwner(owner);
@@ -54,18 +53,16 @@ public class ProfileChooseDialog extends NVC {
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_ChooseProfile_Title));
+		stage.setTitle(Localization.getString(Strings.UI_DIALOG_CHOOSE_PROFILE_TITLE));
 		stage.setResizable(false);
 		stage.setWidth(560);
 		stage.setHeight(230);
 
 		stage.initModality(Modality.WINDOW_MODAL);
 
-		if (Profile.currentProfile() != null) {
-			PlayPadPlugin.styleable().applyStyle(stage);
-		}
+		PlayPadPlugin.styleable().applyStyle(stage);
 	}
 
 	@FXML
@@ -75,7 +72,7 @@ public class ProfileChooseDialog extends NVC {
 
 			getStageContainer().ifPresent(NVCStage::close);
 		} catch (IOException | DocumentException | ProfileNotFoundException e) {
-			showErrorMessage(Localization.getString(Strings.Error_Profile_Save, e.getLocalizedMessage()));
+			showErrorMessage(Localization.getString(Strings.ERROR_PROFILE_SAVE, e.getLocalizedMessage()));
 			Logger.error(e);
 		}
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/profile/ProfileDuplicateDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/profile/ProfileDuplicateDialog.java
index a87b80fddb9d6f9cfc0b02224794d2ea09bf1388..557660f9d12936d5f48e09b41fa9901fe31c5439 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/profile/ProfileDuplicateDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/profile/ProfileDuplicateDialog.java
@@ -1,8 +1,9 @@
 package de.tobias.playpad.viewcontroller.dialog.profile;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
+import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.profile.ref.ProfileReference;
 import de.tobias.playpad.profile.ref.ProfileReferenceManager;
@@ -25,7 +26,7 @@ public class ProfileDuplicateDialog extends TextInputDialog {
 		initOwner(controller.getContainingWindow());
 		initModality(Modality.WINDOW_MODAL);
 		Stage dialog = (Stage) getDialogPane().getScene().getWindow();
-		PlayPadMain.stageIcon.ifPresent(dialog.getIcons()::add);
+		dialog.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		Button button = (Button) getDialogPane().lookupButton(ButtonType.OK);
 		button.setDisable(true); // Initial disable
@@ -38,15 +39,15 @@ public class ProfileDuplicateDialog extends TextInputDialog {
 			}
 		});
 
-		setContentText(Localization.getString(Strings.UI_Dialog_NewProfile_Content));
+		setContentText(Localization.getString(Strings.UI_DIALOG_NEW_PROFILE_CONTENT));
 		showAndWait().filter(name -> !name.isEmpty()).ifPresent(name ->
 		{
 			try {
 				newRef = new ProfileReference(name);
 				ProfileReferenceManager.duplicate(cloneableProfile, newRef);
 			} catch (IOException e) {
-				e.printStackTrace();
-				controller.showErrorMessage(Localization.getString(Strings.Error_Profile_Save, e.getMessage()));
+				Logger.error(e);
+				controller.showErrorMessage(Localization.getString(Strings.ERROR_PROFILE_SAVE, e.getMessage()));
 			}
 		});
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectDeleteDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectDeleteDialog.java
index 9ec8d49d789d92a93487f49acd7aa9bca48655b7..0582ec92c687be891362cd70124c5c137b588558 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectDeleteDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectDeleteDialog.java
@@ -1,7 +1,7 @@
 package de.tobias.playpad.viewcontroller.dialog.project;
 
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
+import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.project.ref.ProjectReference;
 import javafx.scene.control.Alert;
@@ -16,13 +16,13 @@ class ProjectDeleteDialog extends Alert {
 
 	ProjectDeleteDialog(ProjectReference reference, Window owner) {
 		super(AlertType.CONFIRMATION);
-		setHeaderText(Localization.getString(Strings.UI_Dialog_ProjectManager_Delete_Header));
-		setContentText(Localization.getString(Strings.UI_Dialog_ProjectManager_Delete_Content, reference.getName()));
+		setHeaderText(Localization.getString(Strings.UI_DIALOG_PROJECT_MANAGER_DELETE_HEADER));
+		setContentText(Localization.getString(Strings.UI_DIALOG_PROJECT_MANAGER_DELETE_CONTENT, reference.getName()));
 
 		initOwner(owner);
 		initModality(Modality.WINDOW_MODAL);
 
 		Stage stage = (Stage) getDialogPane().getScene().getWindow();
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectDuplicateDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectDuplicateDialog.java
index 01eb915a58ce48a90e6111294d650c9e36270322..4e338d19c37ab10ef66c78ec064a89ebecd924dc 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectDuplicateDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectDuplicateDialog.java
@@ -1,8 +1,9 @@
 package de.tobias.playpad.viewcontroller.dialog.project;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
+import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.project.ref.ProjectReferenceManager;
@@ -24,7 +25,7 @@ public class ProjectDuplicateDialog extends TextInputDialog {
 		initOwner(parent.getContainingWindow());
 		initModality(Modality.WINDOW_MODAL);
 		Stage dialog = (Stage) getDialogPane().getScene().getWindow();
-		PlayPadMain.stageIcon.ifPresent(dialog.getIcons()::add);
+		dialog.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		Button button = (Button) getDialogPane().lookupButton(ButtonType.OK);
 		button.setDisable(true);
@@ -37,14 +38,14 @@ public class ProjectDuplicateDialog extends TextInputDialog {
 			}
 		});
 
-		setContentText(Localization.getString(Strings.UI_Dialog_NewProject_Content));
+		setContentText(Localization.getString(Strings.UI_DIALOG_NEW_PROJECT_CONTENT));
 		showAndWait().filter(name -> !name.isEmpty()).ifPresent(name ->
 		{
 			try {
 				ref = ProjectReferenceManager.duplicate(cloneableProject, name);
 			} catch (Exception e) {
-				e.printStackTrace();
-				parent.showErrorMessage(Localization.getString(Strings.Error_Project_Save, name, e.getMessage()));
+				parent.showErrorMessage(Localization.getString(Strings.ERROR_PROJECT_SAVE, name, e.getMessage()));
+				Logger.error(e);
 			}
 		});
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectExportDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectExportDialog.java
index f2045cb1f1bf113df264d02d713801935c43dca4..15212f59ccb7aac5218b85752f47b1a44496c4c2 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectExportDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectExportDialog.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.viewcontroller.dialog.project;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.threading.Worker;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
@@ -48,7 +49,7 @@ public class ProjectExportDialog extends NVC implements ProjectExporterDelegate
 	private ProjectReference projectRef;
 
 	ProjectExportDialog(ProjectReference projectRef, Window owner) {
-		load("view/dialog/project", "ExportDialog", PlayPadMain.getUiResourceBundle());
+		load("view/dialog/project", "ExportDialog", Localization.getBundle());
 		this.projectRef = projectRef;
 
 		NVCStage nvcStage = applyViewControllerToStage();
@@ -59,9 +60,9 @@ public class ProjectExportDialog extends NVC implements ProjectExporterDelegate
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_ProjectExport_Title));
+		stage.setTitle(Localization.getString(Strings.UI_DIALOG_PROJECT_EXPORT_TITLE));
 		stage.setWidth(375);
 		stage.setHeight(180);
 		stage.initModality(Modality.WINDOW_MODAL);
@@ -79,8 +80,8 @@ public class ProjectExportDialog extends NVC implements ProjectExporterDelegate
 		FileChooser chooser = new FileChooser();
 
 		// Extension Filter in FileChooser
-		String extensionName = Localization.getString(Strings.File_Filter_ZIP);
-		ExtensionFilter extensionFilter = new ExtensionFilter(extensionName, PlayPadMain.projectZIPType);
+		String extensionName = Localization.getString(Strings.FILE_FILTER_ZIP);
+		ExtensionFilter extensionFilter = new ExtensionFilter(extensionName, PlayPadMain.ZIP_TYPE);
 		chooser.getExtensionFilters().add(extensionFilter);
 
 		File file = chooser.showSaveDialog(getContainingWindow());
@@ -104,11 +105,11 @@ public class ProjectExportDialog extends NVC implements ProjectExporterDelegate
 				} catch (IOException e) {
 					busyView.showProgress(false);
 
-					String errorMessage = Localization.getString(Strings.Error_Project_Export, projectRef.getName(), e.getMessage());
+					String errorMessage = Localization.getString(Strings.ERROR_PROJECT_EXPORT, projectRef.getName(), e.getMessage());
 					showErrorMessage(errorMessage);
-					e.printStackTrace();
+					Logger.error(e);
 				} catch (ProjectNotFoundException | DocumentException | ProfileNotFoundException e) {
-					e.printStackTrace();
+					Logger.error(e);
 				} catch (ProjectReader.ProjectReaderDelegate.ProfileAbortException ignored) {
 				}
 			});
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectImportDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectImportDialog.java
index d4285db84931eac00a663a5bd23382fd6c270336..5f204a5df78442fab491b8b94fbecdd85c7834a2 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectImportDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectImportDialog.java
@@ -1,13 +1,12 @@
 package de.tobias.playpad.viewcontroller.dialog.project;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.ui.scene.BusyView;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.profile.ProfileNotFoundException;
 import de.tobias.playpad.profile.ref.ProfileReferenceManager;
 import de.tobias.playpad.project.ProjectNotFoundException;
@@ -70,8 +69,8 @@ public class ProjectImportDialog extends NVC implements ProjectImporterDelegate,
 	private ProjectImporter importer;
 	private Path mediaPath;
 
-	public ProjectImportDialog(Path path, Window owner) throws IOException, DocumentException {
-		load("view/dialog/project", "ImportDialog", PlayPadMain.getUiResourceBundle());
+	public ProjectImportDialog(Path path, Window owner) throws IOException, ProjectImporter.ProjectImportCorruptedException {
+		load("view/dialog/project", "ImportDialog", Localization.getBundle());
 		applyViewControllerToStage().initOwner(owner);
 
 		addCloseKeyShortcut(() -> cancelHandler(null));
@@ -79,8 +78,8 @@ public class ProjectImportDialog extends NVC implements ProjectImporterDelegate,
 		importer = new ProjectImporter(path, this);
 
 		// Set Default Values
-		projectNameTextField.setText(Localization.getString(Strings.Standard_Copy, importer.getProjectName()));
-		profileNameTextField.setText(Localization.getString(Strings.Standard_Copy, importer.getProfileName()));
+		projectNameTextField.setText(Localization.getString(Strings.STANDARD_COPY, importer.getProjectName()));
+		profileNameTextField.setText(Localization.getString(Strings.STANDARD_COPY, importer.getProfileName()));
 
 		profileSection.setDisable(!importer.isIncludeProfile());
 		profileImportCheckbox.setSelected(importer.isIncludeProfile());
@@ -104,21 +103,15 @@ public class ProjectImportDialog extends NVC implements ProjectImporterDelegate,
 
 	@Override
 	public void init() {
-		mediaImportCheckbox.selectedProperty().addListener((observable, oldValue, newValue) -> {
-			if (newValue && mediaPath == null) {
-				importButton.setDisable(true);
-			} else {
-				importButton.setDisable(false);
-			}
-		});
+		mediaImportCheckbox.selectedProperty().addListener((observable, oldValue, newValue) ->
+				importButton.setDisable(newValue && mediaPath == null));
 
 		profileImportCheckbox.selectedProperty().addListener((observable, oldValue, newValue) -> {
 			validateInput();
 			profileNameTextField.setDisable(!newValue);
 		});
-		mediaImportCheckbox.selectedProperty().addListener((observable, oldValue, newValue) -> {
-			mediaPathButton.setDisable(!newValue);
-		});
+		mediaImportCheckbox.selectedProperty().addListener((observable, oldValue, newValue) ->
+				mediaPathButton.setDisable(!newValue));
 
 		projectNameTextField.textProperty().addListener(this);
 		projectNameTextField.textProperty().addListener((observable, oldValue, newValue) ->
@@ -138,19 +131,17 @@ public class ProjectImportDialog extends NVC implements ProjectImporterDelegate,
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		stage.setMinWidth(380);
 		stage.setMaxWidth(380);
 
 		stage.setMinHeight(480);
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_ProjectImport_Title));
+		stage.setTitle(Localization.getString(Strings.UI_DIALOG_PROJECT_IMPORT_TITLE));
 
 		stage.initModality(Modality.WINDOW_MODAL);
 
-		if (Profile.currentProfile() != null) {
-			PlayPadPlugin.styleable().applyStyle(stage);
-		}
+		PlayPadPlugin.styleable().applyStyle(stage);
 	}
 
 	@Override
@@ -162,11 +153,7 @@ public class ProjectImportDialog extends NVC implements ProjectImporterDelegate,
 		boolean validProjectName = ProjectReferenceManager.validateProjectName(projectNameTextField.getText());
 		boolean validProfileName = ProfileReferenceManager.validateName(profileNameTextField.getText());
 
-		if (!validProjectName || (!validProfileName && shouldImportProfile())) {
-			importButton.setDisable(true);
-		} else {
-			importButton.setDisable(false);
-		}
+		importButton.setDisable(!validProjectName || (!validProfileName && shouldImportProfile()));
 	}
 
 	// ActionHandler
@@ -200,9 +187,9 @@ public class ProjectImportDialog extends NVC implements ProjectImporterDelegate,
 			canceled = false;
 
 			getStageContainer().ifPresent(NVCStage::close);
-		} catch (IOException | DocumentException | ProjectNotFoundException | ProfileNotFoundException e) {
-			e.printStackTrace();
-			showErrorMessage(Localization.getString(Strings.Error_Project_Export));
+		} catch (IOException | DocumentException | ProjectNotFoundException | ProfileNotFoundException | ProjectImporter.ProjectImportCorruptedException e) {
+			Logger.error(e);
+			showErrorMessage(Localization.getString(Strings.ERROR_PROJECT_IMPORT));
 		} catch (ProjectReader.ProjectReaderDelegate.ProfileAbortException ignored) {
 		}
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectLoadDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectLoadDialog.java
index 04762dc36a17632c5910817b8e6c48544092e9fc..f1dfdc84a376b2beae954d3aa4f4a71e636fe162 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectLoadDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectLoadDialog.java
@@ -3,7 +3,7 @@ package de.tobias.playpad.viewcontroller.dialog.project;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
+import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.project.ProjectReader;
 import javafx.application.Platform;
@@ -25,23 +25,21 @@ public class ProjectLoadDialog extends NVC implements ProjectReader.ProjectReade
 	private ProgressBar progressbar;
 
 	public ProjectLoadDialog() {
-		load("view/dialog/project", "LoadDialog", PlayPadMain.getUiResourceBundle());
+		load("view/dialog/project", "LoadDialog", Localization.getBundle());
 		applyViewControllerToStage();
 	}
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		stage.setWidth(400);
-		stage.setHeight(100);
+		stage.setHeight(70);
 
 		stage.initModality(Modality.APPLICATION_MODAL);
 		stage.initStyle(StageStyle.UNDECORATED);
 
-		// TODO Rewrite
-		stage.getScene().getStylesheets().add("style/style.css");
-		stage.getScene().getStylesheets().add("style/modern.css");
+		PlayPadPlugin.styleable().applyStyle(stage);
 
 		stage.setAlwaysOnTop(true);
 		stage.centerOnScreen();
@@ -50,7 +48,7 @@ public class ProjectLoadDialog extends NVC implements ProjectReader.ProjectReade
 	@Override
 	public void startReadProject() {
 		getStageContainer().ifPresent(NVCStage::show);
-		statusLabel.setText(Localization.getString(Strings.UI_Dialog_ProjectLoad_StartProject));
+		statusLabel.setText(Localization.getString(Strings.UI_DIALOG_PROJECT_LOAD_START_PROJECT));
 	}
 
 	@Override
@@ -65,7 +63,7 @@ public class ProjectLoadDialog extends NVC implements ProjectReader.ProjectReade
 	public void readMedia(String name) {
 		currentCount++;
 		Platform.runLater(() -> {
-			statusLabel.setText(Localization.getString(Strings.UI_Dialog_ProjectLoad_StartPad, name));
+			statusLabel.setText(Localization.getString(Strings.UI_DIALOG_PROJECT_LOAD_START_PAD, name));
 			progressbar.setProgress(currentCount / (double) itemCount);
 		});
 	}
@@ -79,4 +77,9 @@ public class ProjectLoadDialog extends NVC implements ProjectReader.ProjectReade
 	public void finish() {
 		Platform.runLater(() -> getStageContainer().ifPresent(NVCStage::close));
 	}
+
+	@Override
+	public void abort() {
+		Platform.runLater(() -> getStageContainer().ifPresent(NVCStage::close));
+	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectManagerDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectManagerDialog.java
index 24127762af0f491c57160336ea36eb252b3d94d5..a46ec48057bf5de96232c64014a680bad34919e5 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectManagerDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectManagerDialog.java
@@ -10,9 +10,9 @@ import de.tobias.playpad.Strings;
 import de.tobias.playpad.profile.ProfileNotFoundException;
 import de.tobias.playpad.profile.ref.ProfileReference;
 import de.tobias.playpad.profile.ref.ProfileReferenceManager;
-import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.ProjectNotFoundException;
 import de.tobias.playpad.project.ProjectReader;
+import de.tobias.playpad.project.importer.ProjectImporter;
 import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.project.ref.ProjectReferenceManager;
 import de.tobias.playpad.view.PseudoClasses;
@@ -64,7 +64,7 @@ public class ProjectManagerDialog extends NVC {
 	private Button openButton;
 
 	public ProjectManagerDialog(Window owner) {
-		load("view/dialog/project", "ProjectManagementDialog.fxml", PlayPadMain.getUiResourceBundle());
+		load("view/dialog/project", "ProjectManagementDialog.fxml", Localization.getBundle());
 
 		NVCStage nvcStage = applyViewControllerToStage();
 		nvcStage.initOwner(owner);
@@ -74,7 +74,7 @@ public class ProjectManagerDialog extends NVC {
 
 	@Override
 	public void init() {
-		projectList.setPlaceholder(new Label(Localization.getString(Strings.UI_Placeholder_Project)));
+		projectList.setPlaceholder(new Label(Localization.getString(Strings.UI_PLACEHOLDER_PROJECT)));
 		projectList.setCellFactory(list -> new ProjectCell(false));
 
 		// Set Items
@@ -120,7 +120,7 @@ public class ProjectManagerDialog extends NVC {
 
 		// Name Change Listener
 		nameTextfield.textProperty().addListener((observable, oldValue, newValue) -> {
-			if (Project.validateNameInput(newValue)) {
+			if (ProjectReferenceManager.validateProjectName(newValue)) {
 				ProjectReference reference = getSelectedItem();
 				if (reference != null && ProjectReferenceManager.validateProjectName(reference, newValue)) {
 					reference.setName(newValue);
@@ -144,7 +144,7 @@ public class ProjectManagerDialog extends NVC {
 				try {
 					ProjectReferenceManager.setSync(reference, newValue);
 				} catch (ProjectNotFoundException | ProfileNotFoundException | DocumentException | IOException e) {
-					showErrorMessage(Localization.getString(Strings.Error_Project_Sync_Change, e.getLocalizedMessage()));
+					showErrorMessage(Localization.getString(Strings.ERROR_PROJECT_SYNC_CHANGE, e.getLocalizedMessage()));
 					Logger.error(e);
 				} catch (ProjectReader.ProjectReaderDelegate.ProfileAbortException ignored) {
 				}
@@ -165,13 +165,13 @@ public class ProjectManagerDialog extends NVC {
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		stage.setMinWidth(600);
-		stage.setMinHeight(540);
+		stage.setMinHeight(560);
 		stage.setWidth(600);
 		stage.setHeight(540);
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_ProjectManager_Title));
+		stage.setTitle(Localization.getString(Strings.UI_DIALOG_PROJECT_MANAGER_TITLE));
 
 		stage.initModality(Modality.WINDOW_MODAL);
 
@@ -198,8 +198,8 @@ public class ProjectManagerDialog extends NVC {
 	private void projectImportHandler(ActionEvent event) {
 		FileChooser chooser = new FileChooser();
 
-		String extensionName = Localization.getString(Strings.File_Filter_ZIP);
-		FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter(extensionName, PlayPadMain.projectZIPType);
+		String extensionName = Localization.getString(Strings.FILE_FILTER_ZIP);
+		FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter(extensionName, PlayPadMain.ZIP_TYPE);
 		chooser.getExtensionFilters().add(extensionFilter);
 
 		File file = chooser.showOpenDialog(getContainingWindow());
@@ -209,7 +209,7 @@ public class ProjectManagerDialog extends NVC {
 				ProjectImportDialog dialog = new ProjectImportDialog(file.toPath(), getContainingWindow());
 				Optional<ProjectReference> importedProject = dialog.showAndWait();
 				importedProject.ifPresent(projectList.getItems()::add);
-			} catch (IOException | DocumentException e) {
+			} catch (IOException | ProjectImporter.ProjectImportCorruptedException e) {
 				Logger.error(e);
 			}
 		}
@@ -246,7 +246,7 @@ public class ProjectManagerDialog extends NVC {
 					ProjectReferenceManager.removeProject(reference);
 					projectList.getItems().remove(reference);
 				} catch (IOException e) {
-					showErrorMessage(Localization.getString(Strings.Error_Project_Delete, e.getLocalizedMessage()));
+					showErrorMessage(Localization.getString(Strings.ERROR_PROJECT_DELETE, e.getLocalizedMessage()));
 					Logger.error(e);
 				}
 			});
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectNewDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectNewDialog.java
index 9f255239ddfe74d5692049a5ae7d5f800442da51..bc15c4eff218b031c8b48b2ada3da5497159ddaf 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectNewDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/project/ProjectNewDialog.java
@@ -1,14 +1,13 @@
 package de.tobias.playpad.viewcontroller.dialog.project;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.profile.ref.ProfileReference;
 import de.tobias.playpad.profile.ref.ProfileReferenceManager;
-import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.project.ref.ProjectReferenceManager;
 import de.tobias.playpad.viewcontroller.dialog.profile.NewProfileDialog;
@@ -49,7 +48,7 @@ public class ProjectNewDialog extends NVC {
 	private ProjectReference project;
 
 	public ProjectNewDialog(Window owner) {
-		load("view/dialog", "NewProjectDialog", PlayPadMain.getUiResourceBundle());
+		load("view/dialog", "NewProjectDialog", Localization.getBundle());
 
 		NVCStage nvcStage = applyViewControllerToStage();
 		nvcStage.initOwner(owner);
@@ -61,17 +60,17 @@ public class ProjectNewDialog extends NVC {
 
 	@Override
 	public void init() {
-		nameTextField.textProperty().addListener((a, b, c) -> finishButton.setDisable(!Project.validateNameInput(c)));
+		nameTextField.textProperty().addListener((a, b, c) -> finishButton.setDisable(!ProjectReferenceManager.validateProjectName(c)));
 		finishButton.setDisable(true);
 	}
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 		PlayPadPlugin.styleable().applyStyle(stage);
 		stage.initModality(Modality.WINDOW_MODAL);
 
-		stage.setTitle(Localization.getString(Strings.UI_Dialog_NewProject_Title));
+		stage.setTitle(Localization.getString(Strings.UI_DIALOG_NEW_PROJECT_TITLE));
 		stage.setWidth(560);
 		stage.setHeight(380);
 
@@ -98,8 +97,8 @@ public class ProjectNewDialog extends NVC {
 
 			getStageContainer().ifPresent(NVCStage::close);
 		} catch (IOException e) {
-			showErrorMessage(Localization.getString(Strings.Error_Project_Create, e.getLocalizedMessage()));
-			e.printStackTrace();
+			showErrorMessage(Localization.getString(Strings.ERROR_PROJECT_CREATE, e.getLocalizedMessage()));
+			Logger.error(e);
 		}
 	}
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/BasicMenuToolbarViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/BasicMenuToolbarViewController.java
index 444d861c0b57f178e51b8be6a198cafbf260dc16..83735e21ac0f46412f97377344554a679c6faa03 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/BasicMenuToolbarViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/BasicMenuToolbarViewController.java
@@ -2,19 +2,23 @@ package de.tobias.playpad.viewcontroller.main;
 
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.Strings;
 import de.tobias.playpad.project.Project;
+import de.tobias.playpad.project.page.Page;
 import de.tobias.playpad.settings.GlobalSettings;
-import de.tobias.playpad.settings.keys.Key;
+import de.tobias.playpad.viewcontroller.dialog.PathMatchDialog;
+import javafx.beans.binding.Bindings;
+import javafx.beans.binding.StringBinding;
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
 import javafx.fxml.FXML;
+import javafx.scene.control.Button;
 import javafx.scene.control.Label;
 import javafx.scene.control.Menu;
-import javafx.scene.control.MenuItem;
 import javafx.scene.control.Slider;
-import javafx.scene.input.KeyCombination;
 import javafx.scene.layout.HBox;
 
 import java.util.ResourceBundle;
@@ -61,13 +65,29 @@ public abstract class BasicMenuToolbarViewController extends MenuToolbarViewCont
 			volumeSlider.setValue(volumeSlider.getValue() + ev.getDeltaX() * 0.001);
 		});
 
+		volumeSlider.styleProperty().bind(Bindings.createStringBinding(() -> {
+
+			double min = volumeSlider.getMin();
+			double max = volumeSlider.getMax();
+			double value = volumeSlider.getValue();
+
+			return createSliderStyle(min, max, value);
+
+		}, volumeSlider.valueProperty()));
+
 		FontIcon fontIcon = new FontIcon(FontAwesomeType.EXCLAMATION_TRIANGLE);
 		fontIcon.getStyleClass().add("pad-notfound");
 		fontIcon.setSize(20);
+		fontIcon.setOnMouseClicked(e -> showNotMediaFoundDialog());
 
 		notFoundContainer.getChildren().add(0, fontIcon);
 	}
 
+	public void showNotMediaFoundDialog() {
+		PathMatchDialog dialog = new PathMatchDialog(openProject, getContainingWindow());
+		dialog.showAndWait();
+	}
+
 	@Override
 	public void setNotFoundNumber(int count) {
 		notFoundContainer.setVisible(count > 0);
@@ -83,17 +103,40 @@ public abstract class BasicMenuToolbarViewController extends MenuToolbarViewCont
 		}
 	}
 
-	protected void setKeyBindingForMenu(MenuItem menuItem, Key key) {
-		if (key != null) {
-			if (!key.getKeyCode().isEmpty()) {
-				KeyCombination keyCode = KeyCombination.valueOf(key.getKeyCode());
-				menuItem.setAccelerator(keyCode);
-			}
-		}
-	}
-
 	@Override
 	public void setOpenProject(Project project) {
 		this.openProject = project;
 	}
+
+	@SuppressWarnings("StringBufferReplaceableByString")
+	private String createSliderStyle(double min, double max, double value) {
+		StringBuilder gradient = new StringBuilder("-slider-track-color: ");
+		String defaultBG = "#5c5c5c ";
+		gradient.append("linear-gradient(to right, ").append(defaultBG).append("0%, ");
+
+		double valuePercent = 100.0 * (value - min) / (max - min);
+
+		gradient.append(defaultBG).append(min).append("%, ");
+		gradient.append("#358dab ").append(min).append("%, ");
+		gradient.append("#358dab ").append(valuePercent).append("%, ");
+		gradient.append(defaultBG).append(valuePercent).append("%, ");
+		gradient.append(defaultBG).append("100%); ");
+
+		return gradient.toString();
+	}
+
+	protected Button createPageButton(Page page, int index) {
+		Button button = new Button();
+
+		StringBinding nameBinding = Bindings.when(page.nameProperty().isEmpty())
+				.then(Localization.getString(Strings.UI_WINDOW_MAIN_PAGE_BUTTON, (index + 1)))
+				.otherwise(page.nameProperty());
+		button.textProperty().bind(nameBinding);
+		button.setUserData(index);
+		button.setFocusTraversable(false);
+		button.setOnAction(this);
+
+		return button;
+	}
+
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/MainViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/MainViewController.java
index 4aa46fc2395d2be0337684a289b04bc906d13d0a..bfe085df774bc312a05ea1e770f06d10c348f115 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/MainViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/MainViewController.java
@@ -1,5 +1,13 @@
 package de.tobias.playpad.viewcontroller.main;
 
+import de.thecodelabs.logger.Logger;
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.device.CloseException;
+import de.thecodelabs.midi.device.MidiDeviceInfo;
+import de.thecodelabs.midi.event.KeyEventDispatcher;
+import de.thecodelabs.midi.event.KeyEventType;
+import de.thecodelabs.midi.mapping.KeyType;
+import de.thecodelabs.midi.midi.Midi;
 import de.thecodelabs.utils.threading.Worker;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
@@ -11,16 +19,12 @@ import de.thecodelabs.utils.util.OS.OSType;
 import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.action.Mapping;
-import de.tobias.playpad.action.mapper.listener.KeyboardHandler;
-import de.tobias.playpad.action.mapper.listener.MidiHandler;
+import de.tobias.playpad.action.feedback.ColorAdjuster;
 import de.tobias.playpad.design.ModernDesignSizeHelper;
 import de.tobias.playpad.design.modern.model.ModernGlobalDesign;
-import de.tobias.playpad.layout.desktop.pad.DesktopPadDragListener;
-import de.tobias.playpad.midi.Midi;
-import de.tobias.playpad.midi.MidiListener;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.view.IPadView;
+import de.tobias.playpad.plugin.MainWindowListener;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.profile.ProfileListener;
 import de.tobias.playpad.profile.ProfileSettings;
@@ -53,6 +57,7 @@ import javafx.scene.Scene;
 import javafx.scene.control.Alert;
 import javafx.scene.control.ButtonBar;
 import javafx.scene.control.ButtonType;
+import javafx.scene.input.KeyCode;
 import javafx.scene.input.KeyCombination;
 import javafx.scene.input.KeyEvent;
 import javafx.scene.layout.*;
@@ -89,11 +94,6 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 	private Project openProject;
 	private int currentPageShowing = 0;
 
-	// Mapper
-	private Midi midi;
-	private MidiHandler midiHandler;
-	private KeyboardHandler keyboardHandler;
-
 	// Style
 	private Color gridColor;
 
@@ -112,13 +112,13 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 	private InvalidationListener pagesListener;
 
 	public MainViewController(Consumer<NVC> onFinish) {
-		load("view/main", "MainView", PlayPadMain.getUiResourceBundle(), e ->
+		load("view/main", "MainView", Localization.getBundle(), e ->
 		{
 			NVCStage stage = e.applyViewControllerToStage();
 			stage.addCloseHook(this::closeRequest);
 
 			// Init with existing stage
-			initMapper(openProject);
+			initKeyboardMapper();
 			reloadSettings(null, Profile.currentProfile());
 			onFinish.accept(e);
 
@@ -206,7 +206,7 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 				});
 			}
 		} catch (Exception e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 
@@ -218,17 +218,37 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 				stage.setAlwaysOnTop(Profile.currentProfile().getProfileSettings().isWindowAlwaysOnTop());
 		});
 
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 		stage.setFullScreenExitKeyCombination(KeyCombination.keyCombination(KeyCombination.SHIFT_DOWN + "+Esc"));
-		stage.setTitle(Localization.getString(Strings.UI_Window_Main_Title, "-", "-"));
+		stage.setTitle(Localization.getString(Strings.UI_WINDOW_MAIN_TITLE, "-", "-"));
 		stage.show();
 	}
 
-	private void initMapper(Project project) {
-		this.midi = Midi.getInstance();
-		this.midiHandler = new MidiHandler(midi, this, project);
-		this.midi.setListener(midiHandler);
-		this.keyboardHandler = new KeyboardHandler(project, this);
+	private void initKeyboardMapper() {
+		registerKeyboardListener(KeyEvent.ANY, event -> {
+			if (event.getTarget() instanceof AnchorPane) {
+				if (!event.isShortcutDown()) {
+					KeyCode code = null;
+					KeyEventType type = null;
+
+					if (event.getEventType() == KeyEvent.KEY_PRESSED) {
+						code = event.getCode();
+						type = KeyEventType.DOWN;
+
+					} else if (event.getEventType() == KeyEvent.KEY_RELEASED) {
+						code = event.getCode();
+						type = KeyEventType.UP;
+
+					}
+
+					// Only execute this, then the right event is triggered and this var is set
+					if (code != null) {
+						de.thecodelabs.midi.event.KeyEvent keyEvent = new de.thecodelabs.midi.event.KeyEvent(KeyType.KEYBOARD, type, code.ordinal());
+						KeyEventDispatcher.dispatchEvent(keyEvent);
+					}
+				}
+			}
+		});
 
 		// Request Focus for key listener
 		getParent().requestFocus();
@@ -260,7 +280,7 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 		menuToolbarViewController.getVolumeSlider().valueProperty().addListener(volumeChangeListener);
 
 		// Not Found Icon Update
-		if (menuToolbarViewController != null && openProject != null)
+		if (openProject != null)
 			menuToolbarViewController.setNotFoundNumber(openProject.getNotFoundMedia());
 
 		// Keyboard Shortcuts
@@ -279,24 +299,24 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 
 	private boolean closeRequest() {
 		if (Profile.currentProfile() != null) {
-			ProfileSettings profilSettings = Profile.currentProfile().getProfileSettings();
+			ProfileSettings profileSettings = Profile.currentProfile().getProfileSettings();
 			GlobalSettings globalSettings = PlayPadPlugin.getInstance().getGlobalSettings();
 
 			// Frag den Nutzer ob das Programm wirdklich geschlossen werden sol
 			// wenn ein Pad noch im Status Play ist
 			if (openProject.getActivePlayers() > 0 && globalSettings.isLiveMode()) {
 				Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
-				alert.setContentText(Localization.getString(Strings.UI_Window_Main_CloseRequest));
+				alert.setContentText(Localization.getString(Strings.UI_WINDOW_MAIN_CLOSE_REQUEST));
 
 				alert.initOwner(getStage());
 				alert.initModality(Modality.WINDOW_MODAL);
 				Stage alertStage = (Stage) alert.getDialogPane().getScene().getWindow();
-				PlayPadMain.stageIcon.ifPresent(alertStage.getIcons()::add);
+				alertStage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 				Optional<ButtonType> result = alert.showAndWait();
-				if (result.isPresent())
-					if (result.get() != ButtonType.OK)
-						return false;
+				if (result.isPresent() && result.get() != ButtonType.OK) {
+					return false;
+				}
 			}
 
 			// Save Dialog
@@ -322,17 +342,19 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 				if (Profile.currentProfile() != null)
 					Profile.currentProfile().save();
 			} catch (Exception e) {
-				e.printStackTrace();
-				showErrorMessage(Localization.getString(Strings.Error_Profile_Save));
+				Logger.error(e);
+				showErrorMessage(Localization.getString(Strings.ERROR_PROFILE_SAVE));
 			}
 
-			// Mapper Clear Feedback
-			Profile.currentProfile().getMappings().getActiveMapping().clearFeedback();
-
 			// MIDI Shutdown
 			// Der schließt MIDI, da er es auch öffnet und verantwortlich ist
-			if (profilSettings.isMidiActive()) {
-				midi.close();
+			if (profileSettings.isMidiActive() && Midi.getInstance().isOpen()) {
+				try {
+					Midi.getInstance().clearFeedback();
+					Midi.getInstance().close();
+				} catch (CloseException e) {
+					Logger.error(e);
+				}
 			}
 		}
 		return true;
@@ -341,17 +363,17 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 	private void saveProject() {
 		try {
 			if (openProject.getProjectReference() != null) {
-				ProjectReferenceManager.saveProject(openProject);
-				System.out.println("Saved Project: " + openProject);
+				ProjectReferenceManager.saveSingleProject(openProject);
+				Logger.info("Saved Project: " + openProject);
 			}
 		} catch (Exception e) {
-			e.printStackTrace();
-			showErrorMessage(Localization.getString(Strings.Error_Project_Save));
+			Logger.error(e);
+			showErrorMessage(Localization.getString(Strings.ERROR_PROJECT_SAVE));
 		}
 	}
 
 	@Override
-	public void openProject(Project project) {
+	public void closeProject() {
 		// Remove old listener
 		if (this.openProject != null) {
 			this.openProject.getProjectReference().nameProperty().removeListener(projectTitleListener);
@@ -359,8 +381,15 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 			this.openProject.notFoundMediaProperty().removeListener(notFoundListener);
 			this.openProject.close();
 		}
-
 		removePadContentsFromView();
+		this.openProject = null;
+	}
+
+	@Override
+	public void openProject(Project project) {
+		if (this.openProject != null) {
+			closeProject();
+		}
 
 		openProject = project;
 
@@ -370,13 +399,12 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 		openProject.notFoundMediaProperty().addListener(notFoundListener);
 
 		volumeChangeListener.setOpenProject(openProject);
-		midiHandler.setProject(project);
-		keyboardHandler.setProject(project);
-		Profile.currentProfile().getMappings().getActiveMapping().showFeedback(openProject);
 
-		midiHandler.setProject(project);
-		keyboardHandler.setProject(project);
-		DesktopPadDragListener.setProject(project);
+		Profile profile = Profile.currentProfile();
+		profile.getMappings().getActiveMapping().ifPresent(mapping -> {
+			Mapping.setCurrentMapping(mapping);
+			Midi.getInstance().showFeedback();
+		});
 
 		menuToolbarViewController.setOpenProject(openProject);
 
@@ -454,6 +482,7 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 	 * PadViews
 	 */
 	@Override
+	@SuppressWarnings("Duplicates")
 	public void createPadViews() {
 		if (openProject == null) {
 			return;
@@ -529,16 +558,14 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 			ModernGlobalDesign design = Profile.currentProfile().getProfileSettings().getDesign();
 			PlayPadMain.getProgramInstance().getModernDesign().global().applyStyleSheetToMainViewController(design, this, getStage(), openProject);
 
-			// Mapping feedback
-			Mapping activeMapping = Profile.currentProfile().getMappings().getActiveMapping();
-			activeMapping.clearFeedback();
-			activeMapping.prepareFeedback(openProject);
-			activeMapping.adjustPadColorToMapper();
-			activeMapping.showFeedback(openProject);
+			// Adjust colors
+			if (Mapping.getCurrentMapping() != null) {
+				ColorAdjuster.applyColorsToKeys();
+				Midi.getInstance().showFeedback();
+			}
 		}
 	}
 
-	@Override
 	public void setGridColor(Color color) {
 		this.gridColor = color;
 		try {
@@ -553,7 +580,7 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 				}
 			}
 		} catch (Exception e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 
@@ -572,27 +599,25 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 	@Override
 	public void reloadSettings(Profile old, Profile currentProfile) {
 
-		final DoubleProperty volumeFaderValueProperty = menuToolbarViewController.getVolumeSlider().valueProperty();
+		final DoubleProperty volumeFadeValueProperty = menuToolbarViewController.getVolumeSlider().valueProperty();
 
 		if (old != null) {
 			// Unbind Volume Slider
-			volumeFaderValueProperty.unbindBidirectional(old.getProfileSettings().volumeProperty());
-			volumeFaderValueProperty.removeListener(volumeChangeListener);
+			volumeFadeValueProperty.unbindBidirectional(old.getProfileSettings().volumeProperty());
+			volumeFadeValueProperty.removeListener(volumeChangeListener);
 
-			// Clear Feedback on Devie (LaunchPad Light off)
-			old.getMappings().getActiveMapping().getActions().forEach(action -> action.clearFeedback());
+			// Clear Feedback on Device (LaunchPad Light off)
+			Midi.getInstance().clearFeedback();
 
 			// LockedListener
 			old.getProfileSettings().lockedProperty().removeListener(lockedListener);
 		}
 
 		// Volume
-		volumeFaderValueProperty.bindBidirectional(currentProfile.getProfileSettings().volumeProperty());
-		volumeFaderValueProperty.addListener(volumeChangeListener);
+		volumeFadeValueProperty.bindBidirectional(currentProfile.getProfileSettings().volumeProperty());
+		volumeFadeValueProperty.addListener(volumeChangeListener);
 
 		final ProfileSettings profileSettings = currentProfile.getProfileSettings();
-		final Mapping activeMapping = currentProfile.getMappings().getActiveMapping();
-
 		// LockedListener
 		profileSettings.lockedProperty().addListener(lockedListener);
 
@@ -606,12 +631,8 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 				Platform.runLater(() ->
 				{
 					// Handle Mapper
-					if (currentProfile != null) {
-						activeMapping.initFeedbackType();
-						if (openProject != null) {
-							activeMapping.showFeedback(openProject);
-							currentProfile.getMappings().getActiveMapping().adjustPadColorToMapper();
-						}
+					if (openProject != null) {
+						Midi.getInstance().showFeedback();
 					}
 				});
 			});
@@ -622,12 +643,11 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 			MainLayoutFactory connect = registry.getFactory(currentProfile.getProfileSettings().getMainLayoutType());
 			setMainLayout(connect);
 		} catch (NoSuchComponentException e) {
-			// TODO Error Handling
-			e.printStackTrace();
+			Logger.error(e);
 		}
 
 		loadUserCss();
-		if (old != null && currentProfile != null) {
+		if (old != null) {
 			showPage(currentPageShowing);
 		}
 	}
@@ -636,18 +656,20 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 	 * Init MIDI Device by using the Midi Class and show some feedback the user.
 	 *
 	 * @param name Device Name
-	 * @see Midi#lookupMidiDevice(String)
 	 */
 	private void loadMidiDevice(String name) {
 		try {
-			midi.lookupMidiDevice(name);
-			notificationPane.showAndHide(Localization.getString(Strings.Info_Midi_Device_Connected, name), PlayPadMain.displayTimeMillis);
+			final MidiDeviceInfo midiDeviceInfo = Midi.getInstance().getMidiDeviceInfo(name);
+			if (midiDeviceInfo != null) {
+				Midi.getInstance().openDevice(midiDeviceInfo, Midi.Mode.INPUT, Midi.Mode.OUTPUT);
+				notificationPane.showAndHide(Localization.getString(Strings.INFO_MIDI_DEVICE_CONNECTED, name), PlayPadMain.NOTIFICATION_DISPLAY_TIME);
+			}
 		} catch (NullPointerException e) {
-			e.printStackTrace();
-			showError(Localization.getString(Strings.Error_Midi_Device_Unavailible, name));
+			Logger.error(e);
+			showError(Localization.getString(Strings.ERROR_MIDI_DEVICE_UNAVAILABLE, name));
 		} catch (IllegalArgumentException | MidiUnavailableException e) {
-			showError(Localization.getString(Strings.Error_Midi_Device_Busy, e.getLocalizedMessage()));
-			e.printStackTrace();
+			showError(Localization.getString(Strings.ERROR_MIDI_DEVICE_BUSY, e.getLocalizedMessage()));
+			Logger.error(e);
 		}
 	}
 
@@ -670,16 +692,12 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 
 	@Override
 	public Screen getScreen() {
-		if (getStageContainer().isPresent())
-			return getStageContainer().get().getScreen();
-		return null;
+		return getStageContainer().map(NVCStage::getScreen).orElse(null);
 	}
 
 	@Override
 	public Stage getStage() {
-		if (getStageContainer().isPresent())
-			return getStageContainer().get().getStage();
-		return null;
+		return getStageContainer().map(NVCStage::getStage).orElse(null);
 	}
 
 	@Override
@@ -687,11 +705,6 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 		return menuToolbarViewController;
 	}
 
-	@Override
-	public MidiListener getMidiHandler() {
-		return midiHandler;
-	}
-
 	@Override
 	public NotificationPane getNotificationPane() {
 		return notificationPane;
@@ -743,10 +756,10 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 		getStageContainer().ifPresent(sc ->
 		{
 			if (openProject != null && Profile.currentProfile() != null) {
-				getStage().setTitle(Localization.getString(Strings.UI_Window_Main_Title, openProject.getProjectReference().getName(),
+				getStage().setTitle(Localization.getString(Strings.UI_WINDOW_MAIN_TITLE, openProject.getProjectReference().getName(),
 						Profile.currentProfile().getRef().getName()));
 			} else {
-				getStage().setTitle(Localization.getString(Strings.UI_Window_Main_Title, "-", "-"));
+				getStage().setTitle(Localization.getString(Strings.UI_WINDOW_MAIN_TITLE, "-", "-"));
 			}
 		});
 	}
@@ -762,6 +775,9 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 		if (menuToolbarViewController != null) {
 			menuToolbarViewController.loadKeybinding(keys);
 		}
+
+		// Plugin Hook
+		PlayPadPlugin.getInstance().getMainViewListeners().forEach(MainWindowListener::loadMenuKeyBinding);
 	}
 
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/mapper/KeyboardMapperInputDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/mapper/KeyboardMapperInputDialog.java
index 8a2364bddd3a2353382886291a2619cfa21cf12f..e4a2741d0d777c10d1fed8601bc7c1d577417635 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/mapper/KeyboardMapperInputDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/mapper/KeyboardMapperInputDialog.java
@@ -1,39 +1,47 @@
 package de.tobias.playpad.viewcontroller.mapper;
 
+import de.thecodelabs.midi.mapping.KeyboardKey;
 import de.thecodelabs.utils.util.StringUtils;
-import de.tobias.playpad.action.mapper.KeyboardMapper;
 import javafx.scene.Scene;
 import javafx.scene.control.Alert;
 import javafx.scene.control.ButtonType;
+import javafx.scene.input.KeyEvent;
 import javafx.stage.Stage;
 
 import java.util.Optional;
 
 public class KeyboardMapperInputDialog extends Alert {
 
-	public KeyboardMapperInputDialog(KeyboardMapper mapper) {
+	public KeyboardMapperInputDialog(KeyboardKey mapper) {
 		super(AlertType.NONE);
 
 		Scene scene = getDialogPane().getScene();
 
 		scene.setOnKeyPressed(ev ->
 		{
+			if (checkControlKeys(ev)) return;
 			mapper.setKey(ev.getCode().getName());
 			mapper.setCode(ev.getCode());
 		});
 		scene.setOnKeyReleased(ev ->
 		{
+			if (checkControlKeys(ev)) return;
 			// Close on Finish (alert.close() does not work)
 			((Stage) scene.getWindow()).close();
 		});
 		scene.setOnKeyTyped(ev ->
 		{
+			if (checkControlKeys(ev)) return;
 			if (!StringUtils.isStringNotVisable(ev.getCharacter())) {
 				mapper.setKey(ev.getCharacter().toUpperCase());
 			}
 		});
 	}
 
+	private boolean checkControlKeys(KeyEvent ev) {
+		return ev.isShortcutDown() || ev.isAltDown() || ev.isShiftDown();
+	}
+
 	public boolean showInputDialog() {
 		Optional<ButtonType> result = showAndWait();
 		return !result.isPresent();
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/mapper/KeyboardMapperViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/mapper/KeyboardMapperViewController.java
index 16e5c9b97b82ac7b5781aab07b9e282cf2715707..3b021424da893ef6630c0b686236c95acc38b25a 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/mapper/KeyboardMapperViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/mapper/KeyboardMapperViewController.java
@@ -1,10 +1,10 @@
 package de.tobias.playpad.viewcontroller.mapper;
 
+import de.thecodelabs.midi.mapping.Key;
+import de.thecodelabs.midi.mapping.KeyboardKey;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
+import de.thecodelabs.utils.util.StringUtils;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.action.mapper.KeyboardMapper;
-import de.tobias.playpad.action.mapper.Mapper;
 import de.tobias.playpad.action.mapper.MapperViewController;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
@@ -19,14 +19,14 @@ public class KeyboardMapperViewController extends MapperViewController {
 	@FXML
 	private Button mappingButton;
 
-	private KeyboardMapper mapper;
+	private KeyboardKey mapper;
 
 	public KeyboardMapperViewController() {
-		load("view/mapper", "Keyboard", PlayPadMain.getUiResourceBundle());
+		load("view/mapper", "Keyboard", Localization.getBundle());
 	}
 
 	@Override
-	public Mapper getMapper() {
+	public Key getKey() {
 		return mapper;
 	}
 
@@ -38,8 +38,16 @@ public class KeyboardMapperViewController extends MapperViewController {
 	public void showFeedback() {
 	}
 
+	private String getReadableName() {
+		if (mapper.getKey() == null || !StringUtils.isStringNotVisable(mapper.getKey())) {
+			return mapper.getKey();
+		} else {
+			return mapper.getCode().getName();
+		}
+	}
+
 	private void setLabel() {
-		keyLabel.setText(mapper.getReadableName());
+		keyLabel.setText(getReadableName());
 	}
 
 	@FXML
@@ -49,8 +57,8 @@ public class KeyboardMapperViewController extends MapperViewController {
 
 	private boolean inputDialog() {
 		KeyboardMapperInputDialog alert = new KeyboardMapperInputDialog(mapper);
-		alert.setTitle(Localization.getString(Strings.Mapper_Keyboard_Name));
-		alert.setContentText(Localization.getString(Strings.Info_Mapper_PressKey));
+		alert.setTitle(Localization.getString(Strings.MAPPER_KEYBOARD_NAME));
+		alert.setContentText(Localization.getString(Strings.INFO_MAPPER_PRESS_KEY));
 
 		alert.getButtonTypes().add(ButtonType.CANCEL);
 		alert.initOwner(getContainingWindow());
@@ -64,8 +72,9 @@ public class KeyboardMapperViewController extends MapperViewController {
 		return inputDialog();
 	}
 
-	public void setMapper(KeyboardMapper keyboardMapper) {
-		this.mapper = keyboardMapper;
+	@Override
+	public void setKey(Key keyboardMapper) {
+		this.mapper = (KeyboardKey) keyboardMapper;
 		setLabel();
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/mapper/MidiMapperViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/mapper/MidiMapperViewController.java
index 124485646c83247b0cab20a16fc279d00fbf3882..d41a6e976d3f7077d61df8e3ee8ff07d166cff08 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/mapper/MidiMapperViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/mapper/MidiMapperViewController.java
@@ -1,19 +1,23 @@
 package de.tobias.playpad.viewcontroller.mapper;
 
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.device.MidiDevice;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.feedback.FeedbackValue;
+import de.thecodelabs.midi.mapping.Key;
+import de.thecodelabs.midi.mapping.MidiKey;
+import de.thecodelabs.midi.midi.Midi;
+import de.thecodelabs.midi.midi.MidiCommand;
+import de.thecodelabs.midi.midi.MidiCommandHandler;
+import de.thecodelabs.midi.midi.MidiListener;
+import de.thecodelabs.midi.midi.feedback.MidiFeedbackTranscript;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
+import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.action.feedback.FeedbackType;
-import de.tobias.playpad.action.mapper.Mapper;
+import de.tobias.playpad.action.ActionProvider;
 import de.tobias.playpad.action.mapper.MapperViewController;
-import de.tobias.playpad.action.mapper.MidiMapper;
-import de.tobias.playpad.action.mapper.feedback.DoubleMidiFeedback;
-import de.tobias.playpad.action.mapper.feedback.SingleMidiFeedback;
-import de.tobias.playpad.action.mididevice.MidiDeviceImpl;
-import de.tobias.playpad.midi.Midi;
-import de.tobias.playpad.midi.MidiListener;
-import de.tobias.playpad.viewcontroller.option.feedback.DoubleFeedbackViewController;
 import de.tobias.playpad.viewcontroller.option.feedback.SingleFeedbackViewController;
 import javafx.application.Platform;
 import javafx.event.ActionEvent;
@@ -27,8 +31,6 @@ import javafx.scene.layout.Priority;
 import javafx.scene.layout.VBox;
 import javafx.stage.Stage;
 
-import javax.sound.midi.MidiMessage;
-
 public class MidiMapperViewController extends MapperViewController implements MidiListener {
 
 	@FXML
@@ -39,45 +41,44 @@ public class MidiMapperViewController extends MapperViewController implements Mi
 	@FXML
 	private VBox root;
 
-	private MidiMapper mapper;
+	private MidiKey key;
 
-	private NVC feedbackController;
+	private NVC[] feedbackControllers;
 
 	public MidiMapperViewController() {
-		load("view/mapper", "Midi", PlayPadMain.getUiResourceBundle());
+		load("view/mapper", "Midi", Localization.getBundle());
 	}
 
 	@Override
-	public Mapper getMapper() {
-		return mapper;
+	public Key getKey() {
+		return key;
 	}
 
 	@Override
 	public void hideFeedback() {
-		if (feedbackController != null) {
-			root.getChildren().remove(feedbackController.getParent());
+		if (feedbackControllers != null) {
+			for (NVC feedbackController : feedbackControllers) {
+				root.getChildren().remove(feedbackController.getParent());
+			}
 		}
 	}
 
 	@Override
 	public void showFeedback() {
-		if (feedbackController != null) {
-			if (root.getChildren().contains(feedbackController.getParent()))
+		if (feedbackControllers != null) {
+			for (NVC feedbackController : feedbackControllers) {
 				root.getChildren().remove(feedbackController.getParent());
-			root.getChildren().add(feedbackController.getParent());
-			VBox.setVgrow(feedbackController.getParent(), Priority.ALWAYS);
+				root.getChildren().add(feedbackController.getParent());
+				VBox.setVgrow(feedbackController.getParent(), Priority.ALWAYS);
+			}
 		}
 	}
 
-	/**
-	 * Midi Listener von SettingsViewController, damit dieser wiederhergestellt werden kann am Ende.
-	 */
-	private MidiListener currentListener;
-
 	/**
 	 * Current Alert for mapping.
 	 */
 	private Alert alert;
+
 	// Hilfsvariable um zu speichern, ob der Input Dialog abgebrochen wurde
 	private boolean canceled = false;
 
@@ -85,30 +86,28 @@ public class MidiMapperViewController extends MapperViewController implements Mi
 	private void midiInputRecordButtonHandler(ActionEvent event) {
 		canceled = false;
 
-		currentListener = Midi.getInstance().getListener();
-		Midi.getInstance().setListener(this);
+		MidiCommandHandler.getInstance().addMidiListener(this);
 
 		alert = new Alert(AlertType.NONE);
-		alert.setTitle(Localization.getString(Strings.Mapper_Midi_Name));
-		alert.setContentText(Localization.getString(Strings.Info_Mapper_PressKey));
+		alert.setTitle(Localization.getString(Strings.MAPPER_MIDI_NAME));
+		alert.setContentText(Localization.getString(Strings.INFO_MAPPER_PRESS_KEY));
 		alert.getButtonTypes().add(ButtonType.CANCEL);
 		alert.initOwner(getContainingWindow());
 		alert.showAndWait().ifPresent(result ->
 		{
 			if (result == ButtonType.CANCEL) {
-				Midi.getInstance().setListener(currentListener);
-				currentListener = null;
 				alert = null;
 				canceled = true;
+				MidiCommandHandler.getInstance().removeMidiListener(this);
 			}
 		});
 	}
 
-	/**
-	 * Record new Midi Key
-	 */
 	@Override
-	public void onMidiAction(MidiMessage message) {
+	public void onMidiMessage(MidiCommand midiCommand) {
+		key.setValue(midiCommand.getPayload()[0]);
+		midiCommand.consume();
+
 		Platform.runLater(() ->
 		{
 			if (alert != null) {
@@ -116,13 +115,10 @@ public class MidiMapperViewController extends MapperViewController implements Mi
 				stage.close();
 				alert = null;
 			}
-			mapper.setCommand(message.getMessage()[0]);
-			mapper.setKey(message.getMessage()[1]);
-
-			midiInputKeyLabel.setText(String.valueOf(mapper.getKey()));
+			midiInputKeyLabel.setText(String.valueOf(key.getValue()));
 		});
-		Midi.getInstance().setListener(currentListener);
-		currentListener = null;
+
+		MidiCommandHandler.getInstance().removeMidiListener(this);
 	}
 
 	@Override
@@ -131,26 +127,37 @@ public class MidiMapperViewController extends MapperViewController implements Mi
 		return !canceled;
 	}
 
-	public void setMapper(MidiMapper midiMapper) {
-		this.mapper = midiMapper;
+	@Override
+	public void setKey(Key midiKey) {
+		this.key = (MidiKey) midiKey;
+
+		midiInputKeyLabel.setText(String.valueOf(key.getValue()));
 
-		midiInputKeyLabel.setText(String.valueOf(mapper.getKey()));
+		final MidiDevice device = Midi.getInstance().getDevice();
+		final MidiFeedbackTranscript transcript = Midi.getInstance().getFeedbackTranscript();
 
-		MidiDeviceImpl midiDeviceImpl = Midi.getInstance().getMidiDevice();
-		if (midiDeviceImpl != null) {
-			if (midiDeviceImpl.supportFeedback()) {
+		if (device != null && transcript != null) {
+			if (device.isModeSupported(Midi.Mode.OUTPUT)) {
 				// remove old Elements
-				if (feedbackController != null) {
-					root.getChildren().remove(feedbackController.getParent());
+				if (feedbackControllers != null) {
+					for (NVC feedbackController : feedbackControllers) {
+						root.getChildren().remove(feedbackController.getParent());
+					}
 				}
-				// add new Elements
-				if (mapper.getFeedbackType() == FeedbackType.SINGLE) {
-					feedbackController = new SingleFeedbackViewController((SingleMidiFeedback) mapper.getFeedback(), midiDeviceImpl.getColors());
-				} else if (mapper.getFeedbackType() == FeedbackType.DOUBLE) {
-					feedbackController = new DoubleFeedbackViewController((DoubleMidiFeedback) mapper.getFeedback(), midiDeviceImpl.getColors());
+
+				final Action action = Mapping.getCurrentMapping().getActionForMidiKey(key.getValue());
+				final ActionProvider actionProvider = PlayPadPlugin.getRegistries().getActions().getFactory(action.getActionType());
+				final FeedbackType[] feedbackTypes = actionProvider.supportedFeedbackOptions(action, key.getType());
+
+				final FeedbackValue[] feedbackValues = transcript.getFeedbackValues();
+				this.feedbackControllers = new NVC[feedbackTypes.length];
+				for (int i = 0; i < feedbackTypes.length; i++) {
+					final FeedbackType feedbackType = feedbackTypes[i];
+					NVC controller = new SingleFeedbackViewController(key.getFeedbackForType(feedbackType), feedbackType, feedbackValues, action);
+					this.feedbackControllers[i] = controller;
 				}
-				showFeedback();
 			}
+			showFeedback();
 		}
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/feedback/DoubleFeedbackViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/feedback/DoubleFeedbackViewController.java
deleted file mode 100644
index 6969e2f0ea535ebc9642cd98746209bc95a4c755..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/feedback/DoubleFeedbackViewController.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package de.tobias.playpad.viewcontroller.option.feedback;
-
-import de.thecodelabs.utils.ui.NVC;
-import de.thecodelabs.utils.ui.icon.FontAwesomeType;
-import de.thecodelabs.utils.ui.icon.FontIcon;
-import de.tobias.playpad.PlayPadMain;
-import de.tobias.playpad.action.feedback.DisplayableFeedbackColor;
-import de.tobias.playpad.action.feedback.FeedbackMessage;
-import de.tobias.playpad.action.mapper.feedback.DoubleMidiFeedback;
-import de.tobias.playpad.action.mididevice.MidiDeviceImpl;
-import de.tobias.playpad.midi.Midi;
-import de.tobias.playpad.view.ColorPickerView;
-import javafx.event.ActionEvent;
-import javafx.fxml.FXML;
-import javafx.scene.Node;
-import javafx.scene.control.Button;
-import javafx.scene.layout.HBox;
-import javafx.scene.paint.Color;
-import javafx.scene.paint.Paint;
-import javafx.scene.shape.Rectangle;
-import org.controlsfx.control.PopOver;
-import org.controlsfx.control.PopOver.ArrowLocation;
-
-public class DoubleFeedbackViewController extends NVC {
-
-	@FXML
-	private HBox defaultColorParent;
-	@FXML
-	private Button colorChooseDefaultButton;
-	@FXML
-	private Rectangle colorPreviewDefault;
-
-	@FXML
-	private HBox eventColorParent;
-	@FXML
-	private Button colorChooseEventButton;
-	@FXML
-	private Rectangle colorPreviewEvent;
-
-	private PopOver colorChooser;
-
-	private DoubleMidiFeedback feedback;
-
-	public DoubleFeedbackViewController(DoubleMidiFeedback feedback, DisplayableFeedbackColor[] colors) {
-		load("view/option/feedback", "DoubleFeedback", PlayPadMain.getUiResourceBundle());
-		this.feedback = feedback;
-
-		MidiDeviceImpl midiDeviceImpl = Midi.getInstance().getMidiDevice();
-		if (midiDeviceImpl != null) {
-			DisplayableFeedbackColor colorDefault = midiDeviceImpl.getColor(feedback.getValueForFeedbackMessage(FeedbackMessage.STANDARD));
-			if (colorDefault != null) {
-				colorPreviewDefault.setFill(colorDefault.getPaint());
-				setColorChooseButtonColor(colorDefault.getPaint(), colorChooseDefaultButton);
-			}
-			DisplayableFeedbackColor colorPlay = midiDeviceImpl.getColor(feedback.getValueForFeedbackMessage(FeedbackMessage.EVENT));
-			if (colorPlay != null) {
-				colorPreviewEvent.setFill(colorPlay.getPaint());
-				setColorChooseButtonColor(colorPlay.getPaint(), colorChooseEventButton);
-			}
-		}
-	}
-
-	@Override
-	public void init() {
-		FontIcon iconDefault = new FontIcon(FontAwesomeType.ARROW_CIRCLE_DOWN);
-		iconDefault.getStyleClass().remove(FontIcon.STYLE_CLASS);
-		colorChooseDefaultButton.setGraphic(iconDefault);
-		colorPreviewDefault.widthProperty().bind(colorChooseDefaultButton.widthProperty());
-
-		FontIcon iconEvent = new FontIcon(FontAwesomeType.ARROW_CIRCLE_DOWN);
-		iconEvent.getStyleClass().remove(FontIcon.STYLE_CLASS);
-		colorChooseEventButton.setGraphic(iconEvent);
-		colorPreviewEvent.widthProperty().bind(colorChooseEventButton.widthProperty());
-	}
-
-	@FXML
-	private void colorChooseButtonHandler(ActionEvent event) {
-		if (colorChooser == null) {
-			colorChooser = new PopOver();
-			MidiDeviceImpl midiDeviceImpl = Midi.getInstance().getMidiDevice();
-			if (midiDeviceImpl != null) {
-				DisplayableFeedbackColor color = midiDeviceImpl.getColor(feedback.getValueForFeedbackMessage(FeedbackMessage.STANDARD));
-				if (event.getSource() == colorChooseDefaultButton) {
-					color = midiDeviceImpl.getColor(feedback.getValueForFeedbackMessage(FeedbackMessage.STANDARD));
-				} else if (event.getSource() == colorChooseEventButton) {
-					color = midiDeviceImpl.getColor(feedback.getValueForFeedbackMessage(FeedbackMessage.EVENT));
-				}
-
-				ColorPickerView colorView = new ColorPickerView(color, midiDeviceImpl.getColors(), item ->
-				{
-					colorChooser.hide();
-					if (item instanceof DisplayableFeedbackColor) {
-						if (event.getSource() == colorChooseDefaultButton) {
-							feedback.setFeedbackDefaultValue(((DisplayableFeedbackColor) item).mapperFeedbackValue());
-							colorPreviewDefault.setFill(item.getPaint());
-							setColorChooseButtonColor(item.getPaint(), colorChooseDefaultButton);
-						} else if (event.getSource() == colorChooseEventButton) {
-							feedback.setFeedbackEventValue(((DisplayableFeedbackColor) item).mapperFeedbackValue());
-							colorPreviewEvent.setFill(item.getPaint());
-							setColorChooseButtonColor(item.getPaint(), colorChooseEventButton);
-						}
-					}
-				});
-
-				colorChooser.setContentNode(colorView);
-				colorChooser.setDetachable(false);
-				colorChooser.setOnHiding(e -> colorChooser = null);
-				colorChooser.setCornerRadius(5);
-				colorChooser.setArrowLocation(ArrowLocation.LEFT_CENTER);
-				colorChooser.show((Node) event.getSource());
-			}
-		}
-
-	}
-
-	private void setColorChooseButtonColor(Paint inputColor, Button button) {
-		Color color;
-		if (inputColor.equals(Color.BLACK))
-			color = Color.WHITE;
-		else
-			color = Color.BLACK;
-		((FontIcon) button.getGraphic()).setColor(color);
-	}
-}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/feedback/SingleFeedbackViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/feedback/SingleFeedbackViewController.java
index c6d4105791e9f90512f9b9d6703f38ebd5e3e660..a949622480873dcea5e15793d279d61a25bcf05f 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/feedback/SingleFeedbackViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/feedback/SingleFeedbackViewController.java
@@ -1,19 +1,25 @@
 package de.tobias.playpad.viewcontroller.option.feedback;
 
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.feedback.Feedback;
+import de.thecodelabs.midi.feedback.FeedbackColor;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.feedback.FeedbackValue;
+import de.thecodelabs.midi.midi.Midi;
 import de.thecodelabs.utils.ui.NVC;
-import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
-import de.tobias.playpad.PlayPadMain;
-import de.tobias.playpad.action.feedback.DisplayableFeedbackColor;
-import de.tobias.playpad.action.feedback.FeedbackMessage;
-import de.tobias.playpad.action.mapper.feedback.SingleMidiFeedback;
-import de.tobias.playpad.action.mididevice.MidiDeviceImpl;
-import de.tobias.playpad.midi.Midi;
-import de.tobias.playpad.view.ColorPickerView;
+import de.thecodelabs.utils.util.ColorUtils;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.action.feedback.LightMode;
+import de.tobias.playpad.profile.Profile;
+import de.tobias.playpad.profile.ProfileSettings;
+import de.tobias.playpad.view.FeedbackColorPickerView;
+import de.tobias.playpad.viewcontroller.design.IColorButton;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.scene.Node;
 import javafx.scene.control.Button;
+import javafx.scene.control.Label;
 import javafx.scene.layout.HBox;
 import javafx.scene.paint.Color;
 import javafx.scene.paint.Paint;
@@ -21,8 +27,13 @@ import javafx.scene.shape.Rectangle;
 import org.controlsfx.control.PopOver;
 import org.controlsfx.control.PopOver.ArrowLocation;
 
-public class SingleFeedbackViewController extends NVC {
+import java.util.Arrays;
+import java.util.List;
 
+public class SingleFeedbackViewController extends NVC implements IColorButton {
+
+	@FXML
+	private Label nameLabel;
 	@FXML
 	private HBox defaultColorParent;
 	@FXML
@@ -32,27 +43,51 @@ public class SingleFeedbackViewController extends NVC {
 
 	private PopOver colorChooser;
 
-	private SingleMidiFeedback feedback;
+	private FeedbackColor[] colors;
+	private Feedback feedback;
+	private Action action;
 
-	public SingleFeedbackViewController(SingleMidiFeedback feedback, DisplayableFeedbackColor[] colors) {
-		load("view/option/feedback", "SingleFeedback", PlayPadMain.getUiResourceBundle());
+	public SingleFeedbackViewController(Feedback feedback, FeedbackType type, FeedbackValue[] values, Action action) {
+		load("view/option/feedback", "SingleFeedback", Localization.getBundle());
 		this.feedback = feedback;
+		this.action = action;
+
+		if (!(values instanceof FeedbackColor[])) {
+			throw new IllegalArgumentException("FeedbackValues are not of type FeedbackColor");
+		}
+
+		switch (type) {
+			case DEFAULT:
+				nameLabel.setText(Localization.getString("feedback.label.colorDefault"));
+				break;
+			case EVENT:
+				nameLabel.setText(Localization.getString("feedback.label.colorEvent"));
+				break;
+			case WARNING:
+				nameLabel.setText(Localization.getString("feedback.label.colorWarning"));
+				break;
+		}
+
+		colors = (FeedbackColor[]) values;
+
+		final FeedbackColor feedbackColor = getFeedbackColor(feedback);
+		if (feedbackColor != null) {
+			setColorChooseButtonColor(feedbackColor.getColor(), colorChooseDefaultButton);
+		}
+	}
 
-		MidiDeviceImpl midiDeviceImpl = Midi.getInstance().getMidiDevice();
-		if (midiDeviceImpl != null) {
-			DisplayableFeedbackColor colorDefault = midiDeviceImpl.getColor(feedback.getValueForFeedbackMessage(FeedbackMessage.STANDARD));
-			if (colorDefault != null) {
-				colorPreviewDefault.setFill(colorDefault.getPaint());
-				setColorChooseButtonColor(colorDefault.getPaint(), colorChooseDefaultButton);
+	private FeedbackColor getFeedbackColor(Feedback feedback) {
+		for (FeedbackColor color : colors) {
+			if (color.getValue() == feedback.getValue()) {
+				return color;
 			}
 		}
+		return null;
 	}
 
 	@Override
 	public void init() {
-		FontIcon iconDefault = new FontIcon(FontAwesomeType.ARROW_CIRCLE_DOWN);
-		iconDefault.getStyleClass().remove(FontIcon.STYLE_CLASS);
-		colorChooseDefaultButton.setGraphic(iconDefault);
+		addIconToButton(colorChooseDefaultButton);
 		colorPreviewDefault.widthProperty().bind(colorChooseDefaultButton.widthProperty());
 	}
 
@@ -60,38 +95,43 @@ public class SingleFeedbackViewController extends NVC {
 	private void colorChooseButtonHandler(ActionEvent event) {
 		if (colorChooser == null) {
 			colorChooser = new PopOver();
-			MidiDeviceImpl midiDeviceImpl = Midi.getInstance().getMidiDevice();
-			if (midiDeviceImpl != null) {
-				DisplayableFeedbackColor color = midiDeviceImpl.getColor(feedback.getValueForFeedbackMessage(FeedbackMessage.STANDARD));
-
-				ColorPickerView colorView = new ColorPickerView(color, midiDeviceImpl.getColors(), item ->
-				{
-					colorChooser.hide();
-					if (item instanceof DisplayableFeedbackColor) {
-						if (event.getSource() == colorChooseDefaultButton) {
-							feedback.setFeedbackValue(((DisplayableFeedbackColor) item).mapperFeedbackValue());
-							colorPreviewDefault.setFill(item.getPaint());
-							setColorChooseButtonColor(item.getPaint(), colorChooseDefaultButton);
-						}
-					}
-				});
-
-				colorChooser.setContentNode(colorView);
-				colorChooser.setDetachable(false);
-				colorChooser.setOnHiding(e -> colorChooser = null);
-				colorChooser.setCornerRadius(5);
-				colorChooser.setArrowLocation(ArrowLocation.LEFT_CENTER);
-				colorChooser.show((Node) event.getSource());
+			final FeedbackColor feedbackColor = getFeedbackColor(feedback);
+
+			List<? extends FeedbackColor> selectableColors = Arrays.asList(colors);
+			if (colors instanceof LightMode.ILightMode[]) {
+				ProfileSettings profileSettings = Profile.currentProfile().getProfileSettings();
+				selectableColors = LightMode.filter((LightMode.ILightMode[]) colors, profileSettings.getLightMode());
 			}
+
+			FeedbackColorPickerView colorView = new FeedbackColorPickerView(feedbackColor, selectableColors, item ->
+			{
+				colorChooser.hide();
+				if (event.getSource() == colorChooseDefaultButton) {
+					feedback.setValue(item.getValue());
+					setColorChooseButtonColor(item.getColor(), colorChooseDefaultButton);
+
+					// highlight current button on device
+					Midi.getInstance().clearFeedback();
+					Midi.getInstance().showFeedback(action);
+				}
+			});
+
+			colorChooser.setContentNode(colorView);
+			colorChooser.setDetachable(false);
+			colorChooser.setOnHiding(e -> colorChooser = null);
+			colorChooser.setCornerRadius(5);
+			colorChooser.setArrowLocation(ArrowLocation.LEFT_CENTER);
+			colorChooser.show((Node) event.getSource());
 		}
 	}
 
+
 	private void setColorChooseButtonColor(Paint inputColor, Button button) {
-		Color color;
-		if (inputColor.equals(Color.BLACK))
-			color = Color.WHITE;
-		else
-			color = Color.BLACK;
-		((FontIcon) button.getGraphic()).setColor(color);
+		colorPreviewDefault.setFill(inputColor);
+		if (inputColor instanceof Color) {
+			((FontIcon) button.getGraphic()).setColor(ColorUtils.getAppropriateTextColor((Color) inputColor));
+		} else {
+			((FontIcon) button.getGraphic()).setColor(Color.BLACK);
+		}
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/GlobalSettingsViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/GlobalSettingsViewController.java
index e51f18c51524868bb65e3e0710293544686386d9..068ecda32cf6bd2f68391253facbedee24e5f5d1 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/GlobalSettingsViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/GlobalSettingsViewController.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.viewcontroller.option.global;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.threading.Worker;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
@@ -40,7 +41,7 @@ public class GlobalSettingsViewController extends NVC implements IGlobalSettings
 	private Runnable onFinish;
 
 	public GlobalSettingsViewController(Window owner, Runnable onFinish) {
-		load("view/option/global", "GlobalSettingsView", PlayPadMain.getUiResourceBundle());
+		load("view/option/global", "GlobalSettingsView", Localization.getBundle());
 		this.onFinish = onFinish;
 
 		NVCStage nvcStage = applyViewControllerToStage();
@@ -63,11 +64,11 @@ public class GlobalSettingsViewController extends NVC implements IGlobalSettings
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		stage.setMinWidth(715);
 		stage.setMinHeight(700);
-		stage.setTitle(Localization.getString(Strings.UI_Window_GlobalSettings_Title));
+		stage.setTitle(Localization.getString(Strings.UI_WINDOW_GLOBAL_SETTINGS_TITLE));
 
 		PlayPadPlugin.styleable().applyStyle(stage);
 	}
@@ -96,8 +97,8 @@ public class GlobalSettingsViewController extends NVC implements IGlobalSettings
 		try {
 			globalSettings.save();
 		} catch (Exception e) {
-			showErrorMessage(Localization.getString(Strings.Error_Profile_Save, e.getLocalizedMessage()));
-			e.printStackTrace();
+			showErrorMessage(Localization.getString(Strings.ERROR_PROFILE_SAVE, e.getLocalizedMessage()));
+			Logger.error(e);
 		}
 	}
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/KeysConflictDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/KeysConflictDialog.java
index c1f6da5aa69e599f8bb4dac4482c74f8adcfb6f8..5221ceadfc51985291926be6600f3078ef3a7f98 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/KeysConflictDialog.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/KeysConflictDialog.java
@@ -1,7 +1,7 @@
 package de.tobias.playpad.viewcontroller.option.global;
 
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
+import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.settings.keys.Key;
 import de.tobias.playpad.settings.keys.KeyCollection;
@@ -16,18 +16,18 @@ public class KeysConflictDialog extends Alert {
 	KeysConflictDialog(List<Key> conflicts, KeyCollection collection) {
 		super(AlertType.ERROR);
 
-		String keys = "";
+		StringBuilder keys = new StringBuilder();
 		for (int i = 0; i < conflicts.size(); i++) {
-			keys += "- " + collection.getName(conflicts.get(i).getId());
+			keys.append("- ").append(collection.getName(conflicts.get(i).getId()));
 			if (i + 1 < conflicts.size()) {
-				keys += "\n";
+				keys.append("\n");
 			}
 		}
-		setHeaderText(Localization.getString(Strings.UI_Settings_Keys_Conflict_Header));
-		setContentText(Localization.getString(Strings.UI_Settings_Keys_Conflict_Content, keys));
+		setHeaderText(Localization.getString(Strings.UI_SETTINGS_KEYS_CONFLICT_HEADER));
+		setContentText(Localization.getString(Strings.UI_SETTINGS_KEYS_CONFLICT_CONTENT, keys.toString()));
 
 		Stage dialogStage = (Stage) getDialogPane().getScene().getWindow();
-		PlayPadMain.stageIcon.ifPresent(dialogStage.getIcons()::add);
+		dialogStage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 		initModality(Modality.WINDOW_MODAL);
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/KeysTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/KeysTabViewController.java
index 18f7230d1c0598cd6b30ea4c3dd746f21d377cea..b1df342dac51b4875cbbd507a77ff3503fa2c340 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/KeysTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/KeysTabViewController.java
@@ -2,7 +2,6 @@ package de.tobias.playpad.viewcontroller.option.global;
 
 import de.thecodelabs.utils.util.Localization;
 import de.thecodelabs.utils.util.OS;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.settings.GlobalSettings;
@@ -50,7 +49,7 @@ public class KeysTabViewController extends GlobalSettingsTabViewController imple
 	private ObservableList<Key> keys = FXCollections.observableArrayList();
 
 	KeysTabViewController() {
-		load("view/option/global", "KeysTab", PlayPadMain.getUiResourceBundle());
+		load("view/option/global", "KeysTab", Localization.getBundle());
 	}
 
 	@Override
@@ -113,7 +112,7 @@ public class KeysTabViewController extends GlobalSettingsTabViewController imple
 
 	private void showNewKeyBindingDialog() {
 		Alert alert = new Alert(AlertType.NONE);
-		alert.setContentText(Localization.getString(Strings.UI_Settings_Alert_NewKeyShortcut_Text));
+		alert.setContentText(Localization.getString(Strings.UI_SETTINGS_ALERT_NEW_KEY_SHORTCUT_TEXT));
 		Scene scene = alert.getDialogPane().getScene();
 
 		scene.setOnKeyPressed(ev ->
@@ -138,7 +137,7 @@ public class KeysTabViewController extends GlobalSettingsTabViewController imple
 					keyCollection.editKey(newKey);
 
 					shortcutLabel.setText(currentKey.toString());
-					Platform.runLater(() -> ((Stage) scene.getWindow()).close());
+					Platform.runLater(((Stage) scene.getWindow())::close);
 				} else {
 					KeysConflictDialog dialog = new KeysConflictDialog(keyCollection.getConflicts(newKey), keyCollection);
 					dialog.initOwner(getContainingWindow());
@@ -151,7 +150,7 @@ public class KeysTabViewController extends GlobalSettingsTabViewController imple
 		alert.initOwner(getContainingWindow());
 		alert.initModality(Modality.WINDOW_MODAL);
 		Stage alertStage = (Stage) alert.getDialogPane().getScene().getWindow();
-		PlayPadMain.stageIcon.ifPresent(alertStage.getIcons()::add);
+		alertStage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 		alert.showAndWait();
 	}
 
@@ -163,7 +162,7 @@ public class KeysTabViewController extends GlobalSettingsTabViewController imple
 
 	@Override
 	public void saveSettings(GlobalSettings settings) {
-		// Passiert beim Drücken von Tasten automatisch
+		// Will be saved on key press automatically
 	}
 
 	@Override
@@ -183,7 +182,7 @@ public class KeysTabViewController extends GlobalSettingsTabViewController imple
 
 	@Override
 	public String name() {
-		return Localization.getString(Strings.UI_Window_Settings_Keys_Title);
+		return Localization.getString(Strings.UI_WINDOW_SETTINGS_KEYS_TITLE);
 	}
 
 	private void search() {
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/UpdateTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/UpdateTabViewController.java
index 316b5173a473597f0478b2d0b946f80f2e185315..f3ebf8e5c579a4bbd2e160dd23d71b373a445f9c 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/UpdateTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/UpdateTabViewController.java
@@ -8,7 +8,6 @@ import de.thecodelabs.utils.util.Localization;
 import de.thecodelabs.versionizer.model.Version;
 import de.thecodelabs.versionizer.service.UpdateService;
 import de.tobias.playpad.PlayPad;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.profile.Profile;
@@ -47,7 +46,7 @@ public class UpdateTabViewController extends GlobalSettingsTabViewController {
 	private Label placeholderLabel;
 
 	UpdateTabViewController() {
-		load("view/option/global", "UpdateTab", PlayPadMain.getUiResourceBundle());
+		load("view/option/global", "UpdateTab", Localization.getBundle());
 
 		final PlayPad playPad = PlayPadPlugin.getInstance();
 		GlobalSettings globalSettings = playPad.getGlobalSettings();
@@ -57,7 +56,7 @@ public class UpdateTabViewController extends GlobalSettingsTabViewController {
 		updateButton.setDisable(openUpdateList.getItems().isEmpty());
 
 		ApplicationInfo info = ApplicationUtils.getApplication().getInfo();
-		String currentVersionString = Localization.getString(Strings.UI_Window_Settings_Updates_CurrentVersion, info.getVersion(),
+		String currentVersionString = Localization.getString(Strings.UI_WINDOW_SETTINGS_UPDATES_CURRENT_VERSION, info.getVersion(),
 				info.getBuild());
 		currentVersionLabel.setText(currentVersionString);
 	}
@@ -66,8 +65,8 @@ public class UpdateTabViewController extends GlobalSettingsTabViewController {
 	public void init() {
 		openUpdateList.setCellFactory(list -> new UpdateCell());
 		updateChannelComboBox.getItems().setAll(UpdateService.RepositoryType.RELEASE, UpdateService.RepositoryType.SNAPSHOT);
-		updateChannelComboBox.setCellFactory(list -> new EnumCell<>(Strings.Update_Channel_BaseName));
-		updateChannelComboBox.setButtonCell(new EnumCell<>(Strings.Update_Channel_BaseName));
+		updateChannelComboBox.setCellFactory(list -> new EnumCell<>(Strings.UPDATE_CHANNEL));
+		updateChannelComboBox.setButtonCell(new EnumCell<>(Strings.UPDATE_CHANNEL));
 
 		updateChannelComboBox.valueProperty().addListener((a, b, c) ->
 		{
@@ -79,7 +78,7 @@ public class UpdateTabViewController extends GlobalSettingsTabViewController {
 		progressIndicator.setMinSize(75, 75);
 		progressIndicator.setMaxSize(75, 75);
 
-		placeholderLabel = new Label(Localization.getString(Strings.UI_Placeholder_Updates));
+		placeholderLabel = new Label(Localization.getString(Strings.UI_PLACEHOLDER_UPDATES));
 		openUpdateList.setPlaceholder(placeholderLabel);
 
 		updateButton.setDisable(openUpdateList.getItems().isEmpty());
@@ -128,7 +127,7 @@ public class UpdateTabViewController extends GlobalSettingsTabViewController {
 			try {
 				updateService.runVersionizerInstance(updateService.getAllLatestVersionEntries());
 			} catch (IOException e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 			System.exit(0);
 		});
@@ -157,6 +156,6 @@ public class UpdateTabViewController extends GlobalSettingsTabViewController {
 
 	@Override
 	public String name() {
-		return Localization.getString(Strings.UI_Window_Settings_Updates_Title);
+		return Localization.getString(Strings.UI_WINDOW_SETTINGS_UPDATES_TITLE);
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/DesignPadTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/DesignPadTabViewController.java
index f804da086ae219b45e3a1f3babc2ce66b5170622..9350b63841d763894290086376d135a3df8b02cf 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/DesignPadTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/DesignPadTabViewController.java
@@ -1,17 +1,13 @@
 package de.tobias.playpad.viewcontroller.option.pad;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.action.Mapping;
-import de.tobias.playpad.action.actions.cart.CartAction;
-import de.tobias.playpad.action.factory.CartActionProvider;
 import de.tobias.playpad.design.modern.model.ModernCartDesign;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadSettings;
 import de.tobias.playpad.profile.Profile;
-import de.tobias.playpad.registry.NoSuchComponentException;
 import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
 import de.tobias.playpad.viewcontroller.design.ModernCartDesignViewController;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
@@ -19,8 +15,6 @@ import javafx.fxml.FXML;
 import javafx.scene.control.CheckBox;
 import javafx.scene.layout.VBox;
 
-import java.util.List;
-
 public class DesignPadTabViewController extends PadSettingsTabViewController {
 
 	@FXML
@@ -28,12 +22,10 @@ public class DesignPadTabViewController extends PadSettingsTabViewController {
 	@FXML
 	private CheckBox enableLayoutCheckBox;
 
-	private ModernCartDesignViewController layoutViewController;
-
 	private Pad pad;
 
 	DesignPadTabViewController(Pad pad) {
-		load("view/option/pad", "LayoutTab", PlayPadMain.getUiResourceBundle());
+		load("view/option/pad", "LayoutTab", Localization.getBundle());
 		this.pad = pad;
 	}
 
@@ -51,8 +43,8 @@ public class DesignPadTabViewController extends PadSettingsTabViewController {
 
 					setLayoutViewController(pad);
 				} catch (Exception e) {
-					showErrorMessage(Localization.getString(Strings.Error_Standard_Gen, e.getLocalizedMessage()));
-					e.printStackTrace();
+					showErrorMessage(Localization.getString(Strings.ERROR_STANDARD_GEN, e.getLocalizedMessage()));
+					Logger.error(e);
 				}
 			} else if (!c && padSettings.isCustomDesign()) {
 				padSettings.setCustomDesign(false);
@@ -63,7 +55,7 @@ public class DesignPadTabViewController extends PadSettingsTabViewController {
 
 	@Override
 	public String getName() {
-		return Localization.getString(Strings.UI_Window_PadSettings_Layout_Title);
+		return Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_LAYOUT_TITLE);
 	}
 
 	@Override
@@ -84,8 +76,8 @@ public class DesignPadTabViewController extends PadSettingsTabViewController {
 				ModernCartDesignViewController controller = new ModernCartDesignViewController(design);
 				layoutContainer.getChildren().setAll(controller.getParent());
 			} catch (Exception e) {
-				e.printStackTrace();
-				showErrorMessage(Localization.getString(Strings.Error_Layout_Load, e.getMessage()));
+				Logger.error(e);
+				showErrorMessage(Localization.getString(Strings.ERROR_LAYOUT_LOAD, e.getMessage()));
 			}
 		} else {
 			layoutContainer.getChildren().clear();
@@ -97,16 +89,5 @@ public class DesignPadTabViewController extends PadSettingsTabViewController {
 		// CSS
 		IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController();
 		mainViewController.loadUserCss();
-
-		try {
-			// Mapping Auto Matched Colors
-			Mapping activeMapping = Profile.currentProfile().getMappings().getActiveMapping();
-			List<CartAction> actions = activeMapping.getActions(PlayPadPlugin.getRegistries().getActions().getFactory(CartActionProvider.class));
-			// Update die Mapper der CartAction
-			actions.stream().filter(action -> action.getPad() != null).filter(action -> action.getPad().getPosition() == pad.getPosition())
-					.forEach(item -> item.init(pad.getProject(), mainViewController));
-		} catch (NoSuchComponentException e) {
-			e.printStackTrace();
-		}
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/GeneralPadTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/GeneralPadTabViewController.java
index d63d52d4e0d5dd2c4ecaa5850e9e64211d7f0952..cd36d822fa42ae26dac33467de7f3b1434e23e7a 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/GeneralPadTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/GeneralPadTabViewController.java
@@ -1,7 +1,6 @@
 package de.tobias.playpad.viewcontroller.option.pad;
 
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadSettings;
@@ -35,7 +34,7 @@ public class GeneralPadTabViewController extends PadSettingsTabViewController {
 	private Pad pad;
 
 	GeneralPadTabViewController(Pad pad) {
-		load("view/option/pad", "GeneralTab", PlayPadMain.getUiResourceBundle());
+		load("view/option/pad", "GeneralTab", Localization.getBundle());
 		this.pad = pad;
 
 		if (pad.getStatus() == PadStatus.PLAY || pad.getStatus() == PadStatus.PAUSE) {
@@ -61,13 +60,13 @@ public class GeneralPadTabViewController extends PadSettingsTabViewController {
 
 		});
 		timeDisplayComboBox.getItems().addAll(TimeMode.values());
-		timeDisplayComboBox.setButtonCell(new EnumCell<>(Strings.Pad_TimeMode_BaseName));
-		timeDisplayComboBox.setCellFactory(list -> new EnumCell<>(Strings.Pad_TimeMode_BaseName));
+		timeDisplayComboBox.setButtonCell(new EnumCell<>(Strings.PAD_TIME_MODE));
+		timeDisplayComboBox.setCellFactory(list -> new EnumCell<>(Strings.PAD_TIME_MODE));
 	}
 
 	@Override
 	public String getName() {
-		return Localization.getString(Strings.UI_Window_PadSettings_General_Title);
+		return Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_GENERAL_TITLE);
 	}
 
 	@Override
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PadSettingsViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PadSettingsViewController.java
index 450cad37df3e754bf236652568246533cc935a54..739b65fd2c8591af25fbf2d4eb134ffd7b92332b 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PadSettingsViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PadSettingsViewController.java
@@ -1,9 +1,9 @@
 package de.tobias.playpad.viewcontroller.option.pad;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.pad.Pad;
@@ -40,7 +40,7 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo
 	private Button finishButton;
 
 	public PadSettingsViewController(Pad pad, Window owner) {
-		load("view/option/pad", "PadSettingsView", PlayPadMain.getUiResourceBundle());
+		load("view/option/pad", "PadSettingsView", Localization.getBundle());
 		this.pad = pad;
 
 		addTab(new GeneralPadTabViewController(pad));
@@ -60,7 +60,7 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo
 				if (contentTab != null)
 					addTab(contentTab);
 			} catch (NoSuchComponentException e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		}
 
@@ -82,7 +82,7 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo
 		if (pad.getContent() != null) {
 			final ObservableList<MediaPath> paths = pad.getPaths();
 			if (paths.size() == 1) {
-				Button button = new Button(PlayPadMain.getUiResourceBundle().getString("padSettings.button.path"));
+				Button button = new Button(Localization.getString("padSettings.button.path"));
 
 				MediaPath path = paths.get(0);
 				button.setUserData(path);
@@ -90,7 +90,7 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo
 
 				pathLookupButton = button;
 			} else if (paths.size() > 1) {
-				MenuButton button = new MenuButton(PlayPadMain.getUiResourceBundle().getString("padSettings.button.path"));
+				MenuButton button = new MenuButton(Localization.getString("padSettings.button.path"));
 
 				for (MediaPath path : paths) {
 					MenuItem item = new MenuItem(path.getFileName());
@@ -117,9 +117,9 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo
 	private void setTitle(Pad pad) {
 		String title;
 		if (pad.getStatus() != PadStatus.EMPTY) {
-			title = Localization.getString(Strings.UI_Window_PadSettings_Title, pad.getPositionReadable(), pad.getName());
+			title = Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_TITLE, pad.getPositionReadable(), pad.getName());
 		} else {
-			title = Localization.getString(Strings.UI_Window_PadSettings_Title_Empty, pad.getPositionReadable());
+			title = Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_TITLE_EMPTY, pad.getPositionReadable());
 		}
 		getStageContainer().ifPresent(nvcStage -> nvcStage.getStage().setTitle(title));
 	}
@@ -131,7 +131,7 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		stage.setMinWidth(650);
 		stage.setMinHeight(550);
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java
index 4187959020784d8bb37dcb6a516a6154ff13f87d..67d71214c4bd6b72e4eab97da3d926de39f302d5 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java
@@ -1,16 +1,17 @@
 package de.tobias.playpad.viewcontroller.option.pad;
 
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadSettings;
 import de.tobias.playpad.settings.Fade;
+import de.tobias.playpad.view.PseudoClasses;
 import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
 import de.tobias.playpad.viewcontroller.settings.FadeViewController;
 import de.tobias.playpad.viewcontroller.settings.WarningFeedbackViewController;
 import javafx.fxml.FXML;
 import javafx.scene.control.CheckBox;
+import javafx.scene.control.TextField;
 import javafx.scene.layout.VBox;
 import javafx.util.Duration;
 
@@ -28,10 +29,13 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController {
 	private CheckBox warningEnableCheckBox;
 	private WarningFeedbackViewController warningFeedbackViewController;
 
+	@FXML
+	private TextField cueInTextField;
+
 	private Pad pad;
 
 	PlayerPadTabViewController(Pad pad) {
-		load("view/option/pad", "PlayerTab", PlayPadMain.getUiResourceBundle());
+		load("view/option/pad", "PlayerTab", Localization.getBundle());
 		this.pad = pad;
 	}
 
@@ -41,7 +45,7 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController {
 		fadeViewController = new FadeViewController();
 		fadeContainer.getChildren().add(fadeViewController.getParent());
 
-		warningFeedbackViewController = new WarningFeedbackViewController(null);
+		warningFeedbackViewController = WarningFeedbackViewController.newViewControllerForPad();
 		warningFeedbackContainer.getChildren().add(warningFeedbackViewController.getParent());
 
 		customFadeCheckBox.selectedProperty().addListener((a, b, c) ->
@@ -71,11 +75,28 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController {
 			if (c)
 				warningFeedbackViewController.setPadWarning(pad);
 		});
+
+		cueInTextField.textProperty().addListener((observable, oldValue, newValue) -> {
+			PadSettings padSettings = pad.getPadSettings();
+			if (newValue.isEmpty()) {
+				padSettings.setCueIn(null);
+				cueInTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, false);
+			} else {
+				try {
+					final double seconds = Double.parseDouble(newValue);
+					padSettings.setCueIn(Duration.seconds(seconds));
+
+					cueInTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, false);
+				} catch (NumberFormatException e) {
+					cueInTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, true);
+				}
+			}
+		});
 	}
 
 	@Override
 	public String getName() {
-		return Localization.getString(Strings.UI_Window_PadSettings_Player_Title);
+		return Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_PLAYER_TITLE);
 	}
 
 	@Override
@@ -94,6 +115,11 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController {
 		if (!padSettings.isCustomWarning()) {
 			warningFeedbackContainer.setDisable(true);
 		}
+
+		final Duration cueIn = padSettings.getCueIn();
+		if (cueIn != null) {
+			cueInTextField.setText(String.valueOf(cueIn.toSeconds()));
+		}
 	}
 
 	@Override
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/TriggerPadTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/TriggerPadTabViewController.java
index 6043b5b267807e13945691be174b7e6cfdb01705..33fd3432634f564d5718ba8fc85d4fc4725a42b7 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/TriggerPadTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/TriggerPadTabViewController.java
@@ -1,7 +1,6 @@
 package de.tobias.playpad.viewcontroller.option.pad;
 
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.tigger.Trigger;
@@ -18,7 +17,7 @@ import javafx.scene.control.TreeView;
 import javafx.scene.layout.Priority;
 import javafx.scene.layout.VBox;
 
-import java.util.HashMap;
+import java.util.Map;
 
 public class TriggerPadTabViewController extends PadSettingsTabViewController implements ChangeListener<TreeItem<TriggerDisplayable>> {
 
@@ -30,7 +29,7 @@ public class TriggerPadTabViewController extends PadSettingsTabViewController im
 	private Pad pad;
 
 	TriggerPadTabViewController(Pad pad) {
-		load("view/option/pad", "TriggerTab", PlayPadMain.getUiResourceBundle());
+		load("view/option/pad", "TriggerTab", Localization.getBundle());
 		this.pad = pad;
 	}
 
@@ -41,10 +40,10 @@ public class TriggerPadTabViewController extends PadSettingsTabViewController im
 	}
 
 	private void createTreeView() {
-		HashMap<TriggerPoint, Trigger> triggers = pad.getPadSettings().getTriggers();
+		Map<TriggerPoint, Trigger> triggers = pad.getPadSettings().getTriggers();
 		TreeItem<TriggerDisplayable> rootItem = new TreeItem<>();
 
-		// Sort the tpyes for the treeview
+		// Sort the types for the tree view
 		for (TriggerPoint point : TriggerPoint.values()) {
 			Trigger trigger = triggers.get(point);
 
@@ -70,7 +69,7 @@ public class TriggerPadTabViewController extends PadSettingsTabViewController im
 
 	@Override
 	public String getName() {
-		return Localization.getString(Strings.UI_Window_PadSettings_Trigger_Title);
+		return Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_TRIGGER_TITLE);
 	}
 
 	@Override
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/CartTriggerViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/CartTriggerViewController.java
index e76cf12e9eae01f0546dcde43cddd6df9da4d18b..a5d2f0ea9780c898b90e1ebd98efff2c60d19653 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/CartTriggerViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/CartTriggerViewController.java
@@ -1,6 +1,7 @@
 package de.tobias.playpad.viewcontroller.option.pad.trigger;
 
 import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadStatus;
@@ -29,7 +30,7 @@ public class CartTriggerViewController extends NVC {
 	private CartTriggerItem item;
 
 	public CartTriggerViewController(CartTriggerItem item) {
-		load("view/option/pad/trigger", "CartTrigger", PlayPadMain.getUiResourceBundle());
+		load("view/option/pad/trigger", "CartTrigger", Localization.getBundle());
 		this.item = item;
 
 		Project project = PlayPadMain.getProgramInstance().getCurrentProject();
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/TriggerPointViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/TriggerPointViewController.java
index 0ff09c25560fb8fa477cd36a06c8e83aeacad7fd..77d5166b7191a5da2d5f2565bd1221da47e830b4 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/TriggerPointViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/TriggerPointViewController.java
@@ -1,9 +1,10 @@
 package de.tobias.playpad.viewcontroller.option.pad.trigger;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
-import de.tobias.playpad.PlayPadMain;
+import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.registry.NoSuchComponentException;
 import de.tobias.playpad.tigger.TriggerItem;
@@ -28,7 +29,7 @@ public class TriggerPointViewController extends NVC {
 	private TriggerDisplayable triggerWrapper;
 
 	public TriggerPointViewController(TriggerDisplayable triggerWrapper) {
-		load("view/option/pad/trigger", "TriggerPoint", PlayPadMain.getUiResourceBundle());
+		load("view/option/pad/trigger", "TriggerPoint", Localization.getBundle());
 		this.triggerWrapper = triggerWrapper;
 
 		for (TriggerItem item : triggerWrapper.getTrigger().getItems())
@@ -55,8 +56,7 @@ public class TriggerPointViewController extends NVC {
 				});
 				buttonBox.getChildren().add(button);
 			} catch (NoSuchComponentException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		});
 	}
@@ -81,15 +81,14 @@ public class TriggerPointViewController extends NVC {
 
 				itemView.getChildren().addAll(rootBox);
 
-				deleteButton.setOnAction((e) ->
+				deleteButton.setOnAction(event ->
 				{
 					triggerWrapper.removeItem(item);
 					itemView.getChildren().removeAll(rootBox);
 				});
 			}
 		} catch (NoSuchComponentException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/TriggerTimeViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/TriggerTimeViewController.java
index fe6db699115ca5f694fb814fd2e75e183c5b0e1f..f97fdfbca7b2345527be69c2c5933320262ebe57 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/TriggerTimeViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/TriggerTimeViewController.java
@@ -1,8 +1,8 @@
 package de.tobias.playpad.viewcontroller.option.pad.trigger;
 
 import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.util.Localization;
 import de.thecodelabs.utils.util.TimeUtils;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.tigger.TriggerItem;
 import de.tobias.playpad.view.PseudoClasses;
 import javafx.fxml.FXML;
@@ -19,7 +19,7 @@ public class TriggerTimeViewController extends NVC {
 	private TriggerItem item;
 
 	TriggerTimeViewController(TriggerItem item) {
-		load("view/option/pad/trigger", "TriggerTime", PlayPadMain.getUiResourceBundle());
+		load("view/option/pad/trigger", "TriggerTime", Localization.getBundle());
 		this.item = item;
 
 		timeTextField.setText(String.valueOf(item.getDurationFromPoint().toSeconds()));
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/VolumeTriggerViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/VolumeTriggerViewController.java
index b3be0fd7839f629086754d288c173d4cd703e8f0..10a1a70dfb79ad38c6eedcacaa450384a65cdef9 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/VolumeTriggerViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/VolumeTriggerViewController.java
@@ -35,7 +35,7 @@ public class VolumeTriggerViewController extends NVC {
 	private VolumeTriggerItem item;
 
 	public VolumeTriggerViewController(VolumeTriggerItem item) {
-		load("view/option/pad/trigger", "VolumeTrigger", PlayPadMain.getUiResourceBundle());
+		load("view/option/pad/trigger", "VolumeTrigger", Localization.getBundle());
 		this.item = item;
 
 		volumeSlider.setValue(item.getVolume() * 100.0);
@@ -61,7 +61,7 @@ public class VolumeTriggerViewController extends NVC {
 		volumeSlider.valueProperty().addListener((a, b, c) ->
 		{
 			item.setVolume(c.doubleValue() / 100.0);
-			volumeLabel.setText(Localization.getString(Strings.Standard_Time_Volume, Math.round(c.doubleValue())));
+			volumeLabel.setText(Localization.getString(Strings.STANDARD_TIME_VOLUME, Math.round(c.doubleValue())));
 		});
 
 		durationSlider.valueProperty().addListener((a, b, c) ->
@@ -69,7 +69,7 @@ public class VolumeTriggerViewController extends NVC {
 			item.setDuration(Duration.seconds(c.doubleValue()));
 
 			double seconds = Math.round(item.getDuration().toSeconds() * 10.0) / 10.0;
-			durationLabel.setText(Localization.getString(Strings.Standard_Time_Seconds, seconds));
+			durationLabel.setText(Localization.getString(Strings.STANDARD_TIME_SECONDS, seconds));
 		});
 
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/AudioTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/AudioTabViewController.java
index d6c8b31dae9c96d3558380d58513eeb0dd27f9dd..429067a69cd27a40b405171fe73688a919b9a9ac 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/AudioTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/AudioTabViewController.java
@@ -3,7 +3,6 @@ package de.tobias.playpad.viewcontroller.option.profile;
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.audio.AudioCapability;
@@ -44,7 +43,7 @@ public class AudioTabViewController extends ProfileSettingsTabViewController imp
 	private boolean changeAudioSettings;
 
 	public AudioTabViewController(boolean playerActive) {
-		load("view/option/profile", "AudioTab", PlayPadMain.getUiResourceBundle());
+		load("view/option/profile", "AudioTab", Localization.getBundle());
 
 		if (playerActive) {
 			audioTypeComboBox.setDisable(true);
@@ -178,6 +177,6 @@ public class AudioTabViewController extends ProfileSettingsTabViewController imp
 
 	@Override
 	public String name() {
-		return Localization.getString(Strings.UI_Window_Settings_Audio_Title);
+		return Localization.getString(Strings.UI_WINDOW_SETTINGS_AUDIO_TITLE);
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/DesignTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/DesignTabViewController.java
index 35f56e16cb724ef4b79fcee4ac0c43b04160b8db..bb44a97dd1ae100602091e9bb9cfd2669ed12a16 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/DesignTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/DesignTabViewController.java
@@ -1,7 +1,6 @@
 package de.tobias.playpad.viewcontroller.option.profile;
 
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.design.modern.model.ModernGlobalDesign;
 import de.tobias.playpad.profile.Profile;
@@ -21,7 +20,7 @@ public class DesignTabViewController extends ProfileSettingsTabViewController im
 	private VBox layoutContainer;
 
 	DesignTabViewController() {
-		load("view/option/profile", "LayoutTab", PlayPadMain.getUiResourceBundle());
+		load("view/option/profile", "LayoutTab", Localization.getBundle());
 
 		ModernGlobalDesign design = Profile.currentProfile().getProfileSettings().getDesign();
 		ModernGlobalDesignViewController globalLayoutViewController = new ModernGlobalDesignViewController(design);
@@ -57,6 +56,6 @@ public class DesignTabViewController extends ProfileSettingsTabViewController im
 
 	@Override
 	public String name() {
-		return Localization.getString(Strings.UI_Window_Settings_Layout_Title);
+		return Localization.getString(Strings.UI_WINDOW_SETTINGS_LAYOUT_TITLE);
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/GeneralTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/GeneralTabViewController.java
index b73529945c802ae9bb6b33730c32e9f20f1fe4a0..a1b33fa0d76fac292444eab77e09739446228f65 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/GeneralTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/GeneralTabViewController.java
@@ -1,11 +1,11 @@
 package de.tobias.playpad.viewcontroller.option.profile;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
 import de.thecodelabs.utils.ui.Alertable;
 import de.thecodelabs.utils.util.Localization;
 import de.thecodelabs.utils.util.NumberUtils;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.settings.GlobalSettings;
@@ -52,12 +52,10 @@ public class GeneralTabViewController extends GlobalSettingsTabViewController {
 	@FXML
 	private RadioButton settingsDisable;
 
-	private boolean changeSettings;
-
 	private Alertable alertable;
 
 	public GeneralTabViewController(Alertable alertable) {
-		load("view/option/global", "GeneralTab", PlayPadMain.getUiResourceBundle());
+		load("view/option/global", "GeneralTab", Localization.getBundle());
 		this.alertable = alertable;
 
 		calcCacheSize();
@@ -74,10 +72,7 @@ public class GeneralTabViewController extends GlobalSettingsTabViewController {
 		ToggleGroup settingsGroup = new ToggleGroup();
 		settingsGroup.getToggles().addAll(settingsEnable, settingsDisable);
 
-		liveModeCheckBox.selectedProperty().addListener((a, b, c) ->
-		{
-			disableLiveSettings(c);
-		});
+		liveModeCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> disableLiveSettings(newValue));
 	}
 
 	private void disableLiveSettings(Boolean enableLiveSettings) {
@@ -105,49 +100,43 @@ public class GeneralTabViewController extends GlobalSettingsTabViewController {
 
 	@FXML
 	private void cacheResetButtonHandler(ActionEvent event) {
-		try {
+		try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(ApplicationUtils.getApplication().getPath(PathType.CACHE))) {
 			int deleteFiles = 0;
-			for (Path path : Files.newDirectoryStream(ApplicationUtils.getApplication().getPath(PathType.CACHE))) {
+			for (Path path : directoryStream) {
 				if (Files.isRegularFile(path)) {
-					try {
-						Files.delete(path);
-						deleteFiles++;
-					} catch (Exception e) {
-						e.printStackTrace();
-					}
+					Files.delete(path);
+					deleteFiles++;
 				}
 			}
-			alertable.showInfoMessage(Localization.getString(Strings.Info_Settings_CacheDelete, deleteFiles));
+			alertable.showInfoMessage(Localization.getString(Strings.INFO_SETTINGS_CACHE_DELETE, deleteFiles));
 
 			calcCacheSize();
 		} catch (IOException e) {
-			e.printStackTrace();
-			showErrorMessage(Localization.getString(Strings.Error_Settings_CacheClear, e.getLocalizedMessage()));
+			Logger.error(e);
+			showErrorMessage(Localization.getString(Strings.ERROR_SETTINGS_CACHE_CLEAR, e.getLocalizedMessage()));
 		}
 	}
 
 	@FXML
 	private void resetDialogs(ActionEvent event) {
-		alertable.showInfoMessage(Localization.getString(Strings.Info_Settings_ResetWarning));
+		alertable.showInfoMessage(Localization.getString(Strings.INFO_SETTINGS_RESET_WARNING));
 	}
 
 	private void calcCacheSize() {
-		try {
+		GlobalSettings globalSettings = PlayPadPlugin.getInstance().getGlobalSettings();
+		try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(globalSettings.getCachePath())) {
 			double size = 0;
-			GlobalSettings globalSettings = PlayPadPlugin.getInstance().getGlobalSettings();
 			Path path = globalSettings.getCachePath();
 			if (Files.notExists(path))
 				Files.createDirectories(path);
 
-			DirectoryStream<Path> directoryStream = Files.newDirectoryStream(globalSettings.getCachePath());
 			for (Path item : directoryStream) {
 				size += Files.size(item);
 			}
-			directoryStream.close();
-			cacheSizeLabel.setText(Localization.getString(Strings.UI_Window_Settings_Gen_CacheSize, NumberUtils.convertBytesToAppropriateFormat(size)));
+			cacheSizeLabel.setText(Localization.getString(Strings.UI_WINDOW_SETTINGS_GEN_CACHE_SIZE, NumberUtils.convertBytesToAppropriateFormat(size)));
 		} catch (IOException e) {
-			e.printStackTrace();
-			alertable.showErrorMessage(Localization.getString(Strings.Error_Settings_CacheSize, e.getMessage()));
+			Logger.error(e);
+			alertable.showErrorMessage(Localization.getString(Strings.ERROR_SETTINGS_CACHE_SIZE, e.getMessage()));
 		}
 	}
 
@@ -196,7 +185,7 @@ public class GeneralTabViewController extends GlobalSettingsTabViewController {
 
 	@Override
 	public boolean needReload() {
-		return changeSettings;
+		return false;
 	}
 
 	@Override
@@ -206,6 +195,6 @@ public class GeneralTabViewController extends GlobalSettingsTabViewController {
 
 	@Override
 	public String name() {
-		return Localization.getString(Strings.UI_Window_Settings_Gen_Title);
+		return Localization.getString(Strings.UI_WINDOW_SETTINGS_GEN_TITLE);
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/MappingTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/MappingTabViewController.java
index 269b07d6bf745096c6ec4cce8adc3fda43cbfd90..a184e370feeb0fb15feec5d6325aba4e58fba057 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/MappingTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/MappingTabViewController.java
@@ -1,21 +1,34 @@
 package de.tobias.playpad.viewcontroller.option.profile;
 
+import de.thecodelabs.logger.Logger;
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.MappingCollection;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.device.MidiDeviceInfo;
+import de.thecodelabs.midi.midi.Midi;
+import de.thecodelabs.midi.serialize.MappingSerializer;
 import de.thecodelabs.utils.threading.Worker;
+import de.thecodelabs.utils.ui.Alerts;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.action.*;
-import de.tobias.playpad.midi.Midi;
+import de.tobias.playpad.action.ActionProvider;
+import de.tobias.playpad.action.ActionType;
+import de.tobias.playpad.action.feedback.ColorAdjuster;
+import de.tobias.playpad.action.feedback.LightMode;
+import de.tobias.playpad.action.settings.ActionSettingsEntry;
+import de.tobias.playpad.action.settings.ActionSettingsMappable;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.profile.ProfileSettings;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.registry.Component;
 import de.tobias.playpad.viewcontroller.BaseMapperListViewController;
 import de.tobias.playpad.viewcontroller.IMappingTabViewController;
-import de.tobias.playpad.viewcontroller.cell.DisplayableCell;
 import de.tobias.playpad.viewcontroller.cell.DisplayableTreeCell;
+import de.tobias.playpad.viewcontroller.cell.EnumCell;
+import de.tobias.playpad.viewcontroller.cell.MappingListCell;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import de.tobias.playpad.viewcontroller.option.IProfileReloadTask;
 import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController;
@@ -27,7 +40,6 @@ import javafx.scene.layout.VBox;
 import javafx.stage.FileChooser;
 import javafx.stage.Modality;
 
-import javax.sound.midi.MidiDevice;
 import javax.sound.midi.MidiUnavailableException;
 import java.io.File;
 import java.io.IOException;
@@ -64,77 +76,82 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 	@FXML
 	private ComboBox<String> deviceComboBox;
 
+	@FXML
+	private ComboBox<LightMode> lightModeComboBox;
+
 	// Main View
 	@FXML
-	private TreeView<ActionDisplayable> treeView;
+	private TreeView<ActionSettingsEntry> treeView;
 
 	@FXML
 	private VBox detailView;
 	private BaseMapperListViewController mapperListViewController;
 
-	private Mapping oldMapping;
-	private Mapping mapping;
-
 	MappingTabViewController() {
-		load("view/option/profile", "Mapping", PlayPadMain.getUiResourceBundle());
+		load("view/option/profile", "Mapping", Localization.getBundle());
 	}
 
 	@Override
 	public void init() {
-		mappingComboBox.setCellFactory(list -> new DisplayableCell<>());
-		mappingComboBox.setButtonCell(new DisplayableCell<>());
+		mappingComboBox.setCellFactory(list -> new MappingListCell());
+		mappingComboBox.setButtonCell(new MappingListCell());
 
 		mappingComboBox.getSelectionModel().selectedItemProperty().addListener((a, b, c) ->
 		{
-			mapping = c;
 			Profile.currentProfile().getMappings().setActiveMapping(c);
+			Mapping.setCurrentMapping(c);
+
+			Midi.getInstance().clearFeedback();
+			Midi.getInstance().showFeedback();
+
 			createTreeViewContent();
 		});
 
 		// Midi
-		MidiDevice.Info[] data = Midi.getMidiDevices();
+		MidiDeviceInfo[] data = Midi.getInstance().getMidiDevices();
 		// Gerät anzeigen - Doppelte weg
-		for (MidiDevice.Info item : data) {
-			if (item != null) {
-				if (!deviceComboBox.getItems().contains(item.getName())) {
-					deviceComboBox.getItems().add(item.getName());
-
-					// aktives Gerät wählen
-					if (item.getName().equals(Profile.currentProfile().getProfileSettings().getMidiDevice())) {
-						deviceComboBox.getSelectionModel().select(item.getName());
-					}
+		for (MidiDeviceInfo item : data) {
+			if (item != null && !deviceComboBox.getItems().contains(item.getName())) {
+				deviceComboBox.getItems().add(item.getName());
+
+				// aktives Gerät wählen
+				if (item.getName().equals(Profile.currentProfile().getProfileSettings().getMidiDevice())) {
+					deviceComboBox.getSelectionModel().select(item.getName());
 				}
 			}
 		}
 		midiActiveCheckBox.selectedProperty().addListener((a, b, c) -> deviceComboBox.setDisable(!c));
 
 		// Main View
-		treeView.getSelectionModel().selectedItemProperty().addListener((a, b, c) ->
+		treeView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) ->
 		{
 			detailView.getChildren().clear();
+			Mapping mapping = mappingComboBox.getSelectionModel().getSelectedItem();
+
+			if (newValue != null) {
+				NVC controller = newValue.getValue().getDetailSettingsController(mapping, this);
 
-			if (c != null) {
-				NVC controller = c.getValue().getSettingsViewController();
-				if (controller == null) {
-					controller = c.getValue().getActionSettingsViewController(mapping, this);
-				}
 				if (controller != null) {
 					detailView.getChildren().add(controller.getParent());
 				}
-				if (c.getValue() instanceof Action) {
-					showMapperFor((Action) c.getValue());
+				if (newValue.getValue() instanceof ActionSettingsMappable) {
+					showMapperFor(((ActionSettingsMappable) newValue.getValue()).getAction());
 				}
 			}
 		});
 		treeView.setCellFactory(list -> new DisplayableTreeCell<>());
+
+		lightModeComboBox.getItems().setAll(LightMode.values());
+		lightModeComboBox.setCellFactory(list -> new EnumCell<>("LightMode."));
+		lightModeComboBox.setButtonCell(new EnumCell<>("LightMode."));
 	}
 
-	private TreeItem<ActionDisplayable> createTreeView(Mapping mapping) {
-		TreeItem<ActionDisplayable> rootItem = new TreeItem<>();
+	private TreeItem<ActionSettingsEntry> createTreeView(Mapping mapping) {
+		TreeItem<ActionSettingsEntry> rootItem = new TreeItem<>();
 		Collection<ActionProvider> types = PlayPadPlugin.getRegistries().getActions().getComponents();
 		List<ActionProvider> sortedTypes = types.stream().sorted(Comparator.comparing(Component::getType)).collect(Collectors.toList());
 
-		// Sort the tpyes for the treeview
+		// Sort the types for the tree view
 		for (ActionType actionType : ActionType.values()) {
 			createTreeViewForActionType(mapping, rootItem, sortedTypes, actionType);
 		}
@@ -142,26 +159,25 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 		return rootItem;
 	}
 
-	private void createTreeViewForActionType(Mapping mapping, TreeItem<ActionDisplayable> rootItem, List<ActionProvider> sortedTypes, ActionType type) {
-		for (ActionProvider actionFactory : sortedTypes) {
-			List<Action> actions = mapping.getActionsOfType(actionFactory);
-			if (actionFactory.geActionType() == type) {
-				TreeItem<ActionDisplayable> item = actionFactory.getTreeViewForActions(actions, mapping);
+	private void createTreeViewForActionType(Mapping mapping, TreeItem<ActionSettingsEntry> rootItem, List<ActionProvider> sortedTypes, ActionType type) {
+		for (ActionProvider provider : sortedTypes) {
+			List<Action> actions = mapping.getActionsForType(provider.getType());
+			if (provider.getActionType() == type) {
+				TreeItem<ActionSettingsEntry> item = provider.getTreeItemForActions(actions, mapping);
 				rootItem.getChildren().add(item);
 			}
 		}
 	}
 
 	private void createTreeViewContent() {
-		TreeItem<ActionDisplayable> rootItem = createTreeView(mapping);
+		Mapping mapping = Mapping.getCurrentMapping();
+		TreeItem<ActionSettingsEntry> rootItem = createTreeView(mapping);
 		treeView.setRoot(rootItem);
 	}
 
 	private void setMappingItemsToList() {
-		mappingComboBox.getItems().setAll(Profile.currentProfile().getMappings());
-		mappingComboBox.setValue(Profile.currentProfile().getMappings().getActiveMapping());
-
-		mapping = mappingComboBox.getValue();
+		mappingComboBox.getItems().setAll(Profile.currentProfile().getMappings().getMappings());
+		Profile.currentProfile().getMappings().getActiveMapping().ifPresent(m -> mappingComboBox.setValue(m));
 	}
 
 	@Override
@@ -170,11 +186,15 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 			if (action != null) {
 				mapperListViewController = BaseMapperListViewController.getInstance();
 				mapperListViewController.showAction(action, detailView);
+
+				// highlight current button on device
+				Midi.getInstance().clearFeedback();
+				Midi.getInstance().showFeedback(action);
 			} else {
 				detailView.getChildren().remove(mapperListViewController.getParent());
 			}
 		} catch (Exception e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 
@@ -185,37 +205,38 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 	// Event Handler
 	@FXML
 	private void deviceHandler(ActionEvent event) {
-		ProfileSettings profilSettings = Profile.currentProfile().getProfileSettings();
+		ProfileSettings profileSettings = Profile.currentProfile().getProfileSettings();
 		String device = deviceComboBox.getValue();
 
 		// Ändern und Speichern
-		if (device != null) {
-			if (isMidiActive()) {
-				Midi midi = Midi.getInstance();
-				if (!device.equals(profilSettings.getMidiDevice()) || !midi.isOpen()) {
-					try {
-						// Setup
-						midi.lookupMidiDevice(device);
-						profilSettings.setMidiDeviceName(device);
+		if (device != null && isMidiActive()) {
+			Midi midi = Midi.getInstance();
+			if (!device.equals(profileSettings.getMidiDevice()) || !midi.isOpen()) {
+				try {
+					// Setup
+					final MidiDeviceInfo midiDeviceInfo = midi.getMidiDeviceInfo(device);
+					midi.openDevice(midiDeviceInfo);
 
-						// UI Rückmeldung
-						if (midi.getInputDevice() != null) {
-							showInfoMessage(Localization.getString(Strings.Info_Midi_Device_Connected, device));
-						}
-					} catch (NullPointerException e) {
-						showErrorMessage(Localization.getString(Strings.Error_Midi_Device_Unavailible, device));
-						e.printStackTrace();
-					} catch (IllegalArgumentException | MidiUnavailableException e) {
-						showErrorMessage(Localization.getString(Strings.Error_Midi_Device_Busy, e.getLocalizedMessage()));
-						e.printStackTrace();
+					// UI Rückmeldung
+					if (midi.isOpen()) {
+						profileSettings.setMidiDeviceName(device);
 					}
+				} catch (NullPointerException e) {
+					showErrorMessage(Localization.getString(Strings.ERROR_MIDI_DEVICE_UNAVAILABLE, device));
+					Logger.error(e);
+				} catch (IllegalArgumentException | MidiUnavailableException e) {
+					showErrorMessage(Localization.getString(Strings.ERROR_MIDI_DEVICE_BUSY, e.getLocalizedMessage()));
+					Logger.error(e);
 				}
 			}
 		}
 	}
 
+	@SuppressWarnings("Duplicates")
 	@FXML
 	private void mappingRenameHandler(ActionEvent event) {
+		Mapping mapping = mappingComboBox.getSelectionModel().getSelectedItem();
+
 		TextInputDialog dialog = new TextInputDialog(mapping.getName());
 		dialog.initModality(Modality.WINDOW_MODAL);
 		dialog.initOwner(getContainingWindow());
@@ -227,10 +248,11 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 
 	@FXML
 	private void mappingExportHandler(ActionEvent event) {
+		Mapping mapping = mappingComboBox.getSelectionModel().getSelectedItem();
 		if (mapping != null) {
 			FileChooser chooser = new FileChooser();
 
-			FileChooser.ExtensionFilter filter = new FileChooser.ExtensionFilter(Localization.getString(Strings.File_Filter_Preset), PlayPadMain.midiPresetType);
+			FileChooser.ExtensionFilter filter = new FileChooser.ExtensionFilter(Localization.getString(Strings.FILE_FILTER_PRESET), PlayPadMain.PRESET_TYPE);
 			chooser.getExtensionFilters().add(filter);
 
 			File file = chooser.showSaveDialog(getContainingWindow());
@@ -240,10 +262,10 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 				Worker.runLater(() ->
 				{
 					try {
-						MappingList.exportMidiPreset(path, mapping);
+						MappingSerializer.save(mapping, path);
 					} catch (IOException e) {
-						e.printStackTrace();
-						showErrorMessage(Localization.getString(Strings.Error_Preset_Export, e.getLocalizedMessage()));
+						Logger.error(e);
+						showErrorMessage(Localization.getString(Strings.ERROR_PRESET_EXPORT, e.getLocalizedMessage()));
 					}
 				});
 			}
@@ -252,18 +274,30 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 
 	@FXML
 	private void mappingDeleteHandler(ActionEvent event) {
-		final MappingList mappings = Profile.currentProfile().getMappings();
-		int preset = mappingComboBox.getSelectionModel().getSelectedIndex();
+		final MappingCollection mappings = Profile.currentProfile().getMappings();
+		Mapping preset = mappingComboBox.getSelectionModel().getSelectedItem();
+
+		if (mappings.getMappings().size() <= 1) {
+			Alerts.getInstance()
+					.createAlert(
+							Alert.AlertType.INFORMATION,
+							"Mapping",
+							"Das Mapping kann nicht gelöscht werden, da kein anders existiert.",
+							getContainingWindow()
+					).show();
+			return;
+		}
 
 		Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
-		alert.setContentText("Soll das Mapping Profile " + mappings.get(preset) + " wirklich gelöscht werden?");
+		// TODO Localize
+		alert.setContentText("Soll das Mapping Profile " + preset.getName() + " wirklich gelöscht werden?");
 		alert.initModality(Modality.WINDOW_MODAL);
 		alert.initOwner(getContainingWindow());
 		alert.showAndWait().filter(b -> b == ButtonType.OK).ifPresent(result -> {
-			mappings.remove(preset);
+			mappings.removeMapping(preset);
 			mappingComboBox.getItems().remove(preset);
 
-			if (mappings.size() == 1) {
+			if (mappings.count() == 1) {
 				mappingDeleteButton.setDisable(true);
 			}
 		});
@@ -271,46 +305,45 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 
 	@FXML
 	private void mappingDuplicateHandler(ActionEvent event) {
-		try {
-			Mapping clonedMapping = mapping.clone();
-			clonedMapping.setName(Localization.getString(Strings.Standard_Copy, clonedMapping.getName()));
-
-			// Model
-			Profile.currentProfile().getMappings().add(clonedMapping);
-			// UI
-			mappingComboBox.getItems().add(clonedMapping);
-			mappingComboBox.getSelectionModel().select(clonedMapping);
-		} catch (CloneNotSupportedException e) {
-			e.printStackTrace();
-		}
+		Mapping mapping = mappingComboBox.getSelectionModel().getSelectedItem();
+
+		Mapping clonedMapping = new Mapping(mapping);
+		clonedMapping.setName(Localization.getString(Strings.STANDARD_COPY, clonedMapping.getName()));
+
+		// Model
+		Profile.currentProfile().getMappings().addMapping(clonedMapping);
+		// UI
+		mappingComboBox.getItems().add(clonedMapping);
+		mappingComboBox.getSelectionModel().select(clonedMapping);
 	}
 
 	@FXML
 	private void mappingNewHandler(ActionEvent event) {
-		Mapping preset = new Mapping(true);
-		preset.initActionType(Profile.currentProfile());
+		Mapping preset = Profile.createMappingWithDefaultActions();
 
-		TextInputDialog dialog = new TextInputDialog(mapping.getName());
+
+		TextInputDialog dialog = new TextInputDialog();
 		dialog.initModality(Modality.WINDOW_MODAL);
 		dialog.initOwner(getContainingWindow());
 		dialog.setHeaderText("Umbenennen");
 		dialog.setContentText("Geben Sie einen Namen für das Mapping Profil ein."); // TODO Localize
 		dialog.showAndWait().filter(s -> !s.isEmpty()).ifPresent(preset::setName);
 
-		final MappingList mappings = Profile.currentProfile().getMappings();
-		mappings.add(preset);
+		final MappingCollection mappings = Profile.currentProfile().getMappings();
+		mappings.addMapping(preset);
 		mappingComboBox.getItems().add(preset);
 		mappingComboBox.getSelectionModel().select(preset);
 
-		if (mappings.size() > 1) {
+		if (mappings.count() > 1) {
 			mappingDeleteButton.setDisable(false);
 		}
 	}
 
+	@SuppressWarnings("Duplicates")
 	@FXML
 	private void mappingImportHandler(ActionEvent event) {
 		FileChooser chooser = new FileChooser();
-		chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Localization.getString(Strings.File_Filter_Preset), PlayPadMain.midiPresetType));
+		chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Localization.getString(Strings.FILE_FILTER_PRESET), PlayPadMain.PRESET_TYPE));
 		File file = chooser.showOpenDialog(getContainingWindow());
 		if (file != null) {
 			Path path = file.toPath();
@@ -318,34 +351,31 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 			Worker.runLater(() ->
 			{
 				try {
-					Mapping preset = MappingList.importMappingPreset(path, Profile.currentProfile());
-					final MappingList mappingList = Profile.currentProfile().getMappings();
-					mappingList.add(preset);
+					Mapping preset = MappingSerializer.load(path);
+					final MappingCollection mappingList = Profile.currentProfile().getMappings();
+					mappingList.addMapping(preset);
+
 					Platform.runLater(() ->
 					{
-						mappingComboBox.getItems().add(preset);
-						mappingComboBox.getSelectionModel().select(preset);
-
-						if (mappingList.size() == 1) {
-							mappingDeleteButton.setDisable(true);
-						} else {
-							mappingDeleteButton.setDisable(false);
-						}
+						mappingDeleteButton.setDisable(mappingList.count() == 1);
 
 						// Rename preset if name already esists
 						if (mappingList.containsName(preset.getName())) {
-							TextInputDialog dialog = new TextInputDialog(mapping.getName());
+							TextInputDialog dialog = new TextInputDialog(preset.getName());
 							dialog.initModality(Modality.WINDOW_MODAL);
 							dialog.initOwner(getContainingWindow());
 							dialog.setHeaderText("Umbenennen");
 							dialog.setContentText("Geben Sie einen neuen Namen für das Mapping Profil ein."); // TODO Localize
-							dialog.showAndWait().filter(s -> !s.isEmpty()).ifPresent(mapping::setName);
+							dialog.showAndWait().filter(s -> !s.isEmpty()).ifPresent(preset::setName);
 						}
+
+						mappingComboBox.getItems().add(preset);
+						mappingComboBox.getSelectionModel().select(preset);
 					});
 
 				} catch (Exception e) {
-					e.printStackTrace();
-					showErrorMessage(Localization.getString(Strings.Error_Preset_Import, e.getLocalizedMessage()));
+					Logger.error(e);
+					showErrorMessage(Localization.getString(Strings.ERROR_PRESET_IMPORT, e.getLocalizedMessage()));
 				}
 			});
 		}
@@ -355,13 +385,14 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 	// Tab Utils
 	@Override
 	public void loadSettings(Profile profile) {
-		oldMapping = profile.getMappings().getActiveMapping();
 		setMappingItemsToList();
 		createTreeViewContent();
 
-		midiActiveCheckBox.setSelected(profile.getProfileSettings().isMidiActive());
-		deviceComboBox.setDisable(!profile.getProfileSettings().isMidiActive());
-		deviceComboBox.setValue(profile.getProfileSettings().getMidiDevice());
+		final ProfileSettings profileSettings = profile.getProfileSettings();
+		midiActiveCheckBox.setSelected(profileSettings.isMidiActive());
+		deviceComboBox.setDisable(!profileSettings.isMidiActive());
+		deviceComboBox.setValue(profileSettings.getMidiDevice());
+		lightModeComboBox.setValue(profileSettings.getLightMode());
 	}
 
 	@Override
@@ -370,6 +401,7 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 
 		// Midi
 		profileSettings.setMidiActive(isMidiActive());
+		profileSettings.setLightMode(lightModeComboBox.getValue());
 	}
 
 	@Override
@@ -380,13 +412,9 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 	@Override
 	public Runnable getTask(ProfileSettings settings, Project project, IMainViewController controller) {
 		return () -> {
-			Profile.currentProfile().getMappings().getActiveMapping().adjustPadColorToMapper();
-
-			Mapping activeMapping = Profile.currentProfile().getMappings().getActiveMapping();
-
-			oldMapping.clearFeedback();
-			activeMapping.showFeedback(project);
-			activeMapping.initFeedbackType();
+			Midi.getInstance().clearFeedback();
+			ColorAdjuster.applyColorsToKeys();
+			Midi.getInstance().showFeedback();
 		};
 	}
 
@@ -397,6 +425,6 @@ public class MappingTabViewController extends ProfileSettingsTabViewController i
 
 	@Override
 	public String name() {
-		return Localization.getString(Strings.UI_Window_Settings_Mapping_Title);
+		return Localization.getString(Strings.UI_WINDOW_SETTINGS_MAPPING_TITLE);
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/PlayerTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/PlayerTabViewController.java
index d98b4387195cfa3d50c97ca8ad6d5c71df1e5147..384bb2ed2a3fc5a673a82827410e905ca302a45d 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/PlayerTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/PlayerTabViewController.java
@@ -1,7 +1,6 @@
 package de.tobias.playpad.viewcontroller.option.profile;
 
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.pad.TimeMode;
 import de.tobias.playpad.profile.Profile;
@@ -30,7 +29,7 @@ public class PlayerTabViewController extends ProfileSettingsTabViewController {
 	private ComboBox<TimeMode> timeDisplayComboBox;
 
 	PlayerTabViewController() {
-		load("view/option/profile", "PlayerTab", PlayPadMain.getUiResourceBundle());
+		load("view/option/profile", "PlayerTab", Localization.getBundle());
 
 		// Player
 		FadeViewController fadeViewController = new FadeViewController();
@@ -45,13 +44,13 @@ public class PlayerTabViewController extends ProfileSettingsTabViewController {
 
 	@Override
 	public void init() {
-		WarningFeedbackViewController controller = new WarningFeedbackViewController();
+		WarningFeedbackViewController controller = WarningFeedbackViewController.newViewControllerForProfile();
 		warningFeedbackContainer.getChildren().add(controller.getParent());
 
 		// Player
 		timeDisplayComboBox.getItems().addAll(TimeMode.values());
-		timeDisplayComboBox.setButtonCell(new EnumCell<>(Strings.Pad_TimeMode_BaseName));
-		timeDisplayComboBox.setCellFactory(list -> new EnumCell<>(Strings.Pad_TimeMode_BaseName));
+		timeDisplayComboBox.setButtonCell(new EnumCell<>(Strings.PAD_TIME_MODE));
+		timeDisplayComboBox.setCellFactory(list -> new EnumCell<>(Strings.PAD_TIME_MODE));
 	}
 
 	@Override
@@ -83,6 +82,6 @@ public class PlayerTabViewController extends ProfileSettingsTabViewController {
 
 	@Override
 	public String name() {
-		return Localization.getString(Strings.UI_Window_Settings_Player_Title);
+		return Localization.getString(Strings.UI_WINDOW_SETTINGS_PLAYER_TITLE);
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/ProfileSettingsViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/ProfileSettingsViewController.java
index 7b4731c2d4beda40f3a2322ae330b86ff2c3b205..1c4b3641862810f6d72a8366aad2936365556fc1 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/ProfileSettingsViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/ProfileSettingsViewController.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.viewcontroller.option.profile;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.threading.Worker;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.NVCStage;
@@ -44,7 +45,7 @@ public class ProfileSettingsViewController extends NVC implements IProfileSettin
 	private Runnable onFinish;
 
 	public ProfileSettingsViewController(Window owner, Project project, Runnable onFinish) {
-		load("view/option/profile", "SettingsView", PlayPadMain.getUiResourceBundle());
+		load("view/option/profile", "SettingsView", Localization.getBundle());
 		this.onFinish = onFinish;
 
 		boolean activePlayer = project.hasActivePlayers();
@@ -96,11 +97,11 @@ public class ProfileSettingsViewController extends NVC implements IProfileSettin
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
-		stage.setMinWidth(715);
-		stage.setMinHeight(700);
-		stage.setTitle(Localization.getString(Strings.UI_Window_Settings_Title, Profile.currentProfile().getRef().getName()));
+		stage.setMinWidth(800);
+		stage.setMinHeight(800);
+		stage.setTitle(Localization.getString(Strings.UI_WINDOW_SETTINGS_TITLE, Profile.currentProfile().getRef().getName()));
 
 		PlayPadPlugin.styleable().applyStyle(stage);
 	}
@@ -127,8 +128,8 @@ public class ProfileSettingsViewController extends NVC implements IProfileSettin
 		try {
 			profile.save();
 		} catch (Exception e) {
-			showErrorMessage(Localization.getString(Strings.Error_Profile_Save, e.getLocalizedMessage()));
-			e.printStackTrace();
+			showErrorMessage(Localization.getString(Strings.ERROR_PROFILE_SAVE, e.getLocalizedMessage()));
+			Logger.error(e);
 		}
 	}
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/GeneralTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/GeneralTabViewController.java
index 8aabafa0bd5e1f853e27538ce991a85c299d46f2..dac32ea109085e1fbd079363f87a73ea1a70f18d 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/GeneralTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/GeneralTabViewController.java
@@ -2,7 +2,6 @@ package de.tobias.playpad.viewcontroller.option.project;
 
 import de.thecodelabs.utils.ui.Alertable;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.design.ModernDesignSizeHelper;
 import de.tobias.playpad.project.Project;
@@ -48,7 +47,7 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 	private Label rowErrorLabel;
 
 	GeneralTabViewController(Screen currentScreen, Alertable parentController, boolean activePlayer) {
-		load("view/option/project", "GeneralTab", PlayPadMain.getUiResourceBundle());
+		load("view/option/project", "GeneralTab", Localization.getBundle());
 
 		this.mainWindowScreen = currentScreen;
 		this.parentController = parentController;
@@ -64,7 +63,7 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 		columnTextField.textProperty().addListener((a, b, c) ->
 		{
 			if (c.matches(DIGIT_POSITIVE) && !c.isEmpty()) {
-				ValidationState validationState = validate(Integer.valueOf(c), Dimension.COLUMNS);
+				ValidationState validationState = validate(Integer.parseInt(c), Dimension.COLUMNS);
 				if (validationState == ValidationState.NORMAL) {
 					columnTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, false);
 					columnErrorLabel.setText("");
@@ -74,22 +73,22 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 					String errorText = "";
 					// Error Message
 					if (validationState == ValidationState.TOO_MUCH) {
-						errorText = Localization.getString(Strings.Error_Screen_TooMuch, maxValue(Dimension.COLUMNS));
+						errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_MUCH, maxValue(Dimension.COLUMNS));
 					} else if (validationState == ValidationState.TOO_LESS) {
-						errorText = Localization.getString(Strings.Error_Screen_TooLess, minValue(Dimension.COLUMNS));
+						errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, minValue(Dimension.COLUMNS));
 					}
 					columnErrorLabel.setText(errorText);
 				}
 			} else {
 				columnTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, true);
-				columnErrorLabel.setText(Localization.getString(Strings.Error_Screen_TooLess, minValue(Dimension.COLUMNS)));
+				columnErrorLabel.setText(Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, minValue(Dimension.COLUMNS)));
 			}
 		});
 
 		rowTextField.textProperty().addListener((a, b, c) ->
 		{
 			if (c.matches(DIGIT_POSITIVE) && !c.isEmpty()) {
-				ValidationState validationState = validate(Integer.valueOf(c), Dimension.ROWS);
+				ValidationState validationState = validate(Integer.parseInt(c), Dimension.ROWS);
 				if (validationState == ValidationState.NORMAL) {
 					rowTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, false);
 					rowErrorLabel.setText("");
@@ -99,15 +98,15 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 					String errorText = "";
 					// Error Message
 					if (validationState == ValidationState.TOO_MUCH) {
-						errorText = Localization.getString(Strings.Error_Screen_TooMuch, maxValue(Dimension.ROWS));
+						errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_MUCH, maxValue(Dimension.ROWS));
 					} else if (validationState == ValidationState.TOO_LESS) {
-						errorText = Localization.getString(Strings.Error_Screen_TooLess, minValue(Dimension.ROWS));
+						errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, minValue(Dimension.ROWS));
 					}
 					rowErrorLabel.setText(errorText);
 				}
 			} else {
 				rowTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, true);
-				rowErrorLabel.setText(Localization.getString(Strings.Error_Screen_TooLess, minValue(Dimension.ROWS)));
+				rowErrorLabel.setText(Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, minValue(Dimension.ROWS)));
 			}
 		});
 	}
@@ -147,8 +146,8 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 		double height = mainWindowScreen.getVisualBounds().getMaxY() - mainWindowScreen.getVisualBounds().getMinY();
 
 		try {
-			Integer column = Integer.valueOf(columnTextField.getText());
-			Integer rows = Integer.valueOf(rowTextField.getText());
+			int column = Integer.parseInt(columnTextField.getText());
+			int rows = Integer.parseInt(rowTextField.getText());
 
 			if (column < 3 || rows < 1) {
 				return false;
@@ -183,8 +182,8 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 
 	@Override
 	public void saveSettings(ProjectSettings settings) {
-		int columns = Integer.valueOf(columnTextField.getText());
-		int rows = Integer.valueOf(rowTextField.getText());
+		int columns = Integer.parseInt(columnTextField.getText());
+		int rows = Integer.parseInt(rowTextField.getText());
 
 		changeSettings = settings.getColumns() != columns || settings.getRows() != rows;
 
@@ -201,8 +200,8 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 	@Override
 	public boolean validSettings() {
 		try {
-			return validate(Integer.valueOf(columnTextField.getText()), Dimension.COLUMNS) == ValidationState.NORMAL &&
-					validate(Integer.valueOf(rowTextField.getText()), Dimension.ROWS) == ValidationState.NORMAL;
+			return validate(Integer.parseInt(columnTextField.getText()), Dimension.COLUMNS) == ValidationState.NORMAL &&
+					validate(Integer.parseInt(rowTextField.getText()), Dimension.ROWS) == ValidationState.NORMAL;
 		} catch (NumberFormatException e) {
 			return false;
 		}
@@ -210,7 +209,7 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 
 	@Override
 	public String name() {
-		return Localization.getString(Strings.UI_Window_Settings_Gen_Title);
+		return Localization.getString(Strings.UI_WINDOW_SETTINGS_GEN_TITLE);
 	}
 
 	@Override
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/PathsTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/PathsTabViewController.java
index c7aeb411e059686d542d0ac9ff7d9fe0cf8daeef..5c3fbeb8ffb39f5ca1283346e631079372d6acc3 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/PathsTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/PathsTabViewController.java
@@ -1,9 +1,9 @@
 package de.tobias.playpad.viewcontroller.option.project;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.io.FileUtils;
 import de.thecodelabs.utils.io.PathUtils;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadStatus;
@@ -47,7 +47,7 @@ public class PathsTabViewController extends ProjectSettingsTabViewController imp
 	private transient Optional<Path> oldMediaPath = Optional.empty();
 
 	PathsTabViewController() {
-		load("view/option/project", "PathTab", PlayPadMain.getUiResourceBundle());
+		load("view/option/project", "PathTab", Localization.getBundle());
 	}
 
 	@FXML
@@ -60,7 +60,7 @@ public class PathsTabViewController extends ProjectSettingsTabViewController imp
 			if (currentMediaPath.isPresent()) {
 				boolean subDirectory = PathUtils.isSubDirectory(currentMediaPath.get(), path);
 				if (subDirectory) {
-					showErrorMessage(Localization.getString(Strings.Error_Project_MediaPath));
+					showErrorMessage(Localization.getString(Strings.ERROR_PROJECT_MEDIA_PATH));
 					return;
 				}
 			}
@@ -103,7 +103,7 @@ public class PathsTabViewController extends ProjectSettingsTabViewController imp
 
 	@Override
 	public String name() {
-		return Localization.getString(Strings.UI_Window_Settings_Paths_Title);
+		return Localization.getString(Strings.UI_WINDOW_SETTINGS_PATHS_TITLE);
 	}
 
 	// Reload Data
@@ -152,7 +152,7 @@ public class PathsTabViewController extends ProjectSettingsTabViewController imp
 						}
 					}
 				} catch (Exception e) {
-					e.printStackTrace();
+					Logger.error(e);
 				}
 			}
 
@@ -160,7 +160,7 @@ public class PathsTabViewController extends ProjectSettingsTabViewController imp
 				try {
 					FileUtils.deleteDirectory(oldMediaPath.get());
 				} catch (IOException e) {
-					e.printStackTrace();
+					Logger.error(e);
 				}
 		};
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/ProjectSettingsViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/ProjectSettingsViewController.java
index 2e55a939b2e51d6b88b12107d0a7ecd1ef35caab..9b2c6957ec97cdbfc6d4050cc662d4330fdbd062 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/ProjectSettingsViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/ProjectSettingsViewController.java
@@ -41,7 +41,7 @@ public class ProjectSettingsViewController extends NVC implements IProjectSettin
 	private Runnable onFinish;
 
 	public ProjectSettingsViewController(Screen currentScreen, Window owner, Project project, Runnable onFinish) {
-		load("view/option/project", "ProjectSettingsView", PlayPadMain.getUiResourceBundle());
+		load("view/option/project", "ProjectSettingsView", Localization.getBundle());
 		this.onFinish = onFinish;
 		this.project = project;
 
@@ -66,11 +66,11 @@ public class ProjectSettingsViewController extends NVC implements IProjectSettin
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadMain.stageIcon.ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		stage.setMinWidth(715);
 		stage.setMinHeight(500);
-		stage.setTitle(Localization.getString(Strings.UI_Window_ProjectSettings_Title));
+		stage.setTitle(Localization.getString(Strings.UI_WINDOW_PROJECT_SETTINGS_TITLE));
 
 		PlayPadPlugin.styleable().applyStyle(stage);
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java
index 790e8f56c57f6944bc57e4b0cd576a5e2e68ca2c..14515382904128e4e49c021e0431c02f4a4981fe 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java
@@ -2,7 +2,6 @@ package de.tobias.playpad.viewcontroller.settings;
 
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.settings.Fade;
 import javafx.fxml.FXML;
@@ -34,7 +33,7 @@ public class FadeViewController extends NVC {
 	private Fade fade;
 
 	public FadeViewController() {
-		load("view/settings", "FadeView", PlayPadMain.getUiResourceBundle());
+		load("view/settings", "FadeView", Localization.getBundle());
 	}
 
 	@Override
@@ -43,7 +42,7 @@ public class FadeViewController extends NVC {
 		{
 			Duration seconds = Duration.seconds(c.doubleValue());
 			double displayedTime = Math.round(seconds.toSeconds() * 10) / 10.0;
-			fadeInLabel.setText(Localization.getString(Strings.Standard_Time_Seconds, displayedTime));
+			fadeInLabel.setText(Localization.getString(Strings.STANDARD_TIME_SECONDS, displayedTime));
 			fade.setFadeIn(seconds);
 		});
 
@@ -51,7 +50,7 @@ public class FadeViewController extends NVC {
 		{
 			Duration seconds = Duration.seconds(c.doubleValue());
 			double displayedTime = Math.round(seconds.toSeconds() * 10) / 10.0;
-			fadeOutLabel.setText(Localization.getString(Strings.Standard_Time_Seconds, displayedTime));
+			fadeOutLabel.setText(Localization.getString(Strings.STANDARD_TIME_SECONDS, displayedTime));
 			fade.setFadeOut(seconds);
 		});
 
@@ -67,11 +66,11 @@ public class FadeViewController extends NVC {
 		if (fade != null) {
 			fadeInSlider.setValue(fade.getFadeIn().toSeconds());
 			double displayedInTime = Math.round(fade.getFadeIn().toSeconds() * 10) / 10.0;
-			fadeInLabel.setText(Localization.getString(Strings.Standard_Time_Seconds, displayedInTime));
+			fadeInLabel.setText(Localization.getString(Strings.STANDARD_TIME_SECONDS, displayedInTime));
 
 			fadeOutSlider.setValue(fade.getFadeOut().toSeconds());
 			double displayedOutTime = Math.round(fade.getFadeOut().toSeconds() * 10) / 10.0;
-			fadeOutLabel.setText(Localization.getString(Strings.Standard_Time_Seconds, displayedOutTime));
+			fadeOutLabel.setText(Localization.getString(Strings.STANDARD_TIME_SECONDS, displayedOutTime));
 
 			fadeInStartCheckBox.setSelected(fade.isFadeInStart());
 			fadeInPauseCheckBox.setSelected(fade.isFadeInPause());
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/WarningFeedbackViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/WarningFeedbackViewController.java
index 146759ff222e67823695983a04cb790ea704e2ef..dfe3087c7e911b035ddfa39ba83f795ed0eaa19a 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/WarningFeedbackViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/WarningFeedbackViewController.java
@@ -2,7 +2,6 @@ package de.tobias.playpad.viewcontroller.settings;
 
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.util.Localization;
-import de.tobias.playpad.PlayPadMain;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.profile.Profile;
@@ -19,34 +18,35 @@ public class WarningFeedbackViewController extends NVC {
 	@FXML
 	private Label warningFeedbackTimeLabel;
 
-	public WarningFeedbackViewController() {
-		load("view/settings", "WarningFeedbackSettingsView", PlayPadMain.getUiResourceBundle());
-		ProfileSettings profilSettings = Profile.currentProfile().getProfileSettings();
+	private WarningFeedbackViewController() {
+		load("view/settings", "WarningFeedbackSettingsView", Localization.getBundle());
+	}
 
-		warningFeedbackTimeSlider.setValue(profilSettings.getWarningFeedback().toSeconds());
-		setTimeLabel();
+	public static WarningFeedbackViewController newViewControllerForProfile() {
+		final WarningFeedbackViewController controller = new WarningFeedbackViewController();
+		ProfileSettings profileSettings = Profile.currentProfile().getProfileSettings();
 
-		warningFeedbackTimeSlider.valueProperty().addListener((a, b, c) ->
-		{
-			profilSettings.setWarningTime(Duration.seconds(c.doubleValue()));
-		});
+		controller.warningFeedbackTimeSlider.setValue(profileSettings.getWarningFeedback().toSeconds());
+		controller.setTimeLabel();
+
+		controller.warningFeedbackTimeSlider.valueProperty().addListener((a, b, c) ->
+				profileSettings.setWarningTime(Duration.seconds(c.doubleValue())));
+		return controller;
 	}
 
-	public WarningFeedbackViewController(Pad pad) {
-		load("view/settings/", "WarningFeedbackSettingsView", PlayPadMain.getUiResourceBundle());
+	public static  WarningFeedbackViewController newViewControllerForPad() {
+		return new WarningFeedbackViewController();
 	}
 
 	@Override
 	public void init() {
 		warningFeedbackTimeSlider.valueProperty().addListener((a, b, c) ->
-		{
-			setTimeLabel();
-		});
+				setTimeLabel());
 	}
 
 	private void setTimeLabel() {
 		double displayedTime = Math.round(warningFeedbackTimeSlider.getValue() * 10) / 10.0;
-		warningFeedbackTimeLabel.setText(Localization.getString(Strings.Standard_Time_Seconds, displayedTime));
+		warningFeedbackTimeLabel.setText(Localization.getString(Strings.STANDARD_TIME_SECONDS, displayedTime));
 	}
 
 	public void setPadWarning(Pad pad) {
@@ -56,8 +56,6 @@ public class WarningFeedbackViewController extends NVC {
 		}
 
 		warningFeedbackTimeSlider.valueProperty().addListener((a, b, c) ->
-		{
-			pad.getPadSettings().setWarning(Duration.seconds(c.doubleValue()));
-		});
+				pad.getPadSettings().setWarning(Duration.seconds(c.doubleValue())));
 	}
 }
diff --git a/PlayWall/src/main/resources/colors/ModernColor.json b/PlayWall/src/main/resources/colors/ModernColor.json
new file mode 100644
index 0000000000000000000000000000000000000000..eae7057a68a2decc1663d87c5c93690720c835ac
--- /dev/null
+++ b/PlayWall/src/main/resources/colors/ModernColor.json
@@ -0,0 +1,470 @@
+[
+    {
+        "name": "RED1",
+        "colors": {
+            "hi": "#ef9a9a",
+            "low": "#ef5350",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "RED2",
+        "colors": {
+            "hi": "#ef5350",
+            "low": "#e53935",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "RED3",
+        "colors": {
+            "hi": "#e53935",
+            "low": "#c62828",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "DARK_RED1",
+        "colors": {
+            "hi": "#D92349",
+            "low": "#AD2039",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "DARK_RED2",
+        "colors": {
+            "hi": "#C92349",
+            "low": "#8D2039",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "DARK_RED3",
+        "colors": {
+            "hi": "#A90329",
+            "low": "#6D0019",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "PINK1",
+        "colors": {
+            "hi": "#f48fb1",
+            "low": "#ec407a",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "PINK2",
+        "colors": {
+            "hi": "#ec407a",
+            "low": "#d81b60",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "PINK3",
+        "colors": {
+            "hi": "#d81b60",
+            "low": "#ad1457",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "PURPLE1",
+        "colors": {
+            "hi": "#ce93d8",
+            "low": "#ab47bc",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "PURPLE2",
+        "colors": {
+            "hi": "#ab47bc",
+            "low": "#8e24aa",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "PURPLE3",
+        "colors": {
+            "hi": "#8e24aa",
+            "low": "#6a1b9a",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "LIGHT_BLUE1",
+        "colors": {
+            "hi": "#80deea",
+            "low": "#26c6da",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "LIGHT_BLUE2",
+        "colors": {
+            "hi": "#26c6da",
+            "low": "#00acc1",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "LIGHT_BLUE3",
+        "colors": {
+            "hi": "#00acc1",
+            "low": "#00838f",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "BLUE1",
+        "colors": {
+            "hi": "#90caf9",
+            "low": "#42a5f5",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "BLUE2",
+        "colors": {
+            "hi": "#42a5f5",
+            "low": "#1e88e5",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "BLUE3",
+        "colors": {
+            "hi": "#1e88e5",
+            "low": "#1565c0",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "LIGHT_GREEN1",
+        "colors": {
+            "hi": "#c5e1a5",
+            "low": "#9ccc65",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "LIGHT_GREEN2",
+        "colors": {
+            "hi": "#9ccc65",
+            "low": "#7cb342",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "LIGHT_GREEN3",
+        "colors": {
+            "hi": "#7cb342",
+            "low": "#558b2f",
+            "font": "#ffffff",
+            "button": "#ffffff",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "LIME1",
+        "colors": {
+            "hi": "#e6ee9c",
+            "low": "#d4e157",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "LIME2",
+        "colors": {
+            "hi": "#d4e157",
+            "low": "#c0ca33",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "LIME3",
+        "colors": {
+            "hi": "#c0ca33",
+            "low": "#9e9d24",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "YELLOW1",
+        "colors": {
+            "hi": "#fff59d",
+            "low": "#ffee58",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#333333",
+                "track": "#FFFFFF"
+            }
+        }
+    },
+    {
+        "name": "YELLOW2",
+        "colors": {
+            "hi": "#ffee58",
+            "low": "#fdd835",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#333333",
+                "track": "#FFFFFF"
+            }
+        }
+    },
+    {
+        "name": "YELLOW3",
+        "colors": {
+            "hi": "#fdd835",
+            "low": "#f9a825",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "ORANGE1",
+        "colors": {
+            "hi": "#ffcc80",
+            "low": "#ffa726",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "ORANGE2",
+        "colors": {
+            "hi": "#ffa726",
+            "low": "#fb8c00",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "ORANGE3",
+        "colors": {
+            "hi": "#fb8c00",
+            "low": "#ef6c00",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "GRAY1",
+        "colors": {
+            "hi": "#eeeeee",
+            "low": "#cccccc",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#333333",
+                "track": "#FFFFFF"
+            }
+        }
+    },
+    {
+        "name": "GRAY2",
+        "colors": {
+            "hi": "#cccccc",
+            "low": "#aaaaaa",
+            "font": "#000000",
+            "button": "#000000",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "GRAY3",
+        "colors": {
+            "hi": "#aaaaaa",
+            "low": "#888888",
+            "font": "#FFFFFF",
+            "button": "#FFFFFF",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "GRAY4",
+        "colors": {
+            "hi": "#888888",
+            "low": "#666666",
+            "font": "#FFFFFF",
+            "button": "#FFFFFF",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "GRAY5",
+        "colors": {
+            "hi": "#666666",
+            "low": "#444444",
+            "font": "#FFFFFF",
+            "button": "#FFFFFF",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    },
+    {
+        "name": "GRAY6",
+        "colors": {
+            "hi": "#444444",
+            "low": "#222222",
+            "font": "#FFFFFF",
+            "button": "#FFFFFF",
+            "playbar": {
+                "background": "#ffffff",
+                "track": "#333333"
+            }
+        }
+    }
+]
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/components/Actions.xml b/PlayWall/src/main/resources/components/Actions.xml
index 19c631ad9c6a59114c8f3ad02e4330fdfa2f4509..f992162e06c0982a968ecd169612c8e66f657c9a 100644
--- a/PlayWall/src/main/resources/components/Actions.xml
+++ b/PlayWall/src/main/resources/components/Actions.xml
@@ -1,16 +1,16 @@
 <Actions>
-    <Component id="CART" name="Action.Cart.Name" icon="TH" class="de.thecodelabs.utils.ui.icon.FontAwesomeType"
+    <Component id="CartAction" name="Action.Cart.Name" icon="TH" class="de.thecodelabs.utils.ui.icon.FontAwesomeType"
                size="11">
         de.tobias.playpad.action.factory.CartActionProvider
     </Component>
-    <Component id="PAGE" name="Action.Page.Name" icon="FILE_TEXT" class="de.thecodelabs.utils.ui.icon.FontAwesomeType"
+    <Component id="PageAction" name="Action.Page.Name" icon="FILE_TEXT" class="de.thecodelabs.utils.ui.icon.FontAwesomeType"
                size="11">de.tobias.playpad.action.factory.PageActionProvider
     </Component>
-    <Component id="NAVIGATE" name="Action.Navigate.Name" icon="NAVIGATION"
+    <Component id="NavigateAction" name="Action.Navigate.Name" icon="NAVIGATION"
                class="de.thecodelabs.utils.ui.icon.MaterialDesignIcon" size="11">
         de.tobias.playpad.action.factory.NavigateActionProvider
     </Component>
-    <Component id="STOP" name="Action.Stop.Name" icon="STOP" class="de.thecodelabs.utils.ui.icon.MaterialDesignIcon"
+    <Component id="StopAction" name="Action.Stop.Name" icon="STOP" class="de.thecodelabs.utils.ui.icon.MaterialDesignIcon"
                size="11">de.tobias.playpad.action.factory.StopActionProvider
     </Component>
 </Actions>
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/components/Mapper.xml b/PlayWall/src/main/resources/components/Mapper.xml
deleted file mode 100644
index 619bdad1a3f58031d3bb66e7c1e5d51d01250a8f..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/resources/components/Mapper.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<Actions>
-    <Component id="MIDI" name="Mapper.Midi.Name">de.tobias.playpad.action.mapper.MidiMapperFactory</Component>
-    <Component id="KEYBOARD" name="Mapper.Keyboard.Name">de.tobias.playpad.action.mapper.KeyboardMapperFactory
-    </Component>
-</Actions>
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/config/application.yml b/PlayWall/src/main/resources/config/application.yml
index 711a805ff3ff54ef777edf8a9cf248c507187dc3..9155ec9b59b29fb84a5d0a114fe5bee2775b64b3 100644
--- a/PlayWall/src/main/resources/config/application.yml
+++ b/PlayWall/src/main/resources/config/application.yml
@@ -1,5 +1,5 @@
 name: "PlayWall"
-version: "6.2.0"
+version: "7.0.0"
 build: 40
 identifier: "de.tobias.playpad.v7"
 date: "2019-02-04"
@@ -12,8 +12,8 @@ basePath: "PlayWall"
 serverBaseURL: "https://playwall.thecodelabs.de/files"
 
 userInfo:
-  Website: "https://playwall.thecodelabs.de/"
-  Repository: "https://thecodelabs.de/PlayWall/PlayWallDesktop"
-  ChangelogURL: "https://playwall.thecodelabs.de/php/roadmap/index.php?id=4"
-  Server: "playwall.thecodelabs.de:8090"
-  AccountRegister: "https://playwall.thecodelabs.de/php/index.php"
+  website: "https://playwall.thecodelabs.de/"
+  repository: "https://thecodelabs.de/PlayWall/PlayWallDesktop"
+  changelogURL: "https://playwall.thecodelabs.de/php/roadmap.php"
+  server: "playwall.thecodelabs.de:8090"
+  accountRegister: "https://playwall.thecodelabs.de/php/index.php"
diff --git a/PlayWall/src/main/resources/config/libLogger.yml b/PlayWall/src/main/resources/config/libLogger.yml
index 3c309583f9c0021ad159f12e2b777c4e1aa4ccac..c0dcfdcc5302f6017f63920cc48d58fb22a603c0 100644
--- a/PlayWall/src/main/resources/config/libLogger.yml
+++ b/PlayWall/src/main/resources/config/libLogger.yml
@@ -12,7 +12,7 @@ dateFormatterPattern: "dd.MM.YY HH:mm:ss"
 defaultOutLevel: "DEBUG"
 defaultErrLevel: "ERROR"
 
-showShortPackageName: true
+showShortPackageName: false
 showClassName: true
 showMethodName: true
 showLineNumber: true
diff --git a/PlayWall/src/main/resources/controlsfx_de_DE.properties b/PlayWall/src/main/resources/controlsfx_de_DE.properties
index b5527885b41c5db4266d09631741beb45764cf2a..2f0e34086adb1e12d921def24bd55056a9b88eaa 100644
--- a/PlayWall/src/main/resources/controlsfx_de_DE.properties
+++ b/PlayWall/src/main/resources/controlsfx_de_DE.properties
@@ -3,7 +3,7 @@ dlg.ok.button=OK
 dlg.cancel.button=Abbruch
 dlg.yes.button=Ja
 dlg.no.button=Nein
-dlg.close.button=Schlie\uFFFDen
+dlg.close.button=Schlie\u00DFen
 dlg.detail.button.more=Show Details
 dlg.detail.button.less=Hide Details
 ### Common Dialogs ###
@@ -26,7 +26,7 @@ exception.dlg.label=The exception stacktrace was:
 exception.button.label=Open Exception
 ### Wizard ###
 wizard.next.button=Weiter
-wizard.previous.button=Zur\uFFFDck
+wizard.previous.button=Zur\u00FCck
 ### Property Sheet ###
 bean.property.change.error.title=Property Change Error
 bean.property.change.error.header=Change is not allowed
diff --git a/PlayWall/src/main/resources/icon_large.png b/PlayWall/src/main/resources/icon_large.png
new file mode 100755
index 0000000000000000000000000000000000000000..eaefe5012f62822c47593d9a5205ffec9b14f412
Binary files /dev/null and b/PlayWall/src/main/resources/icon_large.png differ
diff --git a/PlayWall/src/main/resources/lang/_de.properties b/PlayWall/src/main/resources/lang/_de.properties
index d748a318b3ea75be484232da255793d555f4e5f0..cfbdf22ed322a5aa4e6fe39868cd2e6956349c89 100755
--- a/PlayWall/src/main/resources/lang/_de.properties
+++ b/PlayWall/src/main/resources/lang/_de.properties
@@ -32,7 +32,6 @@ UI.Dialog.ProjectManager.Title=Projektverwaltung
 UI.Dialog.Plugins.Title=Erweiterungen
 UI.Dialog.Print.Title=Drucken
 UI.Dialog.Profile.Title=Profilverwaltung
-UI.Dialog.PlayoutLog.Title=PlayoutLog
 # UI - Standard
 UI.Standard.DoNotShow=Nicht mehr anzeigen
 # UI - Layout - Classic - Theme - Enum
@@ -46,14 +45,12 @@ UI.Window.Main.PageButton=Seite {}
 # UI - Dialog - Launch
 UI.Dialog.Launch.Info={} - {}
 # UI - Dialog - ProjectLoad
-UI.Dialof.ProjectLoad.StartProject=Das Projekt wird geladen.
-UI.Dialof.ProjectLoad.StartPad=Die Datei '{}' wird geladen.
+UI.Dialog.ProjectLoad.StartProject=Das Projekt wird geladen.
+UI.Dialog.ProjectLoad.StartPad=Die Datei '{}' wird geladen.
 # UI Window - Settings
 UI.Window.Settings.Gen.Title=Allgemein
 UI.Window.Settings.Gen.CacheSize=Gr\u00F6\u00DFe: {}B
-UI.Window.Settings.Gen.Wait=Die \u00C4nderungen werden \u00FCbernommen. Das kann einen kurzen Moment dauern.
 UI.Window.Settings.Mapping.Title=Mapping
-UI.Window.Settings.Midi.Title=Midi
 UI.Window.Settings.Layout.Title=Layout
 UI.Window.Settings.Player.Title=Player
 UI.Window.Settings.Audio.Title=Audio
@@ -90,8 +87,6 @@ UI.Dialog.About.Graphics=Robert Goldmann
 UI.Dialog.About.Libraries=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).
 UI.Dialog.About.Website=playwall.thecodelabs.de
 UI.Dialog.About.Code=thecodelabs.de/PlayWall/PlayWallDesktop
-# UI - Dialog - Feedback
-UI.Dialog.Feedback.Content=Der Fehlerbericht wird \u00DCbermittelt, dies kann einen Augenblick dauern. Ihre Nummer wird am Ende angezeigt.
 # UI - Placeholder
 UI.Placeholder.Project=Keine Projekte vorhanden
 UI.Placeholder.Preset=Keine Vorlagen vorhanden
@@ -129,7 +124,7 @@ Error.Project.Delete=Das Projekt konnte nicht gel\u00F6scht werden. ({})
 Error.Project.Export=Das Projekt {} konnte nicht exportiert werden. ({})
 Error.Project.Import=Das Projekt konnte nicht importiert werden.
 Error.Project.MediaPath=Der neue Ordner darf kein Unterodner des alten Medienordners sein.
-Error.Project.PageCount=Sie k\u00F6nnen nicht mehr als 8 Seiten erstellen.
+Error.Project.PageCount=Sie k\u00F6nnen nicht mehr als {} Seiten erstellen.
 Error.Project.Sync.Change=Es ist ein Fehler aufgetreten. Versuchen Sie es sp\u00E4ter noch ein mal. ({})
 # Error - Pad - Enum
 Error.Pad.FILE_NOT_FOUND=Die Datei {} konnte nicht gefunden werden.
@@ -144,7 +139,10 @@ Error.Midi.Device.Unavailable=Das Midi-Ger\u00E4t {} konnte nicht gefunden werde
 Error.Midi.Record.Fail=Die gedr\u00FCckte Taste wird bereits verwendet.
 Error.Midi.Send=Der Midi Befehl konnte nicht gesendet werden. ({})
 # Error - Plugins
+Error.Plugins.Header=Plugins
 Error.Plugins.Missing=Es wurden im Projekt Erweiterungen verwendet, welche momentan nicht installiert sind. Sie k\u00F6nnen das Projekt dennoch \u00F6ffnen, es kann aber zu Fehlern dabei kommen, wenn Sie folgende Erweiterungen nicht installiert haben.
+Error.Plugins.Loading=Die Plugins konnten nicht vom geladen werden. Versuchen Sie es sp\u00E4ter erneut.
+Error.Plugins.Install=Es ist ein Fehler beim installieren des Plugins aufgetreten. Versuche Sie es sp\u00E4ter erneut ({})
 # Error - Screen
 Error.Screen.TooMuch=Maxiamle Anzahl der Kacheln {}
 Error.Screen.TooLess=Minmale Anzahl der Kacheln {}
@@ -188,7 +186,7 @@ UI.Dialog.AutoUpdate.Content=Es sind Aktualisierungen verf\u00FCgbar. M\u00F6cht
 UI.Dialog.AutoUpdate.Title=Aktualisierung
 UI.Dialog.AutoUpdate.Checkbox=Diese Aktualisierung nicht mehr anzeigen.
 UI.Dialog.AutoUpdate.Button.Update=Jetzt aktualisieren
-UI.Dialog.AutoUpdate.Button.Cancel=Jetzt nicht aktualisieren
+UI.Dialog.AutoUpdate.Button.Cancel=Abbrechen
 #UI - Dialog - Save
 UI.Dialog.Save.Header=Speichern
 UI.Dialog.Save.Content=M\u00F6chten Sie das Projekt speichern?
@@ -206,9 +204,6 @@ Error.Layout.Load=Es gab einen Fehler beim Laden des Layouts ({})
 UI.Dialog.Update.Cell={}: Installiert: {} - Neu: {}
 UI.Dialog.Update.Info=Die Aktualisierung wird vorbereitet. Bitte schlie\u00DFen Sie nicht das Programm. \nDieser Vorgang kann wenige Minuten dauern.
 UI.Window.Settings.Updates.CurrentVersion={} (Build {})
-# Layout
-Layout.Modern.Name=Modern
-Layout.Classic.Name=Klassisch
 # Trigger
 TriggerPoint.toString={} ({})
 Trigger.Cart.Name=Kacheln
@@ -223,10 +218,13 @@ DnDMode.Move=Tauschen
 # Main Layout
 MainLayout.Desktop=Desktopmodus
 MainLayout.Touch=Touchmodus
+
 # Suche
 Search.Button=Suchen
 Search.Placeholder=Suche
-Search.Alert.NoMatches=Keine Treffer gefunden.
+Search.Alert.NoMatches.Header=Kachelsuche
+Search.Alert.NoMatches.Content=Keine weiteren Treffer zu '{}' gefunden.
+
 # UI - Dialog - Page - Delete
 UI.Dialog.Page.Delete.Header=Seite l\u00F6schen
 UI.Dialog.Page.Delete.Content=M\u00F6chten Sie die Seite unwiederbringlich l\u00F6schen?
@@ -251,8 +249,18 @@ SOUNDCARD=Soundkarte:
 #AudioHandler
 AudioHandler.JavaFX=JavaFX
 AudioHandler.TinySound=TinySound
+
 # Server
-Server.Connected=Mit dem Server verbunden.
-Server.Connection_Lost=NICHT mit dem Server verbunden.
-Server.Disconnected=Anmeldung erforderlich.
-Auth.Logout=Alle Onlineprojekte sind nicht mehr lokal verf\u00FCgbar. \nPlayWall wird beendet.
\ No newline at end of file
+Server.Connected=Mit dem Server verbunden. [BETA]
+Server.Connection_Lost=NICHT mit dem Server verbunden. [BETA]
+Server.Disconnected=Anmeldung erforderlich. [BETA]
+Server.Error.IO=Anmeldung fehlgeschlagen. Der Server ist nicht erreichbar. Versuchen Sie es sp\u00E4ter erneut.
+Server.Error.Login=Anmeldung fehlgeschlagen. Der Nutzername oder das Passwort sind nicht korrekt.
+
+Auth.Logout=Alle Onlineprojekte sind nicht mehr lokal verf\u00FCgbar.
+
+#LightMode Enum
+LightMode.LOW=Niedrig
+LightMode.MIDDLE=Mittel
+LightMode.NORMAL=Hell
+LightMode.HIGH=Billiant
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/lang/ui_de.properties b/PlayWall/src/main/resources/lang/ui_de.properties
index 4f1da3150975a53b18262c747c38a75929251ea5..1876ec12242853a055acb1e74acccedae6ee242f 100755
--- a/PlayWall/src/main/resources/lang/ui_de.properties
+++ b/PlayWall/src/main/resources/lang/ui_de.properties
@@ -20,7 +20,6 @@ main.menuitem.drag=Kacheln verschieben
 main.menuitem.page=Seiten bearbeiten
 main.menuitem.color=Kacheln einf\u00E4rben
 main.menuitem.notfound=Dateiverkn\u00FCpfung...
-main.menuitem.log=Playout Log...
 main.menuitem.plugins=Erweiterungen...
 main.menuitem.projectSettings=Projekteinstellungen...
 main.menuitem.profileSettings=Profileinstellungen...
@@ -77,8 +76,6 @@ settings.update.label.available=Verf\u00FCgbare 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=Programm
-settings.update.label.infoE=Erweiterung
 settings.keys.label.headline=Tastenkombinationen
 settings.keys.label.name=Name:
 settings.keys.label.shortcut=Tastenkombination:
@@ -92,14 +89,17 @@ settings.paths.button.choose=W\u00E4hlen...
 settings.paths.checkbox.mediaActive=Mediendateien beim Import in den Medienordner kopieren
 settings.button.finish=Fertig
 settings.checkbox.activate=Aktivieren
-layout.label.programmLayout=Programmlayout:
-layout.label.customLayout=Eigenes Layout:
-layout.label.baseColor=Akzentfarbe:
-layout.label.background=Hintergrund:
-layout.label.playground=Hintergrund w\u00E4hrend Wiedergabe:
-layout.label.fadeColor=Hintergrund w\u00E4hrend Ausblenden:
-layout.label.warnColor=Warnhinweis:
-layout.label.color=Farbe:
+settings.label.lightmode=Helligkeit
+settings.label.lightmode.info=(Nur f\u00FCr LaunchPad MK2 unterst\u00FCtzt)
+
+plugins.button.install=Installieren
+plugins.button.uninstall=Deinstallieren
+
+layout.label.background=Standard:
+layout.label.play=Wiedergabe:
+layout.label.cueIn=Intro:
+
+layout.label.color=Hintergrundfarbe:
 layout.label.fontSize=Schriftgr\u00F6\u00DFe:
 layout.label.infoLabel=Kopfzeile:
 layout.label.titleLabel=Titel:
@@ -108,6 +108,7 @@ layout.label.warnAnimation=Warnhinweise
 layout.button.reset=Zur\u00FCcksetzen
 layout.label.option=Optionen:
 layout.checkbox.flat=Flat Design
+
 midi.label.key=Taste (Midi):
 midi.button.new=\u00C4ndern
 keyboard.label.key=Taste (Tastatur):
@@ -121,6 +122,7 @@ padSettings.gen.checkbox.customSettings=Eigene Einstellungen
 padSettings.checkbox.loop=Wiederholen
 padSettings.button.finish=Fertig
 padSettings.player.label.warning=Warnhinweise:
+padSettings.player.label.cueIn=Intro Dauer (in s):
 padSettings.player.label.fade=Ein-/Ausblenden:
 padSettings.layout.label.custom=Eigenes Layout:
 padSettings.layout.checkbox.custom=Aktiviert
@@ -183,19 +185,22 @@ print.button.print=Drucken
 settings.audio.type=Ausgabetype w\u00E4hlen:
 newProject.label.name=Name:
 newProject.label.sync=
-newProject.checkbox.sync=Cloud-Synchronisation aktivieren
+newProject.checkbox.sync=Cloud-Synchronisation aktivieren [BETA]
 newProject.label.profile=Profil:
 newProject.button.newProfile=Neues Profil...
 newProject.button.finish=Projekt erstellen
 newProject.button.cancel=Abbrechen
 newProfile.label.name=Name:
-newProfile.label.info=Geben Sie den Namen f\u00FCr das neue Profile ein.
+newProfile.label.info=Geben Sie den Namen f\u00FCr das neue Profil ein.
 newProfile.button.finish=Profil erstellen
 newProfile.button.cancel=Abbrechen
 profileChoose.label.info=Das verwendete Profil wurde nicht gefunden.\nBitte w\u00E4hlen Sie ein anderes Profil aus, welches verwendet werden soll.
 profileChoose.button.finish=Profil w\u00E4hlen
-doubleFeedback.label.colorEvent=Eventfarbe:
-doubleFeedback.label.colorDefault=Standardfarbe:
+
+feedback.label.colorDefault=Standardfarbe:
+feedback.label.colorEvent=Eventfarbe:
+feedback.label.colorWarning=Warnfarbe:
+
 cartAction.label.headline=Einstellungen zur Kachel:
 cartAction.label.type=Typ:
 cartAction.label.autoColor=Feedback-Farbe wie Layout:
@@ -215,3 +220,11 @@ carttrigger.label.add.placeholder=Hinzuf\u00FCgen (Name der Kachel)
 carttrigger.button.add=Hinzuf\u00FCgen
 volumetrigger.label.volume=Lautst\u00E4rke:
 volumetrigger.label.duration=\u00DCberblenddauer:
+
+PathMatchDialog.Label.Headline=Dateienverkn\u00FCpfung
+PathMatchDialog.Table.Column.Select=Auswahl
+PathMatchDialog.Table.Column.FileName=Dateiname
+PathMatchDialog.Table.Column.LocalPath=Lokaler Pfad
+PathMatchDialog.Table.Column.Action=Aktionen
+PathMatchDialog.Button.Cancel=Abbrechen
+PathMatchDialog.Button.Finish=\u00DCbernehmen
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/repository.yml b/PlayWall/src/main/resources/repository.yml
index 826913d6a55a055e639cc49a5322627074ad8573..e510bbbe0a70acb18a2b526dce7e4c99d9afebcd 100644
--- a/PlayWall/src/main/resources/repository.yml
+++ b/PlayWall/src/main/resources/repository.yml
@@ -1,4 +1,4 @@
-url: "https://maven.thecodelabs.de/artifactory"
+url: "https://maven.thecodedev.de/artifactory"
 repository:
   releases: "TheCodeLabs-release"
   snapshots: "TheCodeLabs-snapshots"
diff --git a/PlayWall/src/main/resources/style/components/button.css b/PlayWall/src/main/resources/style/components/button.css
deleted file mode 100644
index 193c8281d73e0a2723a78d15132f338541304a27..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/resources/style/components/button.css
+++ /dev/null
@@ -1,23 +0,0 @@
-.button {
-	-fx-background-color: #5c5c5c;
-	-fx-text-fill: #efefef;
-	-fx-background-radius: 3px;
-	-fx-font-size: 1.1em;
-	-fx-border-width: 0;
-}
-
-.button:focused {
-	-fx-background-color: #358dab;
-	/*-fx-background-color: #878787;*/
-	-fx-text-fill: #EEEEEE !important;
-}
-
-.button:hover {
-	-fx-background-color: #878787;
-	-fx-text-fill: #EEEEEE !important;
-}
-
-.button:default {
-	-fx-background-color: #358dab;
-	-fx-text-fill: #EEEEEE !important;
-}
diff --git a/PlayWall/src/main/resources/style/components/checkbox.css b/PlayWall/src/main/resources/style/components/checkbox.css
deleted file mode 100644
index f50428e06dade49292fbf4f6294c1bd55087049d..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/resources/style/components/checkbox.css
+++ /dev/null
@@ -1,24 +0,0 @@
-.check-box .box {
-	-fx-background-color: transparent;
-	-fx-background-insets: 1;
-	-fx-border-color: #CCCCCC;
-	-fx-border-radius: 3px;
-	-fx-border-width: 2px;
-}
-
-.check-box .mark {
-	-fx-background-color: transparent;
-	-fx-background-insets: 1 0 -1 0, 0;
-	-fx-padding: 0.333333em;
-	-fx-shape: "M14.596,2.055L12.455,0C9.687,2.884,6.011,6.714,5.158,7.602L2.055,4.624L0,6.765l5.242,5.037l0.003-0.004l0.003,0.004L14.596,2.055z";
-	-fx-scale-x: 1.5;
-	-fx-scale-y: 1.5;
-}
-
-.check-box:selected .mark {
-	-fx-background-color: #3E4251;
-}
-
-.check-box:selected .box {
-	-fx-background-color: #CCCCCC;
-}
diff --git a/PlayWall/src/main/resources/style/components/combobox.css b/PlayWall/src/main/resources/style/components/combobox.css
deleted file mode 100644
index fbb22d2ffe0fd9279ab4f9ed42f238a960fd9329..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/resources/style/components/combobox.css
+++ /dev/null
@@ -1,40 +0,0 @@
-.combo-box {
-	-fx-background-color: #5c5c5c;
-	-fx-background-radius: 3px;
-}
-
-.combo-box > .list-cell {
-	-fx-font-weight: bold;
-}
-
-.combo-box .list-cell {
-	-fx-background-color: #6d6d6d;
-	-fx-text-fill: #efefef;
-	-fx-pref-height: 30px;
-}
-
-.combo-box .list-cell:hover {
-	-fx-background-color: #878787;
-}
-
-.combo-box .list-cell:selected {
-	-fx-background-color: #358dab;
-}
-
-.combo-box > .list-cell:selected {
-	-fx-background-color: #5c5c5c;
-}
-
-.combo-box:editable .arrow-button {
-	-fx-background-color: #5c5c5c;
-}
-
-.combo-box .text-input {
-	-fx-border-color: #CCCCCC;
-	-fx-border-width: 1px;
-	-fx-border-radius: 2px;
-	-fx-background-color: transparent;
-	-fx-text-fill: white;
-	-fx-font-size: 14;
-	-fx-prompt-text-fill: #777777;
-}
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/style/components/list.css b/PlayWall/src/main/resources/style/components/list.css
deleted file mode 100644
index 3af0182f577cf2c89629d65d0306522c25003f4c..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/resources/style/components/list.css
+++ /dev/null
@@ -1,87 +0,0 @@
-/*projectList */
-.dark-list {
-	-fx-base: rgb(60, 60, 60);
-}
-
-.dark-list .list-cell {
-	-fx-skin: "com.sun.javafx.scene.control.skin.ListCellSkin";
-	-fx-background-color: -fx-base;
-	-fx-padding: 10px;
-	-fx-text-fill: #FFFFFF;
-	-fx-opacity: 1;
-}
-
-.dark-list .list-cell:filled {
-	/*-fx-background-color: derive(-fx-control-inner-background,-5%);*/
-	-fx-border-width: 0px 0px 1px 0px;
-	-fx-border-color: #00000044;
-}
-
-.dark-list .list-view:focused .list-cell:focused {
-	-fx-background-color: derive(-fx-hover-base, -50%);
-	-fx-background-insets: 0, 1, 2;
-}
-
-.dark-list .list-view:focused .list-cell:focused:odd {
-	-fx-background-color: derive(-fx-hover-base, -50%);
-	-fx-background-insets: 0, 1, 2;
-}
-
-/* When the list-cell is selected and focused */
-.dark-list .list-view:focused .list-cell:filled:focused:selected {
-	-fx-background-color: derive(-fx-hover-base, -50%);
-	-fx-background-insets: 0, 1, 2;
-	-fx-background: derive(-fx-base, -50%);
-	-fx-text-fill: #444444;
-}
-
-.dark-list .list-view:focused .list-cell:filled:selected, .dark-list .list-view:focused .list-cell:filled:selected:hover {
-	-fx-background: derive(-fx-base, -50%);
-	-fx-background-color: derive(-fx-hover-base, -50%);
-	-fx-text-fill: #444444;
-}
-
-.dark-list .list-view:focused .list-cell:filled:focused:selected:hover {
-	-fx-background: derive(-fx-base, -50%);
-	-fx-background-color: derive(-fx-hover-base, -50%);
-	-fx-background-insets: 0, 1, 2;
-	-fx-text-fill: #444444;
-}
-
-/* When the ListView is _not_ focused, we show alternate selection colors */
-.dark-list .list-cell:filled:selected:focused, .dark-list .list-cell:filled:selected, .list-view:horizontal .list-cell:filled:selected {
-	-fx-background-color: derive(-fx-base, +50%);
-	-fx-text-fill: #444444;
-}
-
-.dark-list .list-cell:filled:selected:focused:disabled, .dark-list .list-cell:filled:selected:disabled {
-	-fx-opacity: derive(-fx-hover-base, -50%);
-}
-
-.dark-list .list-cell:filled:hover {
-	-fx-background-color: -fx-hover-base;
-	-fx-text-fill: -fx-text-inner-color;
-}
-
-.dark-list .list-view:focused .list-cell:filled:focused:hover {
-	-fx-background-color: derive(-fx-hover-base, -50%);
-
-	-fx-background-insets: 0, 1, 2;
-	-fx-text-fill: -fx-text-inner-color;
-}
-
-.dark-list .list-view:horizontal .list-cell:filled:selected, .dark-list .list-view:horizontal .list-cell:filled:selected:hover {
-	-fx-background-color: derive(-fx-hover-base, -50%);
-	-fx-text-fill: #444444;
-}
-
-.projectname {
-	-fx-font-size: 14px;
-	-fx-text-fill: #FFFFFF;
-	-fx-font-weight: bold;
-}
-
-.profilename {
-	-fx-font-size: 10px;
-	-fx-text-fill: #DDDDDD;
-}
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/style/components/menu-button.css b/PlayWall/src/main/resources/style/components/menu-button.css
deleted file mode 100644
index 8900a89f88dcc76161ec632ed64072767fed2e52..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/resources/style/components/menu-button.css
+++ /dev/null
@@ -1,17 +0,0 @@
-.menu-button {
-	-fx-background-color: #5c5c5c;
-	-fx-text-fill: #efefef;
-	-fx-background-radius: 3px;
-	-fx-border-width: 0;
-	-fx-pref-height: 30px;
-}
-
-.menu-button:hover {
-	-fx-background-color: #878787;
-	-fx-text-fill: #EEEEEE !important;
-}
-
-.menu-button:default {
-	-fx-background-color: #358dab;
-	-fx-text-fill: #EEEEEE !important;
-}
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/style/components/menu.css b/PlayWall/src/main/resources/style/components/menu.css
deleted file mode 100644
index ba45618956d11bd7122b1bb89412f449d79a7e28..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/resources/style/components/menu.css
+++ /dev/null
@@ -1,16 +0,0 @@
-.menu-bar {
-	-fx-background-color: #333333;
-}
-
-.menu-bar .menu-button {
-	-fx-background-color: #333333;
-}
-
-.menu-bar .menu:showing, .menu-bar .menu:hover {
-	-fx-background-color: #358dab;
-	-fx-background-radius: 0px;
-}
-
-.menu-item:selected, .menu-item:focused {
-	-fx-background-color: #358dab;
-}
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/style/components/radiobutton.css b/PlayWall/src/main/resources/style/components/radiobutton.css
deleted file mode 100644
index ab9218e9ca0cd46c056dd34b5fba2979474253dc..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/resources/style/components/radiobutton.css
+++ /dev/null
@@ -1,24 +0,0 @@
-.radio-button .radio {
-	-fx-background-color: transparent;
-	-fx-background-insets: 1;
-	-fx-border-color: #CCCCCC;
-	-fx-border-radius: 30px;
-	-fx-border-width: 2px;
-}
-
-.radio-button .dot {
-	-fx-background-color: transparent;
-	-fx-background-insets: 0 0 0 0 0, 0;
-	-fx-padding: 0.333333em;
-	-fx-shape: "M-1,0a1,1 0 1,0 2,0a1,1 0 1,0 -2,0"; /* http://complexdan.com/svg-circleellipse-to-path-converter/ */
-	-fx-scale-x: 1.5;
-	-fx-scale-y: 1.5;
-}
-
-.radio-button:selected .dot {
-	-fx-background-color: #CCCCCC;
-}
-
-.radio-button:selected .radio {
-	-fx-background-color: #3E4251;
-}
diff --git a/PlayWall/src/main/resources/style/components/slider.css b/PlayWall/src/main/resources/style/components/slider.css
deleted file mode 100644
index f080e6b7c7f74a083b099b1d1ccc037aaef84382..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/resources/style/components/slider.css
+++ /dev/null
@@ -1,12 +0,0 @@
-.slider .track {
-	-fx-background-color: #5c5c5c;
-	-fx-background-radius: 3px;
-	-fx-background-insets: 1px;
-}
-
-.slider .thumb {
-	-fx-background-color: #CCCCCC;
-	-fx-padding: 0.333333em;
-	-fx-scale-x: 2;
-	-fx-scale-y: 2;
-}
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/style/components/tabs.css b/PlayWall/src/main/resources/style/components/tabs.css
deleted file mode 100644
index fd3ea90a781032074e5aa18c3729863ae6210792..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/resources/style/components/tabs.css
+++ /dev/null
@@ -1,14 +0,0 @@
-/*noinspection CssInvalidPseudoSelector*/
-.tab-pane:top *.tab-header-background {
-	-fx-background-color: #333333;
-}
-
-.tab-pane:top *.tab {
-	-fx-background-color: #5c5c5c;
-}
-
-.tab-pane:top *.tab:selected {
-	-fx-background-color: #358dab;
-	-fx-focus-color: transparent;
-	-fx-faint-focus-color: transparent;
-}
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/style/components/textfield.css b/PlayWall/src/main/resources/style/components/textfield.css
deleted file mode 100644
index 5d5a8939c0b3ed25352ee0a9a56e950db9b21f3b..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/resources/style/components/textfield.css
+++ /dev/null
@@ -1,9 +0,0 @@
-.text-field {
-	-fx-border-color: #CCCCCC;
-	-fx-border-width: 1px;
-	-fx-border-radius: 2px;
-	-fx-background-color: transparent;
-	-fx-text-fill: white;
-	-fx-font-size: 14;
-	-fx-prompt-text-fill: #777777;
-}
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/style/components/toggle-button.css b/PlayWall/src/main/resources/style/components/toggle-button.css
deleted file mode 100644
index b21e51da2101be487adb9d69038c3745ea2b52fe..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/resources/style/components/toggle-button.css
+++ /dev/null
@@ -1,20 +0,0 @@
-.toggle-button {
-	-fx-background-color: #5c5c5c;
-	-fx-text-fill: #efefef;
-}
-
-.toggle-button:focused {
-	-fx-background-color: #358dab;
-	/*-fx-background-color: #878787;*/
-	-fx-text-fill: #EEEEEE !important;
-}
-
-.toggle-button:hover {
-	-fx-background-color: #878787;
-	-fx-text-fill: #EEEEEE !important;
-}
-
-.toggle-button:selected {
-	-fx-background-color: #dbdbdb;
-	-fx-text-fill: #333333 !important;
-}
diff --git a/PlayWall/src/main/resources/style/modern-global.css b/PlayWall/src/main/resources/style/modern-global.css
index 46e6d8940370b0ff3c2376ca8f69d378feb1c104..30c997e4af0d850b0bf01a593321f22d5fa5f1e2 100644
--- a/PlayWall/src/main/resources/style/modern-global.css
+++ b/PlayWall/src/main/resources/style/modern-global.css
@@ -21,6 +21,10 @@
 	-fx-background-color: ${#padColor};
 }
 
+.pad-cue-in${#class} {
+	-fx-background-color: ${#padCueInColor};
+}
+
 .pad-info${#class} {
 	-fx-text-fill: ${#fontColor};
 	-fx-font-size: ${#infoFontSize};
diff --git a/PlayWall/src/main/resources/style/modern-pad.css b/PlayWall/src/main/resources/style/modern-pad.css
index 32f6e10fa0efe158978874ac93eb51bdbd6c92ce..abd17dbdf936ab7d80a0c9fd7a022c98935d9669 100644
--- a/PlayWall/src/main/resources/style/modern-pad.css
+++ b/PlayWall/src/main/resources/style/modern-pad.css
@@ -21,6 +21,11 @@
 	-fx-background-color: ${#padColor};
 }
 
+.pad${#prefix}-cue-in${#class} {
+	-fx-background-color: ${#padCueInColor};
+}
+
+
 .pad${#prefix}-info${#class} {
 	-fx-text-fill: ${#fontColor};
 }
diff --git a/PlayWall/src/main/resources/style/style.css b/PlayWall/src/main/resources/style/style.css
index a413e0b0b09f343ba8c67dbcfe57178906ccca58..1b3a8e9df6eda7ef86c52866e9d5e2d8317df962 100644
--- a/PlayWall/src/main/resources/style/style.css
+++ b/PlayWall/src/main/resources/style/style.css
@@ -1,6 +1,5 @@
 .text-field:error {
-	-fx-text-box-border: red;
-	-fx-focus-color: red;
+	-fx-border-color: red !important;
 }
 
 .color-view-item {
diff --git a/PlayWall/src/main/resources/style/touch.css b/PlayWall/src/main/resources/style/touch.css
index cf359ea800e9c676a32b703490558d126056c13e..b7dfd72a61a695ec760b90abaf6c03e4ddab216a 100644
--- a/PlayWall/src/main/resources/style/touch.css
+++ b/PlayWall/src/main/resources/style/touch.css
@@ -8,7 +8,7 @@
 }
 
 .button {
-	-fx-font-size: 1.4em;
+	-fx-font-size: 1.5em !important;
 }
 
 .slider .track {
@@ -16,8 +16,8 @@
 }
 
 .slider .thumb {
-	-fx-pref-height: 25px;
-	-fx-pref-width: 25px;
+	-fx-pref-height: 22px;
+	-fx-pref-width: 22px;
 }
 
 .close-button > .graphic {
@@ -25,6 +25,9 @@
 	-fx-scale-shape: false;
 	-fx-padding: 1;
 
+	-fx-min-height: 35px;
+	-fx-min-width: 50px;
+
 	-fx-scale-x: 1.8;
 	-fx-scale-y: 1.8;
 	-fx-shape: "M395.992,296.758l1.794-1.794l7.292,7.292l-1.795,1.794 L395.992,296.758z M403.256,294.992l1.794,1.794l-7.292,7.292l-1.794-1.795 L403.256,294.992z";
diff --git a/PlayWall/src/main/resources/view/SplashScreen.fxml b/PlayWall/src/main/resources/view/SplashScreen.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..6c756d4c4508492fc5aa89bb43ba528adc549ca4
--- /dev/null
+++ b/PlayWall/src/main/resources/view/SplashScreen.fxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.*?>
+<?import javafx.scene.image.Image?>
+<?import javafx.scene.image.ImageView?>
+<?import javafx.scene.layout.*?>
+<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="414.0" prefWidth="700.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
+   <children>
+      <ImageView fitHeight="350.0" fitWidth="350.0" layoutX="386.0" layoutY="14.0" pickOnBounds="true" preserveRatio="true" AnchorPane.bottomAnchor="28.0" AnchorPane.rightAnchor="28.0" AnchorPane.topAnchor="28.0">
+         <image>
+            <Image url="@../icon_large.png" />
+         </image>
+      </ImageView>
+      <ProgressBar fx:id="progressBar" layoutX="14.0" layoutY="366.0" prefHeight="7.0" prefWidth="772.0" progress="0.39" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" />
+      <Label layoutX="14.0" layoutY="352.0" text="Loading ..." AnchorPane.bottomAnchor="46.0" AnchorPane.leftAnchor="14.0" />
+      <Label fx:id="titleLabel" layoutX="25.0" layoutY="29.0" styleClass="title" text="PlayWall" AnchorPane.leftAnchor="25.0" AnchorPane.topAnchor="25.0" />
+      <Label fx:id="versionLabel" layoutX="25.0" layoutY="93.0" styleClass="subtitle" text="Version 6.2.0" AnchorPane.leftAnchor="25.0" AnchorPane.topAnchor="90.0" />
+      <Label fx:id="loadingLabel" layoutX="14.0" layoutY="368.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="14.0" />
+   </children>
+</AnchorPane>
diff --git a/PlayWall/src/main/resources/view/dialog/LaunchDialog.fxml b/PlayWall/src/main/resources/view/dialog/LaunchDialog.fxml
index 0edc1cb962d4daef7f1f593e85272f83726549d4..08980f9233284693e6e1b83b30aec53e1a9b3d5d 100644
--- a/PlayWall/src/main/resources/view/dialog/LaunchDialog.fxml
+++ b/PlayWall/src/main/resources/view/dialog/LaunchDialog.fxml
@@ -19,7 +19,6 @@
                     <children>
                         <Button fx:id="newProjectButton" layoutX="115.0" layoutY="259.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#newProjectButtonHandler" text="%launch.button.new" VBox.vgrow="ALWAYS" />
                         <Button fx:id="importProject" layoutX="109.0" layoutY="292.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#importProjectButtonHandler" text="%launch.button.import" VBox.vgrow="ALWAYS" />
-                        <Button fx:id="convertProjectButton" layoutX="109.0" layoutY="292.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#convertProjectButtonHandler" text="%launch.button.convert" VBox.vgrow="ALWAYS" />
                       <Label fx:id="cloudLabel" graphicTextGap="8.0" onMouseClicked="#cloudIconClicked" />
                     </children>
                 </VBox>
diff --git a/PlayWall/src/main/resources/view/dialog/NotFoundDialog.fxml b/PlayWall/src/main/resources/view/dialog/PathMatchDialog.fxml
similarity index 69%
rename from PlayWall/src/main/resources/view/dialog/NotFoundDialog.fxml
rename to PlayWall/src/main/resources/view/dialog/PathMatchDialog.fxml
index b2eef3cd1e8d96314a72bee36ded45d927360212..aea7ca1f70836946d4f963ba4f21795015678d1e 100644
--- a/PlayWall/src/main/resources/view/dialog/NotFoundDialog.fxml
+++ b/PlayWall/src/main/resources/view/dialog/PathMatchDialog.fxml
@@ -8,20 +8,20 @@
 <VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" spacing="14.0"
       xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
     <children>
-        <Label text="Dateienverknüpfung:" underline="true"/>
+        <Label text="%PathMatchDialog.Label.Headline" styleClass="headline"/>
         <TableView fx:id="table" editable="true" VBox.vgrow="ALWAYS">
             <columns>
-                <TableColumn fx:id="selectColumn" prefWidth="75.0" text="Auswahl"/>
-                <TableColumn fx:id="filenameColumn" minWidth="200.0" prefWidth="75.0" text="Dateiname"/>
-                <TableColumn fx:id="localPathColumn" minWidth="300.0" prefWidth="75.0" text="Lokaler Pfad"/>
-                <TableColumn fx:id="actionColumn" prefWidth="75.0" text="Aktionen"/>
+                <TableColumn fx:id="selectColumn" prefWidth="75.0" text="%PathMatchDialog.Table.Column.Select"/>
+                <TableColumn fx:id="filenameColumn" minWidth="200.0" prefWidth="75.0" text="%PathMatchDialog.Table.Column.FileName"/>
+                <TableColumn fx:id="localPathColumn" minWidth="500.0" prefWidth="75.0" text="%PathMatchDialog.Table.Column.LocalPath"/>
+                <TableColumn fx:id="actionColumn" prefWidth="75.0" text="%PathMatchDialog.Table.Column.Action"/>
             </columns>
         </TableView>
         <HBox alignment="CENTER_LEFT" spacing="14.0">
             <children>
                 <Label fx:id="statusLabel" maxWidth="1.7976931348623157E308" text="Label" HBox.hgrow="ALWAYS"/>
-                <Button fx:id="cancelButton" mnemonicParsing="false" onAction="#cancelHandler" text="Abbrechen"/>
-                <Button fx:id="finishButton" mnemonicParsing="false" onAction="#finishHandler" text="Übernehmen"/>
+                <Button fx:id="cancelButton" mnemonicParsing="false" onAction="#cancelHandler" text="%PathMatchDialog.Button.Cancel"/>
+                <Button fx:id="finishButton" mnemonicParsing="false" onAction="#finishHandler" text="%PathMatchDialog.Button.Finish"/>
             </children>
         </HBox>
     </children>
diff --git a/PlayWall/src/main/resources/view/dialog/PluginDialog.fxml b/PlayWall/src/main/resources/view/dialog/PluginDialog.fxml
index 669f1037f7eb20068076497a1d9b6f67319c8748..a4f2758ca28c630f8ef37229e878a116dadc6b2c 100644
--- a/PlayWall/src/main/resources/view/dialog/PluginDialog.fxml
+++ b/PlayWall/src/main/resources/view/dialog/PluginDialog.fxml
@@ -1,36 +1,33 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-
 <?import javafx.geometry.Insets?>
 <?import javafx.scene.control.*?>
 <?import javafx.scene.layout.*?>
-<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
-      prefWidth="600.0" spacing="14.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
+<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" spacing="14.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
     <children>
-        <VBox minWidth="200.0" spacing="14.0">
+        <VBox maxWidth="300.0" minWidth="300.0" spacing="14.0">
             <children>
                 <TextField fx:id="searchField" promptText="Suche...">
                     <VBox.margin>
-                        <Insets/>
+                        <Insets />
                     </VBox.margin>
                 </TextField>
-                <ListView fx:id="pluginList"/>
+                <ListView fx:id="pluginList" />
             </children>
             <HBox.margin>
-                <Insets/>
+                <Insets />
             </HBox.margin>
         </VBox>
         <VBox spacing="14.0">
             <children>
-                <Label fx:id="pluginHeadlineLabel" styleClass="plugin-headline" text="Headline"/>
-                <Button fx:id="pluginInstallButton" mnemonicParsing="false" onAction="#pluginInstallHandler"
-                        text="Installieren"/>
-                <Label fx:id="pluginVersionLabel" text="Aktuelle Version: 1.4.2"/>
-                <Label fx:id="pluginInfoLabel" wrapText="true"/>
+                <Label fx:id="pluginHeadlineLabel" styleClass="plugin-headline" text="Headline" />
+                <Button fx:id="pluginInstallButton" mnemonicParsing="false" onAction="#pluginInstallHandler" text="Installieren" />
+                <Label fx:id="pluginVersionLabel" text="Aktuelle Version: 1.4.2" />
+                <Label fx:id="pluginInfoLabel" wrapText="true" />
             </children>
         </VBox>
     </children>
     <padding>
-        <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/>
+        <Insets bottom="14.0" left="14.0" right="14.0" top="14.0" />
     </padding>
 </HBox>
diff --git a/PlayWall/src/main/resources/view/main/desktop/Header.fxml b/PlayWall/src/main/resources/view/main/desktop/Header.fxml
index 6030f40d1d7119f987f6e305a42a988cd4ec38b7..e18a7a14f0c5dc5fcc12236a2b8e9bd522902747 100644
--- a/PlayWall/src/main/resources/view/main/desktop/Header.fxml
+++ b/PlayWall/src/main/resources/view/main/desktop/Header.fxml
@@ -92,8 +92,6 @@
                                                     shortcut="DOWN"/>
                             </accelerator>
                         </MenuItem>
-                        <MenuItem fx:id="logMenuItem" mnemonicParsing="false" onAction="#logMenuItemHandler"
-                                  text="%main.menuitem.log"/>
                         <SeparatorMenuItem mnemonicParsing="false"/>
                         <MenuItem fx:id="pluginMenu" mnemonicParsing="false" onAction="#pluginMenuItemHandler"
                                   text="%main.menuitem.plugins"/>
@@ -139,7 +137,7 @@
                         <MenuItem mnemonicParsing="false" onAction="#aboutMenuHandler" text="%main.menuitem.about"/>
                         <MenuItem mnemonicParsing="false" onAction="#showChangelogMenuHandler"
                                   text="%main.menuitem.changelog"/>
-                        <MenuItem mnemonicParsing="false" onAction="#visiteWebsiteMenuHandler"
+                        <MenuItem mnemonicParsing="false" onAction="#visitWebsiteMenuHandler"
                                   text="%main.menuitem.website"/>
                     </items>
                 </Menu>
diff --git a/PlayWall/src/main/resources/view/option/feedback/SingleFeedback.fxml b/PlayWall/src/main/resources/view/option/feedback/SingleFeedback.fxml
index 8562170777ecc5e76b32d0a945b912939f35edc3..bb4dbb8423f41ed17a29e2f5c3d6adc420f40cbe 100644
--- a/PlayWall/src/main/resources/view/option/feedback/SingleFeedback.fxml
+++ b/PlayWall/src/main/resources/view/option/feedback/SingleFeedback.fxml
@@ -9,12 +9,11 @@
     <children>
         <HBox fx:id="defaultColorParent" alignment="CENTER_LEFT" maxWidth="1.7976931348623157E308" spacing="14.0">
             <children>
-                <Label alignment="CENTER_RIGHT" layoutX="24.0" layoutY="237.0" prefWidth="150.0"
-                       text="%doubleFeedback.label.colorDefault"/>
+                <Label fx:id="nameLabel" alignment="CENTER_RIGHT" layoutX="24.0" layoutY="237.0" prefWidth="150.0"/>
                 <StackPane layoutX="122.0" layoutY="232.0" maxWidth="1.7976931348623157E308" prefWidth="150.0"
                            HBox.hgrow="ALWAYS">
                     <children>
-                        <Rectangle fx:id="colorPreviewDefault" arcHeight="5.0" arcWidth="5.0" fill="DODGERBLUE"
+                        <Rectangle fx:id="colorPreviewDefault" arcHeight="5.0" arcWidth="5.0" fill="WHITE"
                                    height="26.0" layoutX="122.0" layoutY="272.0" stroke="BLACK" strokeType="INSIDE"
                                    width="128.0" StackPane.alignment="CENTER_LEFT"/>
                         <Button fx:id="colorChooseDefaultButton" alignment="CENTER_RIGHT" layoutX="122.0"
diff --git a/PlayWall/src/main/resources/view/option/layout/ModernLayoutCart.fxml b/PlayWall/src/main/resources/view/option/layout/ModernLayoutCart.fxml
index 4d04cebaf30b25384418f7e4a68364c3af1681bd..4d3d165be6852b06cfdf2750f2bb8af7b6be3023 100644
--- a/PlayWall/src/main/resources/view/option/layout/ModernLayoutCart.fxml
+++ b/PlayWall/src/main/resources/view/option/layout/ModernLayoutCart.fxml
@@ -28,11 +28,19 @@
                 <VBox layoutX="243.0" layoutY="8.0" maxWidth="1.7976931348623157E308" prefWidth="125.0" spacing="14.0">
                     <children>
                         <Label alignment="BOTTOM_LEFT" layoutX="243.0" layoutY="8.0" prefHeight="60.0" prefWidth="150.0"
-                               text="%layout.label.playground" wrapText="true" VBox.vgrow="ALWAYS"/>
+                               text="%layout.label.play" wrapText="true" VBox.vgrow="ALWAYS"/>
                         <Button fx:id="playColorButton" focusTraversable="false" mnemonicParsing="false"
                                 onAction="#playColorButtonHandler" prefWidth="150.0"/>
                     </children>
                 </VBox>
+                <VBox layoutX="243.0" layoutY="8.0" maxWidth="1.7976931348623157E308" prefWidth="125.0" spacing="14.0">
+                    <children>
+                        <Label alignment="BOTTOM_LEFT" layoutX="243.0" layoutY="8.0" prefHeight="60.0" prefWidth="150.0"
+                               text="%layout.label.cueIn" wrapText="true" VBox.vgrow="ALWAYS"/>
+                        <Button fx:id="cueInColorButton" focusTraversable="false" mnemonicParsing="false"
+                                onAction="#cueInColorButtonHandler" prefWidth="150.0"/>
+                    </children>
+                </VBox>
             </children>
         </HBox>
         <Button fx:id="resetButton" mnemonicParsing="false" onAction="#resetButtonHandler" text="%layout.button.reset">
diff --git a/PlayWall/src/main/resources/view/option/layout/ModernLayoutGlobal.fxml b/PlayWall/src/main/resources/view/option/layout/ModernLayoutGlobal.fxml
index f894e0de6559263040b81482ca70b51d308740d0..f6824e995126af2c8498931f52ff3356795fcb46 100644
--- a/PlayWall/src/main/resources/view/option/layout/ModernLayoutGlobal.fxml
+++ b/PlayWall/src/main/resources/view/option/layout/ModernLayoutGlobal.fxml
@@ -28,11 +28,20 @@
                 <VBox layoutX="243.0" layoutY="8.0" maxWidth="1.7976931348623157E308" prefWidth="150.0" spacing="14.0">
                     <children>
                         <Label alignment="BOTTOM_LEFT" layoutX="243.0" layoutY="8.0" prefHeight="60.0" prefWidth="150.0"
-                               text="%layout.label.playground" wrapText="true" VBox.vgrow="ALWAYS"/>
+                               text="%layout.label.play" wrapText="true" VBox.vgrow="ALWAYS"/>
                         <Button fx:id="playColorButton" focusTraversable="false" mnemonicParsing="false"
                                 onAction="#playColorButtonHandler" prefWidth="150.0"/>
                     </children>
                 </VBox>
+                <VBox layoutX="243.0" layoutY="8.0" maxWidth="1.7976931348623157E308" prefWidth="150.0" spacing="14.0">
+                    <children>
+                        <Label alignment="BOTTOM_LEFT" layoutX="243.0" layoutY="8.0" prefHeight="60.0" prefWidth="150.0"
+                               text="%layout.label.cueIn" wrapText="true" VBox.vgrow="ALWAYS"/>
+                        <Button fx:id="cueInColorButton" focusTraversable="false" mnemonicParsing="false"
+                                onAction="#cueInColorButtonHandler" prefWidth="150.0"/>
+                    </children>
+                </VBox>
+
                 <VBox maxWidth="1.7976931348623157E308" prefWidth="150.0" spacing="14.0">
                     <children>
                         <Label alignment="BOTTOM_LEFT" layoutX="243.0" layoutY="8.0" prefHeight="60.0" prefWidth="150.0"
diff --git a/PlayWall/src/main/resources/view/option/pad/PlayerTab.fxml b/PlayWall/src/main/resources/view/option/pad/PlayerTab.fxml
index fc2fb7abdbd2a309beca248e8132eb15856d8715..9f5771e57c8f2ffd7234c4c002ec2b7de8a800d5 100644
--- a/PlayWall/src/main/resources/view/option/pad/PlayerTab.fxml
+++ b/PlayWall/src/main/resources/view/option/pad/PlayerTab.fxml
@@ -3,37 +3,44 @@
 <?import javafx.geometry.Insets?>
 <?import javafx.scene.control.*?>
 <?import javafx.scene.layout.*?>
-<VBox spacing="14.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
+<VBox spacing="14.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
     <children>
         <VBox spacing="14.0">
             <children>
                 <HBox layoutX="14.0" layoutY="253.0" spacing="14.0">
                     <children>
-                        <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%padSettings.player.label.fade"
-                               textAlignment="RIGHT"/>
-                        <CheckBox fx:id="customFadeCheckBox" mnemonicParsing="false"
-                                  text="%padSettings.gen.checkbox.customSettings"/>
+                        <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%padSettings.player.label.fade" textAlignment="RIGHT" />
+                        <CheckBox fx:id="customFadeCheckBox" mnemonicParsing="false" text="%padSettings.gen.checkbox.customSettings" />
                     </children>
                 </HBox>
             </children>
         </VBox>
-        <VBox fx:id="fadeContainer" minHeight="20.0"/>
-        <Separator prefWidth="200.0"/>
+        <VBox fx:id="fadeContainer" minHeight="20.0" />
+        <Separator prefWidth="200.0" />
         <VBox layoutX="14.0" layoutY="139.0" spacing="14.0">
             <children>
                 <HBox layoutX="14.0" layoutY="139.0" spacing="14.0">
                     <children>
-                        <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%padSettings.player.label.warning"
-                               textAlignment="RIGHT"/>
-                        <CheckBox fx:id="warningEnableCheckBox" mnemonicParsing="false"
-                                  text="%padSettings.gen.checkbox.customSettings"/>
+                        <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%padSettings.player.label.warning" textAlignment="RIGHT" />
+                        <CheckBox fx:id="warningEnableCheckBox" mnemonicParsing="false" text="%padSettings.gen.checkbox.customSettings" />
                     </children>
                 </HBox>
-                <VBox fx:id="warningFeedbackContainer" minHeight="25.0"/>
+                <VBox fx:id="warningFeedbackContainer" minHeight="25.0" />
             </children>
         </VBox>
+      <Separator prefWidth="200.0" />
+      <VBox spacing="14.0">
+         <children>
+            <HBox alignment="CENTER_LEFT" layoutX="14.0" layoutY="139.0" spacing="14.0">
+               <children>
+                  <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%padSettings.player.label.cueIn" textAlignment="RIGHT" />
+                   <TextField fx:id="cueInTextField" />
+               </children>
+            </HBox>
+         </children>
+      </VBox>
     </children>
     <padding>
-        <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/>
+        <Insets bottom="14.0" left="14.0" right="14.0" top="14.0" />
     </padding>
 </VBox>
diff --git a/PlayWall/src/main/resources/view/option/profile/Mapping.fxml b/PlayWall/src/main/resources/view/option/profile/Mapping.fxml
index 28e2eac28e61ff26daaf9cbdd99e56b77eeacbde..d52b331da82a236ee33b08ed1d95c7ddf8efd3a0 100644
--- a/PlayWall/src/main/resources/view/option/profile/Mapping.fxml
+++ b/PlayWall/src/main/resources/view/option/profile/Mapping.fxml
@@ -1,29 +1,22 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<?import javafx.geometry.Insets?>
+<?import javafx.geometry.*?>
 <?import javafx.scene.control.*?>
 <?import javafx.scene.layout.*?>
-<VBox spacing="14.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
+<VBox spacing="14.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
     <children>
         <HBox layoutX="14.0" layoutY="14.0" spacing="14.0">
             <children>
-                <Label alignment="BASELINE_RIGHT" layoutX="14.0" layoutY="19.0" maxHeight="1.7976931348623157E308"
-                       prefWidth="150.0" text="%settings.mapping.label.mapping"/>
-                <ComboBox fx:id="mappingComboBox" layoutX="100.0" layoutY="14.0" prefWidth="150.0"/>
+                <Label alignment="BASELINE_RIGHT" layoutX="14.0" layoutY="19.0" maxHeight="1.7976931348623157E308" prefWidth="150.0" text="%settings.mapping.label.mapping" />
+                <ComboBox fx:id="mappingComboBox" layoutX="100.0" layoutY="14.0" prefWidth="150.0" />
                 <MenuButton mnemonicParsing="false" text="%settings.mapping.button.edit">
                     <items>
-                        <MenuItem fx:id="mappingNewButton" mnemonicParsing="false" onAction="#mappingNewHandler"
-                                  text="%settings.mapping.button.edit.new"/>
-                        <MenuItem fx:id="mappingRenameButton" mnemonicParsing="false" onAction="#mappingRenameHandler"
-                                  text="%settings.mapping.button.edit.rename"/>
-                        <MenuItem fx:id="mappingDeleteButton" mnemonicParsing="false" onAction="#mappingDeleteHandler"
-                                  text="%settings.mapping.button.edit.delete"/>
-                        <MenuItem fx:id="mappingDuplicateButton" mnemonicParsing="false"
-                                  onAction="#mappingDuplicateHandler" text="%settings.mapping.button.edit.duplicate"/>
-                        <MenuItem fx:id="mappingImportButton" mnemonicParsing="false" onAction="#mappingImportHandler"
-                                  text="%settings.mapping.button.edit.import"/>
-                        <MenuItem fx:id="mappingExportButton" mnemonicParsing="false" onAction="#mappingExportHandler"
-                                  text="%settings.mapping.button.edit.export"/>
+                        <MenuItem fx:id="mappingNewButton" mnemonicParsing="false" onAction="#mappingNewHandler" text="%settings.mapping.button.edit.new" />
+                        <MenuItem fx:id="mappingRenameButton" mnemonicParsing="false" onAction="#mappingRenameHandler" text="%settings.mapping.button.edit.rename" />
+                        <MenuItem fx:id="mappingDeleteButton" mnemonicParsing="false" onAction="#mappingDeleteHandler" text="%settings.mapping.button.edit.delete" />
+                        <MenuItem fx:id="mappingDuplicateButton" mnemonicParsing="false" onAction="#mappingDuplicateHandler" text="%settings.mapping.button.edit.duplicate" />
+                        <MenuItem fx:id="mappingImportButton" mnemonicParsing="false" onAction="#mappingImportHandler" text="%settings.mapping.button.edit.import" />
+                        <MenuItem fx:id="mappingExportButton" mnemonicParsing="false" onAction="#mappingExportHandler" text="%settings.mapping.button.edit.export" />
                     </items>
                 </MenuButton>
             </children>
@@ -32,40 +25,51 @@
             <children>
                 <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%settings.midi.label.midiDeviceImpl">
                     <HBox.margin>
-                        <Insets top="4.0"/>
+                        <Insets top="4.0" />
                     </HBox.margin>
                 </Label>
                 <HBox maxWidth="1.7976931348623157E308" spacing="14.0" HBox.hgrow="ALWAYS">
                     <children>
-                        <ComboBox fx:id="deviceComboBox" onAction="#deviceHandler" prefWidth="150.0"/>
+                        <ComboBox fx:id="deviceComboBox" onAction="#deviceHandler" prefWidth="150.0" />
                         <CheckBox fx:id="midiActiveCheckBox" mnemonicParsing="false" text="%settings.checkbox.activate">
                             <padding>
-                                <Insets top="5.0"/>
+                                <Insets top="5.0" />
                             </padding>
                             <HBox.margin>
-                                <Insets top="4.0"/>
+                                <Insets top="4.0" />
                             </HBox.margin>
                         </CheckBox>
                     </children>
                 </HBox>
             </children>
         </HBox>
-        <HBox layoutY="50.0" spacing="14.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
-              AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="50.0" VBox.vgrow="ALWAYS">
+      <HBox spacing="14.0">
+         <children>
+            <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%settings.label.lightmode">
+               <HBox.margin>
+                  <Insets top="4.0" />
+               </HBox.margin>
+            </Label>
+            <HBox maxWidth="1.7976931348623157E308" spacing="14.0" HBox.hgrow="ALWAYS">
+               <children>
+                  <ComboBox fx:id="lightModeComboBox" onAction="#deviceHandler" prefWidth="150.0" />
+                  <Label text="%settings.label.lightmode.info" />
+               </children>
+            </HBox>
+         </children>
+      </HBox>
+        <HBox layoutY="50.0" spacing="14.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="50.0" VBox.vgrow="ALWAYS">
             <children>
-                <TreeView fx:id="treeView" prefHeight="400.0" prefWidth="200.0" showRoot="false"
-                          AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="50.0"/>
-                <ScrollPane fitToWidth="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
-                            style="-fx-background-color: transparent;" HBox.hgrow="ALWAYS">
+                <TreeView fx:id="treeView" prefHeight="400.0" prefWidth="200.0" showRoot="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="50.0" />
+                <ScrollPane fitToWidth="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" style="-fx-background-color: transparent;" HBox.hgrow="ALWAYS">
                     <content>
-                        <VBox fx:id="detailView" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
-                              spacing="14.0"/>
+                        <VBox fx:id="detailView" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" spacing="14.0" />
                     </content>
                 </ScrollPane>
             </children>
         </HBox>
     </children>
     <padding>
-        <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/>
+        <Insets bottom="14.0" left="14.0" right="14.0" top="14.0" />
     </padding>
 </VBox>
diff --git a/PlayWall/src/main/sass/components/button.scss b/PlayWall/src/main/sass/components/button.scss
new file mode 100644
index 0000000000000000000000000000000000000000..be8b1559bf573f0054274280785fb857b4d683bb
--- /dev/null
+++ b/PlayWall/src/main/sass/components/button.scss
@@ -0,0 +1,24 @@
+@import "variables";
+
+.button {
+	-fx-background-color: #5c5c5c;
+	-fx-text-fill: $component-text-color;
+	-fx-background-radius: 3px;
+	-fx-font-size: 1.1em;
+	-fx-border-width: 0;
+
+	&:focused {
+		-fx-background-color: $component-focus-background-color;
+		-fx-text-fill: $component-text-color;
+	}
+
+	&:hover {
+		-fx-background-color: $component-hover-background-color;
+		-fx-text-fill: $component-text-color;
+	}
+
+	&:default {
+		-fx-background-color: $component-focus-background-color;
+		-fx-text-fill: $component-text-color;
+	}
+}
diff --git a/PlayWall/src/main/sass/components/checkbox.scss b/PlayWall/src/main/sass/components/checkbox.scss
new file mode 100644
index 0000000000000000000000000000000000000000..a3d737cfce7ea6ef287d934ba356256fe3130339
--- /dev/null
+++ b/PlayWall/src/main/sass/components/checkbox.scss
@@ -0,0 +1,28 @@
+@import "variables";
+
+.check-box {
+	.box {
+		-fx-background-color: transparent;
+		-fx-background-insets: 1;
+		-fx-border-color: #CCCCCC;
+		-fx-border-radius: 3px;
+		-fx-border-width: 2px;
+	}
+
+	.mark {
+		-fx-background-color: transparent;
+		-fx-background-insets: 1 0 -1 0, 0;
+		-fx-padding: 0.333333em;
+		-fx-shape: "M14.596,2.055L12.455,0C9.687,2.884,6.011,6.714,5.158,7.602L2.055,4.624L0,6.765l5.242,5.037l0.003-0.004l0.003,0.004L14.596,2.055z";
+		-fx-scale-x: 1.5;
+		-fx-scale-y: 1.5;
+	}
+
+	&:selected .mark {
+		-fx-background-color: #3E4251;
+	}
+
+	&:selected .box {
+		-fx-background-color: #CCCCCC;
+	}
+}
diff --git a/PlayWall/src/main/sass/components/combobox.scss b/PlayWall/src/main/sass/components/combobox.scss
new file mode 100644
index 0000000000000000000000000000000000000000..26e91049a72a08da07e10853f5b5deeb0259232b
--- /dev/null
+++ b/PlayWall/src/main/sass/components/combobox.scss
@@ -0,0 +1,46 @@
+@import "variables";
+
+.combo-box {
+	-fx-background-color: $component-background-color;
+	-fx-background-radius: 3px;
+
+
+	.list-cell {
+		-fx-background-color: #6d6d6d;
+		-fx-text-fill: $component-text-color;
+		-fx-pref-height: 30px;
+	}
+
+	.list-cell:hover {
+		-fx-background-color: $component-hover-background-color;
+	}
+
+	.list-cell:selected {
+		-fx-background-color: $component-focus-background-color;
+	}
+
+	&:editable .arrow-button {
+		-fx-background-color: $component-background-color;
+	}
+
+	.text-input {
+		-fx-border-color: $component-border-color;
+		-fx-border-width: $component-border-width;
+		-fx-border-radius: $component-border-radius;
+
+		-fx-background-color: $textfield-background;
+
+		-fx-text-fill: $component-text-color;
+		-fx-prompt-text-fill: $textfield-prompt-color;
+
+		-fx-font-size: $textfield-font-size;
+	}
+}
+
+.combo-box > .list-cell {
+	-fx-font-weight: bold;
+}
+
+.combo-box > .list-cell:selected {
+	-fx-background-color: $component-background-color;
+}
diff --git a/PlayWall/src/main/resources/style/components/dialog.css b/PlayWall/src/main/sass/components/dialog.scss
similarity index 84%
rename from PlayWall/src/main/resources/style/components/dialog.css
rename to PlayWall/src/main/sass/components/dialog.scss
index 07c0d52e49a1022966f39cf062e523d96632b6e2..685955e1bac79643245bc615b5ef2b7aedb3a67e 100644
--- a/PlayWall/src/main/resources/style/components/dialog.css
+++ b/PlayWall/src/main/sass/components/dialog.scss
@@ -1,3 +1,5 @@
+@import "variables";
+
 /*noinspection CssInvalidPseudoSelector*/
 .dialog-pane:header *.header-panel {
 	-fx-background-color: rgb(70, 70, 70);
diff --git a/PlayWall/src/main/sass/components/list.scss b/PlayWall/src/main/sass/components/list.scss
new file mode 100644
index 0000000000000000000000000000000000000000..1ea1f4bc53dc52ac2bfb04568b503e2d64412451
--- /dev/null
+++ b/PlayWall/src/main/sass/components/list.scss
@@ -0,0 +1,82 @@
+@import "variables";
+
+.dark-list {
+	-fx-base: rgb(60, 60, 60);
+
+
+	.list-cell {
+		-fx-skin: "com.sun.javafx.scene.control.skin.ListCellSkin";
+		-fx-background-color: -fx-base;
+		-fx-padding: 10px;
+		-fx-text-fill: #FFFFFF;
+		-fx-opacity: 1;
+
+		&:filled {
+			-fx-border-width: 0px 0px 1px 0px;
+			-fx-border-color: #00000044;
+		}
+	}
+
+	.list-view:focused {
+		.list-cell:focused {
+			-fx-background-color: derive(-fx-hover-base, -50%);
+			-fx-background-insets: 0, 1, 2;
+
+			&:odd {
+				@extend .list-cell, :focused;
+			}
+		}
+
+		/* When the list-cell is selected and focused */
+		.list-cell:filled:focused:selected {
+			-fx-background-color: derive(-fx-hover-base, -50%);
+			-fx-background-insets: 0, 1, 2;
+			-fx-background: derive(-fx-base, -50%);
+			-fx-text-fill: $component-text-color;
+		}
+
+		.list-cell:filled:selected {
+			-fx-background: derive(-fx-base, -50%);
+			-fx-background-color: derive(-fx-hover-base, -50%);
+			-fx-text-fill: $component-text-color;
+
+			&:hover {
+				@extend .list-cell, :filled, :selected;
+			}
+		}
+
+		.list-cell:filled:focused:selected:hover {
+			-fx-background: derive(-fx-base, -50%);
+			-fx-background-color: derive(-fx-hover-base, -50%);
+			-fx-background-insets: 0, 1, 2;
+			-fx-text-fill: $component-text-color;
+		}
+	}
+
+	/* When the ListView is _not_ focused, we show alternate selection colors */
+	.list-cell:filled:selected:focused, .list-cell:filled:selected, .list-view:horizontal .list-cell:filled:selected {
+		-fx-background-color: derive(-fx-base, +50%);
+		-fx-text-fill: $component-text-color;
+	}
+
+	.list-cell:filled:selected:focused:disabled, .list-cell:filled:selected:disabled {
+		-fx-opacity: derive(-fx-hover-base, -50%);
+	}
+
+	.list-cell:filled:hover {
+		-fx-background-color: -fx-hover-base;
+		-fx-text-fill: $component-text-color;
+	}
+
+	.list-view:focused .list-cell:filled:focused:hover {
+		-fx-background-color: derive(-fx-hover-base, -50%);
+
+		-fx-background-insets: 0, 1, 2;
+		-fx-text-fill: $component-text-color;
+	}
+
+	.list-view:horizontal .list-cell:filled:selected, .list-view:horizontal .list-cell:filled:selected:hover {
+		-fx-background-color: derive(-fx-hover-base, -50%);
+		-fx-text-fill: $component-text-color;
+	}
+}
\ No newline at end of file
diff --git a/PlayWall/src/main/sass/components/menu-button.scss b/PlayWall/src/main/sass/components/menu-button.scss
new file mode 100644
index 0000000000000000000000000000000000000000..ce6da7585fea10a7e0dc15f06d276c11bdc5d5bd
--- /dev/null
+++ b/PlayWall/src/main/sass/components/menu-button.scss
@@ -0,0 +1,19 @@
+@import "variables";
+
+.menu-button {
+	-fx-background-color: $component-background-color;
+	-fx-text-fill: $component-text-color;
+	-fx-background-radius: 3px;
+	-fx-border-width: 0;
+	-fx-pref-height: 30px;
+
+	&:hover {
+		-fx-background-color: $component-hover-background-color;
+		-fx-text-fill: $component-text-color !important;
+	}
+
+	&:default {
+		-fx-background-color: $component-focus-background-color;
+		-fx-text-fill: $component-text-color !important;
+	}
+}
diff --git a/PlayWall/src/main/sass/components/menu.scss b/PlayWall/src/main/sass/components/menu.scss
new file mode 100644
index 0000000000000000000000000000000000000000..520bf7b6e46a2355717d7d5e1ed680d0ecce4ffa
--- /dev/null
+++ b/PlayWall/src/main/sass/components/menu.scss
@@ -0,0 +1,20 @@
+@import "variables";
+
+.menu-bar {
+	-fx-background-color: #333333;
+
+	.menu-button {
+		-fx-background-color: #333333;
+	}
+
+	.menu:showing, .menu:hover {
+		-fx-background-color: $component-focus-background-color;
+		-fx-background-radius: 0px;
+	}
+}
+
+.menu-item {
+	&:selected, &:focused {
+		-fx-background-color: $component-focus-background-color;
+	}
+}
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/style/components/notification-pane.css b/PlayWall/src/main/sass/components/notification-pane.scss
similarity index 76%
rename from PlayWall/src/main/resources/style/components/notification-pane.css
rename to PlayWall/src/main/sass/components/notification-pane.scss
index 2478b914fd1a40c8d020901730e448619104dde9..cdc792ce48f5b19c4753df35947921de8fbca7f7 100644
--- a/PlayWall/src/main/resources/style/components/notification-pane.css
+++ b/PlayWall/src/main/sass/components/notification-pane.scss
@@ -1,3 +1,5 @@
+@import "variables";
+
 .notification-pane {
 	-fx-background-color: rgb(29, 56, 87);
 }
@@ -15,6 +17,6 @@
 }
 
 .notification-pane .notification-bar > .pane .close-button:hover {
-	-fx-background-color: #878787;
-	-fx-text-fill: #EEEEEE !important;
+	-fx-background-color: $component-hover-background-color;
+	-fx-text-fill: $component-text-color !important;
 }
\ No newline at end of file
diff --git a/PlayWall/src/main/sass/components/progress-bar.scss b/PlayWall/src/main/sass/components/progress-bar.scss
new file mode 100644
index 0000000000000000000000000000000000000000..6ee66b8f4f6b5fda437885646f366315b132d947
--- /dev/null
+++ b/PlayWall/src/main/sass/components/progress-bar.scss
@@ -0,0 +1,16 @@
+@import "variables";
+
+.progress-bar {
+	.track {
+		-fx-background-radius: 2px;
+		-fx-base: $component-background-color;
+		-fx-background-color: $component-background-color;
+	}
+
+	.bar {
+		-fx-background-insets: 0 0 0 0;
+		-fx-padding: 0.25em;
+
+		-fx-background-color: #EEEEEE;
+	}
+}
\ No newline at end of file
diff --git a/PlayWall/src/main/sass/components/radiobutton.scss b/PlayWall/src/main/sass/components/radiobutton.scss
new file mode 100644
index 0000000000000000000000000000000000000000..0c22289cfe013e552a4fd7f90e11120fbb5af2f3
--- /dev/null
+++ b/PlayWall/src/main/sass/components/radiobutton.scss
@@ -0,0 +1,28 @@
+@import "variables";
+
+.radio-button {
+	.radio {
+		-fx-background-color: transparent;
+		-fx-background-insets: 1;
+		-fx-border-color: #CCCCCC;
+		-fx-border-radius: 30px;
+		-fx-border-width: 2px;
+	}
+
+	.dot {
+		-fx-background-color: transparent;
+		-fx-background-insets: 0 0 0 0 0, 0;
+		-fx-padding: 0.333333em;
+		-fx-shape: "M-1,0a1,1 0 1,0 2,0a1,1 0 1,0 -2,0";
+		-fx-scale-x: 1.5;
+		-fx-scale-y: 1.5;
+	}
+
+	&:selected .radio {
+		-fx-background-color: #3E4251;
+	}
+
+	&:selected .dot {
+		-fx-background-color: #CCCCCC;
+	}
+}
diff --git a/PlayWall/src/main/resources/style/components/scrollbar.css b/PlayWall/src/main/sass/components/scrollbar.scss
similarity index 97%
rename from PlayWall/src/main/resources/style/components/scrollbar.css
rename to PlayWall/src/main/sass/components/scrollbar.scss
index e8e7bf834658192242dfc5c27d4a885bd65cff62..c0687ddcf94281d68919a09ca6fe636ee4277d6c 100644
--- a/PlayWall/src/main/resources/style/components/scrollbar.css
+++ b/PlayWall/src/main/sass/components/scrollbar.scss
@@ -1,3 +1,5 @@
+@import "variables";
+
 /* The main scrollbar **track** CSS class  */
 .scroll-bar:horizontal .track,
 .scroll-bar:vertical .track {
diff --git a/PlayWall/src/main/sass/components/slider.scss b/PlayWall/src/main/sass/components/slider.scss
new file mode 100644
index 0000000000000000000000000000000000000000..c370cfd055021322d8b7730550a66410d1ac6fad
--- /dev/null
+++ b/PlayWall/src/main/sass/components/slider.scss
@@ -0,0 +1,23 @@
+@import "variables";
+
+.slider {
+
+	-slider-track-color: $component-background-color;
+
+	.track {
+		-fx-background-radius: 3px;
+		-fx-background-insets: 1px;
+
+		-fx-background-color:
+				-fx-shadow-highlight-color,
+				linear-gradient(to bottom, derive(-fx-text-box-border, -10%), -fx-text-box-border),
+				-slider-track-color ;
+	}
+
+	.thumb {
+		-fx-background-color: #CCCCCC;
+		-fx-padding: 0.333333em;
+		-fx-scale-x: 2;
+		-fx-scale-y: 2;
+	}
+}
\ No newline at end of file
diff --git a/PlayWall/src/main/sass/components/tableview.scss b/PlayWall/src/main/sass/components/tableview.scss
new file mode 100644
index 0000000000000000000000000000000000000000..cf43d9b9dc9fc294cc26f886830b99809eda3ef2
--- /dev/null
+++ b/PlayWall/src/main/sass/components/tableview.scss
@@ -0,0 +1,60 @@
+@import "variables";
+
+.table-view {
+	-fx-table-header-border-color: -fx-box-border;
+	-fx-table-cell-border-color: $component-border-color;
+}
+
+.table-row-cell {
+	-fx-background: -fx-control-inner-background;
+	-fx-background-color: $component-background-color;
+	-fx-text-fill: $component-text-color;
+}
+
+.table-row-cell:odd {
+	-fx-background: $component-background-color-odd !important;
+}
+
+.table-cell {
+	-fx-background-color: null;
+	-fx-border-color: transparent -fx-table-cell-border-color transparent transparent;
+	-fx-text-fill: $component-text-color;
+}
+
+.table-cell:deactivated {
+	-fx-text-fill: $component-text-color-deactivated !important;
+}
+
+.table-view > .virtual-flow > .clipped-container > .sheet > .table-row-cell .table-cell:selected {
+	-fx-background-color: -fx-table-cell-border-color, -fx-background;
+	-fx-background-insets: 0, 0 0 1 0;
+}
+
+/* This is the area behind the column headers. An ideal place to specify background
+   and border colors for the whole area (not individual column-header's). */
+.table-view .column-header-background {
+	-fx-background-color: $component-background-color-dark;
+	-fx-background-insets: 0, 1;
+}
+
+/* The column header row is made up of a number of column-header, one for each
+   TableColumn, and a 'filler' area that extends from the right-most column
+   to the edge of the tableview, or up to the 'column control' button. */
+.table-view .column-header,
+.table-view .filler,
+.table-view > .column-header-background > .show-hide-columns-button,
+.table-view:constrained-resize .filler {
+	-fx-background-color: $component-background-color-dark;
+	-fx-background-insets: 0, 0 1 1 0, 1 2 2 1;
+	-fx-font-weight: bold;
+	-fx-size: 2em;
+	-fx-text-fill: -fx-selection-bar-text;
+	-fx-padding: 0.166667em;
+}
+
+.table-view .column-header .label {
+	-fx-text-fill: $component-text-color;
+}
+.table-row-cell:selected {
+	-fx-background-color: $component-focus-background-color;
+}
\ No newline at end of file
diff --git a/PlayWall/src/main/sass/components/tabs.scss b/PlayWall/src/main/sass/components/tabs.scss
new file mode 100644
index 0000000000000000000000000000000000000000..bffce8d2041eaad81857d5816f5a4603c40970c2
--- /dev/null
+++ b/PlayWall/src/main/sass/components/tabs.scss
@@ -0,0 +1,17 @@
+@import "variables";
+
+.tab-pane {
+	&:top *.tab-header-background {
+		-fx-background-color: #333333;
+	}
+
+	&:top *.tab {
+		-fx-background-color: $component-background-color;
+
+		&:selected {
+			-fx-background-color: $component-focus-background-color;
+			-fx-focus-color: transparent;
+			-fx-faint-focus-color: transparent;
+		}
+	}
+}
\ No newline at end of file
diff --git a/PlayWall/src/main/sass/components/textfield.scss b/PlayWall/src/main/sass/components/textfield.scss
new file mode 100644
index 0000000000000000000000000000000000000000..ab83695de56d1bd064958ee64409d4c9b09dc7a5
--- /dev/null
+++ b/PlayWall/src/main/sass/components/textfield.scss
@@ -0,0 +1,14 @@
+@import "variables";
+
+.text-field {
+	-fx-border-color: $component-border-color;
+	-fx-border-width: $component-border-width;
+	-fx-border-radius: $component-border-radius;
+
+	-fx-background-color: $textfield-background;
+
+	-fx-text-fill: $component-text-color;
+	-fx-prompt-text-fill: $textfield-prompt-color;
+
+	-fx-font-size: $textfield-font-size;
+}
\ No newline at end of file
diff --git a/PlayWall/src/main/sass/components/toggle-button.scss b/PlayWall/src/main/sass/components/toggle-button.scss
new file mode 100644
index 0000000000000000000000000000000000000000..4ebce0abcf9e61e542eac5d50bd5315d64c28312
--- /dev/null
+++ b/PlayWall/src/main/sass/components/toggle-button.scss
@@ -0,0 +1,21 @@
+@import "variables";
+
+.toggle-button {
+	-fx-background-color: $component-background-color;
+	-fx-text-fill: $component-text-color;
+
+	&:focused {
+		-fx-background-color: $component-focus-background-color;
+		-fx-text-fill: $component-text-color !important;
+	}
+
+	&:hover {
+		-fx-background-color: $component-hover-background-color;
+		-fx-text-fill: $component-text-color !important;
+	}
+
+	&:selected {
+		-fx-background-color: #dbdbdb;
+		-fx-text-fill: #333333 !important;
+	}
+}
diff --git a/PlayWall/src/main/sass/components/treeview.scss b/PlayWall/src/main/sass/components/treeview.scss
new file mode 100644
index 0000000000000000000000000000000000000000..eaa47ce1a8f71c4796736db846c70db3048c2164
--- /dev/null
+++ b/PlayWall/src/main/sass/components/treeview.scss
@@ -0,0 +1,77 @@
+@import "variables";
+
+
+.tree-view {
+
+	-fx-base: rgb(60, 60, 60);
+
+	-fx-focus-color: transparent;
+	-fx-faint-focus-color: transparent;
+
+	.tree-cell {
+		-fx-skin: "com.sun.javafx.scene.control.skin.TreeCellSkin";
+		-fx-background-color: -fx-base;
+		-fx-padding: 5px;
+		-fx-text-fill: #FFFFFF;
+		-fx-opacity: 1;
+	}
+
+	.tree-view:focused {
+		.tree-cell:focused {
+			-fx-background-color: derive(-fx-hover-base, -50%);
+			-fx-background-insets: 0, 1, 2;
+		}
+
+		.tree-cell:filled:focused:selected {
+			-fx-background-color: derive(-fx-hover-base, -50%);
+			-fx-background-insets: 0, 1, 2;
+			-fx-background: derive(-fx-base, -50%);
+			-fx-text-fill: $component-text-color;
+		}
+
+		.tree-cell:filled:selected {
+			-fx-background-color: $component-focus-background-color;
+			-fx-text-fill: $component-text-color;
+
+			&:hover {
+				@extend .tree-cell, :filled, :selected;
+			}
+		}
+
+		.tree-cell:filled:focused:selected:hover {
+			-fx-background-color: $component-focus-background-color;
+			-fx-text-fill: $component-text-color;
+		}
+	}
+
+	.tree-cell:filled:selected:focused, .tree-cell:filled:selected, .tree-view:horizontal .tree-cell:filled:selected {
+		-fx-background-color: derive(-fx-base, +50%);
+		-fx-text-fill: $component-text-color;
+	}
+
+	.tree-cell:filled:selected:focused:disabled, .tree-cell:filled:selected:disabled {
+		-fx-opacity: derive(-fx-hover-base, -50%);
+	}
+
+	.tree-cell:filled:hover {
+		-fx-background-color: $component-focus-background-color;
+		-fx-text-fill: $component-text-color;
+	}
+
+	.tree-view:focused .tree-cell:filled:focused:hover {
+		-fx-background-color: $component-focus-background-color;
+		-fx-text-fill: $component-text-color;
+	}
+
+	.tree-view:horizontal .tree-cell:filled:selected, .tree-view:horizontal .tree-cell:filled:selected:hover {
+		-fx-background-color: $component-focus-background-color;
+		-fx-text-fill: $component-text-color;
+	}
+}
+
+.tree-cell .tree-disclosure-node .arrow {
+	-fx-background-color: $component-text-color;
+}
+.tree-cell:expanded .tree-disclosure-node .arrow {
+	-fx-background-color: $component-text-color;
+}
\ No newline at end of file
diff --git a/PlayWall/src/main/sass/components/variables.scss b/PlayWall/src/main/sass/components/variables.scss
new file mode 100644
index 0000000000000000000000000000000000000000..cba2d4931cb3a943f0e3966360aed4569ca4f983
--- /dev/null
+++ b/PlayWall/src/main/sass/components/variables.scss
@@ -0,0 +1,18 @@
+
+$component-background-color: #5c5c5c;
+$component-background-color-dark: #3c3c3c;
+$component-background-color-odd: #7c7c7c;
+
+$component-text-color: #eeeeee;
+$component-text-color-deactivated: #888888;
+
+$component-hover-background-color: #878787;
+$component-focus-background-color: #358dab;
+
+$component-border-color: #CCCCCC;
+$component-border-width: 1px;
+$component-border-radius: 2px;
+
+$textfield-background: transparent;
+$textfield-prompt-color: #777777;
+$textfield-font-size: 14;
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/style/modern.css b/PlayWall/src/main/sass/modern.scss
similarity index 59%
rename from PlayWall/src/main/resources/style/modern.css
rename to PlayWall/src/main/sass/modern.scss
index e5a3a6a4ba852c422d252132fa0b4a6047f1616c..7046c6af039f7e778946349465614c6b1a8e9f6b 100644
--- a/PlayWall/src/main/resources/style/modern.css
+++ b/PlayWall/src/main/sass/modern.scss
@@ -1,3 +1,22 @@
+
+@import "components/button";
+@import "components/menu-button";
+@import "components/combobox";
+@import "components/checkbox";
+@import "components/scrollbar";
+@import "components/textfield";
+@import "components/radiobutton";
+@import "components/slider";
+@import "components/tabs";
+@import "components/notification-pane";
+@import "components/menu";
+@import "components/toggle-button";
+@import "components/list";
+@import "components/progress-bar";
+@import "components/dialog";
+@import "components/treeview";
+@import "components/tableview";
+
 @font-face {
 	font-family: "Lato";
 	src: url("Lato/Lato-Regular.ttf");
@@ -43,12 +62,10 @@ Default elements
 PlayPad Elements
  */
 
-/*noinspection CssInvalidPseudoSelector*/
 .pad:drag {
 	-fx-opacity: 0.8;
 }
 
-/*noinspection CssInvalidPseudoSelector*/
 .text-field:error {
 	-fx-text-box-border: red;
 	-fx-focus-color: red;
@@ -69,11 +86,15 @@ PlayPad Elements
 
 .pad {
 	-fx-background-radius: 5px;
-	-fx-padding: 5 5 5 5;
+}
+
+.pad-cue-in {
+	-fx-background-radius: 5px;
 }
 
 .pad-root {
 	-fx-spacing: 4px;
+	-fx-padding: 5 5 5 5;
 }
 
 .pad-button-box {
@@ -103,18 +124,45 @@ PlayPad Elements
 }
 
 .current-page-button {
-	-fx-background-color: #dbdbdb;
-	-fx-text-fill: #333333;
+	-fx-background-color: #dbdbdb !important;
+	-fx-text-fill: #333333 !important;
 }
 
 .volume-item {
 	-fx-text-fill: white !important;
 }
 
-.progress-bar .bar {
-	-fx-background-color: #EEEEEE;
+.progress-indicator {
+	-fx-progress-color: white;
 }
 
 .progress-indicator .percentage {
 	-fx-fill: white;
 }
+
+
+/*
+	Custom classes
+ */
+
+.title {
+	-fx-font-size: 50;
+	-fx-font-weight: bold;
+}
+
+.subtitle {
+	-fx-font-size: 25;
+	-fx-font-weight: lighter;
+}
+
+
+.projectname {
+	-fx-font-size: 14px;
+	-fx-text-fill: #FFFFFF;
+	-fx-font-weight: bold;
+}
+
+.profilename {
+	-fx-font-size: 10px;
+	-fx-text-fill: #DDDDDD;
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/CartActionHandler.scala b/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/CartActionHandler.scala
index c472bcf36a9d2d2e108827cff2c440daab91bf65..68e7102c0ed6b2764605fc88aff46d9127d2972c 100644
--- a/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/CartActionHandler.scala
+++ b/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/CartActionHandler.scala
@@ -1,10 +1,10 @@
 package de.tobias.playpad.action.actions.cart.handler
 
-import de.tobias.playpad.action.InputType
-import de.tobias.playpad.action.actions.cart.CartAction
+import de.thecodelabs.midi.event.KeyEventType
+import de.tobias.playpad.action.actions.CartAction
 import de.tobias.playpad.pad.Pad
 
 trait CartActionHandler {
 
-	def performAction(inputType: InputType, cartAction: CartAction, pad: Pad): Unit
+	def performAction(keyEventType: KeyEventType, cartAction: CartAction, pad: Pad): Unit
 }
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/CartActionHandlerFactory.scala b/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/CartActionHandlerFactory.scala
index f6b6ba4dc65077bd1378bf75e472cf57ec5bc237..05a7a32b0777fcd0df6b628ecd9a407ec9860efc 100644
--- a/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/CartActionHandlerFactory.scala
+++ b/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/CartActionHandlerFactory.scala
@@ -1,6 +1,6 @@
 package de.tobias.playpad.action.actions.cart.handler
 
-import de.tobias.playpad.action.actions.cart.CartAction.CartActionMode
+import de.tobias.playpad.action.actions.CartAction.CartActionMode
 
 object CartActionHandlerFactory {
 
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayHoldHandler.scala b/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayHoldHandler.scala
index 49c630e54195c69de04572aa46da3e1b7b5dc847..1aa63b52c8dbc071bcd89fb271272dadb25a0511 100644
--- a/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayHoldHandler.scala
+++ b/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayHoldHandler.scala
@@ -1,18 +1,17 @@
 package de.tobias.playpad.action.actions.cart.handler
 
-import de.tobias.playpad.action.InputType
-import de.tobias.playpad.action.actions.cart.CartAction
+import de.thecodelabs.midi.event.KeyEventType
+import de.tobias.playpad.action.actions.CartAction
 import de.tobias.playpad.pad.Pad
 
 class PlayHoldHandler extends CartActionHandler {
 
-	override def performAction(inputType: InputType, cartAction: CartAction, pad: Pad): Unit = {
-		if (inputType eq InputType.PRESSED) {
-			if (pad.isReady) { // Allow the listener to send the feedback
-				cartAction.getPadPositionListener.setSend(false)
+	override def performAction(keyEventType: KeyEventType, cartAction: CartAction, pad: Pad): Unit = {
+		if (keyEventType eq KeyEventType.DOWN) {
+			if (pad.isReady) {
 				pad.play()
 			}
-		} else if (inputType eq InputType.RELEASED) {
+		} else if (keyEventType eq KeyEventType.UP) {
 			if (pad.isPlay) {
 				pad.stop()
 			}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayPauseHandler.scala b/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayPauseHandler.scala
index 8fb1cfda114cd57dad138db5159089ec029663d4..87c26d4ed6f1aaf0c3afbbb8cc50cd8033381db0 100644
--- a/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayPauseHandler.scala
+++ b/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayPauseHandler.scala
@@ -1,18 +1,18 @@
 package de.tobias.playpad.action.actions.cart.handler
 
-import de.tobias.playpad.action.InputType
-import de.tobias.playpad.action.actions.cart.CartAction
+import de.thecodelabs.midi.event.KeyEventType
+import de.tobias.playpad.action.actions.CartAction
 import de.tobias.playpad.pad.Pad
 
 class PlayPauseHandler extends CartActionHandler {
 
-	override def performAction(inputType: InputType, cartAction: CartAction, pad: Pad): Unit = {
-		if (inputType eq InputType.PRESSED) {
+	override def performAction(keyEventType: KeyEventType, cartAction: CartAction, pad: Pad): Unit = {
+		if (keyEventType eq KeyEventType.DOWN) {
 			if (pad.isPlay) {
 				pad.pause()
 			}
 			else { // Allow the listener to send the feedback
-				cartAction.getPadPositionListener.setSend(false)
+				// cartAction.getPadPositionListener.setSend(false) TODO Fix
 				pad.play()
 			}
 		}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayPlayHandler.scala b/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayPlayHandler.scala
index f43a562108b0083b2eac4cbdc8e68af9d69151dc..fec8eebc41c563e11a12bede31da19e7ae882141 100644
--- a/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayPlayHandler.scala
+++ b/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayPlayHandler.scala
@@ -1,13 +1,13 @@
 package de.tobias.playpad.action.actions.cart.handler
 
-import de.tobias.playpad.action.InputType
-import de.tobias.playpad.action.actions.cart.CartAction
+import de.thecodelabs.midi.event.KeyEventType
+import de.tobias.playpad.action.actions.CartAction
 import de.tobias.playpad.pad.{Pad, PadStatus}
 
 class PlayPlayHandler extends CartActionHandler {
 
-	override def performAction(inputType: InputType, cartAction: CartAction, pad: Pad): Unit = {
-		if (inputType eq InputType.PRESSED) {
+	override def performAction(keyEventType: KeyEventType, cartAction: CartAction, pad: Pad): Unit = {
+		if (keyEventType eq KeyEventType.DOWN) {
 			pad.setStatus(PadStatus.RESTART)
 		}
 	}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayStopHandler.scala b/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayStopHandler.scala
index 4ecc60edc7e4cf5fb1accd59a214403e338619f1..11957fa9729dc897f75c0aa43c9544f732ca5d01 100644
--- a/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayStopHandler.scala
+++ b/PlayWall/src/main/scala/de/tobias/playpad/action/actions/cart/handler/PlayStopHandler.scala
@@ -1,17 +1,17 @@
 package de.tobias.playpad.action.actions.cart.handler
 
-import de.tobias.playpad.action.InputType
-import de.tobias.playpad.action.actions.cart.CartAction
+import de.thecodelabs.midi.event.KeyEventType
+import de.tobias.playpad.action.actions.CartAction
 import de.tobias.playpad.pad.Pad
 
 class PlayStopHandler extends CartActionHandler {
 
-	override def performAction(inputType: InputType, cartAction: CartAction, pad: Pad): Unit = {
-		if (inputType eq InputType.PRESSED) {
+	override def performAction(keyEventType: KeyEventType, cartAction: CartAction, pad: Pad): Unit = {
+		if (keyEventType eq KeyEventType.DOWN) {
 			if (pad.isPlay) {
 				pad.stop()
 			} else { // Allow the listener to send the feedback
-				cartAction.getPadPositionListener.setSend(false)
+				// cartAction.getPadPositionListener.setSend(false) TODO Fix
 				pad.play()
 			}
 		}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/design/ModernCartDesignHandlerImpl.scala b/PlayWall/src/main/scala/de/tobias/playpad/design/ModernCartDesignHandlerImpl.scala
index 705ebffffc2196e18a2945f063866125657feded..5bcdce6cc53b63bfb407e300118348890f744395 100644
--- a/PlayWall/src/main/scala/de/tobias/playpad/design/ModernCartDesignHandlerImpl.scala
+++ b/PlayWall/src/main/scala/de/tobias/playpad/design/ModernCartDesignHandlerImpl.scala
@@ -5,8 +5,10 @@ import de.tobias.playpad.design.modern.model.{ModernCartDesign, ModernGlobalDesi
 import de.tobias.playpad.design.modern.{ModernCartDesignHandler, ModernColor}
 import de.tobias.playpad.pad.content.play.Durationable
 import de.tobias.playpad.pad.viewcontroller.IPadViewController
+import de.tobias.playpad.util.Minifier
 import de.tobias.playpad.view.PseudoClasses
 import javafx.util.Duration
+import org.apache.commons.lang3.StringUtils
 import org.springframework.expression.ExpressionParser
 import org.springframework.expression.common.TemplateParserContext
 import org.springframework.expression.spel.standard.SpelExpressionParser
@@ -17,9 +19,11 @@ import scala.jdk.CollectionConverters._
 class ModernCartDesignHandlerImpl extends ModernCartDesignHandler {
 
 	override def generateCss(design: ModernCartDesign, classSuffix: String, flat: Boolean): String = {
-		generateCss(design, flat, classSuffix, design.getBackgroundColor) +
-			generateCss(design, flat, classSuffix, design.getPlayColor, s":${PseudoClasses.PLAY_CLASS.getPseudoClassName}") +
+		StringUtils.join(
+			generateCss(design, flat, classSuffix, design.getBackgroundColor),
+			generateCss(design, flat, classSuffix, design.getPlayColor, s":${PseudoClasses.PLAY_CLASS.getPseudoClassName}"),
 			generateCss(design, flat, classSuffix, design.getBackgroundColor, s":${PseudoClasses.WARN_CLASS.getPseudoClassName}")
+		)
 	}
 
 	private def generateCss(design: ModernCartDesign, flat: Boolean, padIdentifier: String, color: ModernColor, styleState: String = ""): String = {
@@ -27,15 +31,16 @@ class ModernCartDesignHandlerImpl extends ModernCartDesignHandler {
 		val context = new StandardEvaluationContext()
 
 		val resource = ApplicationUtils.getApplication.getClasspathResource("style/modern-pad.css")
-		val string = resource.getAsString
+		val string = Minifier minify resource.getAsString
 
-		val values = Map[String, Any](
+		val values: Map[String, Any] = Map(
 			"prefix" -> padIdentifier,
 			"class" -> styleState,
 			"buttonColor" -> color.getButtonColor,
 			"playbarTrackColor" -> color.getPlaybarColor,
 			"playbarBarColor" -> color.getPlaybarTrackColor,
 			"padColor" -> (if (flat) color.paint() else color.linearGradient()),
+			"padCueInColor" -> (if (flat) design.getCueInColor.paint() else design.getCueInColor.linearGradient()),
 			"fontColor" -> color.getFontColor
 		)
 
@@ -51,14 +56,15 @@ class ModernCartDesignHandlerImpl extends ModernCartDesignHandler {
 			val fadeStopColor = if (globalDesign.isFlatDesign) backgroundColor.toFlatFadeableColor else backgroundColor.toFadeableColor
 			val fadePlayColor = if (globalDesign.isFlatDesign) playColor.toFlatFadeableColor else playColor.toFadeableColor
 
-			var animationDuration = warning
 			val pad = controller.getPad
-			pad.getContent match {
+			val animationDuration = pad.getContent match {
 				case durationable: Durationable =>
 					if (warning greaterThan durationable.getDuration) {
-						animationDuration = durationable.getDuration
+						durationable.getDuration
+					} else {
+						warning
 					}
-				case _ =>
+				case _ => warning
 			}
 			ModernDesignAnimator.animateWarn(controller, fadePlayColor, fadeStopColor, animationDuration)
 		} else {
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/design/ModernGlobalDesignHandlerImpl.scala b/PlayWall/src/main/scala/de/tobias/playpad/design/ModernGlobalDesignHandlerImpl.scala
index c86ba27c29a721faa940faf92f94bc3a674188b4..84450cf5152e1593968a44554ea6ab38dd2cd4ca 100644
--- a/PlayWall/src/main/scala/de/tobias/playpad/design/ModernGlobalDesignHandlerImpl.scala
+++ b/PlayWall/src/main/scala/de/tobias/playpad/design/ModernGlobalDesignHandlerImpl.scala
@@ -10,12 +10,14 @@ import de.tobias.playpad.design.modern.{ModernColor, ModernGlobalDesignHandler}
 import de.tobias.playpad.pad.content.play.Durationable
 import de.tobias.playpad.pad.viewcontroller.IPadViewController
 import de.tobias.playpad.project.Project
+import de.tobias.playpad.util.Minifier
 import de.tobias.playpad.view.{ColorPickerView, PseudoClasses}
 import de.tobias.playpad.viewcontroller.main.IMainViewController
 import de.tobias.playpad.{DisplayableColor, PlayPadMain}
 import javafx.scene.paint.Color
 import javafx.stage.Stage
 import javafx.util.Duration
+import org.apache.commons.lang3.StringUtils
 import org.springframework.expression.ExpressionParser
 import org.springframework.expression.common.TemplateParserContext
 import org.springframework.expression.spel.standard.SpelExpressionParser
@@ -25,26 +27,7 @@ import scala.jdk.CollectionConverters._
 
 class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with ColorModeHandler {
 
-	val styleSheets: Array[String] = Array(
-		"style/components/button.css",
-		"style/components/menu-button.css",
-		"style/components/combobox.css",
-		"style/components/checkbox.css",
-		"style/components/scrollbar.css",
-		"style/components/textfield.css",
-		"style/components/radiobutton.css",
-		"style/components/slider.css",
-		"style/components/tabs.css",
-		"style/components/notification-pane.css",
-		"style/components/menu.css",
-		"style/components/toggle-button.css",
-		"style/components/list.css",
-		"style/components/dialog.css"
-	)
-
 	override def applyStyleSheet(stage: Stage): Unit = {
-		styleSheets.foreach(stage.getScene.getStylesheets.add)
-
 		stage.getScene.getStylesheets.add("style/style.css")
 		stage.getScene.getStylesheets.add("style/modern.css")
 
@@ -66,8 +49,7 @@ class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with Color
 		stringBuilder.append(generateCss(design))
 
 		val cartDesignHandler = PlayPadMain.getProgramInstance.getModernDesign.cart
-
-		project.getPads.forEach(pad => {
+		project.getPage(controller.getPage).getPads.forEach(pad => {
 			val padSettings = pad.getPadSettings
 
 			if (padSettings.isCustomDesign) {
@@ -82,9 +64,11 @@ class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with Color
 	}
 
 	private def generateCss(design: ModernGlobalDesign): String = {
-		generateCss(design, design.getBackgroundColor) +
-			generateCss(design, design.getPlayColor, s":${PseudoClasses.PLAY_CLASS.getPseudoClassName}") +
+		StringUtils.join(
+			generateCss(design, design.getBackgroundColor),
+			generateCss(design, design.getPlayColor, s":${PseudoClasses.PLAY_CLASS.getPseudoClassName}"),
 			generateCss(design, design.getBackgroundColor, s":${PseudoClasses.WARN_CLASS.getPseudoClassName}")
+		)
 	}
 
 	private def generateCss(design: ModernGlobalDesign, color: ModernColor, styleState: String = ""): String = {
@@ -92,14 +76,15 @@ class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with Color
 		val context = new StandardEvaluationContext()
 
 		val resource = ApplicationUtils.getApplication.getClasspathResource("style/modern-global.css")
-		val string = resource.getAsString
+		val string = Minifier minify resource.getAsString
 
-		val values = Map[String, Any](
+		val values: Map[String, Any] = Map(
 			"class" -> styleState,
 			"buttonColor" -> color.getButtonColor,
 			"playbarTrackColor" -> color.getPlaybarColor,
 			"playbarBarColor" -> color.getPlaybarTrackColor,
 			"padColor" -> (if (design.isFlatDesign) color.paint() else color.linearGradient()),
+			"padCueInColor" -> (if (design.isFlatDesign) design.getCueInColor.paint() else design.getCueInColor.linearGradient()),
 			"fontColor" -> color.getFontColor,
 			"infoFontSize" -> s"${design.getInfoFontSize}",
 			"titleFontSize" -> s"${design.getTitleFontSize}"
@@ -112,8 +97,7 @@ class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with Color
 	override def handleWarning(design: ModernGlobalDesign, controller: IPadViewController, warning: Duration): Unit = {
 		if (design.isWarnAnimation) {
 			warnAnimation(design, controller, warning)
-		}
-		else {
+		} else {
 			ModernDesignAnimator.warnFlash(controller)
 		}
 	}
@@ -123,18 +107,18 @@ class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with Color
 		val playColor = if (design.isFlatDesign) design.getPlayColor.toFlatFadeableColor else design.getPlayColor.toFadeableColor
 
 		val pad = controller.getPad
-		var duration = warning
-		pad.getContent match {
+		val duration = pad.getContent match {
 			case durationable: Durationable =>
 				if (warning.greaterThan(durationable.getDuration)) {
-					duration = durationable.getDuration
+					durationable.getDuration
+				} else {
+					warning
 				}
-			case _ =>
+			case _ => warning
 		}
 		ModernDesignAnimator.animateWarn(controller, playColor, stopColor, duration)
 	}
 
-
 	override def stopWarning(design: ModernGlobalDesign, controller: IPadViewController): Unit = ModernDesignAnimator.stopAnimation(controller)
 
 	override def getColorInterface(onSelection: Consumer[DisplayableColor]) = new ColorPickerView(null, ModernColor.values.asInstanceOf[Array[DisplayableColor]], onSelection)
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/CheckUpdateTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/CheckUpdateTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a9e68db3161f8184b972dea93a5cd82d4ea9a704
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/CheckUpdateTask.scala
@@ -0,0 +1,47 @@
+package de.tobias.playpad.initialize
+
+import java.io.IOException
+
+import de.thecodelabs.logger.Logger
+import de.thecodelabs.utils.application
+import de.thecodelabs.utils.threading.Worker
+import de.tobias.playpad.PlayPadImpl
+import de.tobias.playpad.viewcontroller.dialog.AutoUpdateDialog
+import javafx.application.Platform
+import javafx.scene.control.ButtonType
+
+class CheckUpdateTask extends PlayPadInitializeTask {
+	override def name(): String = "Updates"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		val globalSettings = instance.getGlobalSettings
+
+		if (globalSettings.isAutoUpdate && !globalSettings.isIgnoreUpdate) {
+			Worker.runLater(() => {
+				val updateService = instance.getUpdateService
+				updateService.fetchCurrentVersion()
+
+				if (updateService.isUpdateAvailable) {
+					Platform.runLater(() => {
+						val autoUpdateDialog = new AutoUpdateDialog(updateService, null)
+						autoUpdateDialog.showAndWait.ifPresent(response => {
+							if (autoUpdateDialog.isSelected) {
+								globalSettings.setIgnoreUpdate(true)
+							}
+
+							if (response == ButtonType.APPLY) {
+								Logger.info("Install update")
+								try {
+									updateService.runVersionizerInstance(updateService.getAllLatestVersionEntries)
+									System.exit(0)
+								} catch {
+									case e: IOException => Logger.error(e)
+								}
+							}
+						})
+					})
+				}
+			})
+		}
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/ComponentLoadingTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ComponentLoadingTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a9755051dc4153c04c5a49f9c0362dcdd9115ee4
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ComponentLoadingTask.scala
@@ -0,0 +1,30 @@
+package de.tobias.playpad.initialize
+
+import de.thecodelabs.logger.Logger
+import de.thecodelabs.utils.application
+import de.thecodelabs.utils.util.Localization
+import de.tobias.playpad.audio.JavaFXHandlerFactory
+import de.tobias.playpad.{PlayPadImpl, PlayPadPlugin}
+
+class ComponentLoadingTask extends PlayPadInitializeTask {
+	override def name(): String = "Component"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		val resourceBundle = Localization.getBundle
+		val module = instance.getModule
+		val registries = PlayPadPlugin.getRegistries
+
+		try {
+			registries.getActions.loadComponentsFromFile("components/Actions.xml", module, resourceBundle)
+			registries.getAudioHandlers.loadComponentsFromFile("components/AudioHandler.xml", module, resourceBundle)
+			registries.getDragModes.loadComponentsFromFile("components/DragMode.xml", module, resourceBundle)
+			registries.getPadContents.loadComponentsFromFile("components/PadContent.xml", module, resourceBundle)
+			registries.getTriggerItems.loadComponentsFromFile("components/Trigger.xml", module, resourceBundle)
+			registries.getMainLayouts.loadComponentsFromFile("components/Layout.xml", module, resourceBundle)
+
+			registries.getAudioHandlers.setDefaultID(classOf[JavaFXHandlerFactory])
+		} catch {
+			case e: Exception => Logger.error(e)
+		}
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/GlobalSettingsLoadingTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/GlobalSettingsLoadingTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..cc13f88fbff9d6dfeb50a38af14279e87cc01ab5
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/GlobalSettingsLoadingTask.scala
@@ -0,0 +1,18 @@
+package de.tobias.playpad.initialize
+
+import de.thecodelabs.utils.application.App
+import de.thecodelabs.utils.application.container.PathType
+import de.tobias.playpad.PlayPadImpl
+import de.tobias.playpad.settings.GlobalSettings
+
+class GlobalSettingsLoadingTask extends PlayPadInitializeTask {
+
+	override def name(): String = "Global settings"
+
+	override def run(app: App, instance: PlayPadImpl): Unit = {
+		val globalSettingsPath = app.getPath(PathType.CONFIGURATION, GlobalSettings.FILE_NAME)
+		val globalSettings = GlobalSettings.load(globalSettingsPath)
+
+		instance.setGlobalSettings(globalSettings)
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/KeyboardDefaultMappingTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/KeyboardDefaultMappingTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..cf64b19a2b485a981beb5db98b2f17d19dfa2587
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/KeyboardDefaultMappingTask.scala
@@ -0,0 +1,18 @@
+package de.tobias.playpad.initialize
+
+import de.thecodelabs.utils.application
+import de.thecodelabs.utils.application.container.PathType
+import de.thecodelabs.utils.util.Localization
+import de.tobias.playpad.PlayPadImpl
+import de.tobias.playpad.settings.GlobalSettings
+
+class KeyboardDefaultMappingTask extends PlayPadInitializeTask {
+	override def name(): String = "Keyboard Mapping"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		val globalSettingsPath = app.getPath(PathType.CONFIGURATION, GlobalSettings.FILE_NAME)
+		val globalSettings = instance.getGlobalSettings
+
+		globalSettings.getKeyCollection.loadDefaultFromFile("components/Keys.xml", Localization.getBundle)
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/KeyboardLoadingMappingTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/KeyboardLoadingMappingTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..13c7e127085cbef5613d89956159f85b1d157f5c
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/KeyboardLoadingMappingTask.scala
@@ -0,0 +1,17 @@
+package de.tobias.playpad.initialize
+
+import de.thecodelabs.utils.application
+import de.thecodelabs.utils.application.container.PathType
+import de.tobias.playpad.PlayPadImpl
+import de.tobias.playpad.settings.GlobalSettings
+
+class KeyboardLoadingMappingTask extends PlayPadInitializeTask {
+	override def name(): String = "Keyboard Mapping"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		val globalSettingsPath = app.getPath(PathType.CONFIGURATION, GlobalSettings.FILE_NAME)
+		val globalSettings = instance.getGlobalSettings
+
+		globalSettings.getKeyCollection.load(globalSettingsPath)
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/LocalizationLoadingTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/LocalizationLoadingTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..29749f48506ed2042c3ca14228cda0608405fe40
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/LocalizationLoadingTask.scala
@@ -0,0 +1,14 @@
+package de.tobias.playpad.initialize
+
+import de.thecodelabs.utils.application
+import de.thecodelabs.utils.util.Localization
+import de.tobias.playpad.{PlayPadImpl, PlayPadLocalizationDelegate}
+
+class LocalizationLoadingTask extends PlayPadInitializeTask {
+	override def name(): String = "Localization"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		Localization.setDelegate(new PlayPadLocalizationDelegate)
+		Localization.load()
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/MidiActionsInitializerTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/MidiActionsInitializerTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..fab6bfe1c728a1edd52772cad91b767b95cc40e2
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/MidiActionsInitializerTask.scala
@@ -0,0 +1,23 @@
+package de.tobias.playpad.initialize
+import de.thecodelabs.midi.action.{ActionKeyHandler, ActionRegistry}
+import de.thecodelabs.midi.midi.MidiCommandHandler
+import de.thecodelabs.utils.application
+import de.tobias.playpad.{PlayPadImpl, PlayPadPlugin}
+import de.tobias.playpad.action.ActionProvider
+import de.tobias.playpad.midi.PD12
+
+class MidiActionsInitializerTask extends PlayPadInitializeTask {
+
+	override def name(): String = "Midi"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		val registryCollection = PlayPadPlugin.getRegistries
+
+		ActionKeyHandler.setRunOnFxThread(true)
+		registryCollection.getActions.getComponents.forEach((actionProvider: ActionProvider) => {
+			ActionRegistry.registerActionHandler(actionProvider.getActionHandler)
+		})
+
+		MidiCommandHandler.getInstance.addMidiListener(new PD12)
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/NativeAppInitializerTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/NativeAppInitializerTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..5afd167f0dc959eb7ac44277ea4e5b9d5acab202
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/NativeAppInitializerTask.scala
@@ -0,0 +1,14 @@
+package de.tobias.playpad.initialize
+import de.thecodelabs.utils.application
+import de.thecodelabs.utils.application.system.NativeApplication
+import de.tobias.playpad.PlayPadImpl
+import javafx.scene.image.Image
+
+class NativeAppInitializerTask extends PlayPadInitializeTask {
+	override def name(): String = "Native"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		NativeApplication.sharedInstance.setDockIcon(new Image("icon_large.png"))
+		NativeApplication.sharedInstance.setAppearance(true)
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/OpenLastDocumentTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/OpenLastDocumentTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..6d03affb29feefe2543ea12fa07314bdd9215a72
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/OpenLastDocumentTask.scala
@@ -0,0 +1,21 @@
+package de.tobias.playpad.initialize
+
+import java.util.UUID
+
+import de.thecodelabs.utils.application
+import de.tobias.playpad.PlayPadImpl
+import de.tobias.playpad.project.ref.ProjectReferenceManager
+
+class OpenLastDocumentTask extends PlayPadInitializeTask {
+	override def name(): String = "Open Last Document"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		if (instance.getGlobalSettings.isOpenLastDocument) {
+			val value = app.getUserDefaults.getData("project").asInstanceOf[UUID]
+			if (value != null) {
+				instance.openProject(ProjectReferenceManager.getProject(value), null)
+				throw new PlayPadInitializeAbortException(this)
+			}
+		}
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/PluginLoadingTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/PluginLoadingTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..0d415d80d9cd6c21276953546d84d47c187b770e
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/PluginLoadingTask.scala
@@ -0,0 +1,47 @@
+package de.tobias.playpad.initialize
+import java.io.IOException
+import java.nio.file.{Path, Paths}
+
+import de.thecodelabs.logger.Logger
+import de.thecodelabs.utils.application
+import de.thecodelabs.utils.application.ApplicationUtils
+import de.thecodelabs.utils.application.container.PathType
+import de.tobias.playpad.PlayPadImpl
+import de.tobias.playpad.plugin.ModernPluginManager
+
+class PluginLoadingTask extends PlayPadInitializeTask {
+	override def name(): String = "Plugins"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		val parameter = instance.getParameters
+
+		try // Load Plugin Path
+			if (!parameter.getRaw.contains("noplugins")) {
+				var pluginFolder: Path = null
+				if (parameter.getNamed.containsKey("plugin")) {
+					val pluginParam = parameter.getNamed.get("plugin")
+					for (part <- pluginParam.split(":")) {
+						pluginFolder = Paths.get(part)
+						setupPlugins(pluginFolder)
+					}
+				}
+				else {
+					pluginFolder = ApplicationUtils.getApplication.getPath(PathType.LIBRARY)
+					setupPlugins(pluginFolder)
+				}
+			}
+		catch {
+			case e: Exception =>
+				Logger.error("Unable to load plugins")
+				Logger.error(e)
+		}
+	}
+
+	@throws[IOException]
+	private def setupPlugins(pluginPath: Path): Unit = {
+		// Delete old plugins
+		ModernPluginManager.getInstance.deletePlugins()
+		// Load Plugins
+		ModernPluginManager.getInstance.loadFile(pluginPath)
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/ProfileLoadingTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ProfileLoadingTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..9f9ff14a63c6a018cf242fa3e54525ca034cf247
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ProfileLoadingTask.scala
@@ -0,0 +1,21 @@
+package de.tobias.playpad.initialize
+
+import java.io.IOException
+
+import de.thecodelabs.logger.Logger
+import de.thecodelabs.utils.application
+import de.tobias.playpad.PlayPadImpl
+import de.tobias.playpad.profile.ref.ProfileReferenceManager
+import org.dom4j.DocumentException
+
+class ProfileLoadingTask extends PlayPadInitializeTask {
+	override def name(): String = "Profile loading"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		try ProfileReferenceManager.loadProfiles()
+		catch {
+			case e@(_: IOException | _: DocumentException) =>
+				Logger.error(e)
+		}
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/ProjectParameterOpenTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ProjectParameterOpenTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a659cbc9bc55ffca0883c8dc824f0af23ca1a609
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ProjectParameterOpenTask.scala
@@ -0,0 +1,25 @@
+package de.tobias.playpad.initialize
+
+import java.util.UUID
+
+import de.thecodelabs.utils.application
+import de.tobias.playpad.PlayPadImpl
+import de.tobias.playpad.project.ref.ProjectReferenceManager
+;
+
+class ProjectParameterOpenTask extends PlayPadInitializeTask {
+	override def name(): String = "Open"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		val parameter = instance.getParameters
+
+		// Auto Open Project DEBUG
+		if (!parameter.getRaw.isEmpty) {
+			if (parameter.getNamed.containsKey("project")) {
+				val uuid = UUID.fromString(parameter.getNamed.get("project"))
+				instance.openProject(ProjectReferenceManager.getProject(uuid), null)
+				throw new PlayPadInitializeAbortException(this)
+			}
+		}
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/ProjectsLoadingTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ProjectsLoadingTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..b2bc99af6d57599077d177dd93a8e732b9606132
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ProjectsLoadingTask.scala
@@ -0,0 +1,12 @@
+package de.tobias.playpad.initialize
+import de.thecodelabs.utils.application
+import de.tobias.playpad.PlayPadImpl
+import de.tobias.playpad.project.ref.ProjectReferenceManager
+
+class ProjectsLoadingTask extends PlayPadInitializeTask {
+	override def name(): String = "Projects"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		ProjectReferenceManager.loadProjects()
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/ServerInitializeTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ServerInitializeTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a55c2ad0272c3176d8f8b0da730269b4bc23a9c3
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ServerInitializeTask.scala
@@ -0,0 +1,32 @@
+package de.tobias.playpad.initialize
+
+import java.io.IOException
+
+import com.neovisionaries.ws.client.WebSocketException
+import de.thecodelabs.logger.Logger
+import de.thecodelabs.utils.application
+import de.tobias.playpad.server.{Session, SessionDelegate, SessionNotExistsException}
+import de.tobias.playpad.{PlayPadImpl, PlayPadPlugin}
+
+class ServerInitializeTask(delegate: SessionDelegate) extends PlayPadInitializeTask {
+	override def name(): String = "Server"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		// Load Server session key
+		var session = Session.load
+		if (session == null) session = delegate.getSession
+		instance.setSession(session)
+
+		if (session == Session.EMPTY) { // Connect to Server
+			return
+		}
+
+		val server = PlayPadPlugin.getServerHandler.getServer
+		try server.connect(session.getKey)
+		catch {
+			case e@(_: IOException | _: WebSocketException) =>
+				Logger.error(e)
+			case _: SessionNotExistsException =>
+		}
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/ServiceInitializationTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ServiceInitializationTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..7c7795ee81249b886ce185cd11ff51a3de2cbb52
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/ServiceInitializationTask.scala
@@ -0,0 +1,19 @@
+package de.tobias.playpad.initialize
+import de.thecodelabs.utils.application
+import de.tobias.playpad.server.ServerHandlerImpl
+import de.tobias.playpad.server.sync.command.CommandExecutorHandlerImpl
+import de.tobias.playpad.view.MapperListViewControllerImpl
+import de.tobias.playpad.viewcontroller.BaseMapperListViewController
+import de.tobias.playpad.{PlayPadImpl, PlayPadPlugin, RegistryCollectionImpl}
+
+class ServiceInitializationTask extends PlayPadInitializeTask {
+	override def name(): String = "Services"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		PlayPadPlugin.setRegistryCollection(new RegistryCollectionImpl)
+		PlayPadPlugin.setServerHandler(new ServerHandlerImpl)
+		PlayPadPlugin.setCommandExecutorHandler(new CommandExecutorHandlerImpl)
+
+		BaseMapperListViewController.setInstance(new MapperListViewControllerImpl)
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/VersionizerSetupTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/VersionizerSetupTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..ff86099670aaf4222298b81d1ff7afc6b344a1b7
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/VersionizerSetupTask.scala
@@ -0,0 +1,25 @@
+package de.tobias.playpad.initialize
+import de.thecodelabs.storage.settings.StorageTypes
+import de.thecodelabs.utils.application
+import de.thecodelabs.utils.util.SystemUtils
+import de.thecodelabs.versionizer.VersionizerItem
+import de.thecodelabs.versionizer.config.{Artifact, Repository}
+import de.thecodelabs.versionizer.service.UpdateService
+import de.tobias.playpad.PlayPadImpl
+
+class VersionizerSetupTask extends PlayPadInitializeTask {
+	override def name(): String = "Versionizer"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		val artifact = app.getClasspathResource("build-app.json").deserialize(StorageTypes.JSON, classOf[Artifact])
+		val repository = app.getClasspathResource("repository.yml").deserialize(StorageTypes.YAML, classOf[Repository])
+
+		val globalSettings = instance.getGlobalSettings
+
+		val versionizerItem = new VersionizerItem(repository, SystemUtils.getRunPath.toString)
+		val updateService = UpdateService.startVersionizer(versionizerItem, UpdateService.Strategy.JAR, UpdateService.InteractionType.GUI)
+		updateService.addArtifact(artifact, SystemUtils.getRunPath)
+		updateService.setRepositoryType(globalSettings.getUpdateChannel)
+		instance.setUpdateService(updateService)
+	}
+}
diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/VolumeInitializerTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/VolumeInitializerTask.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a09ddf7f3f9bbd541478bbd6f6c16b232f1129bf
--- /dev/null
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/VolumeInitializerTask.scala
@@ -0,0 +1,14 @@
+package de.tobias.playpad.initialize
+import de.thecodelabs.utils.application
+import de.tobias.playpad.PlayPadImpl
+import de.tobias.playpad.volume.{GlobalVolume, PadVolume, VolumeManager}
+
+class VolumeInitializerTask extends PlayPadInitializeTask {
+	override def name(): String = "Volume"
+
+	override def run(app: application.App, instance: PlayPadImpl): Unit = {
+		val volumeManager = VolumeManager.getInstance
+		volumeManager.addFilter(new GlobalVolume)
+		volumeManager.addFilter(new PadVolume)
+	}
+}
diff --git a/PlayWall/src/test/resources/config/libLogger.yml b/PlayWall/src/test/resources/config/libLogger.yml
index 3c309583f9c0021ad159f12e2b777c4e1aa4ccac..c0dcfdcc5302f6017f63920cc48d58fb22a603c0 100644
--- a/PlayWall/src/test/resources/config/libLogger.yml
+++ b/PlayWall/src/test/resources/config/libLogger.yml
@@ -12,7 +12,7 @@ dateFormatterPattern: "dd.MM.YY HH:mm:ss"
 defaultOutLevel: "DEBUG"
 defaultErrLevel: "ERROR"
 
-showShortPackageName: true
+showShortPackageName: false
 showClassName: true
 showMethodName: true
 showLineNumber: true
diff --git a/PlayWallComponents/pom.xml b/PlayWallComponents/pom.xml
index 0989e25925f63a1499331270857aae0495ddde12..ee6a60650ec904e91bf03aab7664557879e48130 100644
--- a/PlayWallComponents/pom.xml
+++ b/PlayWallComponents/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallDesktop</artifactId>
-        <version>6.2.0-SNAPSHOT</version>
+        <version>7.0.0</version>
     </parent>
 
     <artifactId>PlayWallComponents</artifactId>
@@ -52,19 +52,19 @@
         <repository>
             <id>release</id>
             <name>TheCodeLabs-releases</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
         </repository>
         <snapshotRepository>
             <id>snapshots</id>
             <name>TheCodeLabs-snapshots</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
         </snapshotRepository>
     </distributionManagement>
 
     <repositories>
         <repository>
             <id>release</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/Releases</url>
             <releases>
                 <enabled>true</enabled>
             </releases>
@@ -74,7 +74,7 @@
         </repository>
         <repository>
             <id>snapshots</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
             <releases>
                 <enabled>false</enabled>
             </releases>
diff --git a/PlayWallComponents/src/main/java/de/tobias/playpad/audio/TinyAudioHandler.java b/PlayWallComponents/src/main/java/de/tobias/playpad/audio/TinyAudioHandler.java
index 4451f6e67fc37004aaeaffc1b8e6f812e6653832..528044249d7ee7a65416a8afb039626a38db282e 100644
--- a/PlayWallComponents/src/main/java/de/tobias/playpad/audio/TinyAudioHandler.java
+++ b/PlayWallComponents/src/main/java/de/tobias/playpad/audio/TinyAudioHandler.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.audio;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.io.PathUtils;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.pad.Pad;
@@ -93,7 +94,7 @@ public class TinyAudioHandler extends AudioHandler implements Soundcardable, See
 					Thread.sleep(SLEEP_TIME_POSITION);
 				} catch (InterruptedException | ConcurrentModificationException ignored) {
 				} catch (Exception e) {
-					e.printStackTrace();
+					Logger.error(e);
 				}
 			}
 		});
@@ -240,7 +241,7 @@ public class TinyAudioHandler extends AudioHandler implements Soundcardable, See
 			} catch (Exception e) {
 				loadedProperty.set(false);
 				// getContent().getPad().throwException(path, e); TODO Error Handling User
-				e.printStackTrace();
+				Logger.error(e);
 			} finally {
 				Platform.runLater(() ->
 				{
@@ -310,7 +311,7 @@ public class TinyAudioHandler extends AudioHandler implements Soundcardable, See
 				}
 
 			} catch (SecurityException | IllegalArgumentException | LineUnavailableException e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 			// Init mit Default Sound Card, wenn keine Ausgewählt wurde
 			if (!TinySound.isInitialized()) {
diff --git a/PlayWallComponents/src/main/java/de/tobias/playpad/audio/viewcontroller/TinySoundSettingsViewController.java b/PlayWallComponents/src/main/java/de/tobias/playpad/audio/viewcontroller/TinySoundSettingsViewController.java
index 9c0c6533c61842896e1158047181c6900dad4971..b3a502dc7a659a8a1c72e9134829c862f08d9d81 100644
--- a/PlayWallComponents/src/main/java/de/tobias/playpad/audio/viewcontroller/TinySoundSettingsViewController.java
+++ b/PlayWallComponents/src/main/java/de/tobias/playpad/audio/viewcontroller/TinySoundSettingsViewController.java
@@ -1,9 +1,10 @@
 package de.tobias.playpad.audio.viewcontroller;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.threading.Worker;
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
-import de.tobias.playpad.PlayPadPlugin;
+import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.audio.TinyAudioHandler;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.viewcontroller.AudioHandlerViewController;
@@ -35,7 +36,7 @@ public class TinySoundSettingsViewController extends AudioHandlerViewController
 	private Clip clip;
 
 	public TinySoundSettingsViewController() {
-		super("TinySoundSettings", "view/audio", PlayPadPlugin.getInstance().getUIResourceBundle());
+		super("TinySoundSettings", "view/audio", Localization.getBundle());
 
 		// Mixer (ohne Port)
 		List<Info> infos = Arrays.stream(AudioSystem.getMixerInfo()).filter(info -> !info.getName().startsWith("Port"))
@@ -111,7 +112,7 @@ public class TinySoundSettingsViewController extends AudioHandlerViewController
 						try {
 							Thread.sleep(100);
 						} catch (Exception e) {
-							e.printStackTrace();
+							Logger.error(e);
 						}
 					}
 				});
@@ -119,7 +120,7 @@ public class TinySoundSettingsViewController extends AudioHandlerViewController
 			}
 
 		} catch (IOException | LineUnavailableException | UnsupportedAudioFileException e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 
diff --git a/PlayWallComponents/src/main/java/de/tobias/playpad/midi/PD12.java b/PlayWallComponents/src/main/java/de/tobias/playpad/midi/PD12.java
index 1a2bc94a6a833149c8a64e93abeecefae0f11fc1..ab465ca1e026a9f9a73a17212cb5502f2525818b 100644
--- a/PlayWallComponents/src/main/java/de/tobias/playpad/midi/PD12.java
+++ b/PlayWallComponents/src/main/java/de/tobias/playpad/midi/PD12.java
@@ -1,63 +1,29 @@
 package de.tobias.playpad.midi;
 
-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.MidiDeviceImpl;
+import de.thecodelabs.midi.midi.Midi;
+import de.thecodelabs.midi.midi.MidiCommand;
+import de.thecodelabs.midi.midi.MidiCommandType;
+import de.thecodelabs.midi.midi.MidiListener;
 import de.tobias.playpad.profile.Profile;
 import javafx.application.Platform;
 
-import javax.sound.midi.MidiMessage;
-import javax.sound.midi.SysexMessage;
-
-public class PD12 extends MidiDeviceImpl {
-
-	public static final String NAME = "PD 12";
-
-	@Override
-	public String getName() {
-		return NAME;
-	}
+public class PD12 implements MidiListener {
 
 	@Override
-	public boolean supportFeedback() {
-		return false;
-	}
+	public void onMidiMessage(MidiCommand midiCommand) {
+		if (!Midi.getInstance().getDevice().getMidiDeviceInfo().getName().contains("PD 12")) {
+			return;
+		}
 
-	@Override
-	public void onMidiMessage(MidiMessage message) {
-		if (message instanceof SysexMessage) {
-			if (message.getMessage().length == 8) {
-				if (message.getMessage()[0] == -16 && message.getMessage()[1] == 127 && message.getMessage()[2] == 127
-						&& message.getMessage()[3] == 4 && message.getMessage()[4] == 1 && message.getMessage()[5] == 0
-						&& message.getMessage()[7] == -9) {
-					int volume = message.getMessage()[6];
-					double volume_ = volume / 127.0;
-					Platform.runLater(() -> Profile.currentProfile().getProfileSettings().setVolume(volume_));
-				}
+		if (midiCommand.getMidiCommand() == MidiCommandType.SYSTEM_EXCLUSIVE) {
+			final byte[] payload = midiCommand.getPayload();
+			if (payload[0] == 127 && payload[1] == 127
+					&& payload[2] == 4 && payload[3] == 1 && payload[4] == 0
+					&& payload[6] == -9) {
+				int volume = payload[5];
+				double calculatedVolume = volume / 127.0;
+				Platform.runLater(() -> Profile.currentProfile().getProfileSettings().setVolume(calculatedVolume));
 			}
 		}
 	}
-
-	@Override
-	public void handleFeedback(FeedbackMessage type, int key, Feedback feedback) {
-	}
-
-	@Override
-	public void initDevice() {
-	}
-
-	@Override
-	public void clearFeedback() {
-	}
-
-	@Override
-	public DisplayableFeedbackColor getColor(int id) {
-		return null;
-	}
-
-	@Override
-	public DisplayableFeedbackColor[] getColors() {
-		return null;
-	}
 }
diff --git a/PlayWallCore/pom.xml b/PlayWallCore/pom.xml
index 298e37cc46f8efd3a1075959e56da95abd88714f..96ddeb79b523ed5841a1565e6ef2c4bf33b3a044 100644
--- a/PlayWallCore/pom.xml
+++ b/PlayWallCore/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallDesktop</artifactId>
-        <version>6.2.0-SNAPSHOT</version>
+        <version>7.0.0</version>
     </parent>
 
     <artifactId>PlayWallCore</artifactId>
@@ -22,6 +22,10 @@
             <groupId>de.thecodelabs</groupId>
             <artifactId>libLogger</artifactId>
         </dependency>
+        <dependency>
+            <groupId>de.thecodelabs</groupId>
+            <artifactId>libLogger-slf4j</artifactId>
+        </dependency>
         <dependency>
             <groupId>de.thecodelabs</groupId>
             <artifactId>libPlugins-core</artifactId>
@@ -43,6 +47,12 @@
             <version>${jlayer.version}</version>
         </dependency>
 
+        <!--Midi-->
+        <dependency>
+            <groupId>de.thecodelabs</groupId>
+            <artifactId>libMidi</artifactId>
+        </dependency>
+
         <!--Network/Json-->
         <dependency>
             <groupId>com.google.code.gson</groupId>
@@ -99,25 +109,50 @@
             <scope>test</scope>
         </dependency>
 
+        <!-- Plugin Dependencies -->
+
+        <!-- PDF-->
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itextpdf</artifactId>
+            <version>${itextpdf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-csv</artifactId>
+            <version>${jackson-dataformat-csv.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.module</groupId>
+            <artifactId>jackson-module-scala_2.13</artifactId>
+            <version>${jackson-dataformat-csv.version}</version>
+        </dependency>
+
+        <!--Spark-->
+        <dependency>
+            <groupId>com.sparkjava</groupId>
+            <artifactId>spark-core</artifactId>
+            <version>${spark-core.version}</version>
+        </dependency>
     </dependencies>
 
     <distributionManagement>
         <repository>
             <id>release</id>
             <name>TheCodeLabs-releases</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
         </repository>
         <snapshotRepository>
             <id>snapshots</id>
             <name>TheCodeLabs-snapshots</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
         </snapshotRepository>
     </distributionManagement>
 
     <repositories>
         <repository>
             <id>release</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
             <releases>
                 <enabled>true</enabled>
             </releases>
@@ -127,7 +162,7 @@
         </repository>
         <repository>
             <id>snapshots</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
             <releases>
                 <enabled>false</enabled>
             </releases>
@@ -136,5 +171,4 @@
             </snapshots>
         </repository>
     </repositories>
-
 </project>
\ No newline at end of file
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/Displayable.java b/PlayWallCore/src/main/java/de/tobias/playpad/Displayable.java
index 4dc3843112b64197be88e06613a3b1c83e915e39..85e9d9cba76cacddafbead33a59cb3deed87a6c1 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/Displayable.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/Displayable.java
@@ -1,6 +1,5 @@
 package de.tobias.playpad;
 
-import de.thecodelabs.utils.ui.NVC;
 import javafx.beans.property.StringProperty;
 import javafx.scene.Node;
 
@@ -11,13 +10,4 @@ public interface Displayable {
 	default Node getGraphics() {
 		return null;
 	}
-
-	/**
-	 * Optional Method for a displayable cell
-	 *
-	 * @return Einstellungen für dieses Objetkt.
-	 */
-	default NVC getSettingsViewController() {
-		return null;
-	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/DisplayableColor.java b/PlayWallCore/src/main/java/de/tobias/playpad/DisplayableColor.java
index bab00f0381256bf30ecfbb2eca78f9a7fec49f6d..c991b63ec7c2eeb009022a4febd359101e3febb9 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/DisplayableColor.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/DisplayableColor.java
@@ -4,6 +4,6 @@ import javafx.scene.paint.Paint;
 
 public interface DisplayableColor {
 
-	Paint getPaint();
+	Paint getColor();
 
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java b/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java
index dd45280a8beba65bfc78e1e22f4927ef8411d6a0..14d50ffae9ec046ee3cdb1b70fa00542ec112b81 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java
@@ -1,17 +1,25 @@
 package de.tobias.playpad;
 
+import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.versionizer.service.UpdateService;
+import de.tobias.playpad.plugin.GlobalListener;
+import de.tobias.playpad.plugin.MainWindowListener;
 import de.tobias.playpad.plugin.PadListener;
 import de.tobias.playpad.plugin.SettingsListener;
-import de.tobias.playpad.plugin.WindowListener;
+import de.tobias.playpad.profile.ProfileNotFoundException;
 import de.tobias.playpad.project.Project;
+import de.tobias.playpad.project.ProjectNotFoundException;
+import de.tobias.playpad.project.ProjectReader;
+import de.tobias.playpad.project.ProjectReader.ProjectReaderDelegate.ProfileAbortException;
+import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.settings.GlobalSettings;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import javafx.scene.image.Image;
+import org.dom4j.DocumentException;
 
+import java.io.IOException;
 import java.util.List;
-import java.util.Optional;
-import java.util.ResourceBundle;
+import java.util.function.Consumer;
 
 /**
  * Hauptfunktionen für Listener und zur Programmsteuerung für Plugins.
@@ -21,15 +29,15 @@ import java.util.ResourceBundle;
  */
 public interface PlayPad {
 
-	ResourceBundle getUIResourceBundle();
-
 	/**
 	 * Fügt einen Listener für das Hauptfenster hinzu.
 	 *
 	 * @param listener MainView Listener
 	 * @since 2.0.0
 	 */
-	void addMainViewListener(WindowListener<IMainViewController> listener);
+	void addMainViewListener(MainWindowListener listener);
+
+	List<MainWindowListener> getMainViewListeners();
 
 	/**
 	 * Fügt einen Settings Listener hinzu.
@@ -76,6 +84,12 @@ public interface PlayPad {
 	 */
 	List<PadListener> getPadListener();
 
+	void addGlobalListener(GlobalListener globalListener);
+
+	void removeGlobalListener(GlobalListener globalListener);
+
+	List<GlobalListener> getGlobalListeners();
+
 	/**
 	 * Gibt eine Refernz auf das Hauptfenster zurück.
 	 *
@@ -88,7 +102,7 @@ public interface PlayPad {
 	 *
 	 * @return Programmicon
 	 */
-	Optional<Image> getIcon();
+	Image getIcon();
 
 	/**
 	 * Beendet PlayWall.
@@ -109,5 +123,19 @@ public interface PlayPad {
 	 */
 	Project getCurrentProject();
 
+	/**
+	 * Open a project
+	 *
+	 * @param projectReference project reference
+	 * @param onLoaded         on project loaded callback
+	 * @throws IOException                                               io error
+	 * @throws ProjectNotFoundException                                  Project to solve error not found
+	 * @throws ProfileNotFoundException                                  Profile of project not found
+	 * @throws DocumentException                                         XML Error
+	 * @throws ProjectReader.ProjectReaderDelegate.ProfileAbortException Profile Choose aborted
+	 */
+	void openProject(ProjectReference projectReference, Consumer<NVC> onLoaded) throws ProjectNotFoundException, ProfileAbortException, ProfileNotFoundException, DocumentException, IOException;
+
 	UpdateService getUpdateService();
+
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/PlayPadPlugin.java b/PlayWallCore/src/main/java/de/tobias/playpad/PlayPadPlugin.java
index 7ef7ea84252ea92c262d9d359b683df7796cf5fc..643e65bc639f5411f2a6e443c2e4998327c8b02a 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/PlayPadPlugin.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/PlayPadPlugin.java
@@ -32,7 +32,7 @@ public final class PlayPadPlugin {
 		return registryCollection;
 	}
 
-	static void setRegistryCollection(Registries registryCollection) {
+	public static void setRegistryCollection(Registries registryCollection) {
 		PlayPadPlugin.registryCollection = registryCollection;
 	}
 
@@ -40,7 +40,7 @@ public final class PlayPadPlugin {
 		return serverHandler;
 	}
 
-	static void setServerHandler(ServerHandler handler) {
+	public static void setServerHandler(ServerHandler handler) {
 		serverHandler = handler;
 	}
 
@@ -48,7 +48,7 @@ public final class PlayPadPlugin {
 		return commandExecutorHandler;
 	}
 
-	static void setCommandExecutorHandler(CommandExecutorHandler handler) {
+	public static void setCommandExecutorHandler(CommandExecutorHandler handler) {
 		commandExecutorHandler = handler;
 	}
 
@@ -56,7 +56,7 @@ public final class PlayPadPlugin {
 		return modernDesignHandler;
 	}
 
-	static void setStyleable(Styleable modernDesignHandler) {
+	public static void setStyleable(Styleable modernDesignHandler) {
 		PlayPadPlugin.modernDesignHandler = modernDesignHandler;
 	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/Registries.java b/PlayWallCore/src/main/java/de/tobias/playpad/Registries.java
index 9ad4cb02ab675363af7e518ba7391f562e860767..c8a93789547884142b060c5dfbd76535f69c323b 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/Registries.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/Registries.java
@@ -1,7 +1,6 @@
 package de.tobias.playpad;
 
 import de.tobias.playpad.action.ActionProvider;
-import de.tobias.playpad.action.mapper.MapperFactory;
 import de.tobias.playpad.audio.AudioRegistry;
 import de.tobias.playpad.pad.content.PadContentRegistry;
 import de.tobias.playpad.pad.drag.PadDragMode;
@@ -25,8 +24,6 @@ public interface Registries {
 
 	Registry<PadDragMode> getDragModes();
 
-	Registry<MapperFactory> getMappers();
-
 	PadContentRegistry getPadContents();
 
 	Registry<TriggerItemFactory> getTriggerItems();
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/Action.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/Action.java
deleted file mode 100644
index 976831b5b366c2889f518c47b36ce1385074c605..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/Action.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package de.tobias.playpad.action;
-
-import de.tobias.playpad.action.feedback.FeedbackMessage;
-import de.tobias.playpad.action.feedback.FeedbackType;
-import de.tobias.playpad.action.mapper.Mapper;
-import de.tobias.playpad.action.mapper.MapperFeedbackable;
-import de.tobias.playpad.project.Project;
-import de.tobias.playpad.viewcontroller.main.IMainViewController;
-import org.dom4j.Element;
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * Diese Klasse ist die Basis für alle Actions, die durch Mapper auftreten. Die Klasse verarbeitet dabei allen Input und führt die Listener
- * aus.
- *
- * @author tobias
- * @version 5.0.0
- * @see Mapper Mapper sind die Schnittstelle zur Hardware und bestandteil einer Action.
- */
-public abstract class Action implements ActionDisplayable, Cloneable {
-
-	private Mapping mapping;
-
-	/**
-	 * Set a reference to the mapping it referce.
-	 *
-	 * @param mapping mapping
-	 */
-	protected void setMappingRef(Mapping mapping) {
-		this.mapping = mapping;
-	}
-
-	/**
-	 * Get an identification name
-	 *
-	 * @return name
-	 */
-	public abstract String getType();
-
-	/**
-	 * Handle Input from a Mapper. (Ein seperater Listener händelt das Mapper event und sucht die richtigen Actions dazu raus, die dann über
-	 * performAction getriggered werden.)
-	 *
-	 * @param type               input type
-	 * @param project            Current Project
-	 * @param mainViewController MainViewController Implementation
-	 */
-	public abstract void performAction(InputType type, Project project, IMainViewController mainViewController);
-
-	/**
-	 * Handle Output to Mapper (Feedback)
-	 *
-	 * @param message Type of Message (Feedback)
-	 */
-	public void handleFeedback(FeedbackMessage message) {
-		for (Mapper mapper : getMappers()) {
-			if (mapper instanceof MapperFeedbackable) {
-				MapperFeedbackable feedbackable = (MapperFeedbackable) mapper;
-				if (feedbackable.supportFeedback()) {
-					feedbackable.handleFeedback(message);
-				}
-			}
-		}
-	}
-
-	/**
-	 * Init action.
-	 *
-	 * @param project    reference to the current opened project
-	 * @param controller reference to the main view controller
-	 */
-	public abstract void init(Project project, IMainViewController controller);
-
-	/**
-	 * Shows the feedback.
-	 *
-	 * @param project    project
-	 * @param controller main view controller
-	 */
-	public abstract void showFeedback(Project project, IMainViewController controller);
-
-	/**
-	 * Cleared das Feedback auf dem Mapper für diese Action.
-	 */
-	public abstract void clearFeedback();
-
-	/**
-	 * Return List of Mappers for this Action. This list is unmodifiable.
-	 *
-	 * @return mappers
-	 */
-	public List<Mapper> getMappers() {
-		return Collections.unmodifiableList(mapping.getMapperForAction(this));
-	}
-
-	/**
-	 * Return List of Mappers for this Action. This list is unmodifiable.
-	 *
-	 * @return mappers
-	 */
-	public List<Mapper> getMapperSorted() {
-		List<Mapper> list = mapping.getMapperForAction(this);
-		list.sort(Comparator.comparing(Mapper::getType));
-		return Collections.unmodifiableList(list);
-	}
-
-	/**
-	 * Add a mapper to an action
-	 *
-	 * @param mapper new mapper
-	 */
-	public void addMapper(Mapper mapper) {
-		mapping.addMapperToAction(mapper, this);
-	}
-
-	/**
-	 * Remove a mapper from an action
-	 *
-	 * @param mapper old mapper
-	 */
-	public void removeMapper(Mapper mapper) {
-		mapping.removeMapper(mapper, this);
-	}
-
-	/**
-	 * Get the supported feedback type for this action (e.g. SingleFeedback, DoubleFeedback)
-	 *
-	 * @return feedback type
-	 */
-	public abstract FeedbackType geFeedbackType();
-
-	/**
-	 * This will be called on an empty action instance, to load content from an xml element.
-	 *
-	 * @param root Action's root xml element
-	 */
-	public abstract void load(Element root);
-
-	/**
-	 * This method will be call to save the content of an action at savetime. It will be stored in an xml element.
-	 *
-	 * @param root Action's root xml element
-	 */
-	public abstract void save(Element root);
-
-	/**
-	 * Dupliziert das Objekt.
-	 *
-	 * @return Cloned Object
-	 * @throws CloneNotSupportedException Clone Fehlgeschlagen
-	 */
-	public abstract Action cloneAction() throws CloneNotSupportedException;
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/ActionDisplayable.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/ActionDisplayable.java
deleted file mode 100644
index be712ab84f5d0b2eb48f4f77c54cac4b8a40d91d..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/ActionDisplayable.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package de.tobias.playpad.action;
-
-import de.thecodelabs.utils.ui.NVC;
-import de.tobias.playpad.Displayable;
-import de.tobias.playpad.viewcontroller.IMappingTabViewController;
-
-/**
- * Einn zusätzliches Interface für die Klasse {@link ActionProvider} oder {@link Action} mit der es möglich ist für ein ActionType oder eine
- * Action Einstellungen anzuzeigen.
- *
- * @author tobias
- * @since 5.0.0
- */
-public interface ActionDisplayable extends Displayable {
-
-	/**
-	 * Provide a general settings controller for type of actions
-	 *
-	 * @param mapping    current mapping
-	 * @param controller current
-	 * @return ViewController für den ActionType
-	 */
-	default NVC getActionSettingsViewController(Mapping mapping, IMappingTabViewController controller) {
-		return null;
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/ActionProvider.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/ActionProvider.java
index d01d260676d3b18cc53b743da858b4b16081246c..34a0b1dec60d6748d2dcfb2c04d81cad07a4b7e1 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/ActionProvider.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/action/ActionProvider.java
@@ -1,55 +1,33 @@
 package de.tobias.playpad.action;
 
-import de.tobias.playpad.profile.Profile;
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.mapping.KeyType;
+import de.tobias.playpad.action.settings.ActionSettingsEntry;
 import de.tobias.playpad.registry.Component;
 import javafx.scene.control.TreeItem;
 
 import java.util.List;
 
-/**
- * Verwalter einer Action für die Instance und GUI.
- *
- * @author tobias
- * @see Action Implementierung der eigentlichen Action.
- * @since 5.0.0
- */
 public abstract class ActionProvider extends Component {
 
 	public ActionProvider(String type) {
 		super(type);
 	}
 
-	/**
-	 * Erstellt ein TreeItem für die Grupierung der Actions.
-	 *
-	 * @param actions Liste der alle Actionen dieses Types.
-	 * @param mapping Mapping, indem die Actions sind.
-	 * @return TreeItem
-	 */
-	public abstract TreeItem<ActionDisplayable> getTreeViewForActions(List<Action> actions, Mapping mapping);
-
-	/**
-	 * Initialisiert ein Mapping mit allen möglichen Action Varianten. Dies ist nötig, damit alle möglichen Actions in den Einstellungen
-	 * aufgelistet werden können.
-	 *
-	 * @param mapping Mapping
-	 * @param profile Profile für Einstellungen
-	 */
-	public abstract void initActionType(Mapping mapping, Profile profile);
-
-	/**
-	 * Erstellt eine neue Instance der Aktion.
-	 *
-	 * @return Neue Instance.
-	 */
-	public abstract Action newInstance();
-
-	/**
-	 * Gibt die Art der Action zurück. Gibt Auskunft über die Anordnung in den Einstellungen.
-	 *
-	 * @return Art der Aktion
-	 * @see ActionType
-	 */
-	public abstract ActionType geActionType();
+	public abstract String getType();
 
+	public abstract ActionHandler getActionHandler();
+
+	public abstract void createDefaultActions(Mapping mapping);
+
+	public abstract FeedbackType[] supportedFeedbackOptions(Action action, KeyType keyType);
+
+	// Settings
+
+	public abstract ActionType getActionType();
+
+	public abstract TreeItem<ActionSettingsEntry> getTreeItemForActions(List<Action> actions, Mapping mapping);
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/ActionSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/ActionSerializer.java
deleted file mode 100644
index 43a3126a1299192998ee814c89a1050c8314a779..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/ActionSerializer.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package de.tobias.playpad.action;
-
-import de.thecodelabs.storage.xml.XMLDeserializer;
-import de.thecodelabs.storage.xml.XMLHandler;
-import de.thecodelabs.storage.xml.XMLSerializer;
-import de.tobias.playpad.PlayPadPlugin;
-import de.tobias.playpad.action.mapper.Mapper;
-import de.tobias.playpad.action.mapper.MapperSerializer;
-import de.tobias.playpad.plugin.Module;
-import de.tobias.playpad.profile.Profile;
-import de.tobias.playpad.registry.NoSuchComponentException;
-import de.tobias.playpad.registry.Registry;
-import org.dom4j.Element;
-
-import java.util.List;
-
-public class ActionSerializer implements XMLSerializer<Action>, XMLDeserializer<Action> {
-
-	private static final String ACTION_TYPE = "type";
-	private static final String MAPPER = "Mapper";
-
-	private Mapping mapping;
-	private Profile profile;
-
-	public ActionSerializer(Mapping mapping) {
-		this.mapping = mapping;
-	}
-
-	/**
-	 * Speichern.
-	 *
-	 * @param mapping mapping
-	 * @param profile profile
-	 */
-	public ActionSerializer(Mapping mapping, Profile profile) {
-		this.mapping = mapping;
-		this.profile = profile;
-	}
-
-	@Override
-	public Action loadElement(Element element) {
-		String type = element.attributeValue(ACTION_TYPE);
-
-		try {
-			final Registry<ActionProvider> actions = PlayPadPlugin.getRegistries().getActions();
-			Action action = actions.getFactory(type).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;
-		} catch (NoSuchComponentException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-		return null;
-	}
-
-	@Override
-	public void saveElement(Element newElement, Action data) {
-		Module module = PlayPadPlugin.getRegistries().getActions().getModule(data.getType());
-		if (profile != null) {
-			profile.getRef().addRequestedModule(module);
-		}
-
-		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/main/java/de/tobias/playpad/action/InputType.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/InputType.java
deleted file mode 100644
index aa145350e6ae937370f3f140b5ee8335296cd83c..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/InputType.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package de.tobias.playpad.action;
-
-/**
- * Optionne für die verschiedenen Input Möglichkeiten.
- *
- * @author tobias
- * @since 5.0.0
- */
-public enum InputType {
-
-	/**
-	 * Mapper is pressed (e.g. key on the keyboard is pressed)
-	 */
-	PRESSED,
-	/**
-	 * Mapper is releaes (e.g. key on the keyboard is released)
-	 */
-	RELEASED,
-	/**
-	 * Mapper is typed (e.g. key on the keyboard is typed - somewhere in between of pressed and released)
-	 */
-	TYPED
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/Mapping.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/Mapping.java
deleted file mode 100644
index 96c77990a57d2c55851eba4e54aca36eb5e43b13..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/Mapping.java
+++ /dev/null
@@ -1,208 +0,0 @@
-package de.tobias.playpad.action;
-
-import de.tobias.playpad.PlayPadPlugin;
-import de.tobias.playpad.action.feedback.ColorAdjuster;
-import de.tobias.playpad.action.mapper.Mapper;
-import de.tobias.playpad.action.mapper.MapperConnectFeedbackable;
-import de.tobias.playpad.action.mapper.MapperFactory;
-import de.tobias.playpad.profile.Profile;
-import de.tobias.playpad.project.Project;
-import de.tobias.playpad.registry.Registry;
-import de.tobias.playpad.viewcontroller.main.IMainViewController;
-import javafx.beans.property.SimpleStringProperty;
-import javafx.beans.property.StringProperty;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-// COMMENT Mapping
-public class Mapping implements Cloneable, ActionDisplayable {
-
-	private String name;
-	private UUID uuid;
-	private HashMap<Action, List<Mapper>> mapping;
-
-	public Mapping(boolean init) {
-		mapping = new HashMap<>();
-		if (init) {
-			name = "Default";
-			uuid = UUID.randomUUID();
-		}
-		updateDisplayProperty();
-	}
-
-	List<Mapper> getMapperForAction(Action action) {
-		return mapping.getOrDefault(action, null);
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public final UUID getUuid() {
-		return uuid;
-	}
-
-	public void setName(String name) {
-		this.name = name;
-		updateDisplayProperty();
-	}
-
-	public final void setUuid(UUID uuid) {
-		this.uuid = uuid;
-	}
-
-	public Set<Action> getActions() {
-		return mapping.keySet();
-	}
-
-	@SuppressWarnings("unchecked")
-	public <T extends Action> List<T> getActions(ActionProvider type) {
-		return (List<T>) getActionsOfType(type);
-	}
-
-	public List<Action> getActionsOfType(ActionProvider actionFactory) {
-		return mapping.keySet().stream().filter(i -> i.getType().equals(actionFactory.getType())).collect(Collectors.toList());
-	}
-
-	public List<Action> getActionsForMapper(Mapper mapper) {
-		List<Action> actions = new ArrayList<>();
-		for (Action action : mapping.keySet()) {
-			if (mapping.get(action).contains(mapper)) {
-				actions.add(action);
-			}
-		}
-		return actions;
-	}
-
-	public boolean addActionIfNotContains(Action newAction) {
-		for (Action action : mapping.keySet()) {
-			if (action.equals(newAction)) {
-				return false;
-			}
-		}
-		mapping.put(newAction, new ArrayList<>());
-		newAction.setMappingRef(this);
-		return true;
-	}
-
-	void addMapperToAction(Mapper mapper, Action to) {
-		mapping.get(to).add(mapper);
-
-		// Init Mapper to Action (Set kind of Feedback, depending to the action)
-		mapper.setFeedbackType(to.geFeedbackType());
-	}
-
-	public void removeAction(Action action) {
-		mapping.remove(action);
-	}
-
-	void removeMapper(Mapper mapper, Action action) {
-		mapping.get(action).remove(mapper);
-	}
-
-	public void initActionType(Profile profile) {
-		Registry<ActionProvider> actions = PlayPadPlugin.getRegistries().getActions();
-		for (ActionProvider component : actions.getComponents()) {
-			component.initActionType(this, profile);
-		}
-	}
-
-	Set<Action> keySet() {
-		return mapping.keySet();
-	}
-
-	List<Mapper> get(Action action) {
-		return mapping.get(action);
-	}
-
-	public void initFeedbackType() {
-		Registry<MapperFactory> registry = PlayPadPlugin.getRegistries().getMappers();
-		for (MapperFactory mapper : registry.getComponents()) {
-			if (mapper instanceof MapperConnectFeedbackable) {
-				((MapperConnectFeedbackable) mapper).initFeedbackType();
-			}
-		}
-	}
-
-	public void prepareFeedback(Project project) {
-		IMainViewController controller = PlayPadPlugin.getInstance().getMainViewController();
-
-		for (Action action : mapping.keySet()) {
-			try {
-				action.init(project, controller);
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
-		}
-	}
-
-	public void showFeedback(Project project) {
-		IMainViewController controller = PlayPadPlugin.getInstance().getMainViewController();
-		showFeedback(project, controller);
-	}
-
-	private void showFeedback(Project project, IMainViewController controller) {
-		for (Action action : mapping.keySet()) {
-			try {
-				action.showFeedback(project, controller);
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
-		}
-	}
-
-	public void clearFeedback() {
-		Registry<MapperFactory> registry = PlayPadPlugin.getRegistries().getMappers();
-		for (MapperFactory mapper : registry.getComponents()) {
-			if (mapper instanceof MapperConnectFeedbackable) {
-				((MapperConnectFeedbackable) mapper).clearFeedbackType();
-			}
-		}
-
-		getActions().forEach(Action::clearFeedback);
-	}
-
-	public void adjustPadColorToMapper() {
-		ColorAdjuster.applyColorsToMappers();
-	}
-
-	@Override
-	public Mapping clone() throws CloneNotSupportedException {
-		Mapping clone = (Mapping) super.clone();
-
-		clone.mapping = new HashMap<>();
-		for (Action action : mapping.keySet()) {
-			Action actionClone = action.cloneAction();
-			actionClone.setMappingRef(clone);
-			clone.mapping.put(actionClone, new ArrayList<>());
-
-			for (Mapper mapper : action.getMappers()) {
-				Mapper mapperClone = mapper.cloneMapper();
-				actionClone.addMapper(mapperClone);
-			}
-		}
-
-		clone.name = name;
-		clone.uuid = UUID.randomUUID();
-
-		clone.displayProperty = new SimpleStringProperty();
-		return clone;
-	}
-
-	@Override
-	public String toString() {
-		return name;
-	}
-
-	private StringProperty displayProperty = new SimpleStringProperty(toString());
-
-	@Override
-	public StringProperty displayProperty() {
-		return displayProperty;
-	}
-
-	void updateDisplayProperty() {
-		displayProperty.set(toString());
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/MappingList.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/MappingList.java
deleted file mode 100644
index 31eeb1c5881755067a6423c2fadeb6b8e55791e6..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/MappingList.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package de.tobias.playpad.action;
-
-import de.thecodelabs.storage.xml.XMLHandler;
-import de.tobias.playpad.profile.Profile;
-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 java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-// COMMENT MappingList
-public class MappingList extends ArrayList<Mapping> {
-
-	private static final long serialVersionUID = 1L;
-
-	private UUID activeMapping;
-	private WeakReference<Profile> profile;
-
-	public MappingList(Profile profile) {
-		add(new Mapping(true));
-
-		this.profile = new WeakReference<>(profile);
-	}
-
-	public Mapping getActiveMapping() {
-		for (Mapping mapping : this) {
-			if (mapping.getUuid().equals(activeMapping)) {
-				return mapping;
-			}
-		}
-		if (size() > 0) {
-			activeMapping = get(0).getUuid();
-			return get(0);
-		} else {
-			return null;
-		}
-	}
-
-	public void setActiveMapping(Mapping mapping) {
-		activeMapping = mapping.getUuid();
-	}
-
-	private static final String LIST = "List";
-	private static final String MAPPING = "Mapping";
-	private static final String ACTIVE_ATTR = "active";
-
-	public static MappingList load(Path path, Profile profile) throws DocumentException, IOException {
-		MappingList mappings = new MappingList(profile);
-		mappings.clear(); // Clear the default mapping
-
-		if (Files.exists(path)) {
-			SAXReader reader = new SAXReader();
-			Document document = reader.read(Files.newInputStream(path));
-
-			Element rootElement = document.getRootElement();
-			if (rootElement.attributeValue(ACTIVE_ATTR) != null) {
-				mappings.activeMapping = UUID.fromString(rootElement.attributeValue(ACTIVE_ATTR));
-			}
-
-			// 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
-		if (mappings.size() == 0) {
-			mappings.add(new Mapping(true));
-		}
-
-		return mappings;
-	}
-
-	public void save(Path path) throws IOException {
-		Document document = DocumentHelper.createDocument();
-
-		Element rootElement = document.addElement(LIST);
-		if (activeMapping != null)
-			rootElement.addAttribute(ACTIVE_ATTR, activeMapping.toString());
-
-		if (Files.notExists(path)) {
-			Files.createDirectories(path.getParent());
-			Files.createFile(path);
-		}
-
-		XMLHandler<Mapping> handler = new XMLHandler<>(rootElement);
-		handler.saveElements(MAPPING, this, new MappingSerializer(profile.get()));
-
-		if (Files.notExists(path)) {
-			Files.createDirectories(path.getParent());
-			Files.createFile(path);
-		}
-
-		XMLHandler.save(path, document);
-	}
-
-	public static Mapping importMappingPreset(Path path, Profile profile) throws DocumentException, IOException {
-		Mapping mapping = new Mapping(false);
-
-		SAXReader reader = new SAXReader();
-		Document document = reader.read(Files.newInputStream(path));
-		Element rootElement = document.getRootElement();
-
-		MappingSerializer mappingSerializer = new MappingSerializer(profile);
-		mapping = mappingSerializer.loadElement(rootElement);
-		mapping.setUuid(UUID.randomUUID());
-
-		return mapping;
-	}
-
-	public static void exportMidiPreset(Path path, Mapping preset) throws IOException {
-		Document docoment = DocumentHelper.createDocument();
-		Element rootElement = docoment.addElement(MAPPING);
-
-		MappingSerializer mappingSerializer = new MappingSerializer(null);
-		mappingSerializer.saveElement(rootElement, preset);
-
-		XMLWriter writer = new XMLWriter(Files.newOutputStream(path), OutputFormat.createPrettyPrint());
-		writer.write(docoment);
-		writer.close();
-	}
-
-	public boolean containsName(String name) {
-		return stream().anyMatch(i -> i.getName().equals(name));
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/MappingSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/MappingSerializer.java
deleted file mode 100644
index 3825f9778a6e592fa8500b16e73fbebc67e79ef9..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/MappingSerializer.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package de.tobias.playpad.action;
-
-import de.thecodelabs.storage.xml.XMLDeserializer;
-import de.thecodelabs.storage.xml.XMLHandler;
-import de.thecodelabs.storage.xml.XMLSerializer;
-import de.tobias.playpad.profile.Profile;
-import org.dom4j.Element;
-
-import java.util.UUID;
-
-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(Profile profile) {
-		this.profile = profile;
-	}
-
-	@Override
-	public Mapping loadElement(Element element) {
-		Mapping mapping = new Mapping(false);
-
-		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, profile));
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ActionFeedbackSuggester.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ActionFeedbackSuggester.java
new file mode 100644
index 0000000000000000000000000000000000000000..f6ed9f63c71266ee9ac858c3963fc32158adc01b
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ActionFeedbackSuggester.java
@@ -0,0 +1,28 @@
+package de.tobias.playpad.action.feedback;
+
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.tobias.playpad.pad.Pad;
+
+/**
+ * The interface provides methods for handling automatic feedback color choosing for an action.
+ *
+ * @author tobias
+ * @since 5.0.0
+ */
+public interface ActionFeedbackSuggester {
+
+	/**
+	 * Is automatic feedback suggestion enabled
+	 *
+	 * @param action action
+	 * @return <code>true</code> Active
+	 */
+	boolean isAutoFeedbackColors(Action action);
+
+	void suggestFeedback(Action action);
+
+	byte suggestFeedbackChannel(FeedbackType type);
+
+	Pad getPad(Action action);
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ColorAdjustable.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ColorAdjustable.java
deleted file mode 100644
index 54fbdf2a7352b01860079b307d3708185d6e353a..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ColorAdjustable.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package de.tobias.playpad.action.feedback;
-
-import de.tobias.playpad.pad.Pad;
-
-/**
- * Eine Action implementiert dieses Interface, falls die Feedbackfarbe automatisch an die Farbe der Kachel angepasst werden soll.
- *
- * @author tobias
- * @since 5.0.0
- */
-public interface ColorAdjustable {
-
-	/**
-	 * Ist dieses Feature ative.
-	 *
-	 * @return <code>true</code> Active
-	 */
-	boolean isAutoFeedbackColors();
-
-	/**
-	 * Kachel, die mit dieser Action verkünpft ist.
-	 *
-	 * @return Pad
-	 */
-	Pad getPad();
-
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ColorAdjuster.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ColorAdjuster.java
index ada67713e3601858f838775c618e37c96a8b71cb..43b68616b2f60bfe777cb52cef208acb88f6ea2a 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ColorAdjuster.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ColorAdjuster.java
@@ -1,114 +1,156 @@
 package de.tobias.playpad.action.feedback;
 
-import de.tobias.playpad.action.Action;
-import de.tobias.playpad.action.mapper.Mapper;
-import de.tobias.playpad.action.mapper.MapperFeedbackable;
-import de.tobias.playpad.design.modern.model.ModernCartDesign;
-import de.tobias.playpad.design.modern.model.ModernGlobalDesign;
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.action.ActionRegistry;
+import de.thecodelabs.midi.feedback.Feedback;
+import de.thecodelabs.midi.feedback.FeedbackColor;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.feedback.FeedbackValue;
+import de.thecodelabs.midi.mapping.MidiKey;
+import de.thecodelabs.midi.midi.Midi;
+import de.thecodelabs.midi.midi.feedback.MidiFeedbackTranscript;
+import de.tobias.playpad.design.FeedbackDesignColorSuggester;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.profile.Profile;
 import javafx.scene.paint.Color;
 import javafx.scene.paint.Paint;
 
-import java.util.Set;
+import java.util.List;
+import java.util.Optional;
 
 /**
- * Eine Klasse mit nützlichen Methoden um die Farben bei den Mappern anzupassen.
+ * This class provides methods for calculating the best matched feedback color
  *
  * @author tobias
- * @see ColorAdjustable Action muss dieses Interface dafür Implementieren, damit die Farbe Automatisch zum pad gemacht
- * wird.
- * @see ColorAssociator Mapper muss dieses Interface implemetieren, damit die entsprechenden Farbe gefunden werden kann
  * @since 5.1.0
  */
 public class ColorAdjuster {
 
+	private ColorAdjuster() {
+	}
+
 	/**
-	 * Übernimmt die Farben des Pads und den verknüpften Aktionen zu einem Pad auf die Mapper.
+	 * Suggest for all actions in the current mapping feedback values
 	 */
-	public static void applyColorsToMappers() {
+	public static void applyColorsToKeys() {
 		// Apply Layout to Mapper
-		Set<Action> actions = Profile.currentProfile().getMappings().getActiveMapping().getActions();
-		for (Action action : actions) {
-			if (action instanceof ColorAdjustable) {
-				ColorAdjustable adjustable = (ColorAdjustable) action;
-				if (adjustable.isAutoFeedbackColors() && adjustable.getPad() != null) {
-					if (adjustable.getPad().isPadVisible()) {
-						for (Mapper mapper : action.getMappers()) {
-							if (mapper instanceof MapperFeedbackable) {
-								mapColorForMapper(adjustable, mapper);
-							}
-						}
+		final Optional<Mapping> activeMapping = Profile.currentProfile().getMappings().getActiveMapping();
+		activeMapping.ifPresent(mapping -> {
+			final List<Action> actions = mapping.getActions();
+			for (Action action : actions) {
+
+				final ActionHandler actionHandler = ActionRegistry.getActionHandler(action.getActionType());
+
+				if (actionHandler instanceof ActionFeedbackSuggester) {
+					ActionFeedbackSuggester suggester = (ActionFeedbackSuggester) actionHandler;
+
+					if (suggester.isAutoFeedbackColors(action)) {
+						suggester.suggestFeedback(action);
 					}
 				}
 			}
-		}
+		});
 	}
 
-	// COMMENT ColorAdjuster
+	/**
+	 * Suggest the feedback for a midi key depending on an action.
+	 *
+	 * @param suggester feedback suggester
+	 * @param action    action
+	 * @param key       midi key
+	 */
+	public static void setSuggestedFeedbackColors(ActionFeedbackSuggester suggester, Action action, MidiKey key) {
+		MidiFeedbackTranscript transcript = Midi.getInstance().getFeedbackTranscript();
+		if (transcript == null) {
+			return;
+		}
 
-	private static void mapColorForMapper(ColorAdjustable cartAction, Mapper mapper) {
-		MapperFeedbackable feedbackable = (MapperFeedbackable) mapper;
-		if (feedbackable.supportFeedback() && mapper instanceof ColorAssociator) {
-			ColorAssociator colorAssociator = (ColorAssociator) mapper;
+		Pad pad = suggester.getPad(action);
 
-			Pad pad = cartAction.getPad();
-			Color layoutStdColor = null;
-			Color layoutEvColor = null;
+		Color layoutStdColor = null;
+		Color layoutEvColor = null;
 
-			if (pad.getPadSettings().isCustomDesign()) {
-				ModernCartDesign design = pad.getPadSettings().getDesign();
-				if (design != null) {
-					layoutStdColor = design.getAssociatedStandardColor();
-					layoutEvColor = design.getAssociatedEventColor();
-				}
-			} else {
-				ModernGlobalDesign design = Profile.currentProfile().getProfileSettings().getDesign();
-				if (design != null) {
-					layoutStdColor = design.getAssociatedStandardColor();
-					layoutEvColor = design.getAssociatedEventColor();
-				}
-			}
+		FeedbackDesignColorSuggester design;
+		if (pad != null && pad.getPadSettings().isCustomDesign()) {
+			design = pad.getPadSettings().getDesign();
+		} else {
+			design = Profile.currentProfile().getProfileSettings().getDesign();
+		}
 
-			if (layoutStdColor != null) {
-				DisplayableFeedbackColor matchedColor = searchColor(colorAssociator, FeedbackMessage.STANDARD, layoutStdColor);
-				colorAssociator.setColor(FeedbackMessage.STANDARD, matchedColor);
-			}
+		if (design != null) {
+			layoutStdColor = design.getDesignDefaultColor();
+			layoutEvColor = design.getDesignEventColor();
+		}
 
-			if (layoutEvColor != null) {
-				DisplayableFeedbackColor matchedColor = searchColor(colorAssociator, FeedbackMessage.EVENT, layoutEvColor);
-				colorAssociator.setColor(FeedbackMessage.EVENT, matchedColor);
-			}
+		if (layoutStdColor != null) {
+			searchColor(transcript, layoutStdColor).ifPresent(matchedColor -> {
+				final byte channel = suggester.suggestFeedbackChannel(FeedbackType.DEFAULT);
+				key.setDefaultFeedback(new Feedback(channel, matchedColor.getValue()));
+			});
+		}
+
+		if (layoutEvColor != null) {
+			searchColor(transcript, layoutEvColor).ifPresent(matchedColor -> {
+				final byte channel = suggester.suggestFeedbackChannel(FeedbackType.EVENT);
+				key.setEventFeedback(new Feedback(channel, matchedColor.getValue()));
+			});
+		}
+
+		if (layoutEvColor != null) {
+			searchColor(transcript, layoutEvColor).ifPresent(matchedColor -> {
+				final byte channel = suggester.suggestFeedbackChannel(FeedbackType.WARNING);
+				key.setWarningFeedback(new Feedback(channel, matchedColor.getValue()));
+			});
 		}
 	}
 
-	protected static DisplayableFeedbackColor searchColor(ColorAssociator colorAssociator, FeedbackMessage message, Color color) {
-		DisplayableFeedbackColor minColor = colorAssociator.map(color);
-		if (minColor != null) {
-			return minColor;
+	/**
+	 * Get a appropriate feedback color based on a given device and ui color.
+	 *
+	 * @param transcript device implementation
+	 * @param color      ui color
+	 * @return feedback color
+	 */
+	private static Optional<FeedbackValue> searchColor(MidiFeedbackTranscript transcript, Color color) {
+
+		// Look for predefined colors
+		if (transcript instanceof FeedbackColorSuggester) {
+			FeedbackColorSuggester suggester = (FeedbackColorSuggester) transcript;
+
+			final FeedbackColor suggest = suggester.suggest(color);
+			if (suggest != null) {
+				return Optional.of(suggest);
+			}
 		}
+
+		// Calculate
+		return calculateNearestColor(transcript, color);
+	}
+
+	private static Optional<FeedbackValue> calculateNearestColor(MidiFeedbackTranscript transcript, Color color) {
+		FeedbackColor minColor = null;
 		double minVal = 1;
 
-		for (DisplayableFeedbackColor feedbackColor : colorAssociator.getColors()) {
-			Paint paint = feedbackColor.getPaint();
-			if (paint instanceof Color) {
-				Color c = (Color) paint;
-				double diff = Math.sqrt(Math.pow(c.getRed() - color.getRed(), 2) + Math.pow(c.getGreen() - color.getGreen(), 2)
-						+ Math.pow(c.getBlue() - color.getBlue(), 2));
-				if (minVal > diff) {
-					minVal = diff;
-					minColor = feedbackColor;
+		for (FeedbackValue feedbackValue : transcript.getFeedbackValues()) {
+			if (feedbackValue instanceof FeedbackColor) {
+				Paint paint = ((FeedbackColor) feedbackValue).getColor();
+				if (paint instanceof Color) {
+					Color c = (Color) paint;
+					double diff = Math.sqrt(Math.pow(c.getRed() - color.getRed(), 2) + Math.pow(c.getGreen() - color.getGreen(), 2)
+							+ Math.pow(c.getBlue() - color.getBlue(), 2));
+					if (minVal > diff) {
+						minVal = diff;
+						minColor = (FeedbackColor) feedbackValue;
+					}
 				}
 			}
 		}
 		if (minColor != null && minVal < 0.35) {
-			return minColor;
-		} else if (message == FeedbackMessage.STANDARD) {
-			return colorAssociator.getDefaultStandardColor();
-		} else if (message == FeedbackMessage.EVENT) {
-			return colorAssociator.getDefaultEventColor();
+			return Optional.of(minColor);
 		} else {
-			return null;
+			return Optional.empty();
 		}
 	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ColorAssociator.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ColorAssociator.java
deleted file mode 100644
index 2f85e744440a90685bf37cf30ee5b549ef69f0ab..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/ColorAssociator.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package de.tobias.playpad.action.feedback;
-
-import javafx.scene.paint.Color;
-
-/**
- * Dieses Interface wird in einem Mapper implementiert. Dabei handelt er die Anfragen für das Mapping von Farben.
- *
- * @author tobias
- * @since 5.0.0
- */
-public interface ColorAssociator {
-
-	/**
-	 * Gibt die Gerätefarben zurück. Dabei enthalten diese ein Int Value und ein Paint.
-	 *
-	 * @return Liste an Farben
-	 */
-	DisplayableFeedbackColor[] getColors();
-
-	/**
-	 * Standardfarbe, falls nichts passendes gefunden wurde.
-	 *
-	 * @return Standardfarbe
-	 */
-	DisplayableFeedbackColor getDefaultStandardColor();
-
-	/**
-	 * Eventfarbe, falls nichts passendes gefunden wurde.
-	 *
-	 * @return Eventfarbe
-	 */
-	DisplayableFeedbackColor getDefaultEventColor();
-
-	/**
-	 * Setzt die Feedback Farbe für die Instanz des Mappers.
-	 *
-	 * @param feedbackMessage Art der Feedbacknachricht
-	 * @param color           Matched Color
-	 */
-	void setColor(FeedbackMessage feedbackMessage, DisplayableFeedbackColor color);
-
-	/**
-	 * Sucht zu einer {@link Color} die passende FeedbackColor, falls vorhanden.
-	 *
-	 * @param color Kachel Farbe
-	 * @return Feedback Farbe oder null.
-	 */
-	DisplayableFeedbackColor map(Color color);
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/DisplayableFeedbackColor.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/DisplayableFeedbackColor.java
deleted file mode 100644
index 8709c6f4556d468f8769a89d94d4cc969bb3b9ab..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/DisplayableFeedbackColor.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package de.tobias.playpad.action.feedback;
-
-import de.tobias.playpad.DisplayableColor;
-
-public interface DisplayableFeedbackColor extends DisplayableColor {
-
-	int mapperFeedbackValue();
-
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/Feedback.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/Feedback.java
deleted file mode 100644
index 5d543dc672a30cdd6e53e7e5e8fbfb8f72862f8e..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/Feedback.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package de.tobias.playpad.action.feedback;
-
-import de.tobias.playpad.action.mapper.Mapper;
-import org.dom4j.Element;
-
-/**
- * Das ist die Abstrakte Klasse für ein Feedback. Jedes Mapper Gerät kann eine eigene Klasse dafür entwickeln. Allerdings müssen gibt es ur
- * eine beschränkte Anzahl an Typen von Feedbacks.
- *
- * @author tobias
- * @see FeedbackType Type des Feedbacks. Damit wird es im Mapper initalisiert.
- * @see Mapper#initFeedback() Damit wird das Feedback initalisiert im Mapper.
- * @since 5.0.0
- */
-public abstract class Feedback {
-
-	/**
-	 * Gibt den Wert für das Gerät zurück, für eine bestimmte Aktion.
-	 *
-	 * @param message Art der Feedback Meldung
-	 * @return Wert für den Mapper
-	 */
-	public abstract int getValueForFeedbackMessage(FeedbackMessage message);
-
-	/**
-	 * Setzt den Wert für eine Feedback Meldung.
-	 *
-	 * @param feedbackMessage Art der Feedback Meldung
-	 * @param value           Wert für den Mapper
-	 */
-	public abstract void setFeedback(FeedbackMessage feedbackMessage, int value);
-
-	/**
-	 * Lädt alle Informationen aus einem XML Objekt.
-	 *
-	 * @param feedbackObject XML Object.
-	 */
-	public abstract void load(Element feedbackObject);
-
-	/**
-	 * Speichert die Informationen des Feedbacks in ein XML Objekt.
-	 *
-	 * @param feedbackObject Oberstes Objekt der XML Daten
-	 */
-	public abstract void save(Element feedbackObject);
-
-	/**
-	 * Dupliziert ein FeedbackObjeck.
-	 *
-	 * @return Duplikat.
-	 * @throws CloneNotSupportedException Clone Fehlerhaft
-	 */
-	public abstract Feedback cloneFeedback() throws CloneNotSupportedException;
-
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/FeedbackColorSuggester.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/FeedbackColorSuggester.java
new file mode 100644
index 0000000000000000000000000000000000000000..9af2b7699149cbf75ea4ed13c3ac872b224ccd05
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/FeedbackColorSuggester.java
@@ -0,0 +1,9 @@
+package de.tobias.playpad.action.feedback;
+
+import de.thecodelabs.midi.feedback.FeedbackColor;
+import javafx.scene.paint.Color;
+
+public interface FeedbackColorSuggester {
+
+	FeedbackColor suggest(Color color);
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/FeedbackMessage.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/FeedbackMessage.java
deleted file mode 100644
index 94d1b772a9c4d1bc1c1926d4daff209e3c55a895..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/FeedbackMessage.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package de.tobias.playpad.action.feedback;
-
-/**
- * Arten von Feedback Meldungen.
- *
- * @author tobias
- * @see Feedback#getValueForFeedbackMessage(FeedbackMessage)
- * @since 5.0.0
- */
-public enum FeedbackMessage {
-
-	/**
-	 * Feedback Aus.
-	 */
-	OFF,
-	/**
-	 * Standart bei keiner Aktion.
-	 */
-	STANDARD,
-	/**
-	 * Besondere Aktion.
-	 */
-	EVENT,
-	/**
-	 * Wichtiger Hinweis auf dem Mapper.
-	 */
-	WARNING
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/FeedbackType.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/FeedbackType.java
deleted file mode 100644
index 518ed212f7ed8082bbe3f4707230b366f20946ad..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/FeedbackType.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package de.tobias.playpad.action.feedback;
-
-
-public enum FeedbackType {
-
-	SINGLE,
-	DOUBLE
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/LightMode.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/LightMode.java
new file mode 100644
index 0000000000000000000000000000000000000000..17542c04334d2b3ba848a0cc87e587a71eb5c1c4
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/action/feedback/LightMode.java
@@ -0,0 +1,26 @@
+package de.tobias.playpad.action.feedback;
+
+import de.thecodelabs.midi.feedback.FeedbackColor;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public enum LightMode {
+	LOW,
+	MIDDLE,
+	NORMAL,
+	HIGH;
+
+	public interface ILightMode extends FeedbackColor {
+		LightMode getLightMode();
+
+		FeedbackColor translate(LightMode lightMode);
+	}
+
+	public static List<ILightMode> filter(ILightMode[] values, LightMode filter) {
+		return Stream.of(values)
+				.filter(v -> v.getLightMode() == filter)
+				.collect(Collectors.toList());
+	}
+}
\ No newline at end of file
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/Mapper.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/Mapper.java
deleted file mode 100644
index d0f8c46c88f3b1b062c26d51e13b1b77b013e806..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/Mapper.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package de.tobias.playpad.action.mapper;
-
-import de.tobias.playpad.Displayable;
-import de.tobias.playpad.action.Action;
-import de.tobias.playpad.action.feedback.Feedback;
-import de.tobias.playpad.action.feedback.FeedbackType;
-import org.dom4j.Element;
-
-/**
- * Abstrakte Klasse für das Handling von Mappern. Die Aktionen und Handler werden von der Entsprechenden Aktion verwaltet, die dazu gehört.
- * Jeder Mapper muss zu einer Aktion gehören. Zu jedem Mapper gehört auch ein Feedback. Dieses wird mittels Interfaces in der konktreten
- * Implementation definiert. Diese abstrakte Klasse verwaltet allerdings nur den Type des Feedbacks. Die eigentloche Implementierung des
- * Feedbacks ist Aufgabe des konkreten Mappers.
- *
- * @author tobias
- * @see Action Aktion, zu der ein Mapper gehört.
- * @see Feedback Feedback für ein Mapper.
- * @since 5.0.0
- */
-public abstract class Mapper implements Displayable, Cloneable {
-
-	/**
-	 * Feedback für diesen Mapper. (Beispiel Feedback für eine Taste an einem MIDI Gerät.
-	 */
-	protected FeedbackType feedbackType;
-
-	/**
-	 * Setzt den FeedbackType des Mappers und initalisiert ihn.
-	 *
-	 * @param feedbackType neuer FeedbackType
-	 * @see Mapper#initFeedback() wird automatisch aufgerufen.
-	 */
-	@Deprecated // Referenz auf Action, da Action den FeedbackType schon hat
-	public void setFeedbackType(FeedbackType feedbackType) {
-		this.feedbackType = feedbackType;
-		initFeedback();
-	}
-
-	/**
-	 * Gibt den FeedbackType für den entsprechenden Mapper zurück.
-	 *
-	 * @return FeedbackType für den Mapper.
-	 */
-	@Deprecated
-	public FeedbackType getFeedbackType() {
-		return feedbackType;
-	}
-
-	/**
-	 * Muss die entsprechende Implementierung des Feedbacks, sofern überhaupt benütigt initialisieren. Standart Implementierung ist leer, da
-	 * optionale Methode.
-	 */
-	public void initFeedback() {
-
-	}
-
-	/**
-	 * ID des Mappers.
-	 *
-	 * @return IDs
-	 */
-	public abstract String getType();
-
-	/**
-	 * Deserialisierung der Daten
-	 *
-	 * @param element XML Element
-	 * @param action  Zugehörige Action
-	 */
-	public abstract void load(Element element, Action action);
-
-	/**
-	 * Speichert die Einstellungen eines Mappers.
-	 *
-	 * @param element Oberstes Objekt der XML Daten
-	 */
-	public abstract void save(Element element);
-
-	/**
-	 * Dupliziert ein Mapper Objekt.
-	 *
-	 * @return Duplikat.
-	 * @throws CloneNotSupportedException Clone Fehlgeschlagen
-	 */
-	public abstract Mapper cloneMapper() throws CloneNotSupportedException;
-
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperConnectFeedbackable.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperConnectFeedbackable.java
deleted file mode 100644
index a15a912057ae696b36eb1728f6c829013a1389b3..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperConnectFeedbackable.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package de.tobias.playpad.action.mapper;
-
-/**
- * Dieses Interface ermöglicht einem Mapper Gerät (nicht einem speziellen Mapping mit einer Action) sich einzurichten und wieder zu clearen.
- *
- * @author tobias
- */
-public interface MapperConnectFeedbackable {
-
-	void clearFeedbackType();
-
-	void initFeedbackType();
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperFactory.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperFactory.java
deleted file mode 100644
index 0593ca26a35483b9b4f9aa4cd4694d8273883edb..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperFactory.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package de.tobias.playpad.action.mapper;
-
-import de.tobias.playpad.registry.Component;
-
-public abstract class MapperFactory extends Component {
-
-	public MapperFactory(String type) {
-		super(type);
-	}
-
-	public abstract Mapper createNewMapper();
-
-	public abstract MapperViewController getQuickSettingsViewController(Mapper mapper);
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperFeedbackable.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperFeedbackable.java
deleted file mode 100644
index ae78ea90077bda31b947585210c128c329fda5a7..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperFeedbackable.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package de.tobias.playpad.action.mapper;
-
-import de.tobias.playpad.action.feedback.FeedbackMessage;
-
-/**
- * Implement this interface to enable a mapper to receive feedback from an action
- *
- * @author tobias
- */
-public interface MapperFeedbackable {
-
-	boolean supportFeedback();
-
-	void handleFeedback(FeedbackMessage message);
-
-}
\ No newline at end of file
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperSerializer.java
deleted file mode 100644
index d42b38eec8f5ddbcc2772cfccad4032e9ca4f97f..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperSerializer.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package de.tobias.playpad.action.mapper;
-
-import de.thecodelabs.storage.xml.XMLDeserializer;
-import de.thecodelabs.storage.xml.XMLSerializer;
-import de.tobias.playpad.PlayPadPlugin;
-import de.tobias.playpad.action.Action;
-import de.tobias.playpad.registry.NoSuchComponentException;
-import org.dom4j.Element;
-
-/**
- * Laden und Speichern von Mappern (Array von Mappern)
- *
- * @author tobias
- * @since 5.0.1
- */
-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);
-
-		try {
-			MapperFactory component = PlayPadPlugin.getRegistries().getMappers().getFactory(mapperType);
-
-			Mapper mapper = component.createNewMapper();
-			mapper.load(element, action);
-			return mapper;
-		} catch (NoSuchComponentException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-		return null;
-	}
-
-	@Override
-	public void saveElement(Element newElement, Mapper data) {
-		newElement.addAttribute(MAPPER_TYPE, data.getType());
-		data.save(newElement);
-
-	}
-
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperViewController.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperViewController.java
index dd07d6efaa0741919f2dc547e5265fd6118e5faa..591f6095ccb7a505e3dc14c142251938390b50d5 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperViewController.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/action/mapper/MapperViewController.java
@@ -1,9 +1,10 @@
 package de.tobias.playpad.action.mapper;
 
+import de.thecodelabs.midi.mapping.Key;
 import de.thecodelabs.utils.ui.NVC;
 
 /**
- * Übersicht über die Mapper zu einer Action.s
+ * Übersicht über die Mapper zu einer Actions.
  *
  * @author tobias
  * @since 5.0.0
@@ -14,7 +15,9 @@ public abstract class MapperViewController extends NVC {
 
 	public abstract void hideFeedback();
 
-	public abstract Mapper getMapper();
+	public abstract void setKey(Key midiKey);
+
+	public abstract Key getKey();
 
 	/**
 	 * Zeigt einen Dialog für die Eingabe des Mappers.
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/mididevice/DeviceColorAssociatorConnector.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/mididevice/DeviceColorAssociatorConnector.java
deleted file mode 100644
index 9ef99ee272b9ae3a75319ff102a2a330a66758a0..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/mididevice/DeviceColorAssociatorConnector.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package de.tobias.playpad.action.mididevice;
-
-import de.tobias.playpad.action.feedback.DisplayableFeedbackColor;
-import javafx.scene.paint.Color;
-
-public interface DeviceColorAssociatorConnector {
-
-	DisplayableFeedbackColor getDefaultStandardColor();
-
-	DisplayableFeedbackColor getDefaultEventColor();
-
-	DisplayableFeedbackColor[] getColors();
-
-	DisplayableFeedbackColor getPreferColorMapping(Color color);
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/mididevice/MidiDeviceImpl.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/mididevice/MidiDeviceImpl.java
deleted file mode 100644
index 5d781982a360d40fc1e12f80b5efe8240b0909b5..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/action/mididevice/MidiDeviceImpl.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package de.tobias.playpad.action.mididevice;
-
-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.event.Event;
-import de.tobias.playpad.event.EventDispatcher;
-import de.tobias.playpad.event.Listener;
-import de.tobias.playpad.midi.device.DeviceRegistry;
-
-import javax.sound.midi.MidiMessage;
-import java.util.List;
-
-/**
- * Abstraktes Midi Gerät. Jede Implementierung musss hier von erben. Es ist zugleich ein Listener und registriert die Listener beim
- * Erstellen automatisch auf Implementierung. Mögliche Interfaces: DeviceColorAssociatorConnector
- *
- * @author tobias
- * @since 5.0.0
- */
-public abstract class MidiDeviceImpl extends EventDispatcher implements Listener {
-
-	public MidiDeviceImpl() {
-		registerEventListener(this);
-	}
-
-	public abstract String getName();
-
-	// Feedback
-	public abstract boolean supportFeedback();
-
-	public abstract DisplayableFeedbackColor[] getColors();
-
-	public abstract DisplayableFeedbackColor getColor(int id);
-
-	public abstract void initDevice();
-
-	public abstract void handleFeedback(FeedbackMessage type, int key, Feedback feedback);
-
-	public abstract void clearFeedback();
-
-	// Custom Midi Actions
-	public void onMidiMessage(MidiMessage message) {
-	}
-
-	@Override
-	public void dispatchEvent(Event event) {
-		List<ListenerHandler> listeners = this.listeners.get(event.getClass().getName());
-		if (listeners != null) {
-			for (ListenerHandler handler : listeners) {
-				handler.execute(event);
-				System.out.println("Dispatched MidiDeviceImpl Event: " + event);
-			}
-		}
-		DeviceRegistry.getFactoryInstance().dispatchEvent(event);
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/settings/ActionSettingsEntry.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/settings/ActionSettingsEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8aab818a1590bca98e4acfb9b2cf2bd3e553b51
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/action/settings/ActionSettingsEntry.java
@@ -0,0 +1,29 @@
+package de.tobias.playpad.action.settings;
+
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.tobias.playpad.Displayable;
+import de.tobias.playpad.viewcontroller.IMappingTabViewController;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.scene.Node;
+
+public interface ActionSettingsEntry extends Displayable {
+
+	String getName();
+
+	FontIcon getIcon();
+
+	NVC getDetailSettingsController(Mapping mapping, IMappingTabViewController controller);
+
+	@Override
+	default Node getGraphics() {
+		return getIcon();
+	}
+
+	@Override
+	default StringProperty displayProperty() {
+		return new SimpleStringProperty(getName());
+	}
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/action/settings/ActionSettingsMappable.java b/PlayWallCore/src/main/java/de/tobias/playpad/action/settings/ActionSettingsMappable.java
new file mode 100644
index 0000000000000000000000000000000000000000..aefc9df716b51f486b90c920d1e933d53866fbd4
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/action/settings/ActionSettingsMappable.java
@@ -0,0 +1,7 @@
+package de.tobias.playpad.action.settings;
+
+import de.thecodelabs.midi.action.Action;
+
+public interface ActionSettingsMappable {
+	Action getAction();
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/audio/AudioRegistry.java b/PlayWallCore/src/main/java/de/tobias/playpad/audio/AudioRegistry.java
index 41674d8b72f4f245d977b6521eba7564946db823..1f73de203b31626f09fbdc68a111d2962014bac3 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/audio/AudioRegistry.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/audio/AudioRegistry.java
@@ -4,7 +4,6 @@ import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.registry.DefaultComponentRegistry;
 import de.tobias.playpad.registry.NoSuchComponentException;
 
-@Deprecated
 public class AudioRegistry extends DefaultComponentRegistry<AudioHandlerFactory> {
 
 	public AudioRegistry() {
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/design/DesignColorAssociator.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/FeedbackDesignColorSuggester.java
similarity index 81%
rename from PlayWallCore/src/main/java/de/tobias/playpad/design/DesignColorAssociator.java
rename to PlayWallCore/src/main/java/de/tobias/playpad/design/FeedbackDesignColorSuggester.java
index d00cbaeb94264a0ac7c41634a0cdaaa7671cc869..846f33c2947393d070682be584f329988502c638 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/design/DesignColorAssociator.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/FeedbackDesignColorSuggester.java
@@ -9,20 +9,20 @@ import javafx.scene.paint.Color;
  * @author tobias
  * @since 5.0.0
  */
-public interface DesignColorAssociator {
+public interface FeedbackDesignColorSuggester {
 
 	/**
 	 * Gibt die Standardfarbe (Kacheln ohne Aktion) zurück.
 	 *
 	 * @return Farbe der Kachel
 	 */
-	Color getAssociatedStandardColor();
+	Color getDesignDefaultColor();
 
 	/**
 	 * Gibt die Eventfarbe (Kacheln mit Aktion) zurück.
 	 *
 	 * @return Farbe der Kachel
 	 */
-	Color getAssociatedEventColor();
+	Color getDesignEventColor();
 
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/design/ModernDesign.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/ModernDesignHandler.java
similarity index 85%
rename from PlayWallCore/src/main/java/de/tobias/playpad/design/ModernDesign.java
rename to PlayWallCore/src/main/java/de/tobias/playpad/design/ModernDesignHandler.java
index 8e418ddac5afd7d017f26b28a012464b4797f6e5..a96e7a9bf1223c41a82a522f03f0a2ebc1769f04 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/design/ModernDesign.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/ModernDesignHandler.java
@@ -3,7 +3,7 @@ package de.tobias.playpad.design;
 import de.tobias.playpad.design.modern.ModernCartDesignHandler;
 import de.tobias.playpad.design.modern.ModernGlobalDesignHandler;
 
-public interface ModernDesign {
+public interface ModernDesignHandler {
 	ModernGlobalDesignHandler global();
 
 	ModernCartDesignHandler cart();
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernColor.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernColor.java
index 4343558bceca45c9c37f81d1d332f43aeb3d1c6c..7da15f82d91761906a3534072254934696a11123 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernColor.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernColor.java
@@ -1,117 +1,109 @@
 package de.tobias.playpad.design.modern;
 
+import de.thecodelabs.storage.settings.Storage;
+import de.thecodelabs.storage.settings.StorageTypes;
+import de.thecodelabs.utils.application.ApplicationUtils;
 import de.tobias.playpad.DisplayableColor;
+import de.tobias.playpad.design.modern.model.ModernColorBean;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.util.FadeableColor;
 import javafx.scene.paint.*;
 
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.stream.Stream;
+
 public enum ModernColor implements DisplayableColor {
 
-	// - Color Hi -- Color Low -- Font ---- Button -- Bar BG -- Bar Track
-	RED1("#ef9a9a", "#ef5350", "#FFFFFF", "#FFFFFF", "#FFFFFF", "#333333"),
-	RED2("#ef5350", "#e53935", "#FFFFFF", "#FFFFFF", "#FFFFFF", "#333333"),
-	RED3("#e53935", "#c62828", "#FFFFFF", "#FFFFFF", "#FFFFFF", "#333333"),
-
-	// --------- BG ------ PLAY ----- Font ---- Button -- Bar BG -- Bar Track
-	DARK_RED1("#D92349", "#AD2039", "#FFFFFF", "#FFFFFF", "#FFFFFF", "#333333"),
-	DARK_RED2("#C92349", "#8D2039", "#FFFFFF", "#FFFFFF", "#FFFFFF", "#333333"),
-	DARK_RED3("#A90329", "#6D0019", "#FFFFFF", "#FFFFFF", "#FFFFFF", "#333333"),
-
-	// ---- BG ------ PLAY ----- Font ---- Button -- Bar BG -- Bar Track
-	PINK1("#f48fb1", "#ec407a", "#FFFFFF", "#FFFFFF", "#FFFFFF", "#333333"),
-	PINK2("#ec407a", "#d81b60", "#FFFFFF", "#FFFFFF", "#FFFFFF", "#333333"),
-	PINK3("#d81b60", "#ad1457", "#FFFFFF", "#FFFFFF", "#FFFFFF", "#333333"),
-
-	// -------- BG ------ PLAY ----- Font ---- Button -- Bar BG -- Bar Track
-	PURPLE1("#ce93d8", "#ab47bc", "#FFFFFF", "#FFFFFF", "#FFFFFF", "#333333"),
-	PURPLE2("#ab47bc", "#8e24aa", "#FFFFFF", "#FFFFFF", "#FFFFFF", "#333333"),
-	PURPLE3("#8e24aa", "#6a1b9a", "#FFFFFF", "#FFFFFF", "#FFFFFF", "#333333"),
-
-	// ---- BG ------ PLAY ----- Font ---- Button -- Bar BG -- Bar Track
-	LIGHT_BLUE1("#80deea", "#26c6da", "#000000", "#000000", "#FFFFFF", "#333333"),
-	LIGHT_BLUE2("#26c6da", "#00acc1", "#000000", "#000000", "#FFFFFF", "#333333"),
-	LIGHT_BLUE3("#00acc1", "#00838f", "#000000", "#000000", "#FFFFFF", "#333333"),
-
-	// ---- BG ------ PLAY ----- Font ---- Button -- Bar BG -- Bar Track
-	BLUE1("#90caf9", "#42a5f5", "#000000", "#000000", "#FFFFFF", "#333333"),
-	BLUE2("#42a5f5", "#1e88e5", "#000000", "#000000", "#FFFFFF", "#333333"),
-	BLUE3("#1e88e5", "#1565c0", "#000000", "#000000", "#FFFFFF", "#333333"),
-
-	// ------------ BG ------ PLAY ----- Font ---- Button --- Bar BG -- Bar Track
-	LIGHT_GREEN1("#c5e1a5", "#9ccc65", "#000000", "#000000", "#FFFFFF", "#333333"),
-	LIGHT_GREEN2("#9ccc65", "#7cb342", "#000000", "#000000", "#FFFFFF", "#333333"),
-	LIGHT_GREEN3("#7cb342", "#558b2f", "#000000", "#000000", "#FFFFFF", "#333333"),
-
-	// ---- BG ------ PLAY ----- Font ---- Button -- Bar BG -- Bar Track
-	LIME1("#e6ee9c", "#d4e157", "#000000", "#000000", "#FFFFFF", "#333333"),
-	LIME2("#d4e157", "#c0ca33", "#000000", "#000000", "#FFFFFF", "#333333"),
-	LIME3("#c0ca33", "#9e9d24", "#000000", "#000000", "#FFFFFF", "#333333"),
-
-	// ------- BG ------ PLAY ------ Font ---- Button -- Bar BG -- Bar Track
-	YELLOW1("#fff59d", "#ffee58", "#000000", "#000000", "#FFFFFF", "#333333"),
-	YELLOW2("#ffee58", "#fdd835", "#000000", "#000000", "#FFFFFF", "#333333"),
-	YELLOW3("#fdd835", "#f9a825", "#000000", "#000000", "#FFFFFF", "#333333"),
-
-	// ------- BG ------ PLAY ----- Font ---- Button -- Bar BG -- Bar Track
-	ORANGE1("#ffcc80", "#ffa726", "#000000", "#000000", "#FFFFFF", "#333333"),
-	ORANGE2("#ffa726", "#fb8c00", "#000000", "#000000", "#FFFFFF", "#333333"),
-	ORANGE3("#fb8c00", "#ef6c00", "#000000", "#000000", "#FFFFFF", "#333333"),
-
-	// ---- BG ------ PLAY ----- Font ---- Button --- Bar BG --- Bar Track
-	GRAY1("#eeeeee", "#cccccc", "#000000", "#000000", "#FFFFFF", "#333333"),
-	GRAY2("#cccccc", "#aaaaaa", "#000000", "#000000", "#000000", "#FFFFFF"),
-	GRAY3("#aaaaaa", "#888888", "#FFFFFF", "#FFFFFF", "#000000", "#FFFFFF"),
-	GRAY4("#888888", "#666666", "#FFFFFF", "#FFFFFF", "#000000", "#FFFFFF"),
-	GRAY5("#666666", "#444444", "#FFFFFF", "#FFFFFF", "#888888", "#FFFFFF"),
-	GRAY6("#444444", "#222222", "#FFFFFF", "#FFFFFF", "#888888", "#FFFFFF");
-
-	private final String colorHi;
-	private final String colorLow;
-	private final String fontColor;
-	private final String buttonColor;
-	private final String playbarColor;
-	private final String playbarTrackColor;
-
-	ModernColor(String colorHi, String colorLow, String fontColor, String buttonColor, String playbarColor, String playbarTrackColor) {
-		this.colorHi = colorHi;
-		this.colorLow = colorLow;
-		this.fontColor = fontColor;
-		this.buttonColor = buttonColor;
-		this.playbarColor = playbarColor;
-		this.playbarTrackColor = playbarTrackColor;
+	RED1,
+	RED2,
+	RED3,
+
+	DARK_RED1,
+	DARK_RED2,
+	DARK_RED3,
+
+	PINK1,
+	PINK2,
+	PINK3,
+
+	PURPLE1,
+	PURPLE2,
+	PURPLE3,
+
+	LIGHT_BLUE1,
+	LIGHT_BLUE2,
+	LIGHT_BLUE3,
+
+	BLUE1,
+	BLUE2,
+	BLUE3,
+
+	LIGHT_GREEN1,
+	LIGHT_GREEN2,
+	LIGHT_GREEN3,
+
+	LIME1,
+	LIME2,
+	LIME3,
+
+	YELLOW1,
+	YELLOW2,
+	YELLOW3,
+
+	ORANGE1,
+	ORANGE2,
+	ORANGE3,
+
+	GRAY1,
+	GRAY2,
+	GRAY3,
+	GRAY4,
+	GRAY5,
+	GRAY6;
+
+	private static final ModernColorBean[] colors;
+
+	static {
+		final InputStream inputStream = ApplicationUtils.getApplication().getClasspathResource("colors", "ModernColor.json").getInputStream();
+		colors = Storage.load(inputStream, StorageTypes.JSON, ModernColorBean[].class);
+	}
+
+	public Optional<ModernColorBean> getCurrentModernColor() {
+		return Stream.of(colors).filter(color -> color.getName().equals(name())).findAny();
 	}
 
 	public String getColorHi() {
-		return colorHi;
+		return getCurrentModernColor().orElseThrow(IllegalArgumentException::new).getColors().getHi();
 	}
 
 	public String getColorLow() {
-		return colorLow;
+		return getCurrentModernColor().orElseThrow(IllegalArgumentException::new).getColors().getLow();
 	}
 
 	public String getFontColor() {
-		return fontColor;
+		return getCurrentModernColor().orElseThrow(IllegalArgumentException::new).getColors().getFont();
 	}
 
 	public String getButtonColor() {
-		return buttonColor;
+		return getCurrentModernColor().orElseThrow(IllegalArgumentException::new).getColors().getButton();
 	}
 
 	public String getPlaybarColor() {
-		return playbarColor;
+		return getCurrentModernColor().orElseThrow(IllegalArgumentException::new).getColors().getPlaybar().getBackground();
 	}
 
 	public String getPlaybarTrackColor() {
-		return playbarTrackColor;
+		return getCurrentModernColor().orElseThrow(IllegalArgumentException::new).getColors().getPlaybar().getTrack();
 	}
 
 	@Override
-	public Paint getPaint() {
+	public Paint getColor() {
 		if (Profile.currentProfile().getProfileSettings().getDesign().isFlatDesign()) {
 			return Color.web(paint());
 		} else {
-			return new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE, new Stop(0, Color.web(colorHi)),
-					new Stop(1, Color.web(colorLow)));
+			return new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE, new Stop(0, Color.web(getColorHi())),
+					new Stop(1, Color.web(getColorLow())));
 		}
 	}
 
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/model/ModernCartDesign.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/model/ModernCartDesign.java
index 5dc8c5cf28587d3b6245926c00e3dcfba4403a46..0d79598ab08bdc44c125ee494909fe9925942abc 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/model/ModernCartDesign.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/model/ModernCartDesign.java
@@ -1,6 +1,6 @@
 package de.tobias.playpad.design.modern.model;
 
-import de.tobias.playpad.design.DesignColorAssociator;
+import de.tobias.playpad.design.FeedbackDesignColorSuggester;
 import de.tobias.playpad.design.modern.ModernColor;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.server.sync.command.CommandManager;
@@ -12,11 +12,12 @@ import javafx.scene.paint.Color;
 
 import java.util.UUID;
 
-public class ModernCartDesign implements DesignColorAssociator, Cloneable {
+public class ModernCartDesign implements FeedbackDesignColorSuggester {
 
 	private UUID uuid;
 	private ObjectProperty<ModernColor> backgroundColor;
 	private ObjectProperty<ModernColor> playColor;
+	private ObjectProperty<ModernColor> cueInColor;
 
 	private Pad pad;
 	private DesignUpdateListener syncListener;
@@ -26,15 +27,16 @@ public class ModernCartDesign implements DesignColorAssociator, Cloneable {
 	}
 
 	public ModernCartDesign(Pad pad, UUID uuid) {
-		this(pad, uuid, ModernColor.GRAY1, ModernColor.RED3);
+		this(pad, uuid, ModernColor.GRAY1, ModernColor.RED3, ModernColor.RED2);
 	}
 
-	public ModernCartDesign(Pad pad, UUID id, ModernColor backgroundColor, ModernColor playColor) {
+	public ModernCartDesign(Pad pad, UUID id, ModernColor backgroundColor, ModernColor playColor, ModernColor cueInColor) {
 		this.uuid = id;
 		this.pad = pad;
 
 		this.backgroundColor = new SimpleObjectProperty<>(backgroundColor);
 		this.playColor = new SimpleObjectProperty<>(playColor);
+		this.cueInColor = new SimpleObjectProperty<>(cueInColor);
 
 		syncListener = new DesignUpdateListener(this);
 	}
@@ -71,6 +73,18 @@ public class ModernCartDesign implements DesignColorAssociator, Cloneable {
 		return playColor;
 	}
 
+	public ModernColor getCueInColor() {
+		return cueInColor.get();
+	}
+
+	public void setCueInColor(ModernColor cueInColor) {
+		this.cueInColor.set(cueInColor);
+	}
+
+	public ObjectProperty<ModernColor> cueInColorProperty() {
+		return cueInColor;
+	}
+
 	public void addListener() {
 		syncListener.addListener();
 	}
@@ -81,25 +95,29 @@ public class ModernCartDesign implements DesignColorAssociator, Cloneable {
 
 	public void reset() {
 		backgroundColor.set(ModernColor.GRAY1);
-		playColor.set(ModernColor.RED1);
+		playColor.set(ModernColor.RED3);
+		cueInColor.set(ModernColor.RED2);
 	}
 
 
 	// Color Associator
 	@Override
-	public Color getAssociatedEventColor() {
+	public Color getDesignEventColor() {
 		return Color.web(playColor.get().getColorHi());
 	}
 
 	@Override
-	public Color getAssociatedStandardColor() {
+	public Color getDesignDefaultColor() {
 		return Color.web(backgroundColor.get().getColorHi());
 	}
 
-	public ModernCartDesign clone(Pad pad) throws CloneNotSupportedException {
-		ModernCartDesign clone = (ModernCartDesign) super.clone();
+	public ModernCartDesign copy(Pad pad) {
+		ModernCartDesign clone = new ModernCartDesign(pad);
+
 		clone.backgroundColor = new SimpleObjectProperty<>(getBackgroundColor());
 		clone.playColor = new SimpleObjectProperty<>(getPlayColor());
+		clone.cueInColor = new SimpleObjectProperty<>(getCueInColor());
+
 		clone.pad = pad;
 		clone.uuid = UUID.randomUUID();
 
@@ -115,5 +133,6 @@ public class ModernCartDesign implements DesignColorAssociator, Cloneable {
 	public void copyGlobalLayout(ModernGlobalDesign globalDesign) {
 		setBackgroundColor(globalDesign.getBackgroundColor());
 		setPlayColor(globalDesign.getPlayColor());
+		setCueInColor(globalDesign.getCueInColor());
 	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/model/ModernColorBean.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/model/ModernColorBean.java
new file mode 100644
index 0000000000000000000000000000000000000000..526e2d7e7548f30fd1f9a0eaefcfc7949b41dd67
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/model/ModernColorBean.java
@@ -0,0 +1,67 @@
+package de.tobias.playpad.design.modern.model;
+
+import de.thecodelabs.storage.settings.annotation.Key;
+
+public class ModernColorBean {
+
+	public static class Colors {
+		@Key
+		private String hi;
+		@Key
+		private String low;
+		@Key
+		private String font;
+		@Key
+		private String button;
+		@Key
+		private Playbar playbar;
+
+		public String getHi() {
+			return hi;
+		}
+
+		public String getLow() {
+			return low;
+		}
+
+		public String getFont() {
+			return font;
+		}
+
+		public String getButton() {
+			return button;
+		}
+
+		public Playbar getPlaybar() {
+			return playbar;
+		}
+	}
+
+	public static class Playbar {
+		@Key
+		private String background;
+		@Key
+		private String track;
+
+		public String getBackground() {
+			return background;
+		}
+
+		public String getTrack() {
+			return track;
+		}
+	}
+
+	@Key
+	private String name;
+	@Key
+	private Colors colors;
+
+	public String getName() {
+		return name;
+	}
+
+	public Colors getColors() {
+		return colors;
+	}
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/model/ModernGlobalDesign.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/model/ModernGlobalDesign.java
index 1380f1958093722df5b78946d220f64bfee0db03..a5ed9a4559520faa1f4ca812f387e063726b7876 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/model/ModernGlobalDesign.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/model/ModernGlobalDesign.java
@@ -1,13 +1,14 @@
 package de.tobias.playpad.design.modern.model;
 
-import de.tobias.playpad.design.DesignColorAssociator;
+import de.tobias.playpad.design.FeedbackDesignColorSuggester;
 import de.tobias.playpad.design.modern.ModernColor;
 import javafx.scene.paint.Color;
 
-public class ModernGlobalDesign implements DesignColorAssociator {
+public class ModernGlobalDesign implements FeedbackDesignColorSuggester {
 
 	private ModernColor backgroundColor = ModernColor.GRAY1;
 	private ModernColor playColor = ModernColor.RED3;
+	private ModernColor cueInColor = ModernColor.RED2;
 
 	private boolean isWarnAnimation = true;
 
@@ -32,6 +33,14 @@ public class ModernGlobalDesign implements DesignColorAssociator {
 		this.playColor = playColor;
 	}
 
+	public ModernColor getCueInColor() {
+		return cueInColor;
+	}
+
+	public void setCueInColor(ModernColor cueInColor) {
+		this.cueInColor = cueInColor;
+	}
+
 	public boolean isWarnAnimation() {
 		return isWarnAnimation;
 	}
@@ -66,7 +75,8 @@ public class ModernGlobalDesign implements DesignColorAssociator {
 
 	public void reset() {
 		backgroundColor = ModernColor.GRAY1;
-		playColor = ModernColor.RED1;
+		playColor = ModernColor.RED3;
+		cueInColor = ModernColor.RED2;
 
 		isWarnAnimation = true;
 
@@ -77,12 +87,12 @@ public class ModernGlobalDesign implements DesignColorAssociator {
 	}
 
 	@Override
-	public Color getAssociatedEventColor() {
+	public Color getDesignEventColor() {
 		return Color.web(playColor.getColorHi());
 	}
 
 	@Override
-	public Color getAssociatedStandardColor() {
+	public Color getDesignDefaultColor() {
 		return Color.web(backgroundColor.getColorHi());
 	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/serializer/ModernCartDesignSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/serializer/ModernCartDesignSerializer.java
index 34541351898f792fc589025296356b1be43e0078..ce67905eb387db419410d0598eb04264f937b270 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/serializer/ModernCartDesignSerializer.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/serializer/ModernCartDesignSerializer.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.design.modern.serializer;
 
+import de.thecodelabs.logger.Logger;
 import de.tobias.playpad.design.modern.ModernColor;
 import de.tobias.playpad.design.modern.model.ModernCartDesign;
 import de.tobias.playpad.pad.Pad;
@@ -23,7 +24,7 @@ public class ModernCartDesignSerializer {
 			try {
 				design.setBackgroundColor(ModernColor.valueOf(backgroundElement.getStringValue()));
 			} catch (IllegalArgumentException e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		}
 
@@ -32,7 +33,15 @@ public class ModernCartDesignSerializer {
 			try {
 				design.setPlayColor(ModernColor.valueOf(playElement.getStringValue()));
 			} catch (IllegalArgumentException e) {
-				e.printStackTrace();
+				Logger.error(e);
+			}
+		}
+		Element cueInElement = rootElement.element("CueInColor");
+		if (cueInElement != null) {
+			try {
+				design.setCueInColor(ModernColor.valueOf(cueInElement.getStringValue()));
+			} catch (IllegalArgumentException e) {
+				Logger.error(e);
 			}
 		}
 		return design;
@@ -42,5 +51,6 @@ public class ModernCartDesignSerializer {
 		rootElement.addAttribute("id", design.getId().toString());
 		rootElement.addElement("BackgroundColor").addText(design.getBackgroundColor().name());
 		rootElement.addElement("PlayColor").addText(design.getPlayColor().name());
+		rootElement.addElement("CueInColor").addText(design.getCueInColor().name());
 	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/serializer/ModernGlobalDesignSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/serializer/ModernGlobalDesignSerializer.java
index 9ce0ce57909f8be7097d7e247676e913f69a5e28..fac121f89d0f13a4ab388e69bd3eeecb693e9d99 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/serializer/ModernGlobalDesignSerializer.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/serializer/ModernGlobalDesignSerializer.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.design.modern.serializer;
 
+import de.thecodelabs.logger.Logger;
 import de.tobias.playpad.design.modern.ModernColor;
 import de.tobias.playpad.design.modern.model.ModernGlobalDesign;
 import org.dom4j.Element;
@@ -13,7 +14,7 @@ public class ModernGlobalDesignSerializer {
 			try {
 				design.setBackgroundColor(ModernColor.valueOf(backgroundElement.getStringValue()));
 			} catch (IllegalArgumentException e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		}
 
@@ -22,7 +23,16 @@ public class ModernGlobalDesignSerializer {
 			try {
 				design.setPlayColor(ModernColor.valueOf(playElement.getStringValue()));
 			} catch (IllegalArgumentException e) {
-				e.printStackTrace();
+				Logger.error(e);
+			}
+		}
+
+		Element cueInElement = rootElement.element("CueInColor");
+		if (cueInElement != null) {
+			try {
+				design.setCueInColor(ModernColor.valueOf(cueInElement.getStringValue()));
+			} catch (IllegalArgumentException e) {
+				Logger.error(e);
 			}
 		}
 
@@ -30,30 +40,30 @@ public class ModernGlobalDesignSerializer {
 		if (animationElement != null) {
 			Element warnAnimationElement = animationElement.element("Warn");
 			if (warnAnimationElement != null) {
-				design.setWarnAnimation(Boolean.valueOf(warnAnimationElement.getStringValue()));
+				design.setWarnAnimation(Boolean.parseBoolean(warnAnimationElement.getStringValue()));
 			}
 		}
 
 		Element infoFontSizeElement = rootElement.element("InfoFontSize");
 		if (infoFontSizeElement != null) {
 			try {
-				design.setInfoFontSize(Integer.valueOf(infoFontSizeElement.getStringValue()));
+				design.setInfoFontSize(Integer.parseInt(infoFontSizeElement.getStringValue()));
 			} catch (NumberFormatException e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		}
 
 		Element titleFontSizeElement = rootElement.element("TitleFontSize");
 		if (titleFontSizeElement != null) {
 			try {
-				design.setTitleFontSize(Integer.valueOf(titleFontSizeElement.getStringValue()));
+				design.setTitleFontSize(Integer.parseInt(titleFontSizeElement.getStringValue()));
 			} catch (NumberFormatException e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		}
 		Element flatDesignElement = rootElement.element("FlatDesign");
 		if (flatDesignElement != null) {
-			design.setFlatDesign(Boolean.valueOf(flatDesignElement.getStringValue()));
+			design.setFlatDesign(Boolean.parseBoolean(flatDesignElement.getStringValue()));
 		}
 
 		return design;
@@ -62,6 +72,8 @@ public class ModernGlobalDesignSerializer {
 	public void save(Element rootElement, ModernGlobalDesign design) {
 		rootElement.addElement("BackgroundColor").addText(design.getBackgroundColor().name());
 		rootElement.addElement("PlayColor").addText(design.getPlayColor().name());
+		rootElement.addElement("CueInColor").addText(design.getCueInColor().name());
+
 		Element animationElement = rootElement.addElement("Animation");
 		animationElement.addElement("Warn").addText(String.valueOf(design.isWarnAnimation()));
 		rootElement.addElement("InfoFontSize").addText(String.valueOf(design.getInfoFontSize()));
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/event/Event.java b/PlayWallCore/src/main/java/de/tobias/playpad/event/Event.java
deleted file mode 100644
index 63f31fe44502b16d5d2133cf3b79c0da3a0211fb..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/event/Event.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package de.tobias.playpad.event;
-
-public class Event {
-
-	private final long time;
-	private boolean consume;
-
-	public Event() {
-		time = System.currentTimeMillis();
-		consume = false;
-	}
-
-	public long getTime() {
-		return time;
-	}
-
-	public boolean isConsume() {
-		return consume;
-	}
-
-	public void setConsume(boolean consume) {
-		this.consume = consume;
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/event/EventDispatcher.java b/PlayWallCore/src/main/java/de/tobias/playpad/event/EventDispatcher.java
deleted file mode 100644
index 01d69d414a8a3fde4c773553b5e9fa7f283be431..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/event/EventDispatcher.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package de.tobias.playpad.event;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-public abstract class EventDispatcher {
-
-	public class ListenerHandler {
-
-		private Method method;
-		private Listener listener;
-
-		public ListenerHandler(Method method, Listener listener) {
-			this.method = method;
-			this.listener = listener;
-		}
-
-		public Listener getListener() {
-			return listener;
-		}
-
-		public Method getMethod() {
-			return method;
-		}
-
-		public void execute(Event event) {
-			try {
-				if (!event.isConsume()) {
-					method.setAccessible(true);
-					method.invoke(listener, event);
-				}
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
-		}
-
-	}
-
-	public abstract void dispatchEvent(Event event);
-
-	protected HashMap<String, List<ListenerHandler>> listeners = new HashMap<>();
-
-	public void registerEventListener(Listener listener) {
-		for (Method method : listener.getClass().getDeclaredMethods()) {
-			if (method.isAnnotationPresent(EventHandler.class)) {
-				Class<?>[] parameters = method.getParameterTypes();
-				if (parameters.length == 1) {
-					Class<?> eventType = parameters[0];
-
-					if (eventType.getSuperclass().equals(Event.class)) {
-						if (!listeners.containsKey(eventType.getName())) {
-							listeners.put(eventType.getName(), new ArrayList<>());
-						}
-						listeners.get(eventType.getName()).add(new ListenerHandler(method, listener));
-					} else {
-						System.err.println("Method: " + method.getName() + " has wrong arguments");
-					}
-				} else {
-					System.err.println("Method: " + method.getName() + " has wrong arguments");
-				}
-			}
-		}
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/event/EventHandler.java b/PlayWallCore/src/main/java/de/tobias/playpad/event/EventHandler.java
deleted file mode 100644
index 9777c66731694798515386aad99073a84592650f..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/event/EventHandler.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package de.tobias.playpad.event;
-
-import java.lang.annotation.*;
-
-@Target({ElementType.METHOD})
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-public @interface EventHandler {
-
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/event/Listener.java b/PlayWallCore/src/main/java/de/tobias/playpad/event/Listener.java
deleted file mode 100644
index c40d8da36b80c94aa3dc12f2bddeca3346becf0c..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/event/Listener.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package de.tobias.playpad.event;
-
-
-public interface Listener {
-
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/log/LogSeasons.java b/PlayWallCore/src/main/java/de/tobias/playpad/log/LogSeasons.java
deleted file mode 100644
index 52cf961d515ef0e38d165f038718ae9a1b87e354..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/log/LogSeasons.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package de.tobias.playpad.log;
-
-import de.tobias.playpad.log.storage.LogSeasonStorageHandler;
-
-import java.util.List;
-
-public class LogSeasons {
-
-	private static LogSeason INSTANCE;
-	private static LogSeasonStorageHandler storageHandler;
-
-	public static LogSeason getInstance() {
-		return INSTANCE;
-	}
-
-	public static LogSeason createLogSeason(String name, int columns, int rows) {
-		INSTANCE = new LogSeason(name, columns, rows);
-
-		// Save
-		LogSeasonStorageHandler storageHandler = LogSeasons.getStorageHandler();
-		if (storageHandler != null) {
-			storageHandler.addLogSeason(INSTANCE);
-		}
-
-		return INSTANCE;
-	}
-
-	public static LogSeasonStorageHandler getStorageHandler() {
-		return storageHandler;
-	}
-
-	public static void setStorageHandler(LogSeasonStorageHandler storageHandler) {
-		LogSeasons.storageHandler = storageHandler;
-	}
-
-	public static void stop() {
-		INSTANCE = null;
-	}
-
-	public static List<LogSeason> getAllLogSeasonsLazy() {
-		return getStorageHandler().getAllLogSeasonsLazy();
-	}
-
-	public static LogSeason getLogSeason(int id) {
-		return getStorageHandler().getLogSeason(id);
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/log/listener/PadMediaPathLogListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/log/listener/PadMediaPathLogListener.java
deleted file mode 100644
index c1198d1c1699886616d35fb817bb6ae126c46af1..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/log/listener/PadMediaPathLogListener.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package de.tobias.playpad.log.listener;
-
-import de.tobias.playpad.log.LogSeason;
-import de.tobias.playpad.log.LogSeasons;
-import de.tobias.playpad.pad.mediapath.MediaPath;
-import javafx.collections.ListChangeListener;
-
-public class PadMediaPathLogListener implements ListChangeListener<MediaPath> {
-	@Override
-	public void onChanged(Change<? extends MediaPath> c) {
-		LogSeason instance = LogSeasons.getInstance();
-		if (instance != null) {
-			while (c.next()) {
-				if (c.wasAdded()) {
-					for (MediaPath mediaPath : c.getAddedSubList()) {
-						instance.addLogItem(mediaPath);
-					}
-				}
-			}
-		}
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/log/listener/PadPlayLogListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/log/listener/PadPlayLogListener.java
deleted file mode 100644
index 61914c7297dd3f0b64053dea77efe2928544479d..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/log/listener/PadPlayLogListener.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package de.tobias.playpad.log.listener;
-
-import de.thecodelabs.logger.LogLevel;
-import de.thecodelabs.logger.Logger;
-import de.tobias.playpad.log.LogSeason;
-import de.tobias.playpad.log.LogSeasons;
-import de.tobias.playpad.log.PlayOutItem;
-import de.tobias.playpad.pad.Pad;
-import de.tobias.playpad.pad.PadStatus;
-import javafx.beans.value.ChangeListener;
-import javafx.beans.value.ObservableValue;
-
-public class PadPlayLogListener implements ChangeListener<PadStatus> {
-
-	private Pad pad;
-
-	public PadPlayLogListener(Pad pad) {
-		this.pad = pad;
-	}
-
-	@Override
-	public void changed(ObservableValue<? extends PadStatus> observable, PadStatus oldValue, PadStatus newValue) {
-		if (newValue == PadStatus.PLAY) {
-			LogSeason instance = LogSeasons.getInstance();
-			if (instance != null) {
-				instance.getLogItems().stream().filter(item -> item.getUuid().equals(pad.getPaths().get(0).getId())).forEach(item -> {
-					PlayOutItem playoutItem = new PlayOutItem(item.getUuid(), instance, System.currentTimeMillis());
-					item.addPlayOutItem(playoutItem);
-					Logger.log(LogLevel.DEBUG, "Play Item: " + playoutItem);
-				});
-			}
-		}
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/log/storage/LogSeasonStorageHandler.java b/PlayWallCore/src/main/java/de/tobias/playpad/log/storage/LogSeasonStorageHandler.java
deleted file mode 100644
index 56ea7526180ad3258381c52fc59a86a1d565e576..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/log/storage/LogSeasonStorageHandler.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package de.tobias.playpad.log.storage;
-
-import de.tobias.playpad.log.LogItem;
-import de.tobias.playpad.log.LogSeason;
-import de.tobias.playpad.log.PlayOutItem;
-
-import java.util.List;
-
-public interface LogSeasonStorageHandler {
-	void addLogSeason(LogSeason season);
-
-	void addLogItem(LogItem item);
-
-	void addPlayOutItem(PlayOutItem item);
-
-	LogSeason getLogSeason(int id);
-
-	List<LogSeason> getAllLogSeasonsLazy();
-
-	/**
-	 * Close the storage handler.
-	 *
-	 * @throws RuntimeException fail to close handler (e.g. sql error)
-	 */
-	void close() throws RuntimeException;
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/log/storage/SqlLiteLogSeasonStorageHandler.java b/PlayWallCore/src/main/java/de/tobias/playpad/log/storage/SqlLiteLogSeasonStorageHandler.java
deleted file mode 100644
index 811deef577a6c71a9a0fe2e6fe331b589f3272d6..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/log/storage/SqlLiteLogSeasonStorageHandler.java
+++ /dev/null
@@ -1,233 +0,0 @@
-package de.tobias.playpad.log.storage;
-
-import de.thecodelabs.logger.LogLevel;
-import de.thecodelabs.logger.Logger;
-import de.tobias.playpad.log.LogItem;
-import de.tobias.playpad.log.LogSeason;
-import de.tobias.playpad.log.PlayOutItem;
-
-import java.nio.file.Path;
-import java.sql.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-public class SqlLiteLogSeasonStorageHandler implements LogSeasonStorageHandler {
-
-	private Connection connection;
-
-	public SqlLiteLogSeasonStorageHandler(Path path) throws SQLException {
-		connection = DriverManager.getConnection("jdbc:sqlite:" + path.toString());
-
-		if (connection != null) {
-			createDatabaseTable("CREATE TABLE IF NOT EXISTS LogSeason (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR NOT NULL, columns INTEGER NOT NULL, rows INTEGER NOT NULL);");
-			createDatabaseTable("CREATE TABLE IF NOT EXISTS LogItem (uuid VARCHAR NOT NULL, name VARCHAR NOT NULL, color VARCHAR NOT NULL, page INTEGER NOT NULL, position INTEGER NOT NULL, logSeason INTEGER NOT NULL, PRIMARY KEY (uuid, logSeason), FOREIGN KEY (logSeason) REFERENCES LogSeason(id));");
-			createDatabaseTable("CREATE TABLE IF NOT EXISTS PlayOutItem (uuid VARCHAR NOT NULL, time INTEGER NOT NULL, logSeason INTEGER NOT NULL, PRIMARY KEY (uuid, logSeason, time), FOREIGN KEY (uuid) REFERENCES LogItem(uuid));");
-		}
-	}
-
-	private void createDatabaseTable(String statement) throws SQLException {
-		PreparedStatement stmt = connection.prepareStatement(statement);
-		stmt.execute();
-		stmt.close();
-	}
-
-	@Override
-	public void addLogSeason(LogSeason season) {
-		PreparedStatement stmt = null;
-		ResultSet rs = null;
-		try {
-			stmt = connection.prepareStatement("INSERT INTO LogSeason (name, columns, rows) VALUES (?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
-			stmt.setString(1, season.getName());
-			stmt.setInt(2, season.getColumns());
-			stmt.setInt(3, season.getRows());
-			int affectedRows = stmt.executeUpdate();
-
-			if (affectedRows == 0) {
-				throw new SQLException("Creating user failed, no rows affected.");
-			}
-
-			rs = stmt.getGeneratedKeys();
-			if (rs.next()) {
-				season.setId(rs.getInt(1));
-			} else {
-				throw new SQLException("Creating MeasurePoint failed, no ID obtained.");
-			}
-		} catch (SQLException e) {
-			Logger.log(LogLevel.ERROR, e.getLocalizedMessage());
-		} finally {
-			closeResource(rs);
-			closeResource(stmt);
-		}
-	}
-
-	@Override
-	public void addLogItem(LogItem item) {
-		PreparedStatement stmt = null;
-		try {
-			stmt = connection.prepareStatement("INSERT INTO LogItem VALUES (?, ?, ?, ?, ?, ?)");
-			stmt.setString(1, item.getUuid().toString());
-			stmt.setString(2, item.getName());
-			stmt.setString(3, item.getColor());
-			stmt.setInt(4, item.getPage());
-			stmt.setInt(5, item.getPosition());
-			stmt.setInt(6, item.getLogSeason().getId());
-			stmt.executeUpdate();
-		} catch (SQLException e) {
-			e.printStackTrace();
-			Logger.log(LogLevel.ERROR, e.getLocalizedMessage());
-		} finally {
-			closeResource(stmt);
-		}
-	}
-
-	@Override
-	public void addPlayOutItem(PlayOutItem item) {
-		PreparedStatement stmt = null;
-		try {
-			stmt = connection.prepareStatement("INSERT INTO PlayOutItem VALUES (?, ?, ?)");
-			stmt.setString(1, item.getPathUuid().toString());
-			stmt.setInt(3, item.getLogSeason().getId());
-			stmt.setLong(2, item.getTime());
-			stmt.executeUpdate();
-		} catch (SQLException e) {
-			Logger.log(LogLevel.ERROR, e.getLocalizedMessage());
-		} finally {
-			closeResource(stmt);
-		}
-	}
-
-	@Override
-	public List<LogSeason> getAllLogSeasonsLazy() {
-		List<LogSeason> logSeasons = new ArrayList<>();
-		PreparedStatement stmt = null;
-		ResultSet resultSet = null;
-		try {
-			stmt = connection.prepareStatement("SELECT * FROM LogSeason");
-			resultSet = stmt.executeQuery();
-
-			while (resultSet.next()) {
-				LogSeason logSeason = new LogSeason(
-						resultSet.getInt("id"),
-						resultSet.getString("name"),
-						resultSet.getInt("columns"),
-						resultSet.getInt("rows")
-				);
-				logSeasons.add(logSeason);
-			}
-		} catch (SQLException e) {
-			Logger.log(LogLevel.ERROR, e.getLocalizedMessage());
-		} finally {
-			closeResource(resultSet);
-			closeResource(stmt);
-		}
-		return logSeasons;
-	}
-
-	@Override
-	public LogSeason getLogSeason(int id) {
-		PreparedStatement stmt = null;
-		ResultSet resultSet = null;
-		try {
-			stmt = connection.prepareStatement("SELECT * FROM LogSeason WHERE id = ?");
-			stmt.setInt(1, id);
-			resultSet = stmt.executeQuery();
-
-			if (resultSet.next()) {
-				LogSeason logSeason = new LogSeason(
-						resultSet.getInt("id"),
-						resultSet.getString("name"),
-						resultSet.getInt("columns"),
-						resultSet.getInt("rows")
-				);
-				logSeason.getLogItems().addAll(getAllPlayoutItems(logSeason));
-				return logSeason;
-			}
-		} catch (SQLException e) {
-			Logger.log(LogLevel.ERROR, e.getLocalizedMessage());
-		} finally {
-			closeResource(resultSet);
-			closeResource(stmt);
-		}
-		return null;
-	}
-
-	private List<LogItem> getAllPlayoutItems(LogSeason season) {
-		List<LogItem> logItems = new ArrayList<>();
-		PreparedStatement stmt = null;
-		ResultSet resultSet = null;
-		try {
-			stmt = connection.prepareStatement("SELECT * FROM LogItem WHERE logSeason = ?");
-			stmt.setInt(1, season.getId());
-			resultSet = stmt.executeQuery();
-
-			while (resultSet.next()) {
-				LogItem logItem = new LogItem(
-						UUID.fromString(resultSet.getString("uuid")),
-						resultSet.getString("name"),
-						resultSet.getString("color"),
-						resultSet.getInt("page"),
-						resultSet.getInt("position"),
-						season
-				);
-				logItem.getPlayOutItems().addAll(getAllPlayoutItems(logItem));
-				logItems.add(logItem);
-			}
-		} catch (SQLException e) {
-			Logger.log(LogLevel.ERROR, e.getLocalizedMessage());
-		} finally {
-			closeResource(resultSet);
-			closeResource(stmt);
-		}
-		return logItems;
-	}
-
-	private List<PlayOutItem> getAllPlayoutItems(LogItem item) {
-		List<PlayOutItem> playOutItems = new ArrayList<>();
-		PreparedStatement stmt = null;
-		ResultSet resultSet = null;
-		try {
-			stmt = connection.prepareStatement("SELECT * FROM PlayOutItem WHERE uuid = ? AND logSeason = ?");
-			stmt.setString(1, item.getUuid().toString());
-			stmt.setInt(2, item.getLogSeason().getId());
-
-			resultSet = stmt.executeQuery();
-
-			while (resultSet.next()) {
-				PlayOutItem playOutItem = new PlayOutItem(
-						UUID.fromString(resultSet.getString("uuid")),
-						item.getLogSeason(),
-						resultSet.getLong("time")
-				);
-				playOutItems.add(playOutItem);
-			}
-		} catch (SQLException e) {
-			Logger.log(LogLevel.ERROR, e.getLocalizedMessage());
-		} finally {
-			closeResource(resultSet);
-			closeResource(stmt);
-		}
-		return playOutItems;
-	}
-
-	private void closeResource(AutoCloseable stmt) {
-		if (stmt != null) {
-			try {
-				stmt.close();
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
-		}
-	}
-
-	@Override
-	public void close() throws RuntimeException {
-		if (connection != null) {
-			try {
-				connection.close();
-			} catch (SQLException e) {
-				throw new RuntimeException(e);
-			}
-		}
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/midi/Midi.java b/PlayWallCore/src/main/java/de/tobias/playpad/midi/Midi.java
deleted file mode 100644
index bae98fa96d46c6f8dc695ad55983ef806acd0edd..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/midi/Midi.java
+++ /dev/null
@@ -1,167 +0,0 @@
-package de.tobias.playpad.midi;
-
-import de.thecodelabs.logger.Logger;
-import de.tobias.playpad.action.mididevice.MidiDeviceImpl;
-import de.tobias.playpad.midi.device.DeviceRegistry;
-
-import javax.sound.midi.*;
-import javax.sound.midi.MidiDevice.Info;
-import java.lang.reflect.InvocationTargetException;
-
-public class Midi implements AutoCloseable {
-
-	private MidiDevice inputDevice;
-	private MidiDevice outputDevice;
-	private MidiDeviceImpl midiMidiDeviceImplImpl;
-
-	private MidiListener listener;
-
-	private static Midi instance;
-
-	public static Midi getInstance() {
-		if (instance == null) {
-			instance = new Midi();
-		}
-		return instance;
-	}
-
-	private Midi() {
-	}
-
-	public MidiListener getListener() {
-		return listener;
-	}
-
-	public void setListener(MidiListener listener) {
-		this.listener = listener;
-	}
-
-	public static Info[] getMidiDevices() {
-		return MidiSystem.getMidiDeviceInfo();
-	}
-
-	public MidiDevice getInputDevice() {
-		return inputDevice;
-	}
-
-	public MidiDevice getOutputDevice() {
-		return outputDevice;
-	}
-
-	public MidiDeviceImpl getMidiDevice() {
-		return midiMidiDeviceImplImpl;
-	}
-
-	public void lookupMidiDevice(String name) throws IllegalArgumentException, MidiUnavailableException, NullPointerException {
-		boolean first = true;
-
-		Info input = null;
-		Info output = null;
-		for (Info item : Midi.getMidiDevices()) {
-			if (item.getName().equals(name)) {
-				if (first) {
-					input = item;
-					first = false;
-				} else {
-					output = item;
-				}
-			}
-		}
-		if (input == null || output == null) {
-			throw new NullPointerException();
-		}
-		setMidiDevice(input, output);
-	}
-
-	private void setMidiDevice(Info input, Info output) throws MidiUnavailableException, IllegalArgumentException {
-		MidiDevice newInputDevice = MidiSystem.getMidiDevice(input);
-		MidiDevice newOutputDevice = MidiSystem.getMidiDevice(output);
-
-		if (newInputDevice == null && newOutputDevice == null) {
-			return;
-		}
-
-		if (this.inputDevice == newInputDevice && this.outputDevice == newOutputDevice) {
-			return;
-		}
-
-		// Close Old Devices
-		close();
-
-		this.inputDevice = newInputDevice;
-		this.outputDevice = newOutputDevice;
-
-		// Hier wird die DeviceImpl aufgerufen
-		try {
-			this.midiMidiDeviceImplImpl = DeviceRegistry.getFactoryInstance().getDevice(input.getName());
-		} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
-			Logger.error(e);
-		}
-		setupMidiDevice();
-	}
-
-
-	private void setupMidiDevice() throws MidiUnavailableException {
-		if (inputDevice != null) {
-			Transmitter trans = inputDevice.getTransmitter();
-			trans.setReceiver(new MidiInputReceiver());
-
-			// Belegt das Midi Gerät und macht es nutzbar
-			inputDevice.open();
-			if (outputDevice != null) {
-				outputDevice.open();
-			}
-		}
-	}
-
-	public void close() {
-		try {
-			if (inputDevice != null) {
-				inputDevice.getTransmitter().close();
-				inputDevice.close();
-			}
-			if (outputDevice != null) {
-				outputDevice.getReceiver().close();
-				outputDevice.close();
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
-	public void sendMessage(int midiCommand, int midiKey, int midiVelocity) throws MidiUnavailableException, InvalidMidiDataException {
-		if (outputDevice != null) {
-			if (midiCommand != 0) {
-				ShortMessage message = new ShortMessage(midiCommand, midiKey, midiVelocity);
-				outputDevice.getReceiver().send(message, -1);
-			}
-		}
-	}
-
-	private class MidiInputReceiver implements Receiver {
-
-		@Override
-		public void send(MidiMessage msg, long timeStamp) {
-			try {
-				listener.onMidiAction(msg);
-			} catch (Exception e) {
-				Logger.error(e);
-			}
-		}
-
-		@Override
-		public void close() {
-		}
-
-	}
-
-	public boolean isOpen() {
-		return inputDevice != null && outputDevice != null && inputDevice.isOpen() && outputDevice.isOpen();
-	}
-
-	public void sendClearCommand() {
-		if (midiMidiDeviceImplImpl != null) {
-			midiMidiDeviceImplImpl.clearFeedback();
-		}
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/midi/MidiListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/midi/MidiListener.java
deleted file mode 100644
index 65c765ec3d48694acfa55bebfc97509ad2dfc44e..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/midi/MidiListener.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package de.tobias.playpad.midi;
-
-import javax.sound.midi.MidiMessage;
-
-public interface MidiListener {
-
-	void onMidiAction(MidiMessage message);
-
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/midi/device/DefaultMidiDeviceImpl.java b/PlayWallCore/src/main/java/de/tobias/playpad/midi/device/DefaultMidiDeviceImpl.java
deleted file mode 100644
index 273459124a63f682b702b365d02af4135054d61b..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/midi/device/DefaultMidiDeviceImpl.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package de.tobias.playpad.midi.device;
-
-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.MidiDeviceImpl;
-
-public class DefaultMidiDeviceImpl extends MidiDeviceImpl {
-
-	@Override
-	public String getName() {
-		return null;
-	}
-
-	@Override
-	public boolean supportFeedback() {
-		return false;
-	}
-
-	@Override
-	public void handleFeedback(FeedbackMessage type, int key, Feedback feedback) {
-	}
-
-	@Override
-	public void initDevice() {
-	}
-
-	@Override
-	public void clearFeedback() {
-	}
-
-	@Override
-	public DisplayableFeedbackColor getColor(int id) {
-		return null;
-	}
-
-	@Override
-	public DisplayableFeedbackColor[] getColors() {
-		return null;
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/midi/device/DeviceRegistry.java b/PlayWallCore/src/main/java/de/tobias/playpad/midi/device/DeviceRegistry.java
deleted file mode 100644
index 42a602db29625c400e85da256ddf3b9a35a950db..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/midi/device/DeviceRegistry.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package de.tobias.playpad.midi.device;
-
-import de.thecodelabs.logger.LogLevel;
-import de.thecodelabs.logger.Logger;
-import de.tobias.playpad.action.mididevice.MidiDeviceImpl;
-import de.tobias.playpad.event.Event;
-import de.tobias.playpad.event.EventDispatcher;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Verwaltet die Midi Geräte Implementierung. Hier werden Geräte registiert und bei Verwendung instanziert für das Programm.
- *
- * @author tobias
- * @since 3.0.0
- */
-public class DeviceRegistry extends EventDispatcher {
-
-	private static DeviceRegistry instance;
-
-	static {
-		instance = new DeviceRegistry();
-	}
-
-	/**
-	 * Speicher für alle Geräte Implementierungen [Produktname, Implementierung]
-	 */
-	private HashMap<String, Class<? extends MidiDeviceImpl>> devices = new HashMap<>();
-
-	/**
-	 * Registriert eine neue Implementierung für ein Midi Gerät
-	 *
-	 * @param id     Names des Gerätes, muss exakt der Produktname sein
-	 * @param device Implementierung als Klasse, Instanz erstellt das Programm bei bei bedarf
-	 */
-	public void registerDevice(String id, Class<? extends MidiDeviceImpl> device) {
-		devices.put(id, device);
-		Logger.log(LogLevel.DEBUG, "Register MIDI MidiDeviceImpl Impl: " + id);
-	}
-
-	/**
-	 * Instanz einer Implementierung für ein Midi Gerät.
-	 *
-	 * @param id Name des Geräts
-	 * @return Implementierung, DefaultMidiDeviceImpl wenn keine vorhanden oder registriert über register
-	 * @throws InstantiationException Fehler beim instanzieren
-	 * @throws IllegalAccessException Fehler beim instanzieren
-	 * @see DeviceRegistry#registerDevice(String, Class)
-	 * @see DefaultMidiDeviceImpl
-	 */
-	public MidiDeviceImpl getDevice(String id) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
-		if (devices.containsKey(id)) {
-			Logger.debug("Recognize known MIDI device: " + id);
-
-			final Class<? extends MidiDeviceImpl> deviceClass = devices.get(id);
-			final Constructor<? extends MidiDeviceImpl> constructor = deviceClass.getConstructor();
-
-			return constructor.newInstance();
-		} else {
-			Logger.debug("Use Default MIDI device");
-			return new DefaultMidiDeviceImpl();
-		}
-	}
-
-	/**
-	 * Instanz der MidiDeviceImpl Component
-	 *
-	 * @return instance
-	 */
-	public static DeviceRegistry getFactoryInstance() {
-		return instance;
-	}
-
-	/**
-	 * Handel global Events
-	 */
-	@Override
-	public void dispatchEvent(Event event) {
-		List<ListenerHandler> listeners = this.listeners.get(event.getClass().getName());
-		if (listeners != null) {
-			for (ListenerHandler handler : listeners) {
-				handler.execute(event);
-			}
-		}
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java
index 6ff132ec5ac56e0baaa4c9b6472e6c7d34962f33..2a0fd4c28cda491ab99634c36b4f2ac2ac967598 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java
@@ -2,8 +2,6 @@ package de.tobias.playpad.pad;
 
 import de.thecodelabs.utils.io.PathUtils;
 import de.tobias.playpad.PlayPadPlugin;
-import de.tobias.playpad.log.listener.PadMediaPathLogListener;
-import de.tobias.playpad.log.listener.PadPlayLogListener;
 import de.tobias.playpad.pad.content.PadContent;
 import de.tobias.playpad.pad.content.PadContentFactory;
 import de.tobias.playpad.pad.content.play.Pauseable;
@@ -17,14 +15,17 @@ import de.tobias.playpad.pad.listener.trigger.PadTriggerStatusListener;
 import de.tobias.playpad.pad.mediapath.MediaPath;
 import de.tobias.playpad.pad.viewcontroller.IPadViewController;
 import de.tobias.playpad.project.Project;
+import de.tobias.playpad.project.ProjectSettings;
 import de.tobias.playpad.project.page.PadIndex;
 import de.tobias.playpad.project.page.Page;
+import de.tobias.playpad.project.page.PageCoordinate;
 import de.tobias.playpad.registry.NoSuchComponentException;
 import de.tobias.playpad.server.sync.command.CommandManager;
 import de.tobias.playpad.server.sync.command.Commands;
 import de.tobias.playpad.server.sync.listener.upstream.PadUpdateListener;
 import javafx.beans.property.*;
 import javafx.collections.FXCollections;
+import javafx.collections.ListChangeListener;
 import javafx.collections.ObservableList;
 import org.dom4j.Element;
 
@@ -38,7 +39,7 @@ import java.util.UUID;
  * @author tobias
  * @version 6.2.0
  */
-public class Pad implements Cloneable {
+public class Pad {
 
 	private UUID uuid;
 	private IntegerProperty positionProperty = new SimpleIntegerProperty();
@@ -66,8 +67,7 @@ public class Pad implements Cloneable {
 	private transient PadFadeContentListener padFadeContentListener;
 	private transient PadFadeDurationListener padFadeDurationListener;
 
-	private transient PadPlayLogListener padPlayLogListener;
-	private transient PadMediaPathLogListener padMediaPathLogListener;
+	private transient ListChangeListener<MediaPath> mediaPathUpdateListener;
 
 	// Trigger Listener
 	private transient PadTriggerStatusListener padTriggerStatusListener;
@@ -133,14 +133,6 @@ public class Pad implements Cloneable {
 			padFadeContentListener.changed(contentProperty, getContent(), null);
 		}
 
-		if (padPlayLogListener != null && statusProperty != null) {
-			statusProperty.removeListener(padPlayLogListener);
-		}
-
-		if (padMediaPathLogListener != null && mediaPaths != null) {
-			mediaPaths.removeListener(padMediaPathLogListener);
-		}
-
 		// init new listener for properties
 		padStatusControlListener = new PadStatusControlListener(this);
 		statusProperty.addListener(padStatusControlListener);
@@ -157,15 +149,7 @@ public class Pad implements Cloneable {
 		padStatusNotFoundListener = new PadStatusNotFoundListener(project);
 		statusProperty.addListener(padStatusNotFoundListener);
 
-		// PlayOutLog Listener
-		padPlayLogListener = new PadPlayLogListener(this);
-		statusProperty.addListener(padPlayLogListener);
-
-		padMediaPathLogListener = new PadMediaPathLogListener();
-		mediaPaths.addListener(padMediaPathLogListener);
-
 		// Trigger
-
 		padTriggerStatusListener = new PadTriggerStatusListener(this);
 		statusProperty.addListener(padTriggerStatusListener);
 
@@ -175,6 +159,16 @@ public class Pad implements Cloneable {
 		padTriggerContentListener = new PadTriggerContentListener(this);
 		contentProperty.addListener(padTriggerContentListener);
 		padTriggerContentListener.changed(contentProperty, null, getContent());
+
+		// Pad Listener
+		if (mediaPathUpdateListener != null) {
+			mediaPaths.removeListener(mediaPathUpdateListener);
+		}
+		mediaPathUpdateListener = value -> PlayPadPlugin
+				.getInstance()
+				.getPadListener()
+				.forEach(listener -> listener.onMediaPathChanged(this, value));
+		mediaPaths.addListener(mediaPathUpdateListener);
 	}
 
 	public void addSyncListener() {
@@ -268,6 +262,14 @@ public class Pad implements Cloneable {
 		return new PadIndex(getPosition(), getPage().getPosition());
 	}
 
+	public PageCoordinate getPageCoordinate() {
+		ProjectSettings projectSettings = project.getSettings();
+
+		int x = getPosition() % projectSettings.getColumns();
+		int y = getPosition() / projectSettings.getColumns();
+		return new PageCoordinate(x, y);
+	}
+
 	/**
 	 * Get the name of the pad.
 	 *
@@ -363,7 +365,10 @@ public class Pad implements Cloneable {
 
 	public void removePath(MediaPath path) {
 		mediaPaths.remove(path);
+	}
 
+
+	public void removePathListener(MediaPath path) {
 		if (project.getProjectReference().isSync()) {
 			CommandManager.execute(Commands.PATH_REMOVE, project.getProjectReference(), path);
 		}
@@ -598,16 +603,19 @@ public class Pad implements Cloneable {
 	@Override
 	public boolean equals(Object o) {
 		if (this == o) return true;
-		if (o == null || getClass() != o.getClass()) return false;
-
+		if (!(o instanceof Pad)) return false;
 		Pad pad = (Pad) o;
-
 		return Objects.equals(uuid, pad.uuid);
 	}
 
+	@Override
+	public int hashCode() {
+		return Objects.hash(uuid);
+	}
+
 	// Clone
-	public Pad clone(Page page) throws CloneNotSupportedException {
-		Pad clone = (Pad) super.clone();
+	public Pad copy(Page page) {
+		Pad clone = new Pad(project);
 
 		clone.uuid = UUID.randomUUID();
 		clone.positionProperty = new SimpleIntegerProperty(getPosition());
@@ -619,16 +627,15 @@ public class Pad implements Cloneable {
 
 		clone.mediaPaths = FXCollections.observableArrayList();
 		for (MediaPath path : mediaPaths) {
-			MediaPath clonedPath = path.clone(clone);
+			MediaPath clonedPath = path.copy(clone);
 			clone.mediaPaths.add(clonedPath);
 		}
 
 		clone.contentTypeProperty = new SimpleStringProperty(getContentType());
+		clone.contentProperty = new SimpleObjectProperty<>();
 		if (getContent() != null) {
-			clone.contentProperty = new SimpleObjectProperty<>(getContent().clone());
+			clone.contentProperty.set(getContent().copy(clone));
 			clone.getContent().setPad(clone);
-		} else {
-			clone.contentProperty = new SimpleObjectProperty<>();
 		}
 
 		if (project.getProjectReference().isSync()) {
@@ -637,7 +644,7 @@ public class Pad implements Cloneable {
 			clone.addSyncListener();
 		}
 
-		clone.padSettings = padSettings.clone(clone);
+		clone.padSettings = padSettings.copy(clone);
 
 		clone.controller = null;
 		clone.project = project;
@@ -683,7 +690,7 @@ public class Pad implements Cloneable {
 	/**
 	 * Returns true, when pad has content and pad is visible.
 	 *
-	 * @return loaded & visible
+	 * @return loaded &amp; visible
 	 */
 	public boolean hasVisibleContent() {
 		return getContent() != null && getContent().isPadLoaded() && isPadVisible();
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSerializer.java
index 5b719274646377d6e962db9e9bdb9d8cfd7bc6da..3d86977330369691cf79065a194d97cd46f775ad 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSerializer.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSerializer.java
@@ -43,7 +43,7 @@ public class PadSerializer implements XMLSerializer<Pad>, XMLDeserializer<Pad> {
 
 		if (element.attributeValue(UUID_ATTR) != null)
 			pad.setUuid(UUID.fromString(element.attributeValue(UUID_ATTR)));
-		pad.setPosition(Integer.valueOf(element.attributeValue(INDEX_ATTR)));
+		pad.setPosition(Integer.parseInt(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)
@@ -62,30 +62,27 @@ public class PadSerializer implements XMLSerializer<Pad>, XMLDeserializer<Pad> {
 			pad.setContentType(contentType);
 
 			Element pathsElement = contentElement.element(CONTENT_PATHS_ELEMENT);
-			for (Object obj : pathsElement.elements(CONTENT_PATH_ELEMENT)) {
-				if (obj instanceof Element) {
-					Element pathElement = (Element) obj;
-					UUID uuid = UUID.fromString(pathElement.attributeValue(CONTENT_PATH_UUID));
-					Path path = null;
-					String filename = null;
-					if (pathElement.attributeValue(CONTENT_PATH_PATH) != null) {
-						path = Paths.get(pathElement.attributeValue(CONTENT_PATH_PATH));
-						filename = path.getFileName().toString();
-					}
-
-					if (pathElement.attributeValue(CONTENT_PATH_FILENAME) != null) {
-						filename = pathElement.attributeValue(CONTENT_PATH_FILENAME);
-					}
-
-					MediaPath mediaPath = new MediaPath(uuid, filename, pad);
-
-					// Convert old projects to mediapool
-					if (path != null) {
-						MediaPool.getInstance().create(mediaPath, path);
-					}
-
-					pad.getPaths().add(mediaPath);
+			for (Element pathElement : pathsElement.elements(CONTENT_PATH_ELEMENT)) {
+				UUID uuid = UUID.fromString(pathElement.attributeValue(CONTENT_PATH_UUID));
+				Path path = null;
+				String filename = null;
+				if (pathElement.attributeValue(CONTENT_PATH_PATH) != null) {
+					path = Paths.get(pathElement.attributeValue(CONTENT_PATH_PATH));
+					filename = path.getFileName().toString();
 				}
+
+				if (pathElement.attributeValue(CONTENT_PATH_FILENAME) != null) {
+					filename = pathElement.attributeValue(CONTENT_PATH_FILENAME);
+				}
+
+				MediaPath mediaPath = new MediaPath(uuid, filename, pad);
+
+				// Convert old projects to mediapool
+				if (path != null) {
+					MediaPool.getInstance().create(mediaPath, path);
+				}
+
+				pad.getPaths().add(mediaPath);
 			}
 		}
 
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java
index 08ee050db8d224474e960ed54b41b6bc64479523..f85ef7e4c280e323aebcc5ea805e94a0cd5e5dd2 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java
@@ -3,6 +3,7 @@ package de.tobias.playpad.pad;
 import de.tobias.playpad.design.modern.ModernColor;
 import de.tobias.playpad.design.modern.model.ModernCartDesign;
 import de.tobias.playpad.profile.Profile;
+import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.server.sync.command.CommandManager;
 import de.tobias.playpad.server.sync.command.Commands;
 import de.tobias.playpad.server.sync.listener.upstream.PadSettingsUpdateListener;
@@ -13,10 +14,12 @@ import javafx.beans.binding.BooleanBinding;
 import javafx.beans.property.*;
 import javafx.util.Duration;
 
+import java.util.EnumMap;
 import java.util.HashMap;
+import java.util.Map;
 import java.util.UUID;
 
-public class PadSettings implements Cloneable {
+public class PadSettings {
 
 	// Pad Reference
 	private Pad pad;
@@ -30,12 +33,13 @@ public class PadSettings implements Cloneable {
 	private ObjectProperty<TimeMode> timeModeProperty = new SimpleObjectProperty<>();
 	private ObjectProperty<Fade> fadeProperty = new SimpleObjectProperty<>();
 	private ObjectProperty<Duration> warningProperty = new SimpleObjectProperty<>();
+	private ObjectProperty<Duration> cueInProperty = new SimpleObjectProperty<>();
 
 	private BooleanProperty customDesignProperty = new SimpleBooleanProperty(false);
 	private ModernCartDesign design;
 
-	private HashMap<TriggerPoint, Trigger> triggers = new HashMap<>();
-	private HashMap<String, Object> customSettings = new HashMap<>();
+	private Map<TriggerPoint, Trigger> triggers = new EnumMap<>(TriggerPoint.class);
+	private Map<String, Object> customSettings = new HashMap<>();
 
 	// Sync Listener
 	private PadSettingsUpdateListener syncListener;
@@ -106,10 +110,8 @@ public class PadSettings implements Cloneable {
 	}
 
 	public TimeMode getTimeMode() {
-		if (timeModeProperty.isNull().get()) {
-			if (Profile.currentProfile() != null) {
-				return Profile.currentProfile().getProfileSettings().getPlayerTimeDisplayMode();
-			}
+		if (timeModeProperty.isNull().get() && Profile.currentProfile() != null) {
+			return Profile.currentProfile().getProfileSettings().getPlayerTimeDisplayMode();
 		}
 		return timeModeProperty.get();
 	}
@@ -136,10 +138,8 @@ public class PadSettings implements Cloneable {
 	 * @return Fade
 	 */
 	public Fade getFade() {
-		if (fadeProperty.isNull().get()) {
-			if (Profile.currentProfile() != null) {
-				return Profile.currentProfile().getProfileSettings().getFade();
-			}
+		if (fadeProperty.isNull().get() && Profile.currentProfile() != null) {
+			return Profile.currentProfile().getProfileSettings().getFade();
 		}
 		return fadeProperty.get();
 	}
@@ -161,10 +161,8 @@ public class PadSettings implements Cloneable {
 	}
 
 	public Duration getWarning() {
-		if (warningProperty.isNull().get()) {
-			if (Profile.currentProfile() != null) {
-				return Profile.currentProfile().getProfileSettings().getWarningFeedback();
-			}
+		if (warningProperty.isNull().get() && Profile.currentProfile() != null) {
+			return Profile.currentProfile().getProfileSettings().getWarningFeedback();
 		}
 		return warningProperty.get();
 	}
@@ -177,6 +175,18 @@ public class PadSettings implements Cloneable {
 		return warningProperty;
 	}
 
+	public Duration getCueIn() {
+		return cueInProperty.get();
+	}
+
+	public void setCueIn(Duration cueIn) {
+		cueInProperty.set(cueIn);
+	}
+
+	public Duration cueInProperty() {
+		return cueInProperty.get();
+	}
+
 	public boolean isCustomDesign() {
 		return customDesignProperty.get();
 	}
@@ -191,39 +201,30 @@ public class PadSettings implements Cloneable {
 
 	public ModernCartDesign getDesign() {
 		if (design == null) {
-			ModernCartDesign design = new ModernCartDesign(pad);
+			ModernCartDesign newDesign = new ModernCartDesign(pad);
 
 			if (pad.getProject().getProjectReference().isSync()) {
-				CommandManager.execute(Commands.DESIGN_ADD, pad.getProject().getProjectReference(), design);
+				CommandManager.execute(Commands.DESIGN_ADD, pad.getProject().getProjectReference(), newDesign);
 			}
 
-			setDesign(design);
+			setDesign(newDesign);
 
 		}
 		return design;
 	}
 
-	public ModernColor getBackgroundColor() {
-		if (isCustomDesign()) {
-			return design.getBackgroundColor();
-		} else {
-			return Profile.currentProfile().getProfileSettings().getDesign().getBackgroundColor();
-		}
-	}
-
 	public void setDesign(ModernCartDesign design) {
 		this.design = design;
 		if (pad.getProject().getProjectReference().isSync()) {
 			design.addListener();
 		}
-
 	}
 
-	public HashMap<String, Object> getCustomSettings() {
+	public Map<String, Object> getCustomSettings() {
 		return customSettings;
 	}
 
-	public HashMap<TriggerPoint, Trigger> getTriggers() {
+	public Map<TriggerPoint, Trigger> getTriggers() {
 		return triggers;
 	}
 
@@ -248,8 +249,8 @@ public class PadSettings implements Cloneable {
 		return false;
 	}
 
-	public PadSettings clone(Pad pad) throws CloneNotSupportedException {
-		PadSettings clone = (PadSettings) super.clone();
+	public PadSettings copy(Pad pad) {
+		PadSettings clone = new PadSettings(pad);
 		clone.id = UUID.randomUUID();
 
 		clone.volumeProperty = new SimpleDoubleProperty(getVolume());
@@ -272,16 +273,19 @@ public class PadSettings implements Cloneable {
 
 		clone.customDesignProperty = new SimpleBooleanProperty(isCustomDesign());
 		if (design != null) {
-			clone.design = design.clone(pad);
+			clone.design = design.copy(pad);
 		}
 
-		clone.triggers = new HashMap<>(); // TODO Trigger werden nicht Kopiert
+		clone.triggers = new EnumMap<>(TriggerPoint.class);
+		triggers.forEach((key, value) -> clone.triggers.put(key, value.copy()));
+
 		clone.customSettings = new HashMap<>(); // TODO CustomSettings werden nicht Kopiert
 
 		clone.updateTrigger();
 
-		if (pad.getProject().getProjectReference().isSync()) {
-			CommandManager.execute(Commands.PAD_SETTINGS_ADD, pad.getProject().getProjectReference(), clone);
+		final ProjectReference projectReference = pad.getProject().getProjectReference();
+		if (projectReference.isSync()) {
+			CommandManager.execute(Commands.PAD_SETTINGS_ADD, projectReference, clone);
 		}
 
 		return clone;
@@ -300,4 +304,13 @@ public class PadSettings implements Cloneable {
 		syncListener.removeListener();
 	}
 
+	//// Computed
+
+	public ModernColor getBackgroundColor() {
+		if (isCustomDesign()) {
+			return design.getBackgroundColor();
+		} else {
+			return Profile.currentProfile().getProfileSettings().getDesign().getBackgroundColor();
+		}
+	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java
index 2cac4072c074953c9ed377a3375b036d2d170a13..c4a44e1d72c09c8ae1ae8bdd3103f4f68447045f 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java
@@ -23,6 +23,7 @@ public class PadSettingsSerializer {
 	private static final String TIME_MODE_ELEMENT = "TimeMode";
 	private static final String FADE_ELEMENT = "Fade";
 	private static final String WARNING_ELEMENT = "Warning";
+	private static final String CUE_IN_ELEMENT = "CueIn";
 
 	private static final String DESIGN_ELEMENT = "Design";
 	private static final String CUSTOM_DESIGN_ELEMENT = "custom";
@@ -30,6 +31,8 @@ public class PadSettingsSerializer {
 	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";
+	private static final String TRIGGERS_ELEMENT = "Triggers";
+	private static final String TRIGGER_ELEMENT = "Trigger";
 
 	public PadSettings loadElement(Element settingsElement, Pad pad) {
 		PadSettings padSettings;
@@ -41,9 +44,9 @@ public class PadSettingsSerializer {
 		}
 
 		if (settingsElement.element(VOLUME_ELEMENT) != null)
-			padSettings.setVolume(Double.valueOf(settingsElement.element(VOLUME_ELEMENT).getStringValue()));
+			padSettings.setVolume(Double.parseDouble(settingsElement.element(VOLUME_ELEMENT).getStringValue()));
 		if (settingsElement.element(LOOP_ELEMENT) != null)
-			padSettings.setLoop(Boolean.valueOf(settingsElement.element(LOOP_ELEMENT).getStringValue()));
+			padSettings.setLoop(Boolean.parseBoolean(settingsElement.element(LOOP_ELEMENT).getStringValue()));
 		if (settingsElement.element(TIME_MODE_ELEMENT) != null)
 			padSettings.setTimeMode(TimeMode.valueOf(settingsElement.element(TIME_MODE_ELEMENT).getStringValue()));
 		if (settingsElement.element(FADE_ELEMENT) != null)
@@ -56,12 +59,20 @@ public class PadSettingsSerializer {
 				padSettings.setWarning(Duration.seconds(5));
 			}
 		}
+		if (settingsElement.element(CUE_IN_ELEMENT) != null) {
+			try {
+				Duration duration = Duration.valueOf(settingsElement.element(CUE_IN_ELEMENT).getStringValue().replace(" ", ""));
+				padSettings.setCueIn(duration);
+			} catch (Exception e) {
+				padSettings.setCueIn(null);
+			}
+		}
 
 		// Layout
 		Element designElement = settingsElement.element(DESIGN_ELEMENT);
 		if (designElement != null) {
 			if (designElement.attributeValue(CUSTOM_DESIGN_ELEMENT) != null) {
-				padSettings.setCustomDesign(Boolean.valueOf(designElement.attributeValue(CUSTOM_DESIGN_ELEMENT)));
+				padSettings.setCustomDesign(Boolean.parseBoolean(designElement.attributeValue(CUSTOM_DESIGN_ELEMENT)));
 			}
 			ModernCartDesignSerializer serializer = new ModernCartDesignSerializer();
 			ModernCartDesign design = serializer.load(designElement, pad);
@@ -70,29 +81,23 @@ public class PadSettingsSerializer {
 
 		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);
-					padSettings.getCustomSettings().put(key, data);
-				}
+			for (Element item : userInfoElement.elements()) {
+				String key = item.attributeValue(CUSTOM_SETTINGS_TYPE_ATTR);
+				Object data = UserDefaults.loadElement(item);
+				padSettings.getCustomSettings().put(key, data);
 			}
 		}
 
 		// Trigger
-		Element triggersElement = settingsElement.element("Triggers");
+		Element triggersElement = settingsElement.element(TRIGGERS_ELEMENT);
 		if (triggersElement != null) {
-			for (Object triggerObj : triggersElement.elements("Trigger")) {
-				if (triggerObj instanceof Element) {
-					Element triggerElement = (Element) triggerObj;
-					Trigger trigger = new Trigger();
-					trigger.load(triggerElement);
-					padSettings.getTriggers().put(trigger.getTriggerPoint(), trigger);
-				}
+			for (Element triggerElement : triggersElement.elements(TRIGGER_ELEMENT)) {
+				Trigger trigger = new Trigger();
+				trigger.load(triggerElement);
+				padSettings.getTriggers().put(trigger.getTriggerPoint(), trigger);
 			}
 		}
-		padSettings.updateTrigger(); // Damit alle Points da sind
+		padSettings.updateTrigger(); // Add missing trigger points
 
 		return padSettings;
 	}
@@ -109,6 +114,9 @@ public class PadSettingsSerializer {
 		if (padSettings.isCustomFade())
 			padSettings.getFade().save(settingsElement.addElement(FADE_ELEMENT));
 
+		if (padSettings.getCueIn() != null)
+			settingsElement.addElement(CUE_IN_ELEMENT).addText(padSettings.getCueIn().toString());
+
 		// Layout
 		Element designElement = settingsElement.addElement(DESIGN_ELEMENT);
 		if (padSettings.isCustomDesign()) {
@@ -124,10 +132,10 @@ public class PadSettingsSerializer {
 		}
 
 		// Trigger
-		Element triggersElement = settingsElement.addElement("Triggers");
+		Element triggersElement = settingsElement.addElement(TRIGGERS_ELEMENT);
 		for (TriggerPoint point : padSettings.getTriggers().keySet()) {
 			Trigger trigger = padSettings.getTriggers().get(point);
-			Element triggerElement = triggersElement.addElement("Trigger");
+			Element triggerElement = triggersElement.addElement(TRIGGER_ELEMENT);
 			trigger.save(triggerElement);
 		}
 	}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContent.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContent.java
index 2ebfdafbcacfdf64614bdc2758eed4453c6efcb1..bf50a0b447c04de9dd77eadb9a9ee6834ca224bc 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContent.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContent.java
@@ -10,7 +10,7 @@ import de.tobias.playpad.pad.mediapath.MediaPath;
  * @version 5.1.0
  * @see Pad
  */
-public abstract class PadContent implements Cloneable {
+public abstract class PadContent {
 
 	// reference
 	private Pad pad;
@@ -69,12 +69,13 @@ public abstract class PadContent implements Cloneable {
 	@Override
 	protected void finalize() throws Throwable {
 		unloadMedia();
-		this.pad = null;
-	}
-
-	@Override
-	public PadContent clone() throws CloneNotSupportedException {
-		return (PadContent) super.clone();
 	}
 
+	/**
+	 * Create a copy of the PadContent instance
+	 *
+	 * @param pad target pad
+	 * @return copied content
+	 */
+	public abstract PadContent copy(Pad pad);
 }
\ No newline at end of file
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/play/Durationable.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/play/Durationable.java
index cf3f88644c8e6313548c1763c94cd30b63e5ea2e..19c2d4a3537b3d7e0768f22cbb093c52c51dd46c 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/play/Durationable.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/play/Durationable.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.pad.content.play;
 
+import de.tobias.playpad.pad.PadSettings;
 import javafx.beans.property.ReadOnlyObjectProperty;
 import javafx.util.Duration;
 
@@ -12,4 +13,16 @@ public interface Durationable {
 	ReadOnlyObjectProperty<Duration> durationProperty();
 
 	ReadOnlyObjectProperty<Duration> positionProperty();
+
+	default Duration getRemaining(PadSettings padSettings) {
+		if (!padSettings.isLoop()) {
+			final Duration position = getPosition();
+			final Duration duration = getDuration();
+
+			if (position != null && duration != null) {
+				return duration.subtract(position);
+			}
+		}
+		return null;
+	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java
index f5fffa342e6b9fd697740f09a10a325153cc7cce..de3828da7264143b30c1c0a49f94b58407d4919a 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java
@@ -24,8 +24,8 @@ public class Fade {
 		fade(0, 1, duration, null);
 	}
 
-	public void fadeIn(Duration duration, Runnable onFinsih) {
-		fade(0, 1, duration, onFinsih);
+	public void fadeIn(Duration duration, Runnable onFinish) {
+		fade(0, 1, duration, onFinish);
 	}
 
 	public void fadeOut(Duration duration) {
@@ -52,7 +52,6 @@ public class Fade {
 		}
 
 		currentFadeTransition = new Transition() {
-
 			{
 				setCycleDuration(duration);
 			}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusControlListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusControlListener.java
index 5b21ad95d7c702cfe498a7d722be1db3826460f7..882aa5c0f6fb3da0e81e180dd2eff5a45cb11f7b 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusControlListener.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusControlListener.java
@@ -28,9 +28,9 @@ public class PadStatusControlListener implements ChangeListener<PadStatus> {
 		PadSettings padSettings = pad.getPadSettings();
 		ProfileSettings profileSettings = Profile.currentProfile().getProfileSettings();
 
+		PlayPadPlugin.getInstance().getPadListener().forEach(listener -> listener.onStatusChange(pad, newValue));
 		if (newValue == PadStatus.PLAY) {
 			if (pad.getContent() != null) {
-				PlayPadPlugin.getInstance().getPadListener().forEach(listener -> listener.onPlay(pad));
 
 				pad.getProject().updateActivePlayerProperty();
 
@@ -45,9 +45,7 @@ public class PadStatusControlListener implements ChangeListener<PadStatus> {
 				}
 
 				if (pad.getContent() instanceof Fadeable) {
-					if (oldValue == PadStatus.PAUSE && padSettings.getFade().isFadeInPause()) {
-						((Fadeable) pad.getContent()).fadeIn();
-					} else if (padSettings.getFade().isFadeInStart()) {
+					if (padSettings.getFade().isFadeInStart() || (oldValue == PadStatus.PAUSE && padSettings.getFade().isFadeInPause())) {
 						((Fadeable) pad.getContent()).fadeIn();
 					}
 				}
@@ -56,17 +54,13 @@ public class PadStatusControlListener implements ChangeListener<PadStatus> {
 		} else if (newValue == PadStatus.PAUSE) {
 			if (pad.getContent() instanceof Pauseable) {
 				if (pad.getContent() instanceof Fadeable && padSettings.getFade().isFadeOutPause()) {
-					((Fadeable) pad.getContent()).fadeOut(() ->
-					{
-						((Pauseable) pad.getContent()).pause();
-					});
+					((Fadeable) pad.getContent()).fadeOut(() -> ((Pauseable) pad.getContent()).pause());
 				} else {
 					((Pauseable) pad.getContent()).pause();
 				}
 			}
 		} else if (newValue == PadStatus.STOP) {
 			if (pad.getContent() != null) {
-				PlayPadPlugin.getInstance().getPadListener().forEach(listener -> listener.onStop(pad));
 				pad.getProject().updateActivePlayerProperty();
 
 				if (pad.getContent() instanceof Fadeable && !pad.isEof() && padSettings.getFade().isFadeOutStop()) { // Fade nur wenn Pad
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusNotFoundListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusNotFoundListener.java
index f3f4c8db341192e0f22cfa22622dbf483be093f6..560371ae21dd257988c7d62a7735953c0eadc1ca 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusNotFoundListener.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusNotFoundListener.java
@@ -18,9 +18,7 @@ public class PadStatusNotFoundListener implements ChangeListener<PadStatus> {
 
 	@Override
 	public void changed(ObservableValue<? extends PadStatus> observable, PadStatus oldValue, PadStatus newValue) {
-		if (newValue == PadStatus.NOT_FOUND) {
-			project.updateNotFoundProperty();
-		} else if (oldValue == PadStatus.NOT_FOUND) {
+		if (newValue == PadStatus.NOT_FOUND || oldValue == PadStatus.NOT_FOUND) {
 			project.updateNotFoundProperty();
 		}
 	}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/mediapath/MediaPath.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/mediapath/MediaPath.java
index 403d8a17468277ea6b3c5f1e1f2408c31fd47c2e..2287d7e5ac335b679cbf05975645bbd2e0737b97 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/mediapath/MediaPath.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/mediapath/MediaPath.java
@@ -17,7 +17,7 @@ import java.util.UUID;
 /**
  * Created by tobias on 21.02.17.
  */
-public class MediaPath implements Cloneable {
+public class MediaPath {
 
 	private UUID id;
 	private StringProperty fileName;
@@ -105,12 +105,8 @@ public class MediaPath implements Cloneable {
 		return original;
 	}
 
-	public MediaPath clone(Pad pad) throws CloneNotSupportedException {
-		MediaPath clone = (MediaPath) super.clone();
-		clone.id = UUID.randomUUID();
-		clone.fileName = new SimpleStringProperty(fileName.get());
-		clone.pad = pad;
-
+	public MediaPath copy(Pad pad) {
+		MediaPath clone = new MediaPath(UUID.randomUUID(), fileName.get(), pad);
 		MediaPool.getInstance().create(clone, this.getPath());
 
 		if (pad.getProject().getProjectReference().isSync()) {
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/mediapath/MediaPool.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/mediapath/MediaPool.java
index 05f5b7017cc8c0fdcdff9b04bd03f3e42a8c4e33..0c6a9cf510b6ecf24d6690635140cc2561f48544 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/mediapath/MediaPool.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/mediapath/MediaPool.java
@@ -1,23 +1,26 @@
 package de.tobias.playpad.pad.mediapath;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.App;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
 
 import java.io.IOException;
+import java.nio.file.DirectoryStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.sql.*;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.UUID;
 
 /**
  * Created by tobias on 20.03.17.
  */
 public class MediaPool {
 
-	private static final String mediaPoolFile = "media.db";
+	private static final String MEDIA_DB = "media.db";
 
 	private static MediaPool instance;
 
@@ -32,7 +35,7 @@ public class MediaPool {
 		try {
 			Class.forName("org.sqlite.JDBC");
 		} catch (ClassNotFoundException e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 
@@ -40,35 +43,63 @@ public class MediaPool {
 
 	private MediaPool() {
 		App app = ApplicationUtils.getApplication();
-		Path path = app.getPath(PathType.DOCUMENTS, mediaPoolFile);
+		Path path = app.getPath(PathType.DOCUMENTS, MEDIA_DB);
 		if (Files.notExists(path.getParent())) {
 			try {
 				Files.createDirectories(path.getParent());
 			} catch (IOException e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		}
+
 		try {
 			connection = DriverManager.getConnection("jdbc:sqlite:" + path.toString());
+		} catch (SQLException e) {
+			Logger.error(e);
+			return;
+		}
 
-			PreparedStatement subjectCreateStmt = connection.prepareStatement(
-					"CREATE TABLE IF NOT EXISTS `Path` (`id` VARCHAR NOT NULL PRIMARY KEY, `project` VARCHAR NOT NULL, `path` TEXT DEFAULT NULL);");
+		try (PreparedStatement subjectCreateStmt = connection.prepareStatement(
+				"CREATE TABLE IF NOT EXISTS `Path` (`id` VARCHAR NOT NULL PRIMARY KEY, `project` VARCHAR NOT NULL, `path` TEXT DEFAULT NULL);")) {
 			subjectCreateStmt.execute();
-			subjectCreateStmt.close();
 		} catch (SQLException e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 	}
 
+	public List<MediaPath> getMediaPathsForProject(UUID projectId) {
+		List<MediaPath> paths = new ArrayList<>();
+
+		if (connection == null) {
+			return paths;
+		}
+
+		try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM Path WHERE project = ?")) {
+			stmt.setString(1, projectId.toString());
+
+			try (ResultSet result = stmt.executeQuery()) {
+				while (result.next()) {
+					UUID id = UUID.fromString(result.getString("id"));
+					String localPath = result.getString("path");
+
+					MediaPath path = new MediaPath(id, localPath, null);
+					paths.add(path);
+				}
+			}
+		} catch (SQLException e) {
+			Logger.error(e);
+		}
+		return paths;
+	}
+
 	public Path getPath(MediaPath path) {
-		if (connection != null) {
-			PreparedStatement stmt = null;
-			ResultSet result = null;
-			try {
-				stmt = connection.prepareStatement("SELECT * FROM Path WHERE id = ?");
-				stmt.setString(1, path.getId().toString());
-				result = stmt.executeQuery();
+		if (connection == null) {
+			return null;
+		}
+		try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM Path WHERE id = ?")) {
+			stmt.setString(1, path.getId().toString());
 
+			try (ResultSet result = stmt.executeQuery()) {
 				if (result.next()) {
 					String localPath = result.getString("path");
 					if (localPath == null) {
@@ -76,24 +107,9 @@ public class MediaPool {
 					}
 					return Paths.get(localPath);
 				}
-			} catch (SQLException e) {
-				e.printStackTrace();
-			} finally {
-				if (result != null) {
-					try {
-						result.close();
-					} catch (SQLException e) {
-						e.printStackTrace();
-					}
-				}
-				if (stmt != null) {
-					try {
-						stmt.close();
-					} catch (SQLException e) {
-						e.printStackTrace();
-					}
-				}
 			}
+		} catch (SQLException e) {
+			Logger.error(e);
 		}
 		return null;
 	}
@@ -104,23 +120,13 @@ public class MediaPool {
 
 	public void create(MediaPath path, Path localPath) {
 		if (connection != null) {
-			PreparedStatement stmt = null;
-			try {
-				stmt = connection.prepareStatement("INSERT INTO Path VALUES (?, ?, ?)");
+			try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO Path VALUES (?, ?, ?)")) {
 				stmt.setString(1, path.getId().toString());
 				stmt.setString(2, path.getPad().getProject().getProjectReference().getUuid().toString());
 				stmt.setString(3, localPath != null ? localPath.toString() : null);
 				stmt.executeUpdate();
 			} catch (SQLException e) {
-				e.printStackTrace();
-			} finally {
-				if (stmt != null) {
-					try {
-						stmt.close();
-					} catch (SQLException e) {
-						e.printStackTrace();
-					}
-				}
+				Logger.error(e);
 			}
 		}
 	}
@@ -131,22 +137,23 @@ public class MediaPool {
 				create(path);
 			}
 
-			PreparedStatement stmt = null;
-			try {
-				stmt = connection.prepareStatement("UPDATE Path SET path = ? WHERE id = ?");
+			try (PreparedStatement stmt = connection.prepareStatement("UPDATE Path SET path = ? WHERE id = ?")) {
 				stmt.setString(1, localPath.toString());
 				stmt.setString(2, path.getId().toString());
 				stmt.executeUpdate();
 			} catch (SQLException e) {
-				e.printStackTrace();
-			} finally {
-				if (stmt != null) {
-					try {
-						stmt.close();
-					} catch (SQLException e) {
-						e.printStackTrace();
-					}
-				}
+				Logger.error(e);
+			}
+		}
+	}
+
+	public void deleteEntries(UUID projectId) {
+		if (connection != null) {
+			try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM Path WHERE project = ?")) {
+				stmt.setString(1, projectId.toString());
+				stmt.executeUpdate();
+			} catch (SQLException e) {
+				Logger.error(e);
 			}
 		}
 	}
@@ -155,7 +162,7 @@ public class MediaPool {
 		try {
 			connection.close();
 		} catch (SQLException e) {
-			e.printStackTrace();
+			Logger.error(e);
 		} finally {
 			connection = null;
 		}
@@ -164,17 +171,19 @@ public class MediaPool {
 	// Find algorithm
 	public static Path find(String filename, Path baseFolder, boolean includeSubdirectories) throws IOException {
 		List<Path> result = new ArrayList<>();
-		Files.newDirectoryStream(baseFolder).forEach(path -> {
-			if (path.getFileName().toString().equals(filename)) {
-				result.add(path);
-			} else if (Files.isDirectory(path) && includeSubdirectories) {
-				try {
-					result.add(find(filename, path, false));
-				} catch (IOException e) {
-					e.printStackTrace();
+		try (DirectoryStream<Path> stream = Files.newDirectoryStream(baseFolder)) {
+			stream.forEach(path -> {
+				if (path.getFileName().toString().equals(filename)) {
+					result.add(path);
+				} else if (Files.isDirectory(path) && includeSubdirectories) {
+					try {
+						result.add(find(filename, path, false));
+					} catch (IOException e) {
+						Logger.error(e);
+					}
 				}
-			}
-		});
+			});
+		}
 		return result.isEmpty() ? null : result.get(0);
 	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadContentView.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadContentView.java
index 163bc2dd768b4e55b6dbb4f6e7eb7c9b5949908b..c91aa9c7651afdc804ed1e961bf8cf80a1744338 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadContentView.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadContentView.java
@@ -22,5 +22,5 @@ public interface IPadContentView {
 	/**
 	 * Deinitialisiert die View. Hier können mögliche Bindings und Listener entfernt werden.
 	 */
-	void deinit();
+	void deInit();
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadView.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadView.java
index 19510690f7928c76c6c2c4da152be1f4c23bc743..51c6ae1b2d7450bf0cd0c191d822bc7f43be7beb 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadView.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadView.java
@@ -59,10 +59,10 @@ public interface IPadView {
 	/**
 	 * Aktiviert eine Pseudoclass für die View
 	 *
-	 * @param playCalss Pseudoclass
-	 * @param b         <code>true</code> Aktiv
+	 * @param playClass Pseudo class
+	 * @param b         <code>true</code> active
 	 */
-	void pseudoClassState(PseudoClass playCalss, boolean b);
+	void pseudoClassState(PseudoClass playClass, boolean b);
 
 	/**
 	 * Setzt den Style für den Root Node der PadView.
@@ -74,9 +74,9 @@ public interface IPadView {
 	/**
 	 * Hebt eine Kachel hervor (Beispiel mit einer Animation.
 	 *
-	 * @param milliSecounds Dauer in Millisekunden
+	 * @param milliSeconds Dauer in Millisekunden
 	 */
-	void highlightView(int milliSecounds);
+	void highlightView(int milliSeconds);
 
 	/**
 	 * Aktiviert des Error Labels, damit es angezeigt wird.
@@ -92,6 +92,13 @@ public interface IPadView {
 	 */
 	void setPlayBarProgress(double value);
 
+	/**
+	 * Set the cue in progress value.
+	 *
+	 * @param value value between 0 and 1
+	 */
+	void setCueInProgress(double value);
+
 	/**
 	 * Setzt die Playbar sichtbar.
 	 *
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/GlobalAdapter.java b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/GlobalAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa59a4326768c63b4499bb38247b15bf46ca9fdf
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/GlobalAdapter.java
@@ -0,0 +1,16 @@
+package de.tobias.playpad.plugin;
+
+import de.tobias.playpad.project.Project;
+
+public class GlobalAdapter implements GlobalListener {
+
+	@Override
+	public void projectOpened(Project newProject) {
+
+	}
+
+	@Override
+	public void projectClosed(Project currentProject) {
+
+	}
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/GlobalListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/GlobalListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..0885b0c3760210645f76e805812c0d37cf304ddb
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/GlobalListener.java
@@ -0,0 +1,10 @@
+package de.tobias.playpad.plugin;
+
+import de.tobias.playpad.project.Project;
+
+public interface GlobalListener {
+
+	void projectOpened(Project newProject);
+
+	void projectClosed(Project currentProject);
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/MainWindowListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/MainWindowListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed330ccf0418863959b60738f6010d162d03e286
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/MainWindowListener.java
@@ -0,0 +1,9 @@
+package de.tobias.playpad.plugin;
+
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+
+public interface MainWindowListener extends WindowListener<IMainViewController> {
+
+	default void loadMenuKeyBinding() {
+	}
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPlugin.java b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPlugin.java
index 957cf2f064dca9a66b7ac7364043033536f68bb8..5bf588d85c4b3abceccff1404c4567961c9cc569 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPlugin.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPlugin.java
@@ -12,20 +12,17 @@ public class ModernPlugin {
 	private String displayName;
 	private String description;
 
-	private String path;
-
 	private String version;
 	private int build;
 
 	public ModernPlugin() {
 	}
 
-	public ModernPlugin(int id, String name, String displayName, String description, String path, String version, int build) {
+	public ModernPlugin(int id, String name, String displayName, String description, String version, int build) {
 		this.id = id;
 		this.name = name;
 		this.displayName = displayName;
 		this.description = description;
-		this.path = path;
 		this.version = version;
 		this.build = build;
 	}
@@ -54,10 +51,6 @@ public class ModernPlugin {
 		return build;
 	}
 
-	public String getPath() {
-		return path;
-	}
-
 	public String getFileName() {
 		return getName() + EXTENSION;
 	}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPluginManager.java b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPluginManager.java
index 8b80e6baa28c41a37189b8a455abba1fcdc6f340..6a7710569a56500cac8e246091f31523071c9190 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPluginManager.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPluginManager.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.plugin;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.plugins.Plugin;
 import de.thecodelabs.plugins.PluginArtifact;
 import de.thecodelabs.plugins.PluginManager;
@@ -53,6 +54,7 @@ public class ModernPluginManager {
 		if (Files.notExists(path)) {
 			throw new IOException("File not found: " + path);
 		}
+		loadFile(path.getParent());
 	}
 
 	public void loadFile(Path path) {
@@ -94,13 +96,13 @@ public class ModernPluginManager {
 
 		// 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);
+			try (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);
 		}
 	}
@@ -119,7 +121,7 @@ public class ModernPluginManager {
 			}
 			deleteWriter.close();
 		} catch (IOException e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 
 		pluginManager.shutdown();
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/PadListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/PadListener.java
index ec4388da4c5f31ceb8dcd6c91c1a823d04451d1b..5c9df06fdb5af598fe73958e56fed71265f4535b 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/PadListener.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/PadListener.java
@@ -1,6 +1,9 @@
 package de.tobias.playpad.plugin;
 
 import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadStatus;
+import de.tobias.playpad.pad.mediapath.MediaPath;
+import javafx.collections.ListChangeListener;
 
 /**
  * Listener für ein Pad.
@@ -11,17 +14,14 @@ import de.tobias.playpad.pad.Pad;
 public interface PadListener {
 
 	/**
-	 * Wird aufgerufen, sobald ein Pad wiedergegeben wird.
+	 * Call then ever the status of a pad will be changed
 	 *
-	 * @param pad Pad
+	 * @param pad      corresponding pad
+	 * @param newValue new status value
 	 */
-	void onPlay(Pad pad);
+	void onStatusChange(Pad pad, PadStatus newValue);
 
-	/**
-	 * Wird aufgerufen, sobald ein Pad gestoppt wird.
-	 *
-	 * @param pad Pad
-	 */
-	void onStop(Pad pad);
+	default void onMediaPathChanged(Pad pad, ListChangeListener.Change<? extends MediaPath> value) {
+	}
 
 }
\ No newline at end of file
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/WindowListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/WindowListener.java
index e9174ce96e30403264522567240754bc680f599f..a45045f7b4562db014b7a39a32a99f0c04872a8f 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/WindowListener.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/WindowListener.java
@@ -4,7 +4,7 @@ public interface WindowListener<T> {
 
 	void onInit(T t);
 
-	default void onClose(T t) {
+	default void onDeinit(T t) {
 
 	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/profile/Profile.java b/PlayWallCore/src/main/java/de/tobias/playpad/profile/Profile.java
index a1c036f62bbc06e3877c4f305b0cd57a6a257bde..4900d036b2a09c0e936c85cbc6e5b52bebea9964 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/profile/Profile.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/profile/Profile.java
@@ -1,13 +1,17 @@
 package de.tobias.playpad.profile;
 
 import de.thecodelabs.logger.Logger;
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.MappingCollection;
+import de.thecodelabs.midi.serialize.MappingCollectionSerializer;
 import de.thecodelabs.utils.application.App;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
 import de.tobias.playpad.PlayPadPlugin;
-import de.tobias.playpad.action.MappingList;
+import de.tobias.playpad.action.ActionProvider;
 import de.tobias.playpad.profile.ref.ProfileReference;
 import de.tobias.playpad.profile.ref.ProfileReferenceManager;
+import de.tobias.playpad.registry.Registry;
 import org.dom4j.DocumentException;
 
 import java.io.IOException;
@@ -15,11 +19,12 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 
 public class Profile {
 
 	private static final String PROFILE_SETTINGS_XML = "ProfileSettings.xml";
-	private static final String MAPPING_XML = "Mapping.xml";
+	private static final String MAPPING_JSON = "Mapping.json";
 
 	private static List<ProfileListener> listeners = new ArrayList<>();
 	private static Profile currentProfile;
@@ -28,7 +33,7 @@ public class Profile {
 	private ProfileReference ref;
 
 	private ProfileSettings profileSettings;
-	private MappingList mappings;
+	private MappingCollection mappings;
 
 	/**
 	 * Use {@link ProfileReferenceManager#addProfile(ProfileReference)} instead
@@ -38,7 +43,17 @@ public class Profile {
 	public Profile(ProfileReference ref) {
 		this.ref = ref;
 		this.profileSettings = new ProfileSettings();
-		this.mappings = new MappingList(this);
+		this.mappings = new MappingCollection();
+	}
+
+	public static Mapping createMappingWithDefaultActions() {
+		Mapping preset = new Mapping();
+		preset.setName("Default");
+
+		// Add default actions
+		final Registry<ActionProvider> actions = PlayPadPlugin.getRegistries().getActions();
+		actions.getComponents().forEach(provider -> provider.createDefaultActions(preset));
+		return preset;
 	}
 
 	public static void registerListener(ProfileListener listener) {
@@ -61,7 +76,7 @@ public class Profile {
 		listeners.forEach(listener -> listener.reloadSettings(old, currentProfile));
 	}
 
-	public MappingList getMappings() {
+	public MappingCollection getMappings() {
 		return mappings;
 	}
 
@@ -71,16 +86,22 @@ public class Profile {
 
 	public static Profile load(ProfileReference ref) throws DocumentException, IOException, ProfileNotFoundException {
 		if (ref == null) {
-			throw new IllegalArgumentException("Profile is null"); // TODO Check if to catch exception somewhere
+			throw new IllegalArgumentException("Profile is null");
 		}
 		// Altes Speichern bevor neues Geladen
-		if (currentProfile != null)
+		if (currentProfile != null) {
 			currentProfile.save();
+		}
+
+		// Dont load profile, that is currently loaded
+		if (currentProfile != null && currentProfile.getRef().equals(ref)) {
+			return currentProfile;
+		}
 
 		App app = ApplicationUtils.getApplication();
 		Profile profile = new Profile(ref);
 
-		System.out.println("+++ Load Profile: " + ref + " (" + ref.getUuid() + ") +++");
+		Logger.info("+++ Load Profile: " + ref + " (" + ref.getUuid() + ") +++");
 
 		if (Files.exists(app.getPath(PathType.CONFIGURATION, ref.getFileName()))) {
 
@@ -92,12 +113,27 @@ public class Profile {
 				try {
 					l.onLoad(profile);
 				} catch (Exception ex) {
-					ex.printStackTrace();
+					Logger.error(ex);
 				}
 			});
 
 			// Mapping erst danach, weil das auf current Profile zugreifen muss
-			profile.mappings = MappingList.load(app.getPath(PathType.CONFIGURATION, ref.getFileName(), MAPPING_XML), profile);
+			try {
+				profile.mappings = MappingCollectionSerializer.load(app.getPath(PathType.CONFIGURATION, ref.getFileName(), MAPPING_JSON));
+			} catch (IOException e) {
+				profile.mappings = new MappingCollection();
+			}
+
+			// Set current mapping
+			final Optional<Mapping> activeMapping = profile.getMappings().getActiveMapping();
+			final Optional<Mapping> anyMapping = profile.mappings.getMappings().stream().findAny();
+			final Mapping currentMapping = activeMapping.orElse(anyMapping.orElseGet(() -> {
+				final Mapping mapping = createMappingWithDefaultActions();
+				profile.mappings.addMapping(mapping);
+				return mapping;
+			}));
+			profile.mappings.setActiveMapping(currentMapping);
+			Mapping.setCurrentMapping(currentMapping);
 
 			setCurrentProfile(profile);
 
@@ -128,7 +164,7 @@ public class Profile {
 		ref.addRequestedModule(PlayPadPlugin.getRegistries().getAudioHandlers().getModule(profileSettings.getAudioClass()));
 
 		profileSettings.save(getProfilePath(PROFILE_SETTINGS_XML));
-		mappings.save(getProfilePath(MAPPING_XML));
+		MappingCollectionSerializer.save(mappings, getProfilePath(MAPPING_JSON));
 	}
 
 	private Path getProfilePath(String fileName) {
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java b/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java
index 2e83e0afce2c5614b028b8cfc0f3073adc357c9c..a2039d5c3d0b27febb982aff03ae0d02e0bcd698 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java
@@ -4,6 +4,7 @@ import de.thecodelabs.logger.Logger;
 import de.thecodelabs.storage.settings.UserDefaults;
 import de.thecodelabs.storage.settings.annotation.Key;
 import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.action.feedback.LightMode;
 import de.tobias.playpad.design.modern.model.ModernGlobalDesign;
 import de.tobias.playpad.design.modern.serializer.ModernGlobalDesignSerializer;
 import de.tobias.playpad.pad.TimeMode;
@@ -37,6 +38,8 @@ public class ProfileSettings {
 	private String midiDevice;
 	@Key
 	private boolean midiActive = false;
+	@Key
+	private LightMode lightMode = LightMode.NORMAL;
 
 	// Audio Output
 	@Key
@@ -84,6 +87,10 @@ public class ProfileSettings {
 		return midiDevice;
 	}
 
+	public LightMode getLightMode() {
+		return lightMode;
+	}
+
 	public String getMainLayoutType() {
 		return mainLayoutType;
 	}
@@ -133,6 +140,10 @@ public class ProfileSettings {
 		this.midiDevice = midiDevice;
 	}
 
+	public void setLightMode(LightMode lightMode) {
+		this.lightMode = lightMode;
+	}
+
 	public void setMainLayoutType(String mainLayoutType) {
 		this.mainLayoutType = mainLayoutType;
 	}
@@ -193,6 +204,7 @@ public class ProfileSettings {
 	private static final String DESIGN_ELEMENT = "Design";
 	private static final String MIDI_ACTIVE_ELEMENT = "MidiActive";
 	private static final String MIDI_DEVICE_ELEMENT = "MidiDevice";
+	private static final String LIGHT_MODE = "LightMode";
 
 	// File Handler
 	public static ProfileSettings load(Path path) throws DocumentException, IOException {
@@ -204,11 +216,13 @@ public class ProfileSettings {
 			Element root = document.getRootElement();
 
 			if (root.element(LOCKED_ELEMENT) != null)
-				profileSettings.setLocked(Boolean.valueOf(root.element(LOCKED_ELEMENT).getStringValue()));
+				profileSettings.setLocked(Boolean.parseBoolean(root.element(LOCKED_ELEMENT).getStringValue()));
 			if (root.element(MIDI_DEVICE_ELEMENT) != null)
 				profileSettings.setMidiDeviceName(root.element(MIDI_DEVICE_ELEMENT).getStringValue());
 			if (root.element(MIDI_ACTIVE_ELEMENT) != null)
-				profileSettings.setMidiActive(Boolean.valueOf(root.element(MIDI_ACTIVE_ELEMENT).getStringValue()));
+				profileSettings.setMidiActive(Boolean.parseBoolean(root.element(MIDI_ACTIVE_ELEMENT).getStringValue()));
+			if (root.element(LIGHT_MODE) != null)
+				profileSettings.setLightMode(LightMode.valueOf(root.element(LIGHT_MODE).getStringValue()));
 
 			if (root.element(DESIGN_ELEMENT) != null) {
 				Element element = root.element(DESIGN_ELEMENT);
@@ -220,7 +234,7 @@ public class ProfileSettings {
 			}
 
 			if (root.element(MULTIPLE_PLAYER_ELEMENT) != null) {
-				profileSettings.setMultiplePlayer(Boolean.valueOf(root.element(MULTIPLE_PLAYER_ELEMENT).getStringValue()));
+				profileSettings.setMultiplePlayer(Boolean.parseBoolean(root.element(MULTIPLE_PLAYER_ELEMENT).getStringValue()));
 			}
 
 			if (root.element(WARNING_ELEMENT) != null) {
@@ -247,7 +261,7 @@ public class ProfileSettings {
 			}
 
 			if (root.element(WINDOW_ALWAYS_ON_TOP_ELEMENT) != null)
-				profileSettings.setWindowAlwaysOnTop(Boolean.valueOf(root.element(WINDOW_ALWAYS_ON_TOP_ELEMENT).getStringValue()));
+				profileSettings.setWindowAlwaysOnTop(Boolean.parseBoolean(root.element(WINDOW_ALWAYS_ON_TOP_ELEMENT).getStringValue()));
 			if (root.element(AUDIO_CLASS_ELEMENT) != null)
 				profileSettings.setAudioClass(root.element(AUDIO_CLASS_ELEMENT).getStringValue());
 
@@ -263,7 +277,7 @@ public class ProfileSettings {
 				}
 			}
 			if (root.element(VOLUME_ELEMENT) != null)
-				profileSettings.setVolume(Double.valueOf(root.element(VOLUME_ELEMENT).getStringValue()));
+				profileSettings.setVolume(Double.parseDouble(root.element(VOLUME_ELEMENT).getStringValue()));
 		}
 		return profileSettings;
 	}
@@ -278,6 +292,7 @@ public class ProfileSettings {
 		if (midiDevice != null)
 			root.addElement(MIDI_DEVICE_ELEMENT).addText(midiDevice);
 		root.addElement(MIDI_ACTIVE_ELEMENT).addText(String.valueOf(midiActive));
+		root.addElement(LIGHT_MODE).addText(lightMode.name());
 
 		Element designElement = root.addElement(DESIGN_ELEMENT);
 		ModernGlobalDesignSerializer serializer = new ModernGlobalDesignSerializer();
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/profile/ref/ProfileReference.java b/PlayWallCore/src/main/java/de/tobias/playpad/profile/ref/ProfileReference.java
index f84b5a1e9382e9510b04ddfdc99bd0155c70ebc1..7fc86e27521e16b2d1a49ff8f65c25b5db1ac3e7 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/profile/ref/ProfileReference.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/profile/ref/ProfileReference.java
@@ -10,6 +10,7 @@ import javafx.beans.property.StringProperty;
 
 import java.nio.file.Path;
 import java.util.HashSet;
+import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
 
@@ -131,4 +132,17 @@ public class ProfileReference implements Displayable {
 	private void updateDisplayProperty() {
 		displayProperty.set(toString());
 	}
+
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (!(o instanceof ProfileReference)) return false;
+		ProfileReference that = (ProfileReference) o;
+		return Objects.equals(uuid, that.uuid);
+	}
+
+	@Override
+	public int hashCode() {
+		return Objects.hash(uuid);
+	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/profile/ref/ProfileReferenceManager.java b/PlayWallCore/src/main/java/de/tobias/playpad/profile/ref/ProfileReferenceManager.java
index 2f86da0b9b1be015a94c7831ceb1c2ed267c8a34..2daa64e53e24a8446e84ad30ac37cba40f6a8c30 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/profile/ref/ProfileReferenceManager.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/profile/ref/ProfileReferenceManager.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.profile.ref;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.storage.xml.XMLHandler;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
@@ -89,7 +90,7 @@ public final class ProfileReferenceManager {
 			try {
 				Files.createDirectories(path);
 			} catch (IOException e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		}
 	}
@@ -140,7 +141,7 @@ public final class ProfileReferenceManager {
 					if (!Files.isDirectory(path))
 						Files.delete(path);
 				} catch (Exception e) {
-					e.printStackTrace();
+					Logger.error(e);
 				}
 			});
 			Files.delete(root);
@@ -169,7 +170,7 @@ public final class ProfileReferenceManager {
 			// Load data from xml
 			XMLHandler<ProfileReference> handler = new XMLHandler<>(path);
 			ProfileReferenceManager.profiles.setAll(handler.loadElements(PROFILE_ELEMENT, new ProfileReferenceSerializer()));
-			System.out.println("Find Profile: " + ProfileReferenceManager.profiles);
+			Logger.info("Find Profile: " + ProfileReferenceManager.profiles);
 		}
 
 		// Add Default Element if list is empty
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/Project.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/Project.java
index 508d3d6962e5f56fe217b7c30327cd60f6893479..e5b537f66e4d132f88e8f28ef2068ee4bae7b24c 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/Project.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/Project.java
@@ -6,7 +6,6 @@ import de.tobias.playpad.pad.mediapath.MediaPath;
 import de.tobias.playpad.project.page.PadIndex;
 import de.tobias.playpad.project.page.Page;
 import de.tobias.playpad.project.ref.ProjectReference;
-import de.tobias.playpad.project.ref.ProjectReferenceManager;
 import de.tobias.playpad.server.sync.command.CommandManager;
 import de.tobias.playpad.server.sync.command.Commands;
 import de.tobias.playpad.server.sync.listener.upstream.ProjectUpdateListener;
@@ -68,6 +67,10 @@ public class Project {
 
 	public void close() {
 		syncListener.removeListener();
+
+		getPads().parallelStream()
+				.filter(pad -> pad.getStatus() == PadStatus.PLAY || pad.getStatus() == PadStatus.PAUSE)
+				.forEach(Pad::stop);
 	}
 
 	public ProjectSettings getSettings() {
@@ -99,13 +102,14 @@ public class Project {
 	}
 
 	public void setPad(PadIndex index, Pad pad) {
-		if (pad != null) {
-			// Remove Pad from old location
-			if (pad.getPage().getPosition() != index.getPagePosition()) {
-				Page oldPage = pad.getPage();
-				if (oldPage.getPad(pad.getPosition()).equals(pad)) {
-					oldPage.setPad(index.getId(), null);
-				}
+		if (pad == null) {
+			return;
+		}
+		// Remove Pad from old location
+		if (pad.getPage().getPosition() != index.getPagePosition()) {
+			Page oldPage = pad.getPage();
+			if (oldPage.getPad(pad.getPosition()).equals(pad)) {
+				oldPage.setPad(index.getId(), null);
 			}
 		}
 
@@ -118,9 +122,10 @@ public class Project {
 	}
 
 	public Collection<Pad> getPads(Predicate<Pad> predicate) {
-		List<Pad> pads = new ArrayList<>();
-		pages.stream().map(Page::getPads).forEach(pads::addAll);
-		return pads.parallelStream().filter(predicate).collect(Collectors.toList());
+		return pages.parallelStream()
+				.flatMap(p -> p.getPads().stream())
+				.filter(predicate)
+				.collect(Collectors.toList());
 	}
 
 	public void removePad(UUID id) {
@@ -130,11 +135,11 @@ public class Project {
 	}
 
 	// Pages
-	public Page getPage(int psotion) {
-		if (psotion >= pages.size() && psotion < ProjectSettings.MAX_PAGES) {
-			addPage(new Page(psotion, this));
+	public Page getPage(int position) {
+		if (position >= pages.size() && position < ProjectSettings.MAX_PAGES) {
+			addPage(new Page(position, this));
 		}
-		return pages.get(psotion);
+		return pages.get(position);
 	}
 
 
@@ -156,8 +161,7 @@ public class Project {
 	}
 
 	public void setPage(int index, Page page) {
-		if (pages.contains(page))
-			pages.remove(page);
+		pages.remove(page);
 
 		pages.add(index, page);
 		page.setPosition(index);
@@ -256,10 +260,8 @@ public class Project {
 	public List<Pad> findPads(String name) {
 		List<Pad> result = new ArrayList<>();
 		for (Pad pad : getPads()) {
-			if (pad.getStatus() != PadStatus.EMPTY) {
-				if (pad.getName().toLowerCase().contains(name.toLowerCase())) {
-					result.add(pad);
-				}
+			if (pad.getStatus() != PadStatus.EMPTY && pad.getName().toLowerCase().contains(name.toLowerCase())) {
+				result.add(pad);
 			}
 		}
 		return result;
@@ -275,14 +277,4 @@ public class Project {
 		}
 		return null;
 	}
-
-	/**
-	 * Validate the name input for a project name
-	 *
-	 * @param name project name to test
-	 * @return <code>true</code> valid
-	 */
-	public static boolean validateNameInput(String name) {
-		return !name.isEmpty() && !(ProjectReferenceManager.getProjects().contains(name));
-	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectReader.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectReader.java
index cf0f4f167bf250904c3ee9fd38ec4464bb7b6dc4..f0b8d677cc603959758b6febb58ec2d3680f0173 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectReader.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectReader.java
@@ -15,6 +15,9 @@ public interface ProjectReader {
 		ProfileReference getProfileReference() throws ProfileAbortException;
 
 		class ProfileAbortException extends Exception {
+			public ProfileAbortException() {
+				super("Profile is empty");
+			}
 		}
 	}
 
@@ -28,6 +31,8 @@ public interface ProjectReader {
 		void totalMedia(int size);
 
 		void finish();
+
+		void abort();
 	}
 
 	Project read(ProjectReference projectReference, ProjectReaderDelegate delegate) throws IOException, DocumentException, ProjectNotFoundException;
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSettingsSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSettingsSerializer.java
index 4a38e892796e66d995372389f2f956a074cd09c9..3b5607ea5f7f6d6ee8896d4d9ab609dfbb9f671c 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSettingsSerializer.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSettingsSerializer.java
@@ -18,14 +18,14 @@ class ProjectSettingsSerializer {
 	public static ProjectSettings load(Element element) {
 		ProjectSettings settings = new ProjectSettings();
 		if (element.element(COLUMNS_ELEMENT) != null)
-			settings.setColumns(Integer.valueOf(element.element(COLUMNS_ELEMENT).getStringValue()));
+			settings.setColumns(Integer.parseInt(element.element(COLUMNS_ELEMENT).getStringValue()));
 		if (element.element(ROWS_ELEMENT) != null)
-			settings.setRows(Integer.valueOf(element.element(ROWS_ELEMENT).getStringValue()));
+			settings.setRows(Integer.parseInt(element.element(ROWS_ELEMENT).getStringValue()));
 
 		Element mediaElement = element.element(MEDIA_PATH_ELEMENT);
 		if (mediaElement != null) {
 			settings.setMediaPath(Paths.get(mediaElement.getStringValue()));
-			settings.setUseMediaPath(Boolean.valueOf(mediaElement.attributeValue(MEDIA_PATH_ACTIVE_ATTR)));
+			settings.setUseMediaPath(Boolean.parseBoolean(mediaElement.attributeValue(MEDIA_PATH_ACTIVE_ATTR)));
 		}
 
 		return settings;
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSyncSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSyncSerializer.java
index efd05df2582cde1ed5ba5b66bf689dfd488c5e09..80bbb17c550d64a110085693b1d2723ee340bb22 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSyncSerializer.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSyncSerializer.java
@@ -40,10 +40,8 @@ public class ProjectSyncSerializer implements ProjectReader {
 
 			// Pad Settings
 			PadSettingsSerializer padSettingsSerializer = new PadSettingsSerializer();
-			for (Object pageObj : rootElement.elements(ProjectSerializer.PAGE_ELEMENT)) {
-				Element pageElement = (Element) pageObj;
-				for (Object padObj : pageElement.elements(ProjectSerializer.PAD_ELEMENT)) {
-					Element padElement = (Element) padObj;
+			for (Element pageElement : rootElement.elements(ProjectSerializer.PAGE_ELEMENT)) {
+				for (Element padElement : pageElement.elements(ProjectSerializer.PAD_ELEMENT)) {
 					Element settingsElement = padElement.element(PadSerializer.SETTINGS_ELEMENT);
 
 					UUID uuid = UUID.fromString(padElement.attributeValue(PadSerializer.UUID_ATTR));
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/export/ProjectExporter.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/export/ProjectExporter.java
index b1d80599b28dc6a3b571b307a5b9ff9add48c40d..80adc8c6f0f3b59026d07c27b67200ef2e0e4ebd 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/export/ProjectExporter.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/export/ProjectExporter.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.project.export;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.App;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
@@ -7,6 +8,7 @@ import de.thecodelabs.utils.io.FileUtils;
 import de.thecodelabs.utils.util.zip.ZipFile;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.mediapath.MediaPath;
+import de.tobias.playpad.pad.mediapath.MediaPool;
 import de.tobias.playpad.profile.ProfileNotFoundException;
 import de.tobias.playpad.profile.ref.ProfileReference;
 import de.tobias.playpad.project.Project;
@@ -25,6 +27,7 @@ import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Collection;
+import java.util.List;
 
 /**
  * Created by tobias on 11.03.17.
@@ -41,6 +44,8 @@ public class ProjectExporter {
 		ZipFile zip = new ZipFile(zipFile, ZipFile.FileMode.WRITE);
 
 		exportProject(zip, reference);
+		exportMediaPoolEntries(zip, reference);
+
 		if (includeProfile) {
 			exportProfile(zip, reference.getProfileReference());
 		}
@@ -67,8 +72,8 @@ public class ProjectExporter {
 			try {
 				XMLWriter writer = new XMLWriter(os, OutputFormat.createPrettyPrint());
 				writer.write(infoDocument);
-			} catch (Exception e) {
-				e.printStackTrace();
+			} catch (IOException e) {
+				Logger.error(e);
 			}
 		});
 	}
@@ -79,6 +84,28 @@ public class ProjectExporter {
 		zipFile.addFile(projectLocalPath, Paths.get(projectRef.getFileName()));
 	}
 
+	private void exportMediaPoolEntries(ZipFile zip, ProjectReference projectRef) throws IOException {
+		final List<MediaPath> paths = MediaPool.getInstance().getMediaPathsForProject(projectRef.getUuid());
+
+		Document document = DocumentHelper.createDocument();
+
+		Element rootElement = document.addElement("Paths");
+		for (MediaPath mediaPath : paths) {
+			rootElement.addElement("Path")
+					.addAttribute("uuid", String.valueOf(mediaPath.getId()))
+					.addAttribute("path", String.valueOf(mediaPath.getPath()));
+		}
+		zip.addFile(Paths.get("media.xml"), os ->
+		{
+			try {
+				XMLWriter writer = new XMLWriter(os, OutputFormat.createPrettyPrint());
+				writer.write(document);
+			} catch (IOException e) {
+				Logger.error(e);
+			}
+		});
+	}
+
 	private void exportProfile(ZipFile zip, ProfileReference reference) throws IOException {
 		App app = ApplicationUtils.getApplication();
 
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/importer/ConverterV6.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/importer/ConverterV6.java
deleted file mode 100644
index 6f978c21c190e4be43cc886e5cef72c9d6ae90bc..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/importer/ConverterV6.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package de.tobias.playpad.project.importer;
-
-import de.thecodelabs.utils.application.ApplicationUtils;
-import de.thecodelabs.utils.application.container.PathType;
-import de.tobias.playpad.project.ref.ProjectReference;
-import de.tobias.playpad.project.ref.ProjectReferenceManager;
-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;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Created by tobias on 25.02.17.
- */
-public class ConverterV6 {
-
-	private static final String CONTENT_TYPE_ATTR = "type";
-	private static final String CONTENT_PATHS_ELEMENT = "Paths";
-	private static final String CONTENT_PATH_ELEMENT = "Path";
-	private static final String CONTENT_PATH_UUID = "id";
-	private static final String CONTENT_PATH_PATH = "path";
-
-	public static void convert(UUID src, String name) throws IOException, DocumentException {
-		ProjectReference ref = new ProjectReference(src, name);
-
-		Path srcPath = ApplicationUtils.getApplication().getPath(PathType.DOCUMENTS).resolve("../../de.tobias.playpad.v6/Documents/" + src + ".xml");
-		Path desPath = ref.getProjectPath();
-		Files.copy(srcPath, desPath, StandardCopyOption.REPLACE_EXISTING);
-
-		SAXReader reader = new SAXReader();
-		Document document = reader.read(Files.newInputStream(desPath));
-		Element rootElement = document.getRootElement();
-		for (Object pageObj : rootElement.elements("Page")) {
-			Element pageElement = (Element) pageObj;
-			for (Object padObj : pageElement.elements("Pad")) {
-				Element padElement = (Element) padObj;
-				Element contentElement = padElement.element("Content");
-				if (contentElement != null) {
-					String type = contentElement.attributeValue("type");
-					String path = contentElement.getStringValue();
-
-					// Remove Old
-					padElement.remove(contentElement);
-
-					// Add New
-					contentElement = padElement.addElement("Content");
-					contentElement.addAttribute(CONTENT_TYPE_ATTR, type);
-
-					Element pathsElement = contentElement.addElement(CONTENT_PATHS_ELEMENT);
-
-					Element pathElement = pathsElement.addElement(CONTENT_PATH_ELEMENT);
-					pathElement.addAttribute(CONTENT_PATH_UUID, UUID.randomUUID().toString());
-					pathElement.addAttribute(CONTENT_PATH_PATH, path);
-				}
-			}
-		}
-		XMLWriter writer = new XMLWriter(Files.newOutputStream(desPath), OutputFormat.createPrettyPrint());
-		writer.write(document);
-		writer.close();
-	}
-
-	public static List<ProjectReference> loadProjectReferences() throws IOException, DocumentException {
-		List<ProjectReference> projects = new ArrayList<>();
-		Path projectReferencesPath = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION).resolve("../../de.tobias.playpad.v6/Config/Projects.xml");
-		if (Files.exists(projectReferencesPath)) {
-			SAXReader reader = new SAXReader();
-			Document document = reader.read(Files.newInputStream(projectReferencesPath));
-			for (Object object : document.getRootElement().elements(ProjectReferenceManager.PROJECT_ELEMENT)) {
-				if (object instanceof Element) {
-					Element element = (Element) object;
-
-					UUID uuid = UUID.fromString(element.attributeValue("uuid"));
-					String name = element.attributeValue("name");
-
-					ProjectReference ref = new ProjectReference(uuid, name);
-					projects.add(ref);
-				}
-			}
-		}
-		return projects;
-	}
-
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/importer/ProjectImporter.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/importer/ProjectImporter.java
index 06ed30f7c3539a97489a0339223a21a5aa5b0ae9..929439321f5774dd3bec635ffc13d37c5e7c155a 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/importer/ProjectImporter.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/importer/ProjectImporter.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.project.importer;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.App;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
@@ -11,7 +12,7 @@ import de.tobias.playpad.profile.ref.ProfileReference;
 import de.tobias.playpad.profile.ref.ProfileReferenceManager;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.ProjectNotFoundException;
-import de.tobias.playpad.project.ProjectReader;
+import de.tobias.playpad.project.ProjectReader.ProjectReaderDelegate.ProfileAbortException;
 import de.tobias.playpad.project.loader.ProjectLoader;
 import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.project.ref.ProjectReferenceManager;
@@ -25,13 +26,17 @@ import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.UUID;
+import java.util.*;
 
 /**
  * Created by tobias on 11.03.17.
  */
 public class ProjectImporter {
 
+	public static class ProjectImportCorruptedException extends Exception {
+
+	}
+
 	private ProjectImporterDelegate delegate;
 
 	private ZipFile zip;
@@ -47,13 +52,15 @@ public class ProjectImporter {
 
 	private ProjectReference importedProjectReference;
 
-	public ProjectImporter(Path zipFile, ProjectImporterDelegate delegate) throws IOException, DocumentException {
+	public ProjectImporter(Path zipFile, ProjectImporterDelegate delegate) throws IOException,
+			ProjectImportCorruptedException {
 		this.delegate = delegate;
 
 		loadZipFile(zipFile);
 	}
 
-	public void execute() throws IOException, ProjectNotFoundException, DocumentException, ProfileNotFoundException, ProjectReader.ProjectReaderDelegate.ProfileAbortException {
+	public void execute() throws IOException, ProjectNotFoundException, DocumentException, ProfileNotFoundException,
+			ProfileAbortException, ProjectImportCorruptedException {
 		if (includeProfile && delegate.shouldImportProfile()) {
 			importProfile();
 		}
@@ -61,45 +68,103 @@ public class ProjectImporter {
 		importedProjectReference = importProjectFile();
 
 		if (includeMedia && delegate.shouldImportMedia()) {
-			importMedia();
+			importMedia(loadMediaPaths());
+		} else {
+			replaceMediaPathIds(loadMediaPaths());
 		}
 	}
 
-	private void loadZipFile(Path zipFile) throws IOException, DocumentException {
+	private void loadZipFile(Path zipFile) throws IOException, ProjectImportCorruptedException {
 		zip = new ZipFile(zipFile, ZipFile.FileMode.READ);
 
-		App app = ApplicationUtils.getApplication();
-
-		// Load Zip Informations
+		// Load Zip meta information
 		InputStream infoInputStream = zip.inputStream("info.xml");
 		if (infoInputStream == null) {
-			// TODO Throw exception
+			throw new ProjectImportCorruptedException();
 		}
 
+		try {
+			SAXReader reader = new SAXReader();
+			Document document = reader.read(infoInputStream);
+			Element rootElement = document.getRootElement();
+
+			Element projectElement = rootElement.element("Project");
+			if (projectElement != null) {
+				projectUUID = UUID.fromString(projectElement.attributeValue("uuid"));
+				projectName = projectElement.attributeValue("name");
+			}
+
+			Element profileElement = rootElement.element("Profile");
+			if (profileElement != null) {
+				includeProfile = Boolean.parseBoolean(profileElement.attributeValue("export"));
+				profileUUID = UUID.fromString(profileElement.attributeValue("uuid"));
+				profileName = profileElement.attributeValue("name");
+			}
 
-		SAXReader reader = new SAXReader();
-		Document document = reader.read(infoInputStream);
-		Element rootElement = document.getRootElement();
+			Element mediaElement = rootElement.element("Media");
+			if (mediaElement != null) {
+				includeMedia = Boolean.parseBoolean(mediaElement.attributeValue("export"));
+			}
+		} catch (DocumentException e) {
+			throw new ProjectImportCorruptedException();
+		}
+	}
 
-		Element projectElement = rootElement.element("Project");
-		if (projectElement != null) {
-			projectUUID = UUID.fromString(projectElement.attributeValue("uuid"));
-			projectName = projectElement.attributeValue("name");
+	private List<MediaPath> loadMediaPaths() throws IOException, ProjectImportCorruptedException {
+		// Load Zip meta information
+		InputStream infoInputStream = zip.inputStream("media.xml");
+		if (infoInputStream == null) {
+			throw new ProjectImportCorruptedException();
 		}
 
-		Element profileElement = rootElement.element("Profile");
-		if (profileElement != null) {
-			includeProfile = Boolean.valueOf(profileElement.attributeValue("export"));
-			profileUUID = UUID.fromString(profileElement.attributeValue("uuid"));
-			profileName = profileElement.attributeValue("name");
+		try {
+			SAXReader reader = new SAXReader();
+			Document document = reader.read(infoInputStream);
+			Element rootElement = document.getRootElement();
+
+			List<MediaPath> mediaPathList = new ArrayList<>();
+
+			for (Element pathElement : rootElement.elements("Path")) {
+				UUID uuid = UUID.fromString(pathElement.attributeValue("uuid"));
+				Path path = Paths.get(pathElement.attributeValue("path"));
+
+				MediaPath mediaPath = new MediaPath(uuid, path, null);
+				mediaPathList.add(mediaPath);
+			}
+			return mediaPathList;
+		} catch (DocumentException e) {
+			throw new ProjectImportCorruptedException();
 		}
+	}
+
+	private void replaceMediaPathIds(List<MediaPath> mediaPaths) throws ProjectNotFoundException, ProfileAbortException,
+			ProfileNotFoundException, DocumentException, IOException {
+		ProjectLoader loader = new ProjectLoader(importedProjectReference);
+		loader.setLoadMedia(false);
+		Project project = loader.load();
 
-		Element mediaElement = rootElement.element("Media");
-		if (mediaElement != null) {
-			includeMedia = Boolean.valueOf(mediaElement.attributeValue("export"));
+		for (Pad pad : project.getPads()) {
+			Iterator<MediaPath> iterator = pad.getPaths().iterator();
+			while (iterator.hasNext()) {
+				MediaPath oldMediaPath = iterator.next();
+				find(mediaPaths, oldMediaPath.getId()).ifPresent(result -> {
+					try {
+						pad.removePathListener(oldMediaPath);
+						iterator.remove();
+
+						pad.setPath(result.getPath());
+					} catch (NullPointerException e) {
+						Logger.error("Import Error on Pad: " + pad.getUuid());
+					}
+				});
+			}
 		}
 	}
 
+	private Optional<MediaPath> find(List<MediaPath> mediaPaths, UUID id) {
+		return mediaPaths.parallelStream().filter(i -> i.getId().equals(id)).findFirst();
+	}
+
 	private ProjectReference importProjectFile() throws IOException {
 		String newProjectName = delegate.getProjectName();
 		boolean sync = delegate.shouldProjectSynced();
@@ -125,17 +190,17 @@ public class ProjectImporter {
 
 		Path localFolder = app.getPath(PathType.CONFIGURATION, localProfileUUID.toString());
 		Files.createDirectories(localFolder);
-		System.out.println("Create new profile for import: " + localProfileUUID);
+		Logger.info("Create new profile for import: " + localProfileUUID);
 
 		zip.stream().filter(entry -> entry.getName().startsWith(profileFolder.toString())).forEach(entry ->
 		{
-			String name = entry.getName().substring(entry.getName().lastIndexOf("/") + 1);
+			String name = entry.getName().substring(entry.getName().lastIndexOf('/') + 1);
 			try {
 				Path dest = app.getPath(PathType.CONFIGURATION, localProfileUUIDString, name);
 				zip.getFile(Paths.get(entry.getName()), dest);
-				System.out.println("Copied Profile Data: \"" + entry.getName() + "\" to location: " + dest);
+				Logger.info("Copied Profile Data: \"" + entry.getName() + "\" to location: " + dest);
 			} catch (Exception e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		});
 
@@ -145,25 +210,29 @@ public class ProjectImporter {
 		profileUUID = localProfileUUID; // Update Profile UUID with new local profile uuid
 	}
 
-	private void importMedia() throws ProjectNotFoundException, ProfileNotFoundException, DocumentException, IOException, ProjectReader.ProjectReaderDelegate.ProfileAbortException {
+	private void importMedia(List<MediaPath> mediaPaths) throws ProjectNotFoundException, ProfileNotFoundException, DocumentException,
+			IOException, ProfileAbortException {
 		Path folder = delegate.getMediaPath();
 
 		ProjectLoader loader = new ProjectLoader(importedProjectReference);
 		loader.setLoadMedia(false);
-		loader.setLoadMedia(false);
 		Project project = loader.load();
 
 		for (Pad pad : project.getPads()) {
 			for (MediaPath path : pad.getPaths()) {
-				Path fileName = path.getPath().getFileName();
-				Path zipMediaFile = Paths.get("/media").resolve(fileName);
-				Path newMediaPath = folder.resolve(fileName);
+				Optional<MediaPath> result = find(mediaPaths, path.getId());
+
+				if (result.isPresent()) {
+					String fileName = result.get().getFileName();
+					Path zipMediaFile = Paths.get("/media").resolve(fileName);
+					Path newMediaPath = folder.resolve(fileName);
 
-				zip.getFile(zipMediaFile, newMediaPath);
-				path.setPath(newMediaPath, false);
+					zip.getFile(zipMediaFile, newMediaPath);
+					path.setPath(newMediaPath, false);
+				}
 			}
 		}
-		ProjectReferenceManager.saveProject(project);
+		ProjectReferenceManager.saveSingleProject(project);
 	}
 
 	public ProjectReference getProjectReference() {
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/loader/ProjectLoader.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/loader/ProjectLoader.java
index 2afaf44ecb44bc02f9ec9082afbd15d1b717e094..fb19d091fcd0b23f261ad92e35f7df264616236b 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/loader/ProjectLoader.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/loader/ProjectLoader.java
@@ -90,7 +90,14 @@ public class ProjectLoader {
 		if (listener != null)
 			listener.startReadProject();
 
-		Project project = loadProjectImpl(projectReference, delegate);
+		Project project;
+		try {
+			project = loadProjectImpl(projectReference, delegate);
+		} catch (IOException | DocumentException | ProjectNotFoundException e) {
+			if (listener != null)
+				listener.abort();
+			throw e;
+		}
 
 		if (listener != null)
 			listener.finishReadProject();
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/page/PadIndex.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/page/PadIndex.java
index 430d62c87d15739748a26b33662a2887f2d7f327..b8963f7338961defb4f5d8d9b1a1f9f5c0f1a3e9 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/page/PadIndex.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/page/PadIndex.java
@@ -8,10 +8,9 @@ import java.io.Serializable;
  * @author tobias
  * @since 6.0.0
  */
+// Serializable is for Pad Drag and Drop necessary
 public class PadIndex implements Serializable {
 
-	private static final long serialVersionUID = 2026743397726990321L;
-
 	private final int id;
 	private final int page;
 
@@ -53,7 +52,7 @@ public class PadIndex implements Serializable {
 
 	@Override
 	public String toString() {
-		return id + "-" + page;
+		return String.valueOf(id);
 	}
 
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/page/Page.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/page/Page.java
index 28e271d7fb862d9737bf89109fd50f49a1aef5a4..36d9b1d04b488322ad2d1449ca2025ea244e268b 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/page/Page.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/page/Page.java
@@ -16,7 +16,7 @@ import java.util.*;
  * @author tobias
  * @since 6.0.0
  */
-public class Page implements Cloneable {
+public class Page {
 
 	private UUID id;
 	private IntegerProperty positionProperty;
@@ -229,7 +229,8 @@ public class Page implements Cloneable {
 	/**
 	 * Removes a pad from a page and from the cloud.
 	 *
-	 * @param uuid id of the pad
+	 * @param uuid         id of the pad
+	 * @param deleteRemote <code>true</code> delete from remote
 	 */
 	public void removePad(UUID uuid, boolean deleteRemote) {
 		if (projectReference.getProjectReference().isSync() && deleteRemote) {
@@ -248,9 +249,8 @@ public class Page implements Cloneable {
 		return "Page [positionProperty=" + positionProperty + "]";
 	}
 
-	@Override
-	public Page clone() throws CloneNotSupportedException {
-		Page clone = (Page) super.clone();
+	public Page copy() {
+		Page clone = new Page(getPosition(), projectReference);
 		clone.id = UUID.randomUUID();
 		clone.positionProperty = new SimpleIntegerProperty(getPosition());
 		clone.nameProperty = new SimpleStringProperty(getName());
@@ -264,7 +264,7 @@ public class Page implements Cloneable {
 
 		clone.pads = new HashSet<>();
 		for (Pad pad : pads) {
-			Pad padClone = pad.clone(clone);
+			Pad padClone = pad.copy(clone);
 			clone.pads.add(padClone);
 		}
 		return clone;
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/page/PageCoordinate.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/page/PageCoordinate.java
new file mode 100644
index 0000000000000000000000000000000000000000..22ac3dc05068e36420667166f11c054082ffcd90
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/page/PageCoordinate.java
@@ -0,0 +1,28 @@
+package de.tobias.playpad.project.page;
+
+public class PageCoordinate {
+
+	private final int x;
+	private final int y;
+
+	public PageCoordinate(int x, int y) {
+		this.x = x;
+		this.y = y;
+	}
+
+	public int getX() {
+		return x;
+	}
+
+	public int getY() {
+		return y;
+	}
+
+	@Override
+	public String toString() {
+		return "PageCoordinate{" +
+				"x=" + x +
+				", y=" + y +
+				'}';
+	}
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/page/PageSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/page/PageSerializer.java
index cb9bef03b88a9d853f589264d66fa8f78edac5c6..90f2d16482fa3ea63dd206c1c46530b11f32241a 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/page/PageSerializer.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/page/PageSerializer.java
@@ -31,7 +31,7 @@ public class PageSerializer implements XMLSerializer<Page>, XMLDeserializer<Page
 
 	@Override
 	public Page loadElement(Element element) {
-		int id = Integer.valueOf(element.attributeValue(POSITION_ATTR));
+		int id = Integer.parseInt(element.attributeValue(POSITION_ATTR));
 		String name = element.attributeValue(NAME_ATTR);
 
 		String uuidValue = element.attributeValue(UUID_ATTR);
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/ref/ProjectReferenceManager.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/ref/ProjectReferenceManager.java
index 839ad9c7e91e42e2a45affd1cd60b57722df0cdf..3d2b5c6f255b617e8a202cf53bc207f333444c28 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/ref/ProjectReferenceManager.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/ref/ProjectReferenceManager.java
@@ -5,9 +5,14 @@ import de.thecodelabs.storage.xml.XMLHandler;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
 import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.pad.mediapath.MediaPool;
 import de.tobias.playpad.profile.ProfileNotFoundException;
 import de.tobias.playpad.profile.ref.ProfileReference;
-import de.tobias.playpad.project.*;
+import de.tobias.playpad.project.Project;
+import de.tobias.playpad.project.ProjectNotFoundException;
+import de.tobias.playpad.project.ProjectReader.ProjectReaderDelegate.ProfileAbortException;
+import de.tobias.playpad.project.ProjectSerializer;
+import de.tobias.playpad.project.ProjectWriter;
 import de.tobias.playpad.project.loader.ProjectLoader;
 import de.tobias.playpad.server.LoginException;
 import de.tobias.playpad.server.Server;
@@ -55,7 +60,7 @@ public final class ProjectReferenceManager {
 		return null;
 	}
 
-	public static void saveProject(Project project) throws IOException {
+	public static void saveSingleProject(Project project) throws IOException {
 		ProjectWriter writer = new ProjectSerializer();
 		writer.write(project);
 	}
@@ -74,7 +79,7 @@ public final class ProjectReferenceManager {
 		Project project = new Project(ref);
 
 		// Save To Disk
-		saveProject(project);
+		saveSingleProject(project);
 
 		// Save To Cloud
 		if (ref.isSync()) {
@@ -103,8 +108,12 @@ public final class ProjectReferenceManager {
 	public static void removeProject(ProjectReference projectReference) throws IOException {
 		Path path = ApplicationUtils.getApplication().getPath(PathType.DOCUMENTS, projectReference.getUuid() + Project.FILE_EXTENSION);
 
+		// Remove media db entries
+		MediaPool.getInstance().deleteEntries(projectReference.getUuid());
+
 		Files.deleteIfExists(path); // Drive
 		projects.remove(projectReference); // Model
+
 		if (projectReference.isSync()) {
 			CommandManager.execute(Commands.PROJECT_REMOVE, projectReference, projectReference); // Cloud
 		}
@@ -230,7 +239,7 @@ public final class ProjectReferenceManager {
 		return items;
 	}
 
-	public static void setSync(ProjectReference reference, boolean newValue) throws ProjectNotFoundException, ProfileNotFoundException, DocumentException, IOException, ProjectReader.ProjectReaderDelegate.ProfileAbortException {
+	public static void setSync(ProjectReference reference, boolean newValue) throws ProjectNotFoundException, ProfileNotFoundException, DocumentException, IOException, ProfileAbortException {
 		if (newValue) {
 			ProjectLoader loader = new ProjectLoader(reference);
 			Project project = loader.load();
@@ -247,7 +256,9 @@ public final class ProjectReferenceManager {
 	}
 
 	public static boolean validateProjectName(ProjectReference reference, String newValue) {
-		return getProjects().stream().filter(r -> r != reference).noneMatch(p -> p.getName().equals(newValue));
+		return getProjects().stream()
+				.filter(r -> r != reference)
+				.noneMatch(p -> p.getName().equals(newValue));
 	}
 
 	public static boolean validateProjectName(String newValue) {
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/ref/ProjectReferenceSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/ref/ProjectReferenceSerializer.java
index a3e930f854adf344b15adb382c9b3d36f1149472..cead727fb85a92b7c0bef4c705b8158ae74908bd 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/ref/ProjectReferenceSerializer.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/ref/ProjectReferenceSerializer.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.project.ref;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.storage.xml.XMLDeserializer;
 import de.thecodelabs.storage.xml.XMLHandler;
 import de.thecodelabs.storage.xml.XMLSerializer;
@@ -36,8 +37,8 @@ public class ProjectReferenceSerializer implements XMLDeserializer<ProjectRefere
 		if (element.attributeValue(PROFILE_ATTR) != null) {
 			profile = UUID.fromString(element.attributeValue(PROFILE_ATTR));
 		}
-		boolean sync = Boolean.valueOf(element.attributeValue(SYNC_ATTR));
-		long lastModified = Long.valueOf(element.attributeValue(LAST_MODIFIED_ATTR));
+		boolean sync = Boolean.parseBoolean(element.attributeValue(SYNC_ATTR));
+		long lastModified = Long.parseLong(element.attributeValue(LAST_MODIFIED_ATTR));
 
 		XMLHandler<Module> handler = new XMLHandler<>(element);
 		Set<Module> modules = new HashSet<>(handler.loadElements(MODULE_ELEMENT, new ModuleSerializer()));
@@ -50,7 +51,7 @@ public class ProjectReferenceSerializer implements XMLDeserializer<ProjectRefere
 			try {
 				ref.setLastModified(Files.getLastModifiedTime(projectPath).toMillis());
 			} catch (IOException e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		}
 		return ref;
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/registry/ComponentRegistry.java b/PlayWallCore/src/main/java/de/tobias/playpad/registry/ComponentRegistry.java
index aa18241da9d89f30f9649cf89c6db07ba13971a7..2a1d4f9ffdd6fe3536c240aff10024676b06087d 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/registry/ComponentRegistry.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/registry/ComponentRegistry.java
@@ -88,36 +88,33 @@ public class ComponentRegistry<C extends Component> implements Registry<C> {
 			Document document = reader.read(url);
 
 			Element rootElement = document.getRootElement();
-			for (Object obj : rootElement.elements("Component")) {
-				if (obj instanceof Element) {
-					Element element = (Element) obj;
-					String type = element.attributeValue("id");
-
-					// Find the class of the type
-					@SuppressWarnings("unchecked") Class<C> clazz = (Class<C>) loader.loadClass(element.getStringValue().trim());
-					Constructor<C> constructor = clazz.getConstructor(String.class);
-					C factory = constructor.newInstance(type);
-
-					// setup Displayable
-					if (element.attributeValue("name") != null) {
-						String name = element.attributeValue("name");
-						String localizedName = resourceBundle.getString(name);
-						factory.setName(localizedName);
-					}
+			for (Element element : rootElement.elements("Component")) {
+				String type = element.attributeValue("id");
+
+				// Find the class of the type
+				@SuppressWarnings("unchecked") Class<C> clazz = (Class<C>) loader.loadClass(element.getStringValue().trim());
+				Constructor<C> constructor = clazz.getConstructor(String.class);
+				C factory = constructor.newInstance(type);
+
+				// setup Displayable
+				if (element.attributeValue("name") != null) {
+					String name = element.attributeValue("name");
+					String localizedName = resourceBundle.getString(name);
+					factory.setName(localizedName);
+				}
 
-					if (element.attributeValue("icon") != null && element.attributeValue("class") != null && element.attributeValue("size") != null) {
-						String icon = element.attributeValue("icon");
-						Class iconClass = Class.forName(element.attributeValue("class"));
-						int size = Integer.valueOf(element.attributeValue("size"));
-						Object iconObj = Enum.valueOf(iconClass, icon);
-						if (iconObj instanceof FontIconType) {
-							FontIconType iconType = (FontIconType) iconObj;
-							factory.setGraphics(iconType, size);
-						}
+				if (element.attributeValue("icon") != null && element.attributeValue("class") != null && element.attributeValue("size") != null) {
+					String icon = element.attributeValue("icon");
+					Class iconClass = Class.forName(element.attributeValue("class"));
+					int size = Integer.parseInt(element.attributeValue("size"));
+					Object iconObj = Enum.valueOf(iconClass, icon);
+					if (iconObj instanceof FontIconType) {
+						FontIconType iconType = (FontIconType) iconObj;
+						factory.setGraphics(iconType, size);
 					}
-
-					registerComponent(factory, module);
 				}
+
+				registerComponent(factory, module);
 			}
 		} catch (Exception e) {
 			throw new RuntimeException(e);
@@ -126,7 +123,12 @@ public class ComponentRegistry<C extends Component> implements Registry<C> {
 
 	@Override
 	public Module getModule(String id) {
-		return components.get(id).module;
+		final Item<C> item = components.get(id);
+		if (item == null) {
+			Logger.warning("No module found for id: {0}", id);
+			return null;
+		}
+		return item.module;
 	}
 
 
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/registry/DefaultComponentRegistry.java b/PlayWallCore/src/main/java/de/tobias/playpad/registry/DefaultComponentRegistry.java
index 7aee007b21662e747f8df94dc68fbe754b3c3247..c366fe5f0a960c780b74850e9d41f3204067e085 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/registry/DefaultComponentRegistry.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/registry/DefaultComponentRegistry.java
@@ -63,41 +63,38 @@ public class DefaultComponentRegistry<F extends Component> extends ComponentRegi
 			Document document = reader.read(url);
 
 			Element rootElement = document.getRootElement();
-			for (Object obj : rootElement.elements("Component")) {
-				if (obj instanceof Element) {
-					Element element = (Element) obj;
-					String type = element.attributeValue("id");
-
-					// Find the class of the type
-					@SuppressWarnings("unchecked") Class<F> clazz = (Class<F>) loader.loadClass(element.getStringValue().trim());
-					Constructor<F> constructor = clazz.getConstructor(String.class);
-					F factory = constructor.newInstance(type);
-
-					registerComponent(factory, module);
-
-					if (element.attributeValue("default") != null) {
-						String defaultValue = element.attributeValue("default");
-						if (defaultValue.equals("true")) {
-							setDefault(factory);
-						}
-					}
+			for (Element element : rootElement.elements("Component")) {
+				String type = element.attributeValue("id");
+
+				// Find the class of the type
+				@SuppressWarnings("unchecked") Class<F> clazz = (Class<F>) loader.loadClass(element.getStringValue().trim());
+				Constructor<F> constructor = clazz.getConstructor(String.class);
+				F factory = constructor.newInstance(type);
+
+				registerComponent(factory, module);
 
-					// setup Displayable
-					if (element.attributeValue("name") != null) {
-						String name = element.attributeValue("name");
-						String localizedName = resourceBundle.getString(name);
-						factory.setName(localizedName);
+				if (element.attributeValue("default") != null) {
+					String defaultType = element.attributeValue("default");
+					if (defaultType.equals("true")) {
+						setDefault(factory);
 					}
+				}
+
+				// setup Displayable
+				if (element.attributeValue("name") != null) {
+					String name = element.attributeValue("name");
+					String localizedName = resourceBundle.getString(name);
+					factory.setName(localizedName);
+				}
 
-					if (element.attributeValue("icon") != null && element.attributeValue("class") != null && element.attributeValue("size") != null) {
-						String icon = element.attributeValue("icon");
-						Class iconClass = Class.forName(element.attributeValue("class"));
-						int size = Integer.valueOf(element.attributeValue("size"));
-						Object iconObj = Enum.valueOf(iconClass, icon);
-						if (iconObj instanceof FontIconType) {
-							FontIconType iconType = (FontIconType) iconObj;
-							factory.setGraphics(iconType, size);
-						}
+				if (element.attributeValue("icon") != null && element.attributeValue("class") != null && element.attributeValue("size") != null) {
+					String icon = element.attributeValue("icon");
+					Class iconClass = Class.forName(element.attributeValue("class"));
+					int size = Integer.parseInt(element.attributeValue("size"));
+					Object iconObj = Enum.valueOf(iconClass, icon);
+					if (iconObj instanceof FontIconType) {
+						FontIconType iconType = (FontIconType) iconObj;
+						factory.setGraphics(iconType, size);
 					}
 				}
 			}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/registry/NoSuchComponentException.java b/PlayWallCore/src/main/java/de/tobias/playpad/registry/NoSuchComponentException.java
index 7f33c5a619d12c431b12473238585e701eafe11a..d1c83ba9468d73c0a1bf55163b58d12574b3963d 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/registry/NoSuchComponentException.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/registry/NoSuchComponentException.java
@@ -7,4 +7,8 @@ public class NoSuchComponentException extends RuntimeException {
 	public NoSuchComponentException(String id) {
 		super("No component for id: " + id);
 	}
+
+	public NoSuchComponentException(Throwable cause) {
+		super(cause);
+	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/Server.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/Server.java
index 16ea6b42364d7b1149f26debfdd9dd3137957466..0b71f4248eba6110c1ce64a6137ddd9e891577ce 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/server/Server.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/server/Server.java
@@ -59,6 +59,8 @@ public interface Server {
 	 * @param username username
 	 * @param password password
 	 * @return session key
+	 * @throws IOException    server communication error
+	 * @throws LoginException login error
 	 */
 	String getSession(String username, String password) throws IOException, LoginException;
 
@@ -68,7 +70,8 @@ public interface Server {
 	 * Get a list of the synced projects.
 	 *
 	 * @return synced projects
-	 * @throws IOException notwork error
+	 * @throws IOException    notwork error
+	 * @throws LoginException login error
 	 */
 	List<ProjectReference> getSyncedProjects() throws IOException, LoginException;
 
@@ -94,6 +97,7 @@ public interface Server {
 	 *
 	 * @param projectReference project reference
 	 * @return last modification
+	 * @throws IOException server communication error
 	 */
 	Version getLastServerModification(ProjectReference projectReference) throws IOException;
 
@@ -101,6 +105,8 @@ public interface Server {
 	 * Connect to sync server with key.
 	 *
 	 * @param key auth key
+	 * @throws IOException        server communication error
+	 * @throws WebSocketException error creating websocket connection
 	 */
 	void connect(String key) throws IOException, WebSocketException;
 
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/SessionNotExisitsException.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/SessionNotExisitsException.java
deleted file mode 100644
index f01363135f377103ee66740198653c6f48e0f2e6..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/server/SessionNotExisitsException.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package de.tobias.playpad.server;
-
-public class SessionNotExisitsException extends Exception {
-	public SessionNotExisitsException() {
-		super("Session invalid");
-	}
-
-	public SessionNotExisitsException(String message) {
-		super(message);
-	}
-}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/SessionNotExistsException.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/SessionNotExistsException.java
new file mode 100644
index 0000000000000000000000000000000000000000..304e8fd438a8fc57d93483093de99e7ed7ac0ee7
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/server/SessionNotExistsException.java
@@ -0,0 +1,11 @@
+package de.tobias.playpad.server;
+
+public class SessionNotExistsException extends Exception {
+	public SessionNotExistsException() {
+		super("Session invalid");
+	}
+
+	public SessionNotExistsException(String message) {
+		super(message);
+	}
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/PropertyDef.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/PropertyDef.java
index a591b605e20c6d3a8ebaacdd4f6b294a5f7f829f..014a2e80cb3f59977d3299a1a028646dd25264ed 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/PropertyDef.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/PropertyDef.java
@@ -4,6 +4,10 @@ package de.tobias.playpad.server.sync;
  * Created by tobias on 19.02.17.
  */
 public class PropertyDef {
+
+	private PropertyDef() {
+	}
+
 	public static final String ID = "id";
 	public static final String CMD = "cmd";
 	public static final String TIME = "time";
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/ServerUtils.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/ServerUtils.java
index 3a28f2e1b2cf2ba05cd557713d994caf3934b194..47e0a643100871e1be91128a0ff4d6c2e8e8691f 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/ServerUtils.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/ServerUtils.java
@@ -1,11 +1,16 @@
 package de.tobias.playpad.server.sync;
 
+import de.thecodelabs.logger.Logger;
 import de.tobias.playpad.server.sync.listener.ServerListener;
 
 /**
  * Created by tobias on 19.02.17.
  */
 public class ServerUtils {
+
+	private ServerUtils() {
+	}
+
 	public static boolean isNewValueComingFromServer() {
 		StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
 		for (StackTraceElement element : stackTrace) {
@@ -17,7 +22,7 @@ public class ServerUtils {
 					}
 				}
 			} catch (Exception e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		}
 		return false;
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/command/Command.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/command/Command.java
index ea76d4f7369a23d43e1334157abca2b298ebeb8e..7faab034a53d6d878a66a3666315ae6eb81bc311 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/command/Command.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/command/Command.java
@@ -11,6 +11,7 @@ public interface Command {
 	 * Execute a command.
 	 *
 	 * @param data optional data parameter
+	 * @return response to communication peer
 	 */
 	JsonObject execute(Object data);
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/command/CommandManager.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/command/CommandManager.java
index 61900d919356a5910300b6d82c9e52c1fe8eaf41..94ece2443a483218a6d9cdefc33600ca0686c4cc 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/command/CommandManager.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/command/CommandManager.java
@@ -14,6 +14,9 @@ public class CommandManager {
 		executor = PlayPadPlugin.getCommandExecutorHandler().getCommandExecutor();
 	}
 
+	private CommandManager() {
+	}
+
 	public static void register(String name, Command command) {
 		executor.register(name, command);
 	}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/command/Commands.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/command/Commands.java
index cba55e29db2fa0deb16798c550e93bff75f84205..2376f18a6551408fc92abdf3bead24c1fc353a17 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/command/Commands.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/command/Commands.java
@@ -4,6 +4,10 @@ package de.tobias.playpad.server.sync.command;
  * Created by tobias on 19.02.17.
  */
 public class Commands {
+
+	private Commands() {
+	}
+
 	public static final String PROJECT_ADD = "pro-add";
 	public static final String PROJECT_UPDATE = "pro-update";
 	public static final String PROJECT_REMOVE = "pro-rm";
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/conflict/ConflictSolver.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/conflict/ConflictSolver.java
index 4055ca2c7eb7fda22806f2167bf85187322956fb..e01c73a8fe4e1b4ae696146cb1581bb7cab5bc1c 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/conflict/ConflictSolver.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/conflict/ConflictSolver.java
@@ -21,6 +21,11 @@ public interface ConflictSolver {
 	 * @param executor command executor
 	 * @param project  project
 	 * @param type     strategy type
+	 * @throws IOException                                               server communication error
+	 * @throws ProjectNotFoundException                                  Project to solve error not found
+	 * @throws ProfileNotFoundException                                  Profile of project not found
+	 * @throws DocumentException                                         XML Error
+	 * @throws ProjectReader.ProjectReaderDelegate.ProfileAbortException Profile Choose aborted
 	 */
 	void solveConflict(CommandExecutor executor, ProjectReference project, ConflictStrategyType type) throws ProjectNotFoundException, ProfileNotFoundException, DocumentException, IOException, ProjectReader.ProjectReaderDelegate.ProfileAbortException;
 
@@ -30,6 +35,7 @@ public interface ConflictSolver {
 	 * @param executor  command executor
 	 * @param reference project reference
 	 * @return conflict type
+	 * @throws IOException server communication error
 	 */
 	ConflictType checkConflict(CommandExecutor executor, ProjectReference reference) throws IOException;
 
@@ -38,6 +44,7 @@ public interface ConflictSolver {
 	 *
 	 * @param reference project reference
 	 * @return list of versions
+	 * @throws IOException server communication error
 	 */
 	List<Version> getVersions(ProjectReference reference) throws IOException;
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/conflict/ConflictType.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/conflict/ConflictType.java
index ce9dd337cad61deb5a0947193ad19861141d73fc..36b91f5e5e49b0b2288ed22ea3165e86f0eddae6 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/conflict/ConflictType.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/conflict/ConflictType.java
@@ -7,5 +7,5 @@ public enum ConflictType {
 	LOCAL_CHANGES,
 	SERVER_CHANGES,
 	BOTH_CHANGES,
-	NON;
+	NONE
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/listener/downstream/project/ProjectAddListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/listener/downstream/project/ProjectAddListener.java
index fc6500a4a3d3872dfedb1d684e5674c6e1518504..4e6eb15093cbc0d9dfae8c648d01f3e122e29b0a 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/listener/downstream/project/ProjectAddListener.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/listener/downstream/project/ProjectAddListener.java
@@ -2,6 +2,7 @@ package de.tobias.playpad.server.sync.listener.downstream.project;
 
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
+import de.thecodelabs.logger.Logger;
 import de.tobias.playpad.project.ref.ProjectReferenceManager;
 import de.tobias.playpad.server.sync.PropertyDef;
 import de.tobias.playpad.server.sync.listener.ServerListener;
@@ -24,7 +25,7 @@ public class ProjectAddListener implements ServerListener {
 			try {
 				ProjectReferenceManager.addProject(name, null, true);
 			} catch (IOException e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		}
 	}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/listener/downstream/project/ProjectRemoveListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/listener/downstream/project/ProjectRemoveListener.java
index 0ec40d9f5cbac1e50442924cb65290a429e4cd99..c4bddd767496a023972d287786ee7d19bb4d6f78 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/listener/downstream/project/ProjectRemoveListener.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/listener/downstream/project/ProjectRemoveListener.java
@@ -2,6 +2,7 @@ package de.tobias.playpad.server.sync.listener.downstream.project;
 
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
+import de.thecodelabs.logger.Logger;
 import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.project.ref.ProjectReferenceManager;
 import de.tobias.playpad.server.sync.PropertyDef;
@@ -24,7 +25,7 @@ public class ProjectRemoveListener implements ServerListener {
 			try {
 				ProjectReferenceManager.removeProject(ref);
 			} catch (IOException e) {
-				e.printStackTrace();
+				Logger.error(e);
 			}
 		}
 	}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/listener/upstream/ProjectUpdateListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/listener/upstream/ProjectUpdateListener.java
index 5ae6a807aa3bbda588d216d867cafa11c7d7915f..6b225653d2ebc7b3144392ec98ea20e789ca5990 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/listener/upstream/ProjectUpdateListener.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/server/sync/listener/upstream/ProjectUpdateListener.java
@@ -20,8 +20,8 @@ public class ProjectUpdateListener {
 		this.project = project;
 
 		nameListener = (observable, oldValue, newValue) -> {
-			Change change = new Change(PropertyDef.PAGE_POSITION, newValue, project);
-			CommandManager.execute(Commands.PAGE_UPDATE, project.getProjectReference(), change);
+			Change change = new Change(PropertyDef.PROJECT_NAME, newValue, project);
+			CommandManager.execute(Commands.PROJECT_UPDATE, project.getProjectReference(), change);
 		};
 	}
 
@@ -36,6 +36,6 @@ public class ProjectUpdateListener {
 
 	public void removeListener() {
 		added = false;
-		project.getProjectReference().nameProperty().addListener(nameListener);
+		project.getProjectReference().nameProperty().removeListener(nameListener);
 	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java b/PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java
index 7945d9253f1e9b849ac1bd00a66fb0ff6844a40a..4b30a96f2101acc9136fb218a92918d1edea5a69 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.settings;
 
+import de.thecodelabs.logger.Logger;
 import de.tobias.playpad.pad.PadSettings;
 import de.tobias.playpad.profile.ProfileSettings;
 import javafx.util.Duration;
@@ -136,20 +137,20 @@ public class Fade {
 
 			Element fadeInElement = container.element(FADE_IN);
 			if (fadeInElement.attributeValue(ON_PAUSE_ATTR) != null)
-				fade.setFadeInStart(Boolean.valueOf(fadeInElement.attributeValue(ON_START_ATTR)));
+				fade.setFadeInStart(Boolean.parseBoolean(fadeInElement.attributeValue(ON_START_ATTR)));
 			if (fadeInElement.attributeValue(ON_STOP_ATTR) != null)
-				fade.setFadeInPause(Boolean.valueOf(fadeInElement.attributeValue(ON_PAUSE_ATTR)));
+				fade.setFadeInPause(Boolean.parseBoolean(fadeInElement.attributeValue(ON_PAUSE_ATTR)));
 			fade.setFadeIn(Duration.valueOf(fadeInElement.getStringValue().replace(" ", "")));
 
 			Element fadeOutElement = container.element(FADE_OUT);
 			if (fadeOutElement.attributeValue(ON_PAUSE_ATTR) != null)
-				fade.setFadeOutPause(Boolean.valueOf(fadeOutElement.attributeValue(ON_PAUSE_ATTR)));
+				fade.setFadeOutPause(Boolean.parseBoolean(fadeOutElement.attributeValue(ON_PAUSE_ATTR)));
 			if (fadeOutElement.attributeValue(ON_STOP_ATTR) != null)
-				fade.setFadeOutStop(Boolean.valueOf(fadeOutElement.attributeValue(ON_STOP_ATTR)));
+				fade.setFadeOutStop(Boolean.parseBoolean(fadeOutElement.attributeValue(ON_STOP_ATTR)));
 			fade.setFadeOut(Duration.valueOf(fadeOutElement.getStringValue().replace(" ", "")));
 			return fade;
 		} catch (Exception e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 		return null;
 	}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/settings/GlobalSettings.java b/PlayWallCore/src/main/java/de/tobias/playpad/settings/GlobalSettings.java
index 13818213614d4923163a7b463d9974dd5c238860..11820aa886ed7e11ebc5ebd4b7a551d81ccfe0fd 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/settings/GlobalSettings.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/settings/GlobalSettings.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.settings;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
 import de.tobias.playpad.PlayPad;
@@ -28,6 +29,8 @@ import static de.thecodelabs.versionizer.service.UpdateService.RepositoryType;
  */
 public class GlobalSettings {
 
+	public static final String FILE_NAME = "GlobalSettings.xml";
+
 	private Path savePath;
 
 	// Key Binding
@@ -183,11 +186,11 @@ public class GlobalSettings {
 				Element root = document.getRootElement();
 
 				if (root.element(AUTO_UPDATE_ELEMENT) != null) {
-					settings.setAutoUpdate(Boolean.valueOf(root.element(AUTO_UPDATE_ELEMENT).getStringValue()));
+					settings.setAutoUpdate(Boolean.parseBoolean(root.element(AUTO_UPDATE_ELEMENT).getStringValue()));
 				}
 
 				if (root.element(IGNORE_UPDATE_ELEMENT) != null) {
-					settings.setIgnoreUpdate(Boolean.valueOf(root.element(IGNORE_UPDATE_ELEMENT).getStringValue()));
+					settings.setIgnoreUpdate(Boolean.parseBoolean(root.element(IGNORE_UPDATE_ELEMENT).getStringValue()));
 				}
 
 				if (root.element(UPDATE_CHANNEL_ELEMENT) != null) {
@@ -195,24 +198,24 @@ public class GlobalSettings {
 						final RepositoryType repositoryType = RepositoryType.valueOf(root.element(UPDATE_CHANNEL_ELEMENT).getStringValue());
 						settings.setUpdateChannel(repositoryType);
 					} catch (IllegalArgumentException e) {
-						e.printStackTrace();
+						Logger.error(e);
 					}
 				}
 
 				Element liveElement = root.element(LIVE_MODE_ELEMENT);
 				if (liveElement != null) {
-					settings.setLiveMode(Boolean.valueOf(liveElement.getStringValue()));
+					settings.setLiveMode(Boolean.parseBoolean(liveElement.getStringValue()));
 					if (liveElement.attributeValue(LIVE_MODE_PAGE_ATTR) != null) {
-						settings.setLiveModePage(Boolean.valueOf(liveElement.attributeValue(LIVE_MODE_PAGE_ATTR)));
+						settings.setLiveModePage(Boolean.parseBoolean(liveElement.attributeValue(LIVE_MODE_PAGE_ATTR)));
 					}
 					if (liveElement.attributeValue(LIVE_MODE_DRAG_ATTR) != null) {
-						settings.setLiveModeDrag(Boolean.valueOf(liveElement.attributeValue(LIVE_MODE_DRAG_ATTR)));
+						settings.setLiveModeDrag(Boolean.parseBoolean(liveElement.attributeValue(LIVE_MODE_DRAG_ATTR)));
 					}
 					if (liveElement.attributeValue(LIVE_MODE_FILE_ATTR) != null) {
-						settings.setLiveModeFile(Boolean.valueOf(liveElement.attributeValue(LIVE_MODE_FILE_ATTR)));
+						settings.setLiveModeFile(Boolean.parseBoolean(liveElement.attributeValue(LIVE_MODE_FILE_ATTR)));
 					}
 					if (liveElement.attributeValue(LIVE_MODE_SETTINGS_ATTR) != null) {
-						settings.setLiveModeSettings(Boolean.valueOf(liveElement.attributeValue(LIVE_MODE_SETTINGS_ATTR)));
+						settings.setLiveModeSettings(Boolean.parseBoolean(liveElement.attributeValue(LIVE_MODE_SETTINGS_ATTR)));
 					}
 				}
 
@@ -222,12 +225,12 @@ public class GlobalSettings {
 
 				// Dialogs
 				if (root.element(IGNORE_SAVE_DIALOG_ELEMENT) != null) {
-					settings.setIgnoreSaveDialog(Boolean.valueOf(root.element(IGNORE_SAVE_DIALOG_ELEMENT).getStringValue()));
+					settings.setIgnoreSaveDialog(Boolean.parseBoolean(root.element(IGNORE_SAVE_DIALOG_ELEMENT).getStringValue()));
 				}
 
 				// Behaviour
 				if (root.element(OPEN_LAST_DOCUMENT_ELEMENT) != null) {
-					settings.setOpenLastDocument(Boolean.valueOf(root.element(OPEN_LAST_DOCUMENT_ELEMENT).getStringValue()));
+					settings.setOpenLastDocument(Boolean.parseBoolean(root.element(OPEN_LAST_DOCUMENT_ELEMENT).getStringValue()));
 				}
 			}
 			return settings;
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/Key.java b/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/Key.java
index ea03cac0283c33ed248753d6c1db344d954bd429..b35139b5d7b4d8875ccdfa49d43a328f057ca1ee 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/Key.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/Key.java
@@ -130,6 +130,9 @@ public class Key implements Displayable {
 	 */
 	@Override
 	public String toString() {
+		if (key == null) {
+			return "";
+		}
 		if (!getKeyCode().isEmpty())
 			try {
 				return KeyCombination.valueOf(getKeyCode()).getDisplayText();
@@ -149,6 +152,6 @@ public class Key implements Displayable {
 	}
 
 	public boolean isEmpty() {
-		return key.isEmpty() && !ctrl && !shift & !meta && !alt;
+		return key.isEmpty() && !ctrl && !shift && !meta && !alt;
 	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/KeyCollection.java b/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/KeyCollection.java
index 2414977a9dfc3e1970ae1343e51e2c0180d4b203..2a4707d63c1365d326ad693cc09e2d5140bb53a4 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/KeyCollection.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/KeyCollection.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.settings.keys;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.storage.xml.XMLHandler;
 import de.thecodelabs.utils.util.OS;
 import de.tobias.playpad.settings.GlobalSettings;
@@ -22,7 +23,7 @@ import java.util.stream.Collectors;
  */
 public class KeyCollection {
 
-	// Schlüssel: ID, Value: Key
+	// Id -> Key Mapping
 	private HashMap<String, KeyCollectionEntry> keys;
 
 	/**
@@ -141,8 +142,7 @@ public class KeyCollection {
 
 				if (root.element(GlobalSettings.KEYS_ELEMENT) != null) {
 					XMLHandler<Key> handler = new XMLHandler<>(root.element(GlobalSettings.KEYS_ELEMENT));
-					List<Key> keys = handler.loadElements(KEY_ELEMENT, new KeySerializer());
-					for (Key key : keys) {
+					for (Key key : handler.loadElements(KEY_ELEMENT, new KeySerializer())) {
 						updateKey(key);
 					}
 				}
@@ -181,28 +181,24 @@ public class KeyCollection {
 			if (keysElement != null) {
 				KeySerializer keySerializer = new KeySerializer();
 
-				for (Object obj : keysElement.elements(KEY_ELEMENT)) {
-					if (obj instanceof Element) {
-						Element keyElement = (Element) obj;
-
-						try {
-							String name = loadName(keyElement, bundle);
-							Key key = keySerializer.loadElement(keyElement);
-							KeyCollectionEntry entry = new KeyCollectionEntry(name, key);
-
-							try {
-								register(entry);
-							} catch (KeyConflictException e) {
-								// TODO Auto-generated catch block
-								e.printStackTrace();
-							}
-						} catch (MissingResourceException ignored) {
-						}
-					}
+				for (Element keyElement : keysElement.elements(KEY_ELEMENT)) {
+					loadKey(bundle, keySerializer, keyElement);
 				}
 			}
 		} catch (DocumentException e) {
-			e.printStackTrace();
+			Logger.error(e);
+		}
+	}
+
+	private void loadKey(ResourceBundle bundle, KeySerializer keySerializer, Element keyElement) {
+		try {
+			String name = loadName(keyElement, bundle);
+			Key key = keySerializer.loadElement(keyElement);
+			KeyCollectionEntry entry = new KeyCollectionEntry(name, key);
+
+			register(entry);
+		} catch (MissingResourceException | KeyConflictException e) {
+			Logger.error(e);
 		}
 	}
 
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/KeyCollectionEntry.java b/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/KeyCollectionEntry.java
index f401475a34b185374fa963b5734e58c8a0e0d490..edde590a0bfdef5cafcd8d9d09fc0e09348bd249 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/KeyCollectionEntry.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/KeyCollectionEntry.java
@@ -6,7 +6,7 @@ package de.tobias.playpad.settings.keys;
  * @author tobias
  * @since 6.0.0
  */
-class KeyCollectionEntry {
+public class KeyCollectionEntry {
 
 	private final String name;
 	private Key key;
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/KeySerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/KeySerializer.java
index 408d77000ced1967f48a508ce282794fce5f89cc..936f8f68924b5b18663d174114782fc960957993 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/KeySerializer.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/settings/keys/KeySerializer.java
@@ -15,22 +15,10 @@ public class KeySerializer implements XMLSerializer<Key>, XMLDeserializer<Key> {
 
 	@Override
 	public Key loadElement(Element element) {
-		boolean shift = false;
-		if (element.attributeValue(SHIFT_ATTR) != null) {
-			shift = Boolean.valueOf(element.attributeValue(SHIFT_ATTR));
-		}
-		boolean meta = false;
-		if (element.attributeValue(META_ATTR) != null) {
-			meta = Boolean.valueOf(element.attributeValue(META_ATTR));
-		}
-		boolean ctrl = false;
-		if (element.attributeValue(CTRL_ATTR) != null) {
-			ctrl = Boolean.valueOf(element.attributeValue(CTRL_ATTR));
-		}
-		boolean alt = false;
-		if (element.attributeValue(ALT_ATTR) != null) {
-			alt = Boolean.valueOf(element.attributeValue(ALT_ATTR));
-		}
+		boolean shift = loadModifier(SHIFT_ATTR, element);
+		boolean meta = loadModifier(META_ATTR, element);
+		boolean ctrl = loadModifier(CTRL_ATTR, element);
+		boolean alt = loadModifier(ALT_ATTR, element);
 
 		String key = "";
 		if (element.attributeValue(KEY_ATTR) != null) {
@@ -45,6 +33,13 @@ public class KeySerializer implements XMLSerializer<Key>, XMLDeserializer<Key> {
 		return new Key(id, key, ctrl, alt, meta, shift);
 	}
 
+	private boolean loadModifier(String key, Element element) {
+		if (element.attributeValue(key) != null) {
+			return Boolean.parseBoolean(element.attributeValue(key));
+		}
+		return false;
+	}
+
 	@Override
 	public void saveElement(Element newElement, Key data) {
 		newElement.addAttribute(SHIFT_ATTR, String.valueOf(data.isShift()));
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java
index 8cc6e7e5663c372966eff579612fa0deb848f256..2f65d793a5a5e39a17060ed14d72f6d2b0cfe773 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.tigger;
 
+import de.thecodelabs.logger.Logger;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadStatus;
@@ -51,6 +52,17 @@ public class Trigger {
 		this.triggerPoint = triggerPoint;
 	}
 
+	public Trigger copy() {
+		Trigger clone = new Trigger(triggerPoint);
+		clone.items = new ArrayList<>();
+
+		for (TriggerItem item : items) {
+			clone.items.add(item.copy());
+		}
+
+		return clone;
+	}
+
 	private static final String TYPE_ATTR = "type";
 	private static final String ITEM_ELEMENT = "Item";
 	private static final String POINT_ATTR = "point";
@@ -59,23 +71,20 @@ public class Trigger {
 		try {
 			triggerPoint = TriggerPoint.valueOf(element.attributeValue(POINT_ATTR));
 		} catch (Exception e) {
+			Logger.error(e);
 		}
 
-		for (Object itemObj : element.elements(ITEM_ELEMENT)) {
-			if (itemObj instanceof Element) {
-				Element itemElement = (Element) itemObj;
-				String type = itemElement.attributeValue(TYPE_ATTR);
-
-				Registry<TriggerItemFactory> registry = PlayPadPlugin.getRegistries().getTriggerItems();
-				try {
-					TriggerItemFactory connect = registry.getFactory(type);
-					TriggerItem item = connect.newInstance(this);
-					item.load(itemElement);
-					items.add(item);
-				} catch (NoSuchComponentException e) {
-					e.printStackTrace();
-					// TODO Error Handling
-				}
+		for (Element itemElement : element.elements(ITEM_ELEMENT)) {
+			String type = itemElement.attributeValue(TYPE_ATTR);
+
+			Registry<TriggerItemFactory> registry = PlayPadPlugin.getRegistries().getTriggerItems();
+			try {
+				TriggerItemFactory connect = registry.getFactory(type);
+				TriggerItem item = connect.newInstance(this);
+				item.load(itemElement);
+				items.add(item);
+			} catch (NoSuchComponentException e) {
+				Logger.error(e);
 			}
 		}
 	}
@@ -98,26 +107,34 @@ public class Trigger {
 	public void handle(Pad pad, Duration duration, Project project, IMainViewController mainViewController, Profile currentProfile) {
 		for (TriggerItem item : items) {
 			if (triggerPoint == TriggerPoint.START) {
-				if (pad.getStatus() == PadStatus.PLAY) {
-					// Mitten drin, wenn die Zeit die gepsiel wurde größer ist als die gesetzte und noch der Trigger noch nicht ausgeführt
-					// wurde (null)
-					if ((item.getPerformedAt() == null && item.getDurationFromPoint().lessThan(duration))
-							// Wenn der Trigger am Anfang ist
-							|| (duration.equals(Duration.ZERO) && item.getDurationFromPoint().equals(Duration.ZERO))) {
-						item.performAction(pad, project, mainViewController, currentProfile);
-						item.setPerformedAt(duration);
-					} else if (item.getDurationFromPoint().greaterThan(duration)) {
-						item.setPerformedAt(null);
-					}
-				}
+				handleStartPoint(pad, duration, project, mainViewController, currentProfile, item);
 			} else if ((triggerPoint == TriggerPoint.EOF_STOP)) {
-				// Wenn Trigger noch nicht gespiel wurde (null) und Zeit größer ist als gesetzte Zeit (oder 0)
-				if (item.getPerformedAt() == null && (item.getDurationFromPoint().greaterThan(duration) || duration.equals(Duration.ZERO))) {
-					item.performAction(pad, project, mainViewController, currentProfile);
-					item.setPerformedAt(duration);
-				} else if (item.getDurationFromPoint().lessThan(duration)) {
-					item.setPerformedAt(null);
-				}
+				handleEndPoint(pad, duration, project, mainViewController, currentProfile, item);
+			}
+		}
+	}
+
+	private void handleEndPoint(Pad pad, Duration duration, Project project, IMainViewController mainViewController, Profile currentProfile, TriggerItem item) {
+		// Wenn Trigger noch nicht gespiel wurde (null) und Zeit größer ist als gesetzte Zeit (oder 0)
+		if (item.getPerformedAt() == null && (item.getDurationFromPoint().greaterThan(duration) || duration.equals(Duration.ZERO))) {
+			item.performAction(pad, project, mainViewController, currentProfile);
+			item.setPerformedAt(duration);
+		} else if (item.getDurationFromPoint().lessThan(duration)) {
+			item.setPerformedAt(null);
+		}
+	}
+
+	private void handleStartPoint(Pad pad, Duration duration, Project project, IMainViewController mainViewController, Profile currentProfile, TriggerItem item) {
+		if (pad.getStatus() == PadStatus.PLAY) {
+			// Mitten drin, wenn die Zeit die gepsiel wurde größer ist als die gesetzte und noch der Trigger noch nicht ausgeführt
+			// wurde (null)
+			if ((item.getPerformedAt() == null && item.getDurationFromPoint().lessThan(duration))
+					// Wenn der Trigger am Anfang ist
+					|| (duration.equals(Duration.ZERO) && item.getDurationFromPoint().equals(Duration.ZERO))) {
+				item.performAction(pad, project, mainViewController, currentProfile);
+				item.setPerformedAt(duration);
+			} else if (item.getDurationFromPoint().greaterThan(duration)) {
+				item.setPerformedAt(null);
 			}
 		}
 	}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerItem.java b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerItem.java
index db9a1b7d8c74f47a60dbd70fdfdbad8cf59f13f8..37d97209cac1ee728b838bf05d3715c250469593 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerItem.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerItem.java
@@ -9,9 +9,9 @@ import org.dom4j.Element;
 
 public abstract class TriggerItem {
 
-	protected Duration durationFromPoint;
+	private Duration durationFromPoint;
 
-	protected transient Duration performedAt;
+	private transient Duration performedAt;
 
 	public TriggerItem() {
 		durationFromPoint = Duration.ZERO;
@@ -43,6 +43,8 @@ public abstract class TriggerItem {
 
 	public abstract void performAction(Pad pad, Project project, IMainViewController controller, Profile profile);
 
+	public abstract TriggerItem copy();
+
 	private static final String DURATION_ATTR = "duration";
 
 	/**
@@ -52,7 +54,7 @@ public abstract class TriggerItem {
 	 */
 	public void load(Element element) {
 		if (element.attributeValue(DURATION_ATTR) != null) {
-			durationFromPoint = Duration.millis(Double.valueOf(element.attributeValue(DURATION_ATTR)));
+			durationFromPoint = Duration.millis(Double.parseDouble(element.attributeValue(DURATION_ATTR)));
 		}
 	}
 
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/util/FadeableColor.java b/PlayWallCore/src/main/java/de/tobias/playpad/util/FadeableColor.java
index 3e6761580b276ebdc45aec2f6f382c732434e0f2..8cdb173b7fed8dd3c883c25a4325fee54af0c66a 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/util/FadeableColor.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/util/FadeableColor.java
@@ -46,10 +46,9 @@ public class FadeableColor implements Interpolatable<FadeableColor> {
 		if (t >= 1.0)
 			return endValue;
 
-		FadeableColor current = this;
-		List<Stop> stops = new ArrayList<>();
-		for (int i = 0; i < current.getStops().size(); i++) {
-			Color startColor = current.getStops().get(i).getColor();
+		List<Stop> stopList = new ArrayList<>();
+		for (int i = 0; i < this.getStops().size(); i++) {
+			Color startColor = this.getStops().get(i).getColor();
 			Color endColor = endValue.getStops().get(i).getColor();
 
 			double red = startColor.getRed() + (endColor.getRed() - startColor.getRed()) * t;
@@ -58,11 +57,11 @@ public class FadeableColor implements Interpolatable<FadeableColor> {
 			double opacity = startColor.getOpacity() + (endColor.getOpacity() - startColor.getOpacity()) * t;
 
 			Color color = new Color(red, green, blue, opacity);
-			Stop stop = new Stop(current.getStops().get(i).getOffset(), color);
-			stops.add(stop);
+			Stop stop = new Stop(this.getStops().get(i).getOffset(), color);
+			stopList.add(stop);
 		}
 
-		return new FadeableColor(stops);
+		return new FadeableColor(stopList);
 	}
 
 	@Override
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/util/Minifier.java b/PlayWallCore/src/main/java/de/tobias/playpad/util/Minifier.java
new file mode 100644
index 0000000000000000000000000000000000000000..934d3d4a00aef83470b17c489553d645154d8293
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/util/Minifier.java
@@ -0,0 +1,19 @@
+package de.tobias.playpad.util;
+
+public class Minifier {
+
+	private Minifier() {
+	}
+
+	private static String[] expressions = {
+			"\n",
+			"\t"
+	};
+
+	public static String minify(String input) {
+		for (String expression : expressions) {
+			input = input.replaceAll(expression, "");
+		}
+		return input;
+	}
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/BaseMapperListViewController.java b/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/BaseMapperListViewController.java
index 66432de2a008f75816ac12fd8a8bd2a0fcc58c4b..49a1208174749c5363af23b377171f2799c6ee6d 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/BaseMapperListViewController.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/BaseMapperListViewController.java
@@ -1,7 +1,7 @@
 package de.tobias.playpad.viewcontroller;
 
-import de.tobias.playpad.action.Action;
-import de.tobias.playpad.action.mapper.Mapper;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.mapping.Key;
 import de.tobias.playpad.action.mapper.MapperViewController;
 import javafx.scene.Parent;
 import javafx.scene.control.ScrollPane;
@@ -21,9 +21,13 @@ public abstract class BaseMapperListViewController {
 		BaseMapperListViewController.instance = instance;
 	}
 
+	/*
+
+	 */
+
 	public interface MapperAddListener {
 
-		void onAdd(Mapper mapper, MapperViewController controller);
+		void onAdd(Key mapper, MapperViewController controller);
 	}
 
 	public abstract List<MapperViewController> getControllers();
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/IMappingTabViewController.java b/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/IMappingTabViewController.java
index 18cd15934d565f7f2c643c7ebfcfc8b75c3fecb1..6c702c4292f5bb7685ceb308a9cf8dee0035b36d 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/IMappingTabViewController.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/IMappingTabViewController.java
@@ -1,6 +1,6 @@
 package de.tobias.playpad.viewcontroller;
 
-import de.tobias.playpad.action.Action;
+import de.thecodelabs.midi.action.Action;
 
 /**
  * Schnittstelle für den Mapping Tab ViewController. Der Controller hat zwei Bereiche: ActionType (Optional), Action
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/main/IMainViewController.java b/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/main/IMainViewController.java
index 94a0901b91ffe4c0e244c2410253ce036fa94620..74d3f11ea2299ef40c7faf255474d20ed2b8f0be 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/main/IMainViewController.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/main/IMainViewController.java
@@ -3,7 +3,6 @@ package de.tobias.playpad.viewcontroller.main;
 import de.thecodelabs.utils.ui.Alertable;
 import de.thecodelabs.utils.ui.NotificationHandler;
 import de.thecodelabs.utils.ui.scene.NotificationPane;
-import de.tobias.playpad.midi.MidiListener;
 import de.tobias.playpad.pad.view.IPadView;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.page.Page;
@@ -105,6 +104,8 @@ public interface IMainViewController extends NotificationHandler, Alertable {
 	 */
 	boolean showPage(Page page);
 
+	void closeProject();
+
 	/**
 	 * Opens a project
 	 *
@@ -124,13 +125,6 @@ public interface IMainViewController extends NotificationHandler, Alertable {
 	 */
 	List<IPadView> getPadViews();
 
-	/**
-	 * Gibt den MIDI Handler des Hauptfensters für die Kacheln zurück.
-	 *
-	 * @return MIDI Handler
-	 */
-	MidiListener getMidiHandler();
-
 	/**
 	 * Setzt das MainLayout des Hauptfensters.
 	 *
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/main/MenuToolbarViewController.java b/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/main/MenuToolbarViewController.java
index f4130144d24a629d7b79b048f00eabca7c654068..53e53c759b44d1faed8da6b5ee671a4444992d7e 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/main/MenuToolbarViewController.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/viewcontroller/main/MenuToolbarViewController.java
@@ -3,11 +3,13 @@ package de.tobias.playpad.viewcontroller.main;
 import de.thecodelabs.utils.ui.NVC;
 import de.tobias.playpad.profile.ProfileSettings;
 import de.tobias.playpad.project.Project;
+import de.tobias.playpad.settings.keys.Key;
 import de.tobias.playpad.settings.keys.KeyCollection;
 import de.tobias.playpad.view.main.MenuType;
 import javafx.scene.Node;
 import javafx.scene.control.MenuItem;
 import javafx.scene.control.Slider;
+import javafx.scene.input.KeyCombination;
 
 import java.util.ResourceBundle;
 
@@ -149,6 +151,13 @@ public abstract class MenuToolbarViewController extends NVC {
 	 */
 	public abstract void loadKeybinding(KeyCollection keys);
 
+	public void setKeyBindingForMenu(MenuItem menuItem, Key key) {
+		if (key != null && !key.getKeyCode().isEmpty()) {
+			KeyCombination keyCode = KeyCombination.valueOf(key.getKeyCode());
+			menuItem.setAccelerator(keyCode);
+		}
+	}
+
 	/**
 	 * Setzt eine Refernce des aktuellen Projectes auf den ViewController.
 	 *
diff --git a/PlayWallPluginAwake/src/main/resources/lang/awake_de.properties b/PlayWallPluginAwake/src/main/resources/lang/awake_de.properties
deleted file mode 100644
index 745ae728a30e3c2a58a2ac45213763c3fdd1e178..0000000000000000000000000000000000000000
--- a/PlayWallPluginAwake/src/main/resources/lang/awake_de.properties
+++ /dev/null
@@ -1 +0,0 @@
-menutitle=Ruhezustand verhindern
\ No newline at end of file
diff --git a/PlayWallPluginEqualizer/src/main/resources/lang/equalizer_de.properties b/PlayWallPluginEqualizer/src/main/resources/lang/equalizer_de.properties
deleted file mode 100644
index 4a858949fbefebcb42ee459657d81f87e8a407c5..0000000000000000000000000000000000000000
--- a/PlayWallPluginEqualizer/src/main/resources/lang/equalizer_de.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-eq.checkbox.enabled=Equalizer aktiviert
-eq.button.reset=Zur\u00FCcksetzen
-eq.button.finish=Fertig
-eq.slider=Hz
-eq.menuitem.name=Equalizer
-eq.title=Equalizer
\ No newline at end of file
diff --git a/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk2/LaunchPadMK2.java b/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk2/LaunchPadMK2.java
deleted file mode 100644
index 1238b9ee32cfbd6cb1143cda030e161ed85f34c4..0000000000000000000000000000000000000000
--- a/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk2/LaunchPadMK2.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package de.tobias.playpad.launchpadplugin.midi.mk2;
-
-import de.thecodelabs.logger.Logger;
-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.DeviceColorAssociatorConnector;
-import de.tobias.playpad.action.mididevice.MidiDeviceImpl;
-import de.tobias.playpad.launchpadplugin.impl.MapParser;
-import de.tobias.playpad.midi.Midi;
-import javafx.scene.paint.Color;
-
-import javax.sound.midi.InvalidMidiDataException;
-import javax.sound.midi.MidiUnavailableException;
-import javax.sound.midi.ShortMessage;
-import java.net.URL;
-import java.util.Map;
-
-public class LaunchPadMK2 extends MidiDeviceImpl implements DeviceColorAssociatorConnector {
-
-	public static final String NAME = "Launchpad MK2";
-
-	// Modern Colors mapped to the colors of the launchpad
-	private static Map<String, String> mapProperties;
-
-	static {
-		try {
-			URL resource = LaunchPadMK2.class.getClassLoader().getResource("launchpad_mk2.map");
-			mapProperties = MapParser.load(resource);
-		} catch (Exception e) {
-			Logger.error(e);
-		}
-	}
-
-	@Override
-	public String getName() {
-		return NAME;
-	}
-
-	@Override
-	public boolean supportFeedback() {
-		return true;
-	}
-
-	@Override
-	public void initDevice() {
-		// nothing to do
-	}
-
-	@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) {
-				Logger.error(e);
-			}
-		} else {
-			try {
-				Midi.getInstance().sendMessage(145, key, feedback.getValueForFeedbackMessage(FeedbackMessage.STANDARD));
-			} catch (MidiUnavailableException | InvalidMidiDataException e) {
-				Logger.error(e);
-			}
-		}
-	}
-
-	@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) {
-				Logger.error(e);
-			}
-		}
-
-		// 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) {
-				Logger.error(e);
-			}
-		}
-	}
-
-	@Override
-	public DisplayableFeedbackColor getColor(int id) {
-		return LaunchPadMK2Color.valueOf(id);
-	}
-
-	@Override
-	public DisplayableFeedbackColor[] getColors() {
-		return LaunchPadMK2Color.values();
-	}
-
-	@Override
-	public DisplayableFeedbackColor getDefaultEventColor() {
-		return LaunchPadMK2Color.C1_2;
-	}
-
-	@Override
-	public DisplayableFeedbackColor getDefaultStandardColor() {
-		return LaunchPadMK2Color.C5_2;
-	}
-
-	@Override
-	public DisplayableFeedbackColor getPreferColorMapping(Color color) {
-		if (mapProperties.containsKey(color.toString())) {
-			String nameOfConst = mapProperties.get(color.toString());
-			return LaunchPadMK2Color.valueOf(nameOfConst);
-		}
-		return null;
-	}
-}
diff --git a/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/s/LaunchPadS.java b/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/s/LaunchPadS.java
deleted file mode 100644
index 2432014fb34503c8fb7293403924aab698258e82..0000000000000000000000000000000000000000
--- a/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/s/LaunchPadS.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package de.tobias.playpad.launchpadplugin.midi.s;
-
-import de.thecodelabs.logger.Logger;
-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.DeviceColorAssociatorConnector;
-import de.tobias.playpad.action.mididevice.MidiDeviceImpl;
-import de.tobias.playpad.midi.Midi;
-import javafx.scene.paint.Color;
-
-import javax.sound.midi.InvalidMidiDataException;
-import javax.sound.midi.MidiUnavailableException;
-
-public class LaunchPadS extends MidiDeviceImpl implements DeviceColorAssociatorConnector {
-
-	public static final String NAME = "Launchpad S";
-
-	@Override
-	public String getName() {
-		return NAME;
-	}
-
-	@Override
-	public boolean supportFeedback() {
-		return true;
-	}
-
-	@Override
-	public void initDevice() {
-		// Flash Enable
-		try {
-			Midi.getInstance().sendMessage(176, 0, 40);
-		} catch (MidiUnavailableException | InvalidMidiDataException e) {
-			Logger.error(e);
-		}
-	}
-
-	@Override
-	public void handleFeedback(FeedbackMessage type, int key, Feedback feedback) {
-		initDevice();
-
-		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) {
-			Logger.error(e);
-		}
-	}
-
-	@Override
-	public void clearFeedback() {
-		try {
-			Midi.getInstance().sendMessage(176, 0, 0);
-		} catch (MidiUnavailableException | InvalidMidiDataException e) {
-			Logger.error(e);
-		}
-	}
-
-	@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 getPreferColorMapping(Color color) {
-		return null;
-	}
-}
diff --git a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/BlackAction.java b/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/BlackAction.java
deleted file mode 100644
index 42cfdd6b1c28f7c174d63673137470aea3cb9230..0000000000000000000000000000000000000000
--- a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/BlackAction.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package de.tobias.playpad.plugin.media.action;
-
-import de.thecodelabs.utils.ui.icon.FontAwesomeType;
-import de.thecodelabs.utils.ui.icon.FontIcon;
-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.plugin.media.main.impl.MediaPluginImpl;
-import de.tobias.playpad.project.Project;
-import de.tobias.playpad.viewcontroller.main.IMainViewController;
-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;
-import org.dom4j.Element;
-
-public class BlackAction extends Action implements Displayable {
-
-	private ChangeListener<Boolean> blindFeedbackListener;
-
-	BlackAction() {
-		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 init(Project project, IMainViewController controller) {
-		// Listener für Eingaben
-		BooleanProperty blindProperty = MediaPluginImpl.blindProperty();
-		blindProperty.removeListener(blindFeedbackListener);
-		blindProperty.addListener(blindFeedbackListener);
-	}
-
-	@Override
-	public void showFeedback(Project project, IMainViewController controller) {
-		BooleanProperty blindProperty = MediaPluginImpl.blindProperty();
-
-		// Handle Current Feedback
-		blindFeedbackListener.changed(blindProperty, null, blindProperty.getValue());
-	}
-
-	@Override
-	public FeedbackType geFeedbackType() {
-		return FeedbackType.DOUBLE;
-	}
-
-	@Override
-	public String getType() {
-		return BlackActionFactory.TYPE;
-	}
-
-	@Override
-	public void load(Element root) {
-	}
-
-	@Override
-	public void save(Element root) {
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		return obj.getClass().equals(getClass()) || super.equals(obj);
-	}
-
-	@Override
-	public StringProperty displayProperty() {
-		return new SimpleStringProperty(MediaPluginImpl.getInstance().getBundle().getString("black_action.name"));
-	}
-
-	@Override
-	public Node getGraphics() {
-		return new Label("", new FontIcon(FontAwesomeType.DESKTOP));
-	}
-
-	@Override
-	public Action cloneAction() throws CloneNotSupportedException {
-		return (BlackAction) super.clone();
-	}
-}
diff --git a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/BlackActionFactory.java b/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/BlackActionFactory.java
deleted file mode 100644
index a9c44fba087b94281cef62b9a9be4eb84f59b600..0000000000000000000000000000000000000000
--- a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/BlackActionFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package de.tobias.playpad.plugin.media.action;
-
-import de.tobias.playpad.action.*;
-import de.tobias.playpad.profile.Profile;
-import javafx.scene.control.TreeItem;
-
-import java.util.List;
-
-public class BlackActionFactory extends ActionProvider {
-
-	static final String TYPE = "BLACK";
-
-	public BlackActionFactory(String type) {
-		super(type);
-	}
-
-	@Override
-	public TreeItem<ActionDisplayable> getTreeViewForActions(List<Action> actions, Mapping mapping) {
-		return new TreeItem<>(actions.get(0));
-	}
-
-	@Override
-	public void initActionType(Mapping mapping, Profile profile) {
-		mapping.addActionIfNotContains(new BlackAction());
-	}
-
-	@Override
-	public Action newInstance() {
-		return new BlackAction();
-	}
-
-	@Override
-	public ActionType geActionType() {
-		return ActionType.SETTINGS;
-	}
-
-	@Override
-	public String getType() {
-		return TYPE;
-	}
-}
diff --git a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/Strings.java b/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/Strings.java
deleted file mode 100644
index 5363873f10de72161bf4fe67fc97682d6a939021..0000000000000000000000000000000000000000
--- a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/Strings.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package de.tobias.playpad.plugin.media.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/PlayWallPluginMedia/src/main/resources/Actions.xml b/PlayWallPluginMedia/src/main/resources/Actions.xml
deleted file mode 100644
index a13d24e0171fdd7f6ca4997baa1d4c56ca8b635a..0000000000000000000000000000000000000000
--- a/PlayWallPluginMedia/src/main/resources/Actions.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<Actions>
-    <Component id="BLIND" name="black_action.name">de.tobias.playpad.plugin.media.action.BlackActionFactory
-    </Component>
-</Actions>
\ No newline at end of file
diff --git a/PlayWallPluginMedia/src/main/resources/PadContent.xml b/PlayWallPluginMedia/src/main/resources/PadContent.xml
deleted file mode 100644
index b1b5f901a0a33c5228b1c79a10a8c005713c0b31..0000000000000000000000000000000000000000
--- a/PlayWallPluginMedia/src/main/resources/PadContent.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<Actions>
-    <Component id="video" name="Content.Video.Name">de.tobias.playpad.plugin.media.video.VideoPadContentFactory
-    </Component>
-    <Component id="image" name="Content.Image.Name">de.tobias.playpad.plugin.media.image.ImagePadContentFactory
-    </Component>
-</Actions>
\ No newline at end of file
diff --git a/PlayWallPluginMedia/src/main/resources/lang/video_de.properties b/PlayWallPluginMedia/src/main/resources/lang/video_de.properties
deleted file mode 100644
index 5b8ba754cc86e1a535c3e8cdbbd23a22a9b079ea..0000000000000000000000000000000000000000
--- a/PlayWallPluginMedia/src/main/resources/lang/video_de.properties
+++ /dev/null
@@ -1,12 +0,0 @@
-settings.tab=Video/Bild
-settings.video.tab=Video
-settings.video.label.screens=Bildschirme:
-settings.video.label.screenChoice=Bildschirm f\uFFFDr Videowiedergabe:
-settings.video.checkbox.fullscreen=Vollbild
-settings.video.checkbox.openAtLaunch=Fenster beim Start \uFFFDffnen
-pad.label.lastFrame=Letztes Bild am Ende des Videos einfrieren (Freeze)
-pad.checkbox.lastFrame=Aktivieren
-
-black_action.name=Schwarzbild Video
-Content.Video.Name=Video
-Content.Image.Name=Bild
\ No newline at end of file
diff --git a/PlayWallPluginAwake/pom.xml b/PlayWallPlugins/PlayWallPluginAwake/pom.xml
similarity index 86%
rename from PlayWallPluginAwake/pom.xml
rename to PlayWallPlugins/PlayWallPluginAwake/pom.xml
index 935f9e4dea311269191e6c07303db29a2a3a7d47..0b75388b2ab9faa42936b8e4bb2309ed2ad6ac40 100644
--- a/PlayWallPluginAwake/pom.xml
+++ b/PlayWallPlugins/PlayWallPluginAwake/pom.xml
@@ -6,14 +6,14 @@
 
     <parent>
         <groupId>de.tobias.playpad</groupId>
-        <artifactId>PlayWallDesktop</artifactId>
-        <version>6.2.0-SNAPSHOT</version>
+        <artifactId>PlayWallPlugins</artifactId>
+        <version>7.0.0</version>
     </parent>
 
     <artifactId>PlayWallPluginAwake</artifactId>
 
     <properties>
-        <project.outputDirectory>../build/${project.version}</project.outputDirectory>
+        <project.outputDirectory>../../build/${project.version}</project.outputDirectory>
         <project.artifactName>${project.artifactId}-v${project.version}</project.artifactName>
     </properties>
 
@@ -75,19 +75,19 @@
         <repository>
             <id>release</id>
             <name>TheCodeLabs-releases</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
         </repository>
         <snapshotRepository>
             <id>snapshots</id>
             <name>TheCodeLabs-snapshots</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
         </snapshotRepository>
     </distributionManagement>
 
     <repositories>
         <repository>
             <id>release</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
             <releases>
                 <enabled>true</enabled>
             </releases>
@@ -97,7 +97,7 @@
         </repository>
         <repository>
             <id>snapshots</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
             <releases>
                 <enabled>false</enabled>
             </releases>
diff --git a/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java b/PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java
similarity index 91%
rename from PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java
rename to PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java
index a7997323573835199cf423448b489056b4647b12..aa546a3218fa87200ddeb5090f9b0e7328200391 100644
--- a/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java
+++ b/PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java
@@ -8,10 +8,10 @@ import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
 import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.plugin.MainWindowListener;
 import de.tobias.playpad.plugin.Module;
 import de.tobias.playpad.plugin.PlayPadPluginStub;
 import de.tobias.playpad.plugin.SettingsListener;
-import de.tobias.playpad.plugin.WindowListener;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.view.main.MenuType;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
@@ -24,10 +24,9 @@ import org.dom4j.DocumentException;
 import java.io.IOException;
 import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
-import java.util.ResourceBundle;
 
 @SuppressWarnings("unused")
-public class AwakePluginImpl implements PlayPadPluginStub, PluginArtifact, WindowListener<IMainViewController>, EventHandler<ActionEvent>, SettingsListener {
+public class AwakePluginImpl implements PlayPadPluginStub, PluginArtifact, MainWindowListener, EventHandler<ActionEvent>, SettingsListener {
 
 	private Module module;
 
@@ -38,11 +37,9 @@ public class AwakePluginImpl implements PlayPadPluginStub, PluginArtifact, Windo
 
 	private AwakeSettings settings = new AwakeSettings();
 
-	private ResourceBundle bundle;
-
 	@Override
 	public void startup(PluginDescriptor descriptor) {
-		bundle = Localization.loadBundle("lang/awake", getClass().getClassLoader());
+		Localization.addResourceBundle("lang/awake", getClass().getClassLoader());
 
 		module = new Module(descriptor.getName(), descriptor.getArtifactId());
 
@@ -90,7 +87,7 @@ public class AwakePluginImpl implements PlayPadPluginStub, PluginArtifact, Windo
 	public void onInit(IMainViewController viewController) {
 		activeMenu = new CheckMenuItem();
 		activeMenu.setOnAction(this);
-		activeMenu.setText(bundle.getString("menutitle"));
+		activeMenu.setText(Localization.getString("plugin.awake.menu_item"));
 		activeMenu.setSelected(settings.active);
 
 		viewController.performLayoutDependedAction((oldToolbar, newToolbar) ->
diff --git a/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakeSettings.java b/PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakeSettings.java
similarity index 93%
rename from PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakeSettings.java
rename to PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakeSettings.java
index dfc3d61c8d12f681a031174a09400c4fe4c01c7d..88d5270961b58d1d9858beddb23efc8587135ffd 100644
--- a/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakeSettings.java
+++ b/PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakeSettings.java
@@ -24,7 +24,7 @@ class AwakeSettings {
 		Document document = reader.read(Files.newInputStream(path));
 
 		Element rootElement = document.getRootElement();
-		settings.active = Boolean.valueOf(rootElement.element(ACTIVE_ELEMENT).getStringValue());
+		settings.active = Boolean.parseBoolean(rootElement.element(ACTIVE_ELEMENT).getStringValue());
 
 		return settings;
 	}
diff --git a/PlayWallPlugins/PlayWallPluginAwake/src/main/resources/lang/awake_de.properties b/PlayWallPlugins/PlayWallPluginAwake/src/main/resources/lang/awake_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..8474885345f6b3e5e85afe18206b2dd034b9f45f
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginAwake/src/main/resources/lang/awake_de.properties
@@ -0,0 +1 @@
+plugin.awake.menu_item=Ruhezustand verhindern
\ No newline at end of file
diff --git a/PlayWallPluginAwake/src/main/resources/plugin.yml b/PlayWallPlugins/PlayWallPluginAwake/src/main/resources/plugin.yml
similarity index 100%
rename from PlayWallPluginAwake/src/main/resources/plugin.yml
rename to PlayWallPlugins/PlayWallPluginAwake/src/main/resources/plugin.yml
diff --git a/PlayWallPluginEqualizer/pom.xml b/PlayWallPlugins/PlayWallPluginEqualizer/pom.xml
similarity index 86%
rename from PlayWallPluginEqualizer/pom.xml
rename to PlayWallPlugins/PlayWallPluginEqualizer/pom.xml
index 316961310b79d1f1ab6a0477a10c23df893eb4ef..2f684d16bd6f27bf97a0fe1285fb81cf5fd5dac8 100644
--- a/PlayWallPluginEqualizer/pom.xml
+++ b/PlayWallPlugins/PlayWallPluginEqualizer/pom.xml
@@ -6,14 +6,14 @@
 
     <parent>
         <groupId>de.tobias.playpad</groupId>
-        <artifactId>PlayWallDesktop</artifactId>
-        <version>6.2.0-SNAPSHOT</version>
+        <artifactId>PlayWallPlugins</artifactId>
+        <version>7.0.0</version>
     </parent>
 
     <artifactId>PlayWallPluginEqualizer</artifactId>
 
     <properties>
-        <project.outputDirectory>../build/${project.version}</project.outputDirectory>
+        <project.outputDirectory>../../build/${project.version}</project.outputDirectory>
         <project.artifactName>${project.artifactId}-v${project.version}</project.artifactName>
     </properties>
 
@@ -75,19 +75,19 @@
         <repository>
             <id>release</id>
             <name>TheCodeLabs-releases</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
         </repository>
         <snapshotRepository>
             <id>snapshots</id>
             <name>TheCodeLabs-snapshots</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
         </snapshotRepository>
     </distributionManagement>
 
     <repositories>
         <repository>
             <id>release</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
             <releases>
                 <enabled>true</enabled>
             </releases>
@@ -97,7 +97,7 @@
         </repository>
         <repository>
             <id>snapshots</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
             <releases>
                 <enabled>false</enabled>
             </releases>
diff --git a/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/Equalizer.java b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/Equalizer.java
similarity index 90%
rename from PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/Equalizer.java
rename to PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/Equalizer.java
index 1a50970d417f624a8b6386149045595b133f430a..89f40d1f7b4586064d9124bcce8b893181046399 100644
--- a/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/Equalizer.java
+++ b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/Equalizer.java
@@ -106,14 +106,13 @@ public class Equalizer {
 			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());
+			for (Element element : root.elements(BAND_ELEMENT)) {
+				int bandwidth = Integer.parseInt(element.attribute(WIDTH_ATTR).getValue());
+				double gain = Double.parseDouble(element.getStringValue());
 				instance.setGain(bandwidth, gain);
 			}
 			if (root.element(ENABLE_ELEMENT) != null)
-				instance.setEnable(Boolean.valueOf(root.element(ENABLE_ELEMENT).getStringValue()));
+				instance.setEnable(Boolean.parseBoolean(root.element(ENABLE_ELEMENT).getStringValue()));
 		}
 	}
 }
diff --git a/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerPluginImpl.java b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerPluginImpl.java
similarity index 81%
rename from PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerPluginImpl.java
rename to PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerPluginImpl.java
index 42e9f6f3f9fa008b88bffecd2e1fa0ed5ff1d55b..6ff24f83ac9122fa073da85a772a97ff6be76307 100644
--- a/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerPluginImpl.java
+++ b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerPluginImpl.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.equalizerplugin.impl;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.plugins.PluginArtifact;
 import de.thecodelabs.plugins.PluginDescriptor;
 import de.thecodelabs.utils.application.ApplicationUtils;
@@ -8,12 +9,13 @@ import de.thecodelabs.utils.ui.NVCStage;
 import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.equalizerplugin.Equalizer;
 import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.pad.content.PadContent;
 import de.tobias.playpad.pad.content.play.Equalizeable;
+import de.tobias.playpad.plugin.MainWindowListener;
 import de.tobias.playpad.plugin.Module;
 import de.tobias.playpad.plugin.PadListener;
 import de.tobias.playpad.plugin.PlayPadPluginStub;
-import de.tobias.playpad.plugin.WindowListener;
 import de.tobias.playpad.view.main.MenuType;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import javafx.event.ActionEvent;
@@ -25,29 +27,22 @@ import javafx.stage.Stage;
 import org.dom4j.DocumentException;
 
 import java.io.IOException;
-import java.util.ResourceBundle;
 
-public class EqualizerPluginImpl implements PlayPadPluginStub, PluginArtifact, WindowListener<IMainViewController>, EventHandler<ActionEvent>, PadListener {
+@SuppressWarnings("unused")
+public class EqualizerPluginImpl implements PlayPadPluginStub, PluginArtifact, MainWindowListener, EventHandler<ActionEvent>, PadListener {
 
 	private Module module;
 
 	private Stage mainStage;
 	private EqualizerViewController equalizerViewController;
-	private static ResourceBundle bundle;
-
-	private MenuItem eqMenuItem;
-
-	static ResourceBundle getBundle() {
-		return bundle;
-	}
 
 	@Override
 	public void startup(PluginDescriptor descriptor) {
-		bundle = Localization.loadBundle("lang/equalizer", EqualizerPluginImpl.class.getClassLoader());
+		Localization.addResourceBundle("lang/equalizer", EqualizerPluginImpl.class.getClassLoader());
 		try {
 			Equalizer.load(ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, "equalizer.xml"));
 		} catch (DocumentException | IOException e) {
-			e.printStackTrace();
+			Logger.error(e);
 		}
 
 		module = new Module(descriptor.getName(), descriptor.getArtifactId());
@@ -55,20 +50,20 @@ public class EqualizerPluginImpl implements PlayPadPluginStub, PluginArtifact, W
 		de.tobias.playpad.PlayPadPlugin.getInstance().addMainViewListener(this);
 		de.tobias.playpad.PlayPadPlugin.getInstance().addPadListener(this);
 
-		System.out.println("Enable Equalizer Plugin");
+		Logger.info("Enable Equalizer Plugin");
 	}
 
 	@Override
 	public void shutdown() {
-		System.out.println("Disable Equalizer Plugin");
+		Logger.info("Disable Equalizer Plugin");
 	}
 
 	@Override
 	public void onInit(IMainViewController t) {
 		mainStage = t.getStage();
 
-		eqMenuItem = new MenuItem();
-		eqMenuItem.setText(bundle.getString("eq.menuitem.name"));
+		MenuItem eqMenuItem = new MenuItem();
+		eqMenuItem.setText(Localization.getString("plugin.equalizer.menuitem.name"));
 		eqMenuItem.setOnAction(this);
 
 		t.performLayoutDependedAction((oldToolbar, newToolbar) ->
@@ -80,7 +75,15 @@ public class EqualizerPluginImpl implements PlayPadPluginStub, PluginArtifact, W
 	}
 
 	@Override
-	public void onPlay(Pad pad) {
+	public void onStatusChange(Pad pad, PadStatus newValue) {
+		if (newValue == PadStatus.PLAY) {
+			onPlay(pad);
+		} else if (newValue == PadStatus.STOP) {
+			onStop(pad);
+		}
+	}
+
+	private void onPlay(Pad pad) {
 		PadContent content = pad.getContent();
 		if (content instanceof Equalizeable) {
 
@@ -96,8 +99,7 @@ public class EqualizerPluginImpl implements PlayPadPluginStub, PluginArtifact, W
 		}
 	}
 
-	@Override
-	public void onStop(Pad pad) {
+	private void onStop(Pad pad) {
 		PadContent content = pad.getContent();
 		if (content instanceof Equalizeable) {
 
diff --git a/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerViewController.java b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerViewController.java
similarity index 90%
rename from PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerViewController.java
rename to PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerViewController.java
index 66464b8b1c5e193bca7ea322fdeeae6af36fc31f..d2d229b3ed97d06f53dcd329bc7b0b8e4aaed4c9 100644
--- a/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerViewController.java
+++ b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerViewController.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.equalizerplugin.impl;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
 import de.thecodelabs.utils.ui.NVC;
@@ -39,8 +40,8 @@ public class EqualizerViewController extends NVC {
 	@FXML
 	private CheckBox enableCheckBox;
 
-	public EqualizerViewController(Window owner) {
-		load("view", "equalizerView", EqualizerPluginImpl.getBundle());
+	EqualizerViewController(Window owner) {
+		load("view", "equalizerView", Localization.getBundle());
 
 		applyViewControllerToStage().initOwner(owner);
 
@@ -61,7 +62,7 @@ public class EqualizerViewController extends NVC {
 			slider.getStyleClass().add("equalizer-slider");
 			slider.setUserData(band);
 
-			Label infoLabel = new Label(NumberUtils.convertBytesToAppropriateFormat(band, 0) + EqualizerPluginImpl.getBundle().getString("eq.slider"));
+			Label infoLabel = new Label(NumberUtils.convertBytesToAppropriateFormat(band, 0) + Localization.getString("plugin.equalizer.slider"));
 			infoLabel.getStyleClass().add("equalizer-label");
 
 			bandBox.getChildren().addAll(slider, infoLabel);
@@ -91,9 +92,9 @@ public class EqualizerViewController extends NVC {
 
 	@Override
 	public void initStage(Stage stage) {
-		PlayPadPlugin.getInstance().getIcon().ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
-		stage.setTitle(EqualizerPluginImpl.getBundle().getString("eq.title"));
+		stage.setTitle(Localization.getString("plugin.equalizer.title"));
 		stage.setMinWidth(500);
 		stage.setMinHeight(250);
 
@@ -119,7 +120,7 @@ public class EqualizerViewController extends NVC {
 			Equalizer.save(ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, "equalizer.xml"));
 		} catch (IOException e) {
 			showErrorMessage(Localization.getString("error.file.save", e.getLocalizedMessage()));
-			e.printStackTrace();
+			Logger.error(e);
 		}
 		getStageContainer().ifPresent(NVCStage::close);
 	}
diff --git a/PlayWallPlugins/PlayWallPluginEqualizer/src/main/resources/lang/equalizer_de.properties b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/resources/lang/equalizer_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..236ef21fb0496ead5434f830690d0188fe3848cd
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/resources/lang/equalizer_de.properties
@@ -0,0 +1,6 @@
+plugin.equalizer.checkbox.enabled=Equalizer aktiviert
+plugin.equalizer.button.reset=Zur\u00FCcksetzen
+plugin.equalizer.button.finish=Fertig
+plugin.equalizer.slider=Hz
+plugin.equalizer.menuitem.name=Equalizer
+plugin.equalizer.title=Equalizer
\ No newline at end of file
diff --git a/PlayWallPluginEqualizer/src/main/resources/plugin.yml b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/resources/plugin.yml
similarity index 100%
rename from PlayWallPluginEqualizer/src/main/resources/plugin.yml
rename to PlayWallPlugins/PlayWallPluginEqualizer/src/main/resources/plugin.yml
diff --git a/PlayWallPluginEqualizer/src/main/resources/style/style.css b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/resources/style/style.css
similarity index 100%
rename from PlayWallPluginEqualizer/src/main/resources/style/style.css
rename to PlayWallPlugins/PlayWallPluginEqualizer/src/main/resources/style/style.css
diff --git a/PlayWallPluginEqualizer/src/main/resources/view/equalizerView.fxml b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/resources/view/equalizerView.fxml
similarity index 77%
rename from PlayWallPluginEqualizer/src/main/resources/view/equalizerView.fxml
rename to PlayWallPlugins/PlayWallPluginEqualizer/src/main/resources/view/equalizerView.fxml
index 3bbcecebf50eb6f9c97056e79b7537250d837ca1..9a62e73dd124bd2c63a8b3df452318d883ff89af 100644
--- a/PlayWallPluginEqualizer/src/main/resources/view/equalizerView.fxml
+++ b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/resources/view/equalizerView.fxml
@@ -9,16 +9,16 @@
         <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"
+                  onAction="#enableCheckBoxHandler" text="%plugin.equalizer.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"
+                        onAction="#resetButtonHandler" text="%plugin.equalizer.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"
+                        onAction="#finishButtonHandler" text="%plugin.equalizer.button.finish" AnchorPane.bottomAnchor="10.0"
                         AnchorPane.rightAnchor="14.0"/>
             </children>
         </HBox>
diff --git a/PlayWallPluginLaunchpad/pom.xml b/PlayWallPlugins/PlayWallPluginLaunchpad/pom.xml
similarity index 86%
rename from PlayWallPluginLaunchpad/pom.xml
rename to PlayWallPlugins/PlayWallPluginLaunchpad/pom.xml
index 592679ca5ac4266e4121866e2d7ad505f11878a0..f1c9f0194a904834ccd797601f47f8a3f57c5270 100644
--- a/PlayWallPluginLaunchpad/pom.xml
+++ b/PlayWallPlugins/PlayWallPluginLaunchpad/pom.xml
@@ -6,14 +6,14 @@
 
     <parent>
         <groupId>de.tobias.playpad</groupId>
-        <artifactId>PlayWallDesktop</artifactId>
-        <version>6.2.0-SNAPSHOT</version>
+        <artifactId>PlayWallPlugins</artifactId>
+        <version>7.0.0</version>
     </parent>
 
     <artifactId>PlayWallPluginLaunchpad</artifactId>
 
     <properties>
-        <project.outputDirectory>../build/${project.version}</project.outputDirectory>
+        <project.outputDirectory>../../build/${project.version}</project.outputDirectory>
         <project.artifactName>${project.artifactId}-v${project.version}</project.artifactName>
     </properties>
 
@@ -74,19 +74,19 @@
         <repository>
             <id>release</id>
             <name>TheCodeLabs-releases</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
         </repository>
         <snapshotRepository>
             <id>snapshots</id>
             <name>TheCodeLabs-snapshots</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
         </snapshotRepository>
     </distributionManagement>
 
     <repositories>
         <repository>
             <id>release</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
             <releases>
                 <enabled>true</enabled>
             </releases>
@@ -96,7 +96,7 @@
         </repository>
         <repository>
             <id>snapshots</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
             <releases>
                 <enabled>false</enabled>
             </releases>
diff --git a/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java
similarity index 67%
rename from PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java
rename to PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java
index dd80ff18daac0fbe98d9f4c2bacd95a259daef68..3c153f971bccd8dc41be1b3c7cd99470d0c89286 100644
--- a/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java
+++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java
@@ -1,11 +1,11 @@
 package de.tobias.playpad.launchpadplugin.impl;
 
 import de.thecodelabs.logger.Logger;
+import de.thecodelabs.midi.midi.feedback.MidiFeedbackTranscriptionRegistry;
 import de.thecodelabs.plugins.PluginArtifact;
 import de.thecodelabs.plugins.PluginDescriptor;
 import de.tobias.playpad.launchpadplugin.midi.mk2.LaunchPadMK2;
 import de.tobias.playpad.launchpadplugin.midi.s.LaunchPadS;
-import de.tobias.playpad.midi.device.DeviceRegistry;
 import de.tobias.playpad.plugin.Module;
 import de.tobias.playpad.plugin.PlayPadPluginStub;
 
@@ -18,9 +18,11 @@ public class LaunchpadPluginImpl implements PlayPadPluginStub, PluginArtifact {
 	public void startup(PluginDescriptor descriptor) {
 		module = new Module(descriptor.getName(), descriptor.getArtifactId());
 
-		DeviceRegistry deviceFactory = DeviceRegistry.getFactoryInstance();
-		deviceFactory.registerDevice(LaunchPadMK2.NAME, LaunchPadMK2.class);
-		deviceFactory.registerDevice(LaunchPadS.NAME, LaunchPadS.class);
+		final MidiFeedbackTranscriptionRegistry registry = MidiFeedbackTranscriptionRegistry.getInstance();
+		registry.register(LaunchPadMK2.NAME, new LaunchPadMK2());
+		registry.register(LaunchPadMK2.NATIVE_NAME, new LaunchPadMK2());
+		registry.register(LaunchPadS.NAME, new LaunchPadS());
+		registry.register(LaunchPadS.NATIVE_NAME, new LaunchPadS());
 
 		Logger.debug("Enable LaunchPad Plugin");
 	}
diff --git a/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/MapParser.java b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/MapParser.java
similarity index 96%
rename from PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/MapParser.java
rename to PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/MapParser.java
index 47619aaa58b99b520c692502ba98bf1c6fced0ea..6870092286dc3456b5a0991a3f032792ef845e76 100644
--- a/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/MapParser.java
+++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/MapParser.java
@@ -9,6 +9,9 @@ import java.util.Map;
 
 public class MapParser {
 
+	private MapParser() {
+	}
+
 	public static Map<String, String> load(URL resource) throws IOException {
 		Map<String, String> items = new HashMap<>();
 		for (String line : IOUtils.readURL(resource).split("\n")) {
diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk2/LaunchPadMK2.java b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk2/LaunchPadMK2.java
new file mode 100644
index 0000000000000000000000000000000000000000..bd6f1c60c5d2bf91a7d71ee5fcf51429fdf258f8
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk2/LaunchPadMK2.java
@@ -0,0 +1,108 @@
+package de.tobias.playpad.launchpadplugin.midi.mk2;
+
+import de.thecodelabs.logger.Logger;
+import de.thecodelabs.midi.feedback.Feedback;
+import de.thecodelabs.midi.feedback.FeedbackColor;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.feedback.FeedbackValue;
+import de.thecodelabs.midi.mapping.MidiKey;
+import de.thecodelabs.midi.midi.Midi;
+import de.thecodelabs.midi.midi.MidiCommand;
+import de.thecodelabs.midi.midi.MidiCommandType;
+import de.thecodelabs.midi.midi.feedback.MidiFeedbackTranscript;
+import de.tobias.playpad.action.feedback.FeedbackColorSuggester;
+import de.tobias.playpad.action.feedback.LightMode;
+import de.tobias.playpad.launchpadplugin.impl.MapParser;
+import de.tobias.playpad.profile.Profile;
+import javafx.scene.paint.Color;
+
+import java.net.URL;
+import java.util.Map;
+import java.util.Optional;
+
+public class LaunchPadMK2 implements MidiFeedbackTranscript, FeedbackColorSuggester {
+
+	public static final String NAME = "Launchpad MK2";
+	public static final String NATIVE_NAME = "CoreMIDI4J - Launchpad MK2";
+
+	// Modern Colors mapped to the colors of the launchpad
+	private static Map<String, String> mapProperties;
+
+	static {
+		try {
+			URL resource = LaunchPadMK2.class.getClassLoader().getResource("launchpad_mk2.map");
+			mapProperties = MapParser.load(resource);
+		} catch (Exception e) {
+			Logger.error(e);
+		}
+	}
+
+	@Override
+	public void clearFeedback() {
+		final int maxMainKeyNumber = 89;
+
+		for (byte i = 11; i <= maxMainKeyNumber; i++) {
+			Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.NOTE_ON, i, (byte) 0));
+		}
+
+		// Obere Reihe an Tasten
+		final int liveKeyMin = 104;
+		final int liveKeyMax = 111;
+
+		for (byte i = liveKeyMin; i <= liveKeyMax; i++) {
+			Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.CONTROL_CHANGE, i, (byte) 0));
+		}
+	}
+
+	@Override
+	public void sendFeedback(MidiKey midiKey, FeedbackType feedbackType) {
+		final byte key = midiKey.getValue();
+
+		if (feedbackType == FeedbackType.NONE) {
+			if (key >= 104 && key <= 111) {
+				Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.CONTROL_CHANGE, key, (byte) 0));
+			} else {
+				Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.NOTE_ON, key, (byte) 0));
+			}
+		}
+
+		Feedback feedback = midiKey.getFeedbackForType(feedbackType);
+
+		if (feedback == null) {
+			return;
+		}
+
+		final byte value = feedback.getValue();
+
+		if (key >= 104 && key <= 111) {
+			Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.CONTROL_CHANGE, key, value));
+		} else {
+			if (feedbackType == FeedbackType.WARNING) {
+				sendFeedback(midiKey, FeedbackType.DEFAULT);
+			}
+			Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.NOTE_ON, feedback.getChannel(), key, value));
+		}
+	}
+
+	@Override
+	public FeedbackValue[] getFeedbackValues() {
+		return LaunchPadMK2Color.values();
+	}
+
+	@Override
+	public Optional<FeedbackValue> getFeedbackValueOfByte(byte b) {
+		return Optional.ofNullable(LaunchPadMK2Color.valueOf(b));
+	}
+
+	@Override
+	public FeedbackColor suggest(Color color) {
+		if (mapProperties.containsKey(color.toString())) {
+			String nameOfConst = mapProperties.get(color.toString());
+			final LaunchPadMK2Color mk2Color = LaunchPadMK2Color.valueOf(nameOfConst);
+
+			LightMode lightMode = Profile.currentProfile().getProfileSettings().getLightMode();
+			return mk2Color.translate(lightMode);
+		}
+		return null;
+	}
+}
diff --git a/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk2/LaunchPadMK2Color.java b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk2/LaunchPadMK2Color.java
similarity index 83%
rename from PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk2/LaunchPadMK2Color.java
rename to PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk2/LaunchPadMK2Color.java
index 750da844cbfb607017bacd3f4c45d335d8f4b3d3..a0d357257ae6fe9a7ec84e15eb65ad904d5471c9 100644
--- a/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk2/LaunchPadMK2Color.java
+++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk2/LaunchPadMK2Color.java
@@ -1,9 +1,11 @@
 package de.tobias.playpad.launchpadplugin.midi.mk2;
 
-import de.tobias.playpad.action.feedback.DisplayableFeedbackColor;
+import de.thecodelabs.midi.feedback.FeedbackColor;
+import de.tobias.playpad.action.feedback.LightMode;
 import javafx.scene.paint.Color;
+import javafx.scene.paint.Paint;
 
-public enum LaunchPadMK2Color implements DisplayableFeedbackColor {
+public enum LaunchPadMK2Color implements FeedbackColor, LightMode.ILightMode {
 
 	// White
 	C0_1(1, Color.rgb(255, 255, 255), LightMode.LOW),
@@ -98,16 +100,7 @@ public enum LaunchPadMK2Color implements DisplayableFeedbackColor {
 	C15_1(60, Color.rgb(255, 100, 69), LightMode.HIGH),
 	C15_2(61, Color.rgb(255, 100, 69), LightMode.NORMAL),
 	C15_3(62, Color.rgb(255, 100, 69), LightMode.MIDDLE),
-	C15_4(63, Color.rgb(255, 100, 69), LightMode.LOW),
-
-	;
-
-	public enum LightMode {
-		LOW,
-		MIDDLE,
-		NORMAL,
-		HIGH
-	}
+	C15_4(63, Color.rgb(255, 100, 69), LightMode.LOW);
 
 	private int midi;
 	private Color color;
@@ -119,19 +112,38 @@ public enum LaunchPadMK2Color implements DisplayableFeedbackColor {
 		this.lightMode = lightMode;
 	}
 
+
 	@Override
-	public int mapperFeedbackValue() {
-		return midi;
+	public Paint getColor() {
+		return color;
 	}
 
 	@Override
-	public Color getPaint() {
-		return color;
+	public byte getValue() {
+		return (byte) midi;
+	}
+
+	@Override
+	public LightMode getLightMode() {
+		return lightMode;
+	}
+
+	@Override
+	public FeedbackColor translate(LightMode lightMode) {
+		for (LaunchPadMK2Color instance : values()) {
+			if (instance.getColor().equals(this.getColor())) {
+				if (instance.lightMode == lightMode) {
+					return instance;
+				}
+			}
+		}
+		return null;
 	}
 
-	public static DisplayableFeedbackColor valueOf(int id) {
+
+	public static FeedbackColor valueOf(int id) {
 		for (LaunchPadMK2Color color : values()) {
-			if (color.mapperFeedbackValue() == id) {
+			if (color.getValue() == id) {
 				return color;
 			}
 		}
diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/s/LaunchPadS.java b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/s/LaunchPadS.java
new file mode 100644
index 0000000000000000000000000000000000000000..5430a12198e95a567572cf49d18aa3077b5cd4b9
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/s/LaunchPadS.java
@@ -0,0 +1,62 @@
+package de.tobias.playpad.launchpadplugin.midi.s;
+
+import de.thecodelabs.midi.feedback.Feedback;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.feedback.FeedbackValue;
+import de.thecodelabs.midi.mapping.MidiKey;
+import de.thecodelabs.midi.midi.Midi;
+import de.thecodelabs.midi.midi.MidiCommand;
+import de.thecodelabs.midi.midi.MidiCommandType;
+import de.thecodelabs.midi.midi.feedback.MidiFeedbackTranscript;
+
+import java.util.Optional;
+
+public class LaunchPadS implements MidiFeedbackTranscript {
+
+	public static final String NAME = "Launchpad S";
+	public static final String NATIVE_NAME = "CoreMIDI4J - Launchpad S";
+
+	@Override
+	public void sendFeedback(MidiKey midiKey, FeedbackType feedbackType) {
+		initDevice();
+
+		MidiCommandType command = MidiCommandType.NOTE_ON;
+		byte key = midiKey.getValue();
+
+		if (key >= 104 && key <= 111) {
+			command = MidiCommandType.CONTROL_CHANGE;
+		}
+
+		Feedback feedback = midiKey.getFeedbackForType(feedbackType);
+
+		if (feedback == null) {
+			return;
+		}
+
+		if (feedbackType != FeedbackType.WARNING) {
+			Midi.getInstance().sendMessage(new MidiCommand(command, key, feedback.getValue()));
+		} else {
+			Midi.getInstance().sendMessage(new MidiCommand(command, key, (byte) (feedback.getValue() - 4)));
+		}
+	}
+
+	@Override
+	public FeedbackValue[] getFeedbackValues() {
+		return LaunchPadSColor.values();
+	}
+
+	@Override
+	public Optional<FeedbackValue> getFeedbackValueOfByte(byte b) {
+		return Optional.ofNullable(LaunchPadSColor.valueOf(b));
+	}
+
+	public void initDevice() {
+		// Flash Enable
+		Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.CONTROL_CHANGE, (byte) 0, (byte) 40));
+	}
+
+	@Override
+	public void clearFeedback() {
+		Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.CONTROL_CHANGE, (byte) 0, (byte) 0));
+	}
+}
diff --git a/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/s/LaunchPadSColor.java b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/s/LaunchPadSColor.java
similarity index 60%
rename from PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/s/LaunchPadSColor.java
rename to PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/s/LaunchPadSColor.java
index 2d5ba4b94a16f8f7e848bf821eed822816a84187..b7c0439db9c9733d1f2d1b45d5b2419a8f440118 100644
--- a/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/s/LaunchPadSColor.java
+++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/s/LaunchPadSColor.java
@@ -1,9 +1,10 @@
 package de.tobias.playpad.launchpadplugin.midi.s;
 
-import de.tobias.playpad.action.feedback.DisplayableFeedbackColor;
+import de.thecodelabs.midi.feedback.FeedbackColor;
 import javafx.scene.paint.Color;
+import javafx.scene.paint.Paint;
 
-public enum LaunchPadSColor implements DisplayableFeedbackColor {
+public enum LaunchPadSColor implements FeedbackColor {
 
 	YELLOW(62, Color.YELLOW),
 	AMBER(63, Color.WHEAT),
@@ -19,22 +20,22 @@ public enum LaunchPadSColor implements DisplayableFeedbackColor {
 		this.color = color;
 	}
 
-	@Override
-	public int mapperFeedbackValue() {
-		return midi;
+	public static FeedbackColor valueOf(byte id) {
+		for (LaunchPadSColor color : values()) {
+			if (color.getValue() == id) {
+				return color;
+			}
+		}
+		return null;
 	}
 
 	@Override
-	public Color getPaint() {
+	public Paint getColor() {
 		return color;
 	}
 
-	public static DisplayableFeedbackColor valueOf(int id) {
-		for (LaunchPadSColor color : values()) {
-			if (color.mapperFeedbackValue() == id) {
-				return color;
-			}
-		}
-		return null;
+	@Override
+	public byte getValue() {
+		return (byte) midi;
 	}
 }
diff --git a/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk2.map b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk2.map
similarity index 100%
rename from PlayWallPluginLaunchpad/src/main/resources/launchpad_mk2.map
rename to PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk2.map
diff --git a/PlayWallPluginLaunchpad/src/main/resources/plugin.yml b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/plugin.yml
similarity index 100%
rename from PlayWallPluginLaunchpad/src/main/resources/plugin.yml
rename to PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/plugin.yml
diff --git a/PlayWallPluginMedia/pom.xml b/PlayWallPlugins/PlayWallPluginMedia/pom.xml
similarity index 86%
rename from PlayWallPluginMedia/pom.xml
rename to PlayWallPlugins/PlayWallPluginMedia/pom.xml
index 8f5e729cda8a8417f0427191cb27c6147eb41bc6..d5f6d3fd27513fd1353c526155279ff694bc9983 100644
--- a/PlayWallPluginMedia/pom.xml
+++ b/PlayWallPlugins/PlayWallPluginMedia/pom.xml
@@ -6,14 +6,14 @@
 
     <parent>
         <groupId>de.tobias.playpad</groupId>
-        <artifactId>PlayWallDesktop</artifactId>
-        <version>6.2.0-SNAPSHOT</version>
+        <artifactId>PlayWallPlugins</artifactId>
+        <version>7.0.0</version>
     </parent>
 
     <artifactId>PlayWallPluginMedia</artifactId>
 
     <properties>
-        <project.outputDirectory>../build/${project.version}</project.outputDirectory>
+        <project.outputDirectory>../../build/${project.version}</project.outputDirectory>
         <project.artifactName>${project.artifactId}-v${project.version}</project.artifactName>
     </properties>
 
@@ -74,19 +74,19 @@
         <repository>
             <id>release</id>
             <name>TheCodeLabs-releases</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
         </repository>
         <snapshotRepository>
             <id>snapshots</id>
             <name>TheCodeLabs-snapshots</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
         </snapshotRepository>
     </distributionManagement>
 
     <repositories>
         <repository>
             <id>release</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
             <releases>
                 <enabled>true</enabled>
             </releases>
@@ -96,7 +96,7 @@
         </repository>
         <repository>
             <id>snapshots</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
             <releases>
                 <enabled>false</enabled>
             </releases>
diff --git a/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/BlackAction.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/BlackAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..7fcabacfd522e5558f1c99de99faa4fa58b0164b
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/BlackAction.java
@@ -0,0 +1,28 @@
+package de.tobias.playpad.plugin.media.action;
+
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.event.KeyEvent;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.tobias.playpad.plugin.media.main.impl.MediaPluginImpl;
+
+public class BlackAction extends ActionHandler {
+
+	public static final String TYPE = "BLACK";
+
+	@Override
+	public String actionType() {
+		return TYPE;
+	}
+
+	@Override
+	public FeedbackType handle(KeyEvent keyEvent, Action action) {
+		MediaPluginImpl.blindProperty().set(!MediaPluginImpl.blindProperty().get());
+		return getCurrentFeedbackType(action);
+	}
+
+	@Override
+	public FeedbackType getCurrentFeedbackType(Action action) {
+		return MediaPluginImpl.blindProperty().getValue() ? FeedbackType.EVENT : FeedbackType.DEFAULT;
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/BlackActionProvider.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/BlackActionProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..266e1ecedb8327cfc672fa944d970c6cc4b22258
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/BlackActionProvider.java
@@ -0,0 +1,63 @@
+package de.tobias.playpad.plugin.media.action;
+
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.mapping.KeyType;
+import de.tobias.playpad.action.ActionProvider;
+import de.tobias.playpad.action.ActionType;
+import de.tobias.playpad.action.settings.ActionSettingsEntry;
+import de.tobias.playpad.plugin.media.action.settings.BlackActionTypeSettingsEntry;
+import javafx.scene.control.TreeItem;
+
+import java.util.List;
+
+import static de.tobias.playpad.plugin.media.action.BlackAction.TYPE;
+
+public class BlackActionProvider extends ActionProvider {
+
+	public BlackActionProvider(String type) {
+		super(TYPE);
+	}
+
+	@Override
+	public String getType() {
+		return TYPE;
+	}
+
+	@Override
+	public void createDefaultActions(Mapping mapping) {
+		mapping.addUniqueAction(new Action(getType()));
+	}
+
+	@Override
+	public ActionHandler getActionHandler() {
+		return new BlackAction();
+	}
+
+	@Override
+	public FeedbackType[] supportedFeedbackOptions(Action action, KeyType keyType) {
+		switch (keyType) {
+			case KEYBOARD:
+				return new FeedbackType[0];
+			case MIDI:
+				return new FeedbackType[]{FeedbackType.DEFAULT, FeedbackType.EVENT};
+		}
+		return new FeedbackType[0];
+	}
+
+	/*
+
+	 */
+
+	@Override
+	public ActionType getActionType() {
+		return ActionType.SETTINGS;
+	}
+
+	@Override
+	public TreeItem<ActionSettingsEntry> getTreeItemForActions(List<Action> actions, Mapping mapping) {
+		return new TreeItem<>(new BlackActionTypeSettingsEntry(actions.stream().findFirst().orElse(null)));
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/settings/BlackActionTypeSettingsEntry.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/settings/BlackActionTypeSettingsEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..26eaff5c46399734e4b3dc2cd0bdc6940dff01dc
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/action/settings/BlackActionTypeSettingsEntry.java
@@ -0,0 +1,39 @@
+package de.tobias.playpad.plugin.media.action.settings;
+
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.action.settings.ActionSettingsEntry;
+import de.tobias.playpad.action.settings.ActionSettingsMappable;
+import de.tobias.playpad.viewcontroller.IMappingTabViewController;
+
+public class BlackActionTypeSettingsEntry implements ActionSettingsEntry, ActionSettingsMappable {
+
+	private Action action;
+
+	public BlackActionTypeSettingsEntry(Action action) {
+		this.action = action;
+	}
+
+	@Override
+	public Action getAction() {
+		return action;
+	}
+
+	@Override
+	public String getName() {
+		return Localization.getString("plugin.media.black_action.name");
+	}
+
+	@Override
+	public FontIcon getIcon() {
+		return null;
+	}
+
+	@Override
+	public NVC getDetailSettingsController(Mapping mapping, IMappingTabViewController controller) {
+		return null;
+	}
+}
diff --git a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImageContent.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImageContent.java
similarity index 94%
rename from PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImageContent.java
rename to PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImageContent.java
index 07690ba2b8971f4e571c9ef63ed626cff73c5ca6..02a9b5c4b719d5de1b2d6df56893f91cb701df54 100644
--- a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImageContent.java
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImageContent.java
@@ -86,8 +86,8 @@ public class ImageContent extends PadContent {
 	}
 
 	@Override
-	public PadContent clone() throws CloneNotSupportedException {
-		ImageContent clone = (ImageContent) super.clone();
+	public PadContent copy(Pad pad) {
+		ImageContent clone = new ImageContent(getType(), pad);
 		clone.loadMedia();
 		return clone;
 	}
diff --git a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImagePadContentFactory.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImagePadContentFactory.java
similarity index 99%
rename from PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImagePadContentFactory.java
rename to PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImagePadContentFactory.java
index e8861e05f372edc947007c8d16ed5392a06c52c2..4a9a5ec7b072aa401cb87eea1093050a199b6539 100644
--- a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImagePadContentFactory.java
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImagePadContentFactory.java
@@ -96,7 +96,7 @@ public class ImagePadContentFactory extends PadContentFactory {
 		}
 
 		@Override
-		public void deinit() {
+		public void deInit() {
 			nameLabel.textProperty().unbind();
 		}
 
diff --git a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/VideoSettings.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/VideoSettings.java
similarity index 89%
rename from PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/VideoSettings.java
rename to PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/VideoSettings.java
index a5f895fac8241f3c426edb65c9c13e5f95cd6238..db2d994eaf1b681c41af4daffb25fbca1ea039b1 100644
--- a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/VideoSettings.java
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/VideoSettings.java
@@ -52,11 +52,11 @@ public class VideoSettings {
 			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()));
+				setScreenId(Integer.parseInt(root.element(SCREEN_ID_ELEMENT).getStringValue()));
 			if (root.element(FULL_SCREEN_ELEMENT) != null)
-				setFullScreen(Boolean.valueOf(root.element(FULL_SCREEN_ELEMENT).getStringValue()));
+				setFullScreen(Boolean.parseBoolean(root.element(FULL_SCREEN_ELEMENT).getStringValue()));
 			if (root.element(OPEN_AT_LAUNCH_ELEMENT) != null)
-				setOpenAtLaunch(Boolean.valueOf(root.element(OPEN_AT_LAUNCH_ELEMENT).getStringValue()));
+				setOpenAtLaunch(Boolean.parseBoolean(root.element(OPEN_AT_LAUNCH_ELEMENT).getStringValue()));
 		}
 	}
 
diff --git a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaPluginImpl.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaPluginImpl.java
similarity index 82%
rename from PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaPluginImpl.java
rename to PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaPluginImpl.java
index 0a93f6de9c6daa3af0bdaa46d50b9feebe7fa037..0565647dc30745ffb5da019f0910176bad972704 100644
--- a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaPluginImpl.java
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaPluginImpl.java
@@ -1,6 +1,7 @@
 package de.tobias.playpad.plugin.media.main.impl;
 
 import de.thecodelabs.logger.Logger;
+import de.thecodelabs.midi.action.ActionRegistry;
 import de.thecodelabs.plugins.PluginArtifact;
 import de.thecodelabs.plugins.PluginDescriptor;
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
@@ -13,6 +14,7 @@ import de.tobias.playpad.pad.content.PadContentFactory;
 import de.tobias.playpad.plugin.Module;
 import de.tobias.playpad.plugin.PlayPadPluginStub;
 import de.tobias.playpad.plugin.SettingsListener;
+import de.tobias.playpad.plugin.media.action.BlackAction;
 import de.tobias.playpad.plugin.media.main.VideoSettings;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.registry.Registry;
@@ -29,7 +31,6 @@ import org.dom4j.DocumentException;
 import java.io.IOException;
 import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
-import java.util.ResourceBundle;
 
 public class MediaPluginImpl implements PlayPadPluginStub, PluginArtifact, SettingsListener, ChangeListener<Boolean> {
 
@@ -39,7 +40,6 @@ public class MediaPluginImpl implements PlayPadPluginStub, PluginArtifact, Setti
 	private MediaViewController videoViewController;
 	private VideoSettings settings = new VideoSettings();
 
-	private ResourceBundle bundle;
 	private HUD blindHUD;
 	private static BooleanProperty blindProperty;
 
@@ -53,42 +53,45 @@ public class MediaPluginImpl implements PlayPadPluginStub, PluginArtifact, Setti
 
 		MediaPluginImpl.blindProperty = new SimpleBooleanProperty();
 
-		bundle = Localization.loadBundle("lang/video", getClass().getClassLoader());
-		videoViewController = new MediaViewController(settings);
-
 		// Load Content Types
+		Localization.addResourceBundle("lang/video", getClass().getClassLoader());
 		try {
 			Registry<PadContentFactory> padContents = PlayPadPlugin.getRegistries().getPadContents();
-			padContents.loadComponentsFromFile("PadContent.xml", getClass().getClassLoader(), module, bundle);
+			padContents.loadComponentsFromFile("PadContent.xml", getClass().getClassLoader(), module, Localization.getBundle());
+
+			ActionRegistry.registerActionHandler(new BlackAction());
 		} catch (Exception e) {
 			Logger.error(e);
 		}
 
 		PlayPadPlugin.getInstance().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);
-			});
-		}
+		Platform.runLater(() -> {
+			videoViewController = new MediaViewController(settings);
+
+			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);
+				});
+			}
+		});
 
 		try {
 			Registry<ActionProvider> padContents = PlayPadPlugin.getRegistries().getActions();
-			padContents.loadComponentsFromFile("Actions.xml", getClass().getClassLoader(), module, bundle);
+			padContents.loadComponentsFromFile("Actions.xml", getClass().getClassLoader(), module, Localization.getBundle());
 		} catch (Exception e) {
 			Logger.error(e);
 		}
@@ -142,10 +145,6 @@ public class MediaPluginImpl implements PlayPadPluginStub, PluginArtifact, Setti
 		return videoViewController;
 	}
 
-	public ResourceBundle getBundle() {
-		return bundle;
-	}
-
 	public static BooleanProperty blindProperty() {
 		return blindProperty;
 	}
diff --git a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaSettingsTabViewController.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaSettingsTabViewController.java
similarity index 94%
rename from PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaSettingsTabViewController.java
rename to PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaSettingsTabViewController.java
index a3833257ae7c3731f80d2aa3fe15b29caad637ae..2d0c0e7996d1e3d1045e901c81403dd6177a7868 100644
--- a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaSettingsTabViewController.java
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaSettingsTabViewController.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.plugin.media.main.impl;
 
+import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.plugin.media.main.VideoSettings;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.profile.ProfileSettings;
@@ -19,7 +20,6 @@ import javafx.stage.Screen;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.ResourceBundle;
 
 public class MediaSettingsTabViewController extends ProfileSettingsTabViewController implements IProfileReloadTask {
 
@@ -33,14 +33,12 @@ public class MediaSettingsTabViewController extends ProfileSettingsTabViewContro
 	private CheckBox videoOpenAtLaunchCheckBox;
 
 	private VideoSettings settings;
-	private ResourceBundle bundle;
 
 	private boolean changeSettings = false;
 
 	public MediaSettingsTabViewController(VideoSettings settings) {
-		load("view", "SettingsPane", MediaPluginImpl.getInstance().getBundle());
+		load("view", "SettingsPane", Localization.getBundle());
 		this.settings = settings;
-		this.bundle = MediaPluginImpl.getInstance().getBundle();
 	}
 
 	@Override
@@ -135,6 +133,6 @@ public class MediaSettingsTabViewController extends ProfileSettingsTabViewContro
 
 	@Override
 	public String name() {
-		return bundle.getString("settings.tab");
+		return Localization.getString("plugin.media.settings.tab");
 	}
 }
diff --git a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaViewController.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaViewController.java
similarity index 98%
rename from PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaViewController.java
rename to PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaViewController.java
index 2137c19d1406374241fa51e1f2cc45acf1bd2e28..0fc73f78e3662bcc5411bc07689ede642f3c991c 100644
--- a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaViewController.java
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaViewController.java
@@ -64,7 +64,7 @@ public class MediaViewController implements ProfileListener {
 
 		stage = new Stage();
 		stage.setScene(new Scene(stackPane, Color.BLACK));
-		PlayPadPlugin.getInstance().getIcon().ifPresent(stage.getIcons()::add);
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		Path path = ApplicationUtils.getApplication().getPath(PathType.CONFIGURATION, "style.css");
 		if (Files.exists(path))
diff --git a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoContent.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoContent.java
similarity index 93%
rename from PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoContent.java
rename to PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoContent.java
index fe6b9f5a47d2376dea7a3bd7d9eaa0226998a945..ba1af9b930e6d324e0d6e30b53644a8cb358aa5d 100644
--- a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoContent.java
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoContent.java
@@ -78,12 +78,11 @@ public class VideoContent extends PadContent implements Pauseable, Durationable,
 	public boolean stop() {
 		PadSettings padSettings = getPad().getPadSettings();
 
-		if (padSettings.getCustomSettings().containsKey(VIDEO_LAST_FRAME) && !holdLastFrame && getPad().isEof()) {
-			if ((boolean) padSettings.getCustomSettings().get(VIDEO_LAST_FRAME)) {
-				getPad().setStatus(PadStatus.PAUSE);
-				holdLastFrame = true;
-				return false;
-			}
+		if (padSettings.getCustomSettings().containsKey(VIDEO_LAST_FRAME) && !holdLastFrame && getPad().isEof() &&
+				(boolean) padSettings.getCustomSettings().get(VIDEO_LAST_FRAME)) {
+			getPad().setStatus(PadStatus.PAUSE);
+			holdLastFrame = true;
+			return false;
 		}
 		player.stop();
 		MediaPluginImpl.getInstance().getVideoViewController().setMediaPlayer(null, null);
@@ -212,8 +211,8 @@ public class VideoContent extends PadContent implements Pauseable, Durationable,
 	}
 
 	@Override
-	public PadContent clone() throws CloneNotSupportedException {
-		VideoContent clone = (VideoContent) super.clone();
+	public PadContent copy(Pad pad) {
+		VideoContent clone = new VideoContent(getType(), pad);
 		clone.loadMedia();
 		return clone;
 	}
diff --git a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadContentFactory.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadContentFactory.java
similarity index 98%
rename from PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadContentFactory.java
rename to PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadContentFactory.java
index d4e86fcdd06b1032e6206f36284ae6d471835d35..a8aca757db9af4a5e11da5973d0ffcd899ef1c37 100644
--- a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadContentFactory.java
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadContentFactory.java
@@ -73,7 +73,7 @@ public class VideoPadContentFactory extends PadContentFactory {
 		}
 
 		@Override
-		public void deinit() {
+		public void deInit() {
 			nameLabel.textProperty().unbind();
 		}
 	}
diff --git a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadSettingsTabViewController.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadSettingsTabViewController.java
similarity index 79%
rename from PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadSettingsTabViewController.java
rename to PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadSettingsTabViewController.java
index 08540d0f01a1f66b783df141bd2ccc4addadea29..3fc41155d4adc763851a44949396233530de031a 100644
--- a/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadSettingsTabViewController.java
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadSettingsTabViewController.java
@@ -1,7 +1,7 @@
 package de.tobias.playpad.plugin.media.video;
 
+import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.pad.Pad;
-import de.tobias.playpad.plugin.media.main.impl.MediaPluginImpl;
 import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
 import javafx.fxml.FXML;
 import javafx.scene.control.CheckBox;
@@ -12,12 +12,12 @@ public class VideoPadSettingsTabViewController extends PadSettingsTabViewControl
 	private CheckBox lastFrameCheckBox;
 
 	VideoPadSettingsTabViewController() {
-		load("view/", "SettingsPadPane", MediaPluginImpl.getInstance().getBundle());
+		load("view/", "SettingsPadPane", Localization.getBundle());
 	}
 
 	@Override
 	public String getName() {
-		return MediaPluginImpl.getInstance().getBundle().getString("settings.video.tab");
+		return Localization.getString("plugin.media.settings.video.tab");
 	}
 
 	@Override
diff --git a/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/Actions.xml b/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/Actions.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3fc9e2994c0c993db274036cf9b5aa5318c94eed
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/Actions.xml
@@ -0,0 +1,3 @@
+<Actions>
+    <Component id="BLACK" name="plugin.media.black_action.name">de.tobias.playpad.plugin.media.action.BlackActionProvider</Component>
+</Actions>
\ No newline at end of file
diff --git a/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/PadContent.xml b/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/PadContent.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6aeff86fed5dd04b1be71cfe467136de4cd59b36
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/PadContent.xml
@@ -0,0 +1,4 @@
+<Actions>
+    <Component id="video" name="plugin.media.content.Video.Name">de.tobias.playpad.plugin.media.video.VideoPadContentFactory</Component>
+    <Component id="image" name="plugin.media.content.Image.Name">de.tobias.playpad.plugin.media.image.ImagePadContentFactory</Component>
+</Actions>
\ No newline at end of file
diff --git a/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/lang/video_de.properties b/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/lang/video_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..b4e2cc373cd3aa650b56c85c43403ac848d009f3
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/lang/video_de.properties
@@ -0,0 +1,13 @@
+plugin.media.settings.tab=Video/Bild
+plugin.media.settings.video.tab=Video
+plugin.media.settings.video.label.screens=Bildschirme:
+plugin.media.settings.video.label.screenChoice=Bildschirm f\u00FCr Videowiedergabe:
+plugin.media.settings.video.checkbox.fullscreen=Vollbild
+plugin.media.settings.video.checkbox.openAtLaunch=Fenster beim Start \u00F6ffnen
+
+plugin.media.pad.label.lastFrame=Letztes Bild am Ende des Videos einfrieren (Freeze)
+plugin.media.pad.checkbox.lastFrame=Aktivieren
+
+plugin.media.black_action.name=Schwarzbild Video
+plugin.media.content.Video.Name=Video
+plugin.media.content.Image.Name=Bild
\ No newline at end of file
diff --git a/PlayWallPluginMedia/src/main/resources/plugin.yml b/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/plugin.yml
similarity index 100%
rename from PlayWallPluginMedia/src/main/resources/plugin.yml
rename to PlayWallPlugins/PlayWallPluginMedia/src/main/resources/plugin.yml
diff --git a/PlayWallPluginMedia/src/main/resources/view/SettingsPadPane.fxml b/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/view/SettingsPadPane.fxml
similarity index 85%
rename from PlayWallPluginMedia/src/main/resources/view/SettingsPadPane.fxml
rename to PlayWallPlugins/PlayWallPluginMedia/src/main/resources/view/SettingsPadPane.fxml
index d407cd939961b606b8adaee546afb3e65fd25b99..d87fee7e7b2cd3c9890cf0fb6f0127942944d1cc 100644
--- a/PlayWallPluginMedia/src/main/resources/view/SettingsPadPane.fxml
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/view/SettingsPadPane.fxml
@@ -9,9 +9,9 @@
         <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"/>
+                       text="%plugin.media.pad.label.lastFrame"/>
                 <CheckBox fx:id="lastFrameCheckBox" layoutX="14.0" layoutY="14.0" mnemonicParsing="false"
-                          text="%pad.checkbox.lastFrame"/>
+                          text="%plugin.media.pad.checkbox.lastFrame"/>
             </children>
         </HBox>
     </children>
diff --git a/PlayWallPluginMedia/src/main/resources/view/SettingsPane.fxml b/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/view/SettingsPane.fxml
similarity index 82%
rename from PlayWallPluginMedia/src/main/resources/view/SettingsPane.fxml
rename to PlayWallPlugins/PlayWallPluginMedia/src/main/resources/view/SettingsPane.fxml
index 1797ebe5e66ff909042861028d20dbac56b44351..3a22bd0688fedcbf8f1f1317bfd2e5bd9bd2ceb1 100644
--- a/PlayWallPluginMedia/src/main/resources/view/SettingsPane.fxml
+++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/resources/view/SettingsPane.fxml
@@ -9,7 +9,7 @@
         <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"/>
+                <Label text="%plugin.media.settings.video.label.screens"/>
                 <VBox alignment="TOP_CENTER">
                     <children>
                         <Pane fx:id="screenViewPane" prefWidth="617.0" VBox.vgrow="ALWAYS"/>
@@ -17,7 +17,7 @@
                 </VBox>
                 <HBox prefHeight="100.0" prefWidth="200.0" spacing="14.0">
                     <children>
-                        <Label text="%settings.video.label.screenChoice">
+                        <Label text="%plugin.media.settings.video.label.screenChoice">
                             <HBox.margin>
                                 <Insets top="4.0"/>
                             </HBox.margin>
@@ -26,9 +26,9 @@
                             <children>
                                 <ComboBox fx:id="screenComboBox" prefWidth="150.0"/>
                                 <CheckBox fx:id="fullscreenCheckBox" mnemonicParsing="false"
-                                          text="%settings.video.checkbox.fullscreen"/>
+                                          text="%plugin.media.settings.video.checkbox.fullscreen"/>
                                 <CheckBox fx:id="videoOpenAtLaunchCheckBox" mnemonicParsing="false"
-                                          text="%settings.video.checkbox.openAtLaunch"/>
+                                          text="%plugin.media.settings.video.checkbox.openAtLaunch"/>
                             </children>
                         </VBox>
                     </children>
diff --git a/PlayWallPluginNativeAudio/j4n/NAudio.dll b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/NAudio.dll
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/NAudio.dll
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/NAudio.dll
diff --git a/PlayWallPluginNativeAudio/j4n/NativeAudio.dll b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/NativeAudio.dll
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/NativeAudio.dll
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/NativeAudio.dll
diff --git a/PlayWallPluginNativeAudio/j4n/NativeAudio.j4n.dll b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/NativeAudio.j4n.dll
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/NativeAudio.j4n.dll
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/NativeAudio.j4n.dll
diff --git a/PlayWallPluginNativeAudio/j4n/NativeAudio.j4n.jar b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/NativeAudio.j4n.jar
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/NativeAudio.j4n.jar
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/NativeAudio.j4n.jar
diff --git a/PlayWallPluginNativeAudio/j4n/NativeAudio.proxygen.xml b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/NativeAudio.proxygen.xml
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/NativeAudio.proxygen.xml
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/NativeAudio.proxygen.xml
diff --git a/PlayWallPluginNativeAudio/j4n/build.cmd b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/build.cmd
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/build.cmd
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/build.cmd
diff --git a/PlayWallPluginNativeAudio/j4n/clr/nativeaudio/LoopStream.generated.cs b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/clr/nativeaudio/LoopStream.generated.cs
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/clr/nativeaudio/LoopStream.generated.cs
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/clr/nativeaudio/LoopStream.generated.cs
diff --git a/PlayWallPluginNativeAudio/j4n/clr/nativeaudio/NativeAudio.generated.cs b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/clr/nativeaudio/NativeAudio.generated.cs
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/clr/nativeaudio/NativeAudio.generated.cs
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/clr/nativeaudio/NativeAudio.generated.cs
diff --git a/PlayWallPluginNativeAudio/j4n/generate.bat b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/generate.bat
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/generate.bat
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/generate.bat
diff --git a/PlayWallPluginNativeAudio/j4n/jni4net.j-0.8.8.0.jar b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/jni4net.j-0.8.8.0.jar
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/jni4net.j-0.8.8.0.jar
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/jni4net.j-0.8.8.0.jar
diff --git a/PlayWallPluginNativeAudio/j4n/jni4net.n-0.8.8.0.dll b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/jni4net.n-0.8.8.0.dll
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/jni4net.n-0.8.8.0.dll
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/jni4net.n-0.8.8.0.dll
diff --git a/PlayWallPluginNativeAudio/j4n/jni4net.n.w32.v40-0.8.8.0.dll b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/jni4net.n.w32.v40-0.8.8.0.dll
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/jni4net.n.w32.v40-0.8.8.0.dll
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/jni4net.n.w32.v40-0.8.8.0.dll
diff --git a/PlayWallPluginNativeAudio/j4n/jni4net.n.w64.v40-0.8.8.0.dll b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/jni4net.n.w64.v40-0.8.8.0.dll
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/jni4net.n.w64.v40-0.8.8.0.dll
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/jni4net.n.w64.v40-0.8.8.0.dll
diff --git a/PlayWallPluginNativeAudio/j4n/jvm/nativeaudio/LoopStream.java b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/jvm/nativeaudio/LoopStream.java
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/jvm/nativeaudio/LoopStream.java
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/jvm/nativeaudio/LoopStream.java
diff --git a/PlayWallPluginNativeAudio/j4n/jvm/nativeaudio/NativeAudio.java b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/jvm/nativeaudio/NativeAudio.java
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/jvm/nativeaudio/NativeAudio.java
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/jvm/nativeaudio/NativeAudio.java
diff --git a/PlayWallPluginNativeAudio/j4n/proxygen.exe b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/proxygen.exe
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/proxygen.exe
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/proxygen.exe
diff --git a/PlayWallPluginNativeAudio/j4n/proxygen.exe.config b/PlayWallPlugins/PlayWallPluginNativeAudio/j4n/proxygen.exe.config
similarity index 100%
rename from PlayWallPluginNativeAudio/j4n/proxygen.exe.config
rename to PlayWallPlugins/PlayWallPluginNativeAudio/j4n/proxygen.exe.config
diff --git a/PlayWallPluginNativeAudio/pom.xml b/PlayWallPlugins/PlayWallPluginNativeAudio/pom.xml
similarity index 89%
rename from PlayWallPluginNativeAudio/pom.xml
rename to PlayWallPlugins/PlayWallPluginNativeAudio/pom.xml
index a66858a0aa6daa0530666ac65199fa6744d06b80..37ae3f2dc0e501acddd346ec5c2ab0aff044ac16 100644
--- a/PlayWallPluginNativeAudio/pom.xml
+++ b/PlayWallPlugins/PlayWallPluginNativeAudio/pom.xml
@@ -7,16 +7,15 @@
 
     <parent>
         <groupId>de.tobias.playpad</groupId>
-        <artifactId>PlayWallDesktop</artifactId>
-        <version>6.2.0-SNAPSHOT</version>
+        <artifactId>PlayWallPlugins</artifactId>
+        <version>7.0.0</version>
     </parent>
 
     <properties>
-        <scala-library.version>2.13.0</scala-library.version>
         <jni4net.j.version>0.8.8.0</jni4net.j.version>
         <nativeAudio.version>1.0.0</nativeAudio.version>
 
-        <project.outputDirectory>../build/${project.version}</project.outputDirectory>
+        <project.outputDirectory>../../build/${project.version}</project.outputDirectory>
         <project.artifactName>${project.artifactId}-v${project.version}</project.artifactName>
     </properties>
 
@@ -122,19 +121,19 @@
         <repository>
             <id>release</id>
             <name>TheCodeLabs-releases</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
         </repository>
         <snapshotRepository>
             <id>snapshots</id>
             <name>TheCodeLabs-snapshots</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
         </snapshotRepository>
     </distributionManagement>
 
     <repositories>
         <repository>
             <id>release</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
             <releases>
                 <enabled>true</enabled>
             </releases>
@@ -144,7 +143,7 @@
         </repository>
         <repository>
             <id>snapshots</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
             <releases>
                 <enabled>false</enabled>
             </releases>
diff --git a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/AVAudioPlayerBridge.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/AVAudioPlayerBridge.java
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/AVAudioPlayerBridge.java
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/AVAudioPlayerBridge.java
diff --git a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/AudioDevice.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/AudioDevice.java
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/AudioDevice.java
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/AudioDevice.java
diff --git a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/NativeAudioMacHandler.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/NativeAudioMacHandler.java
similarity index 96%
rename from PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/NativeAudioMacHandler.java
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/NativeAudioMacHandler.java
index 8407f4dd088658d9bf12f2dd5dbd3fe1563b390c..0e94b7cbc3e8cea525918de0eed9cd6bf12a433f 100644
--- a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/NativeAudioMacHandler.java
+++ b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/NativeAudioMacHandler.java
@@ -48,9 +48,6 @@ public class NativeAudioMacHandler extends AudioHandler implements Peakable, See
 	@Override
 	public void play() {
 		bridge.setLoop(getContent().getPad().getPadSettings().isLoop());
-		if (!getContent().getPad().isPaused()) {
-			bridge.seek(0); // Force player to seek to 0 sec for playing from start
-		}
 		bridge.play();
 	}
 
diff --git a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/NativeAudioMacHandlerFactory.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/NativeAudioMacHandlerFactory.java
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/NativeAudioMacHandlerFactory.java
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/NativeAudioMacHandlerFactory.java
diff --git a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/delegate/AVAudioPlayerBridgeDelegate.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/delegate/AVAudioPlayerBridgeDelegate.java
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/delegate/AVAudioPlayerBridgeDelegate.java
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/delegate/AVAudioPlayerBridgeDelegate.java
diff --git a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/settings/NativeAudioMacSettingsViewController.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/settings/NativeAudioMacSettingsViewController.java
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/settings/NativeAudioMacSettingsViewController.java
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/mac/settings/NativeAudioMacSettingsViewController.java
diff --git a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java
similarity index 98%
rename from PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java
index 54bc85c696df5c89e8203f87de4a60dea74b6e42..e0e75d8214d02545871f708dc5f0cacfe6bf9019 100644
--- a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java
+++ b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.audio.windows;
 
+import de.thecodelabs.logger.Logger;
 import de.tobias.playpad.audio.AudioHandler;
 import de.tobias.playpad.audio.Soundcardable;
 import de.tobias.playpad.pad.Pad;
@@ -72,7 +73,7 @@ public class NativeAudioWinHandler extends AudioHandler implements Soundcardable
 				} catch (InterruptedException e) {
 					break;
 				} catch (Exception e) {
-					e.printStackTrace();
+					Logger.error(e);
 				}
 			}
 		});
diff --git a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandlerFactory.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandlerFactory.java
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandlerFactory.java
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandlerFactory.java
diff --git a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinSettingsViewController.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinSettingsViewController.java
similarity index 98%
rename from PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinSettingsViewController.java
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinSettingsViewController.java
index e38eb3dcbbb3c7b61cfa8dd8eff4816fb54051c0..2cab6fd05236b841c0baf701f20b55e8b151630c 100644
--- a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinSettingsViewController.java
+++ b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinSettingsViewController.java
@@ -1,5 +1,6 @@
 package de.tobias.playpad.audio.windows;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.utils.application.App;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
@@ -95,7 +96,7 @@ public class NativeAudioWinSettingsViewController extends AudioHandlerViewContro
 					try {
 						Thread.sleep(50);
 					} catch (InterruptedException e) {
-						e.printStackTrace();
+						Logger.error(e);
 					}
 				}
 				if (audioPlayer != null)
diff --git a/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/plugin/NativeAudioPathType.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/plugin/NativeAudioPathType.java
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/plugin/NativeAudioPathType.java
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/plugin/NativeAudioPathType.java
diff --git a/PlayWallPluginNativeAudio/src/main/java/de_tobias_playpad_audio_mac_AVAudioPlayerBridge.h b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de_tobias_playpad_audio_mac_AVAudioPlayerBridge.h
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/java/de_tobias_playpad_audio_mac_AVAudioPlayerBridge.h
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de_tobias_playpad_audio_mac_AVAudioPlayerBridge.h
diff --git a/PlayWallPluginNativeAudio/src/main/resources/META-INF/MANIFEST.MF b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/META-INF/MANIFEST.MF
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/META-INF/MANIFEST.MF
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/META-INF/MANIFEST.MF
diff --git a/PlayWallPluginNativeAudio/src/main/resources/mac/libNativeAudio.dylib b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/mac/libNativeAudio.dylib
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/mac/libNativeAudio.dylib
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/mac/libNativeAudio.dylib
diff --git a/PlayWallPluginNativeAudio/src/main/resources/mac/namacSettings.fxml b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/mac/namacSettings.fxml
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/mac/namacSettings.fxml
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/mac/namacSettings.fxml
diff --git a/PlayWallPluginNativeAudio/src/main/resources/plugin.yml b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/plugin.yml
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/plugin.yml
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/plugin.yml
diff --git a/PlayWallPluginNativeAudio/src/main/resources/win/NAudio.dll b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/NAudio.dll
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/win/NAudio.dll
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/NAudio.dll
diff --git a/PlayWallPluginNativeAudio/src/main/resources/win/NativeAudio.dll b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/NativeAudio.dll
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/win/NativeAudio.dll
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/NativeAudio.dll
diff --git a/PlayWallPluginNativeAudio/src/main/resources/win/NativeAudio.j4n.dll b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/NativeAudio.j4n.dll
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/win/NativeAudio.j4n.dll
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/NativeAudio.j4n.dll
diff --git a/PlayWallPluginNativeAudio/src/main/resources/win/NativeAudio.j4n.jar b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/NativeAudio.j4n.jar
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/win/NativeAudio.j4n.jar
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/NativeAudio.j4n.jar
diff --git a/PlayWallPluginNativeAudio/src/main/resources/win/jni4net.j-0.8.8.0.jar b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/jni4net.j-0.8.8.0.jar
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/win/jni4net.j-0.8.8.0.jar
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/jni4net.j-0.8.8.0.jar
diff --git a/PlayWallPluginNativeAudio/src/main/resources/win/jni4net.n-0.8.8.0.dll b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/jni4net.n-0.8.8.0.dll
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/win/jni4net.n-0.8.8.0.dll
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/jni4net.n-0.8.8.0.dll
diff --git a/PlayWallPluginNativeAudio/src/main/resources/win/jni4net.n.w32.v40-0.8.8.0.dll b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/jni4net.n.w32.v40-0.8.8.0.dll
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/win/jni4net.n.w32.v40-0.8.8.0.dll
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/jni4net.n.w32.v40-0.8.8.0.dll
diff --git a/PlayWallPluginNativeAudio/src/main/resources/win/jni4net.n.w64.v40-0.8.8.0.dll b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/jni4net.n.w64.v40-0.8.8.0.dll
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/win/jni4net.n.w64.v40-0.8.8.0.dll
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/jni4net.n.w64.v40-0.8.8.0.dll
diff --git a/PlayWallPluginNativeAudio/src/main/resources/win/nawinSettings.fxml b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/nawinSettings.fxml
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/resources/win/nawinSettings.fxml
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/resources/win/nawinSettings.fxml
diff --git a/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/NativeAudioPluginImpl.scala b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/NativeAudioPluginImpl.scala
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/NativeAudioPluginImpl.scala
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/NativeAudioPluginImpl.scala
diff --git a/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/loader/AudioModuleLoader.scala b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/loader/AudioModuleLoader.scala
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/loader/AudioModuleLoader.scala
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/loader/AudioModuleLoader.scala
diff --git a/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/loader/MacAudioImplLoader.scala b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/loader/MacAudioImplLoader.scala
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/loader/MacAudioImplLoader.scala
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/loader/MacAudioImplLoader.scala
diff --git a/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/loader/WindowsAudioImplLoader.scala b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/loader/WindowsAudioImplLoader.scala
similarity index 100%
rename from PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/loader/WindowsAudioImplLoader.scala
rename to PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/loader/WindowsAudioImplLoader.scala
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/pom.xml b/PlayWallPlugins/PlayWallPluginPlayoutLog/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8aed454d716696eca879c7ab1a2e116fec8fde17
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/pom.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>de.tobias.playpad</groupId>
+        <artifactId>PlayWallPlugins</artifactId>
+        <version>7.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <properties>
+        <project.outputDirectory>../../build/${project.version}</project.outputDirectory>
+        <project.artifactName>${project.artifactId}-v${project.version}</project.artifactName>
+    </properties>
+
+    <artifactId>PlayWallPluginPlayoutLog</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>de.tobias.playpad</groupId>
+            <artifactId>PlayWallCore</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- PDF-->
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itextpdf</artifactId>
+            <version>${itextpdf.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-csv</artifactId>
+            <version>${jackson-dataformat-csv.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.module</groupId>
+            <artifactId>jackson-module-scala_2.13</artifactId>
+            <version>${jackson-dataformat-csv.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>de.thecodelabs</groupId>
+                <artifactId>versionizer-maven-plugin</artifactId>
+                <version>1.0.1</version>
+                <configuration>
+                    <resourceFile>plugin.yml</resourceFile>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>resource-fill</id>
+                        <goals>
+                            <goal>resource-fill</goal>
+                        </goals>
+                        <phase>compile</phase>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!--Scala Plugin-->
+            <plugin>
+                <groupId>net.alchim31.maven</groupId>
+                <artifactId>scala-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>scala-compile-first</id>
+                        <phase>process-resources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                            <goal>compile</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>scala-test-compile</id>
+                        <phase>process-test-resources</phase>
+                        <goals>
+                            <goal>testCompile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <version>3.1.1</version>
+                <configuration>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                    <outputDirectory>${project.outputDirectory}</outputDirectory>
+                    <finalName>${project.artifactName}</finalName>
+                    <appendAssemblyId>false</appendAssemblyId>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>assemble-all</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <distributionManagement>
+        <repository>
+            <id>release</id>
+            <name>TheCodeLabs-releases</name>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
+        </repository>
+        <snapshotRepository>
+            <id>snapshots</id>
+            <name>TheCodeLabs-snapshots</name>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+    <repositories>
+        <repository>
+            <id>release</id>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>snapshots</id>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+</project>
\ No newline at end of file
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/ColorUtils.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/ColorUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..2143f5e35d997c1d9176a03c99aeac929b8a9c36
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/ColorUtils.java
@@ -0,0 +1,21 @@
+package de.tobias.playpad.plugin.playout;
+
+import com.itextpdf.text.BaseColor;
+
+/**
+ * Created by tobias on 26.03.17.
+ */
+public class ColorUtils {
+
+	private ColorUtils() {
+	}
+
+	public static BaseColor toBaseColor(String hexCode) {
+		hexCode = hexCode.replace("#", "");
+		return new BaseColor(
+				Integer.valueOf(hexCode.substring(0, 2), 16),
+				Integer.valueOf(hexCode.substring(2, 4), 16),
+				Integer.valueOf(hexCode.substring(4, 6), 16)
+		);
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/PlayoutLogPlugin.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/PlayoutLogPlugin.java
new file mode 100644
index 0000000000000000000000000000000000000000..278ec6c4523045ae4784801f2b38d254efc57e0d
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/PlayoutLogPlugin.java
@@ -0,0 +1,70 @@
+package de.tobias.playpad.plugin.playout;
+
+import de.thecodelabs.logger.LogLevel;
+import de.thecodelabs.logger.Logger;
+import de.thecodelabs.plugins.PluginArtifact;
+import de.thecodelabs.plugins.PluginDescriptor;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.plugin.Module;
+import de.tobias.playpad.plugin.PlayPadPluginStub;
+import de.tobias.playpad.plugin.playout.log.LogSeasons;
+import de.tobias.playpad.plugin.playout.log.listener.PadPlayLogListener;
+import de.tobias.playpad.plugin.playout.viewcontroller.MainViewControllerListener;
+import de.tobias.playpad.plugin.playout.viewcontroller.PlayoutLogStatusIconListener;
+import de.tobias.playpad.settings.keys.Key;
+import de.tobias.playpad.settings.keys.KeyCollectionEntry;
+import de.tobias.playpad.settings.keys.KeyConflictException;
+
+@SuppressWarnings("unused")
+public class PlayoutLogPlugin implements PlayPadPluginStub, PluginArtifact {
+
+	private Module module;
+
+	public static final String KEY_COLLECTION_PLAYOUT = "playoutlog";
+
+	@Override
+	public void startup(PluginDescriptor descriptor) {
+		Localization.addResourceBundle("lang/playoutlog", getClass().getClassLoader());
+
+		module = new Module(descriptor.getName(), descriptor.getArtifactId());
+
+		// Register Key Mapping
+		KeyCollectionEntry keyCollectionEntry = new KeyCollectionEntry("Playout Log", new Key(KEY_COLLECTION_PLAYOUT));
+		try {
+			PlayPadPlugin.getInstance().getGlobalSettings().getKeyCollection().register(keyCollectionEntry);
+		} catch (KeyConflictException e) {
+			Logger.error(e);
+		}
+
+		PlayoutLogStatusIconListener playoutLogStatusIconListener = new PlayoutLogStatusIconListener();
+
+		PlayPadPlugin.getInstance().addMainViewListener(new MainViewControllerListener());
+		PlayPadPlugin.getInstance().addMainViewListener(playoutLogStatusIconListener);
+
+		PlayPadPlugin.getInstance().addGlobalListener(new ProjectListener());
+		PlayPadPlugin.getInstance().addPadListener(new PadPlayLogListener());
+
+		LogSeasons.addListener(playoutLogStatusIconListener);
+
+		PlayOutLogInitializer.init();
+
+		Logger.debug("Enable Playout Log Plugin");
+	}
+
+	@Override
+	public void shutdown() {
+		Logger.debug("Disable Playout Log Plugin");
+
+		try {
+			LogSeasons.getStorageHandler().close();
+		} catch (Exception e) {
+			Logger.log(LogLevel.ERROR, "Cannot close LogSeasonStorageHandler (" + e.getLocalizedMessage() + ")");
+		}
+	}
+
+	@Override
+	public Module getModule() {
+		return module;
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/Strings.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/Strings.java
new file mode 100644
index 0000000000000000000000000000000000000000..3de3d5a958aa526087d4d25ea52a02159f2a62e3
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/Strings.java
@@ -0,0 +1,17 @@
+package de.tobias.playpad.plugin.playout;
+
+public final class Strings {
+
+	private Strings() {
+	}
+
+	public static final String UI_DIALOG_PLAYOUT_LOG_TITLE = "UI.Dialog.PlayoutLog.Title";
+
+	public static final String MENU_ITEM_LOG = "main.menuitem.log";
+
+	public static final String PLAYOUT_LOG_DIALOG_LABEL_HEADLINE = "PlayoutLogDialog.Label.Headline";
+	public static final String PLAYOUT_LOG_DIALOG_BUTTON_START = "PlayoutLogDialog.Button.Start";
+	public static final String PLAYOUT_LOG_DIALOG_BUTTON_STOP = "PlayoutLogDialog.Button.Stop";
+	public static final String PLAYOUT_LOG_DIALOG_BUTTON_EXPORT = "PlayoutLogDialog.Button.Export";
+	public static final String PLAYOUT_LOG_DIALOG_BUTTON_DELETE = "PlayoutLogDialog.Button.Delete";
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/log/PlayoutLogPdfExport.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/export/PlayoutLogPdfExport.java
similarity index 93%
rename from PlayWall/src/main/java/de/tobias/playpad/log/PlayoutLogPdfExport.java
rename to PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/export/PlayoutLogPdfExport.java
index 383ac40182354577d0e94b5df0a21aab0c96bab5..b7507b32691a9c8caee562c878274a701163549f 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/log/PlayoutLogPdfExport.java
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/export/PlayoutLogPdfExport.java
@@ -1,9 +1,11 @@
-package de.tobias.playpad.log;
+package de.tobias.playpad.plugin.playout.export;
 
 import com.itextpdf.text.*;
 import com.itextpdf.text.pdf.*;
 import de.tobias.playpad.design.modern.ModernColor;
-import de.tobias.playpad.util.ColorUtils;
+import de.tobias.playpad.plugin.playout.ColorUtils;
+import de.tobias.playpad.plugin.playout.log.LogItem;
+import de.tobias.playpad.plugin.playout.log.LogSeason;
 
 import java.io.IOException;
 import java.nio.file.Files;
@@ -57,7 +59,7 @@ public class PlayoutLogPdfExport {
 					break;
 				}
 			}
-			logItemList.add(new LogItem(UUID.randomUUID(), "", "FFFFFF", page, i, season)); // add empty car
+			logItemList.add(new LogItem(UUID.randomUUID(), "", "FFFFFF", page, i, season)); // add empty cart
 			logItemList.sort(Comparator.comparingInt(LogItem::getPosition));
 		}
 
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/log/LogItem.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/LogItem.java
similarity index 92%
rename from PlayWallCore/src/main/java/de/tobias/playpad/log/LogItem.java
rename to PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/LogItem.java
index 5783006a1d4128151cfce7a5464a83220fdecd17..e73cec1bc194625a87ceaba87194dafef76de62b 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/log/LogItem.java
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/LogItem.java
@@ -1,7 +1,7 @@
-package de.tobias.playpad.log;
+package de.tobias.playpad.plugin.playout.log;
 
-import de.tobias.playpad.log.storage.LogSeasonStorageHandler;
 import de.tobias.playpad.pad.mediapath.MediaPath;
+import de.tobias.playpad.plugin.playout.log.storage.LogSeasonStorageHandler;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -24,7 +24,7 @@ public class LogItem {
 		this(
 				mediaPath.getId(),
 				mediaPath.getPad().getName(),
-				mediaPath.getPad().getPadSettings().getBackgroundColor().getColorHi(),
+				mediaPath.getPad().getPadSettings().getBackgroundColor().getColorLow(),
 				mediaPath.getPad().getPage().getPosition(),
 				mediaPath.getPad().getPosition(),
 				logSeason
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/log/LogSeason.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/LogSeason.java
similarity index 85%
rename from PlayWallCore/src/main/java/de/tobias/playpad/log/LogSeason.java
rename to PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/LogSeason.java
index 1edfe77a43024fee9f637fcbd39d935b62a23559..0390a6715894332672ea3ee5a810168b2f4b6f43 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/log/LogSeason.java
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/LogSeason.java
@@ -1,8 +1,9 @@
-package de.tobias.playpad.log;
+package de.tobias.playpad.plugin.playout.log;
 
-import de.tobias.playpad.log.storage.LogSeasonStorageHandler;
+import de.thecodelabs.utils.threading.Worker;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.mediapath.MediaPath;
+import de.tobias.playpad.plugin.playout.log.storage.LogSeasonStorageHandler;
 import de.tobias.playpad.project.Project;
 
 import java.util.ArrayList;
@@ -35,7 +36,7 @@ public class LogSeason {
 	}
 
 	public void createProjectSnapshot(Project project) {
-		project.getPads().forEach(this::addLogItem);
+		Worker.runLater(() -> project.getPads().parallelStream().forEach(this::addLogItem));
 	}
 
 	public void addLogItem(Pad pad) {
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/LogSeasons.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/LogSeasons.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b8ff4dc4ced7a915d39b3616e77b23e923c4662
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/LogSeasons.java
@@ -0,0 +1,73 @@
+package de.tobias.playpad.plugin.playout.log;
+
+import de.tobias.playpad.plugin.playout.log.storage.LogSeasonStorageHandler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LogSeasons {
+
+	private static LogSeason currentLogSession;
+	private static LogSeasonStorageHandler storageHandler;
+
+	private static List<LogSessionListener> listeners = new ArrayList<>();
+
+	private LogSeasons() {
+
+	}
+
+	public static LogSeason getCurrentSession() {
+		return currentLogSession;
+	}
+
+	public static LogSeason createLogSeason(String name, int columns, int rows) {
+		currentLogSession = new LogSeason(name, columns, rows);
+
+		// Save
+		LogSeasonStorageHandler storageHandler = LogSeasons.getStorageHandler();
+		if (storageHandler != null) {
+			storageHandler.addLogSeason(currentLogSession);
+		}
+
+		listeners.forEach(l -> l.playoutLogStarted(currentLogSession));
+
+		return currentLogSession;
+	}
+
+	public static LogSeasonStorageHandler getStorageHandler() {
+		return storageHandler;
+	}
+
+	public static void setStorageHandler(LogSeasonStorageHandler storageHandler) {
+		LogSeasons.storageHandler = storageHandler;
+	}
+
+	public static void stop() {
+		listeners.forEach(l -> l.playoutLogStopped(currentLogSession));
+		currentLogSession = null;
+	}
+
+	public static List<LogSeason> getAllLogSeasonsLazy() {
+		return getStorageHandler().getAllLogSeasonsLazy();
+	}
+
+	public static void deleteSession(int id) {
+		getStorageHandler().deleteSession(id);
+	}
+
+	public static LogSeason getLogSeason(int id) {
+		return getStorageHandler().getLogSeason(id);
+	}
+
+	/*
+	Listener
+	 */
+
+	public static void addListener(LogSessionListener logSessionListener) {
+		listeners.add(logSessionListener);
+	}
+
+	public static void removeListener(LogSessionListener logSessionListener) {
+		listeners.remove(logSessionListener);
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/LogSessionListener.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/LogSessionListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..8054cccec40ce925b933d52f690ee87fdc11de69
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/LogSessionListener.java
@@ -0,0 +1,8 @@
+package de.tobias.playpad.plugin.playout.log;
+
+public interface LogSessionListener
+{
+	void playoutLogStarted(LogSeason logSeason);
+
+	void playoutLogStopped(LogSeason logSeason);
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/log/PlayOutItem.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/PlayOutItem.java
similarity index 92%
rename from PlayWallCore/src/main/java/de/tobias/playpad/log/PlayOutItem.java
rename to PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/PlayOutItem.java
index 6f37072178642f137cfea50dbc33e6667806dfc9..c5e574609741fc3ab38a8256428559effc07f357 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/log/PlayOutItem.java
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/PlayOutItem.java
@@ -1,4 +1,4 @@
-package de.tobias.playpad.log;
+package de.tobias.playpad.plugin.playout.log;
 
 import java.util.UUID;
 
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/listener/PadPlayLogListener.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/listener/PadPlayLogListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..05ce0b71bd3f45bcb790fdf0f8fae52ccd1b6354
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/listener/PadPlayLogListener.java
@@ -0,0 +1,43 @@
+package de.tobias.playpad.plugin.playout.log.listener;
+
+import de.thecodelabs.logger.LogLevel;
+import de.thecodelabs.logger.Logger;
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.PadStatus;
+import de.tobias.playpad.pad.mediapath.MediaPath;
+import de.tobias.playpad.plugin.PadListener;
+import de.tobias.playpad.plugin.playout.log.LogSeason;
+import de.tobias.playpad.plugin.playout.log.LogSeasons;
+import de.tobias.playpad.plugin.playout.log.PlayOutItem;
+import javafx.collections.ListChangeListener;
+
+public class PadPlayLogListener implements PadListener {
+
+	@Override
+	public void onStatusChange(Pad pad, PadStatus newValue) {
+		if (newValue == PadStatus.PLAY) {
+			LogSeason instance = LogSeasons.getCurrentSession();
+			if (instance != null) {
+				instance.getLogItems().stream().filter(item -> item.getUuid().equals(pad.getPaths().get(0).getId())).forEach(item -> {
+					PlayOutItem playoutItem = new PlayOutItem(item.getUuid(), instance, System.currentTimeMillis());
+					item.addPlayOutItem(playoutItem);
+					Logger.log(LogLevel.DEBUG, "Play Item: " + playoutItem);
+				});
+			}
+		}
+	}
+
+	@Override
+	public void onMediaPathChanged(Pad pad, ListChangeListener.Change<? extends MediaPath> value) {
+		LogSeason instance = LogSeasons.getCurrentSession();
+		if (instance != null) {
+			while (value.next()) {
+				if (value.wasAdded()) {
+					for (MediaPath mediaPath : value.getAddedSubList()) {
+						instance.addLogItem(mediaPath);
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/storage/LogSeasonStorageHandler.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/storage/LogSeasonStorageHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..b03378b969f7ba18a1bfdf9033d0085f06b57abc
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/log/storage/LogSeasonStorageHandler.java
@@ -0,0 +1,22 @@
+package de.tobias.playpad.plugin.playout.log.storage;
+
+import de.tobias.playpad.plugin.playout.log.LogItem;
+import de.tobias.playpad.plugin.playout.log.LogSeason;
+import de.tobias.playpad.plugin.playout.log.PlayOutItem;
+
+import java.util.List;
+
+public interface LogSeasonStorageHandler extends AutoCloseable {
+
+	void addLogSeason(LogSeason season);
+
+	void addLogItem(LogItem item);
+
+	void addPlayOutItem(PlayOutItem item);
+
+	LogSeason getLogSeason(int id);
+
+	List<LogSeason> getAllLogSeasonsLazy();
+
+	void deleteSession(int id);
+}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/storage/PlayoutLogSettings.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/storage/PlayoutLogSettings.java
new file mode 100644
index 0000000000000000000000000000000000000000..a4ee3885c98e0928bb2c98774bc867e069774fe4
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/storage/PlayoutLogSettings.java
@@ -0,0 +1,16 @@
+package de.tobias.playpad.plugin.playout.storage;
+
+import de.thecodelabs.storage.proxy.DefaultBoolean;
+import de.thecodelabs.storage.proxy.Setter;
+import de.thecodelabs.storage.proxy.Settings;
+import de.thecodelabs.storage.settings.annotation.FilePath;
+
+@FilePath("PlayOutLog.json")
+public interface PlayoutLogSettings extends Settings {
+
+	@DefaultBoolean(false)
+	boolean autoStartLogging();
+
+	@Setter
+	void autoStartLogging(boolean value);
+}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/storage/SqlLiteLogSeasonStorageHandler.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/storage/SqlLiteLogSeasonStorageHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..b1659620bbb27ed772068f26cd6fcf400d7ba397
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/storage/SqlLiteLogSeasonStorageHandler.java
@@ -0,0 +1,209 @@
+package de.tobias.playpad.plugin.playout.storage;
+
+import de.thecodelabs.logger.Logger;
+import de.tobias.playpad.plugin.playout.log.LogItem;
+import de.tobias.playpad.plugin.playout.log.LogSeason;
+import de.tobias.playpad.plugin.playout.log.PlayOutItem;
+import de.tobias.playpad.plugin.playout.log.storage.LogSeasonStorageHandler;
+
+import java.nio.file.Path;
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class SqlLiteLogSeasonStorageHandler implements LogSeasonStorageHandler {
+
+	private Connection connection;
+
+	public SqlLiteLogSeasonStorageHandler(Path path) throws SQLException {
+		connection = DriverManager.getConnection("jdbc:sqlite:" + path.toString());
+
+		createDatabaseTable("CREATE TABLE IF NOT EXISTS LogSeason (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR NOT NULL, columns INTEGER NOT NULL, rows INTEGER NOT NULL);");
+		createDatabaseTable("CREATE TABLE IF NOT EXISTS LogItem (uuid VARCHAR NOT NULL, name VARCHAR NOT NULL, color VARCHAR NOT NULL, page INTEGER NOT NULL, position INTEGER NOT NULL, logSeason INTEGER NOT NULL, PRIMARY KEY (uuid, logSeason), FOREIGN KEY (logSeason) REFERENCES LogSeason(id));");
+		createDatabaseTable("CREATE TABLE IF NOT EXISTS PlayOutItem (uuid VARCHAR NOT NULL, time INTEGER NOT NULL, logSeason INTEGER NOT NULL, PRIMARY KEY (uuid, logSeason, time), FOREIGN KEY (uuid) REFERENCES LogItem(uuid));");
+	}
+
+	private void createDatabaseTable(String statement) throws SQLException {
+		try (PreparedStatement stmt = connection.prepareStatement(statement)) {
+			stmt.execute();
+		}
+	}
+
+	@Override
+	public void addLogSeason(LogSeason season) {
+		try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO LogSeason (name, columns, rows) VALUES (?, ?, ?)", Statement.RETURN_GENERATED_KEYS)) {
+			stmt.setString(1, season.getName());
+			stmt.setInt(2, season.getColumns());
+			stmt.setInt(3, season.getRows());
+			int affectedRows = stmt.executeUpdate();
+
+			if (affectedRows == 0) {
+				throw new SQLException("Creating log season failed, no rows affected.");
+			}
+
+			try (ResultSet rs = stmt.getGeneratedKeys()) {
+				if (rs.next()) {
+					season.setId(rs.getInt(1));
+				} else {
+					throw new SQLException("Creating log season failed, no ID obtained.");
+				}
+			}
+		} catch (SQLException e) {
+			Logger.error(e);
+		}
+	}
+
+	@Override
+	public void addLogItem(LogItem item) {
+		try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO LogItem VALUES (?, ?, ?, ?, ?, ?)")) {
+			stmt.setString(1, item.getUuid().toString());
+			stmt.setString(2, item.getName());
+			stmt.setString(3, item.getColor());
+			stmt.setInt(4, item.getPage());
+			stmt.setInt(5, item.getPosition());
+			stmt.setInt(6, item.getLogSeason().getId());
+
+			stmt.executeUpdate();
+		} catch (SQLException e) {
+			Logger.error(e);
+		}
+	}
+
+	@Override
+	public void addPlayOutItem(PlayOutItem item) {
+		try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO PlayOutItem VALUES (?, ?, ?)")) {
+			stmt.setString(1, item.getPathUuid().toString());
+			stmt.setInt(3, item.getLogSeason().getId());
+			stmt.setLong(2, item.getTime());
+			stmt.executeUpdate();
+		} catch (SQLException e) {
+			Logger.error(e);
+		}
+	}
+
+	@Override
+	public List<LogSeason> getAllLogSeasonsLazy() {
+		List<LogSeason> logSeasons = new ArrayList<>();
+
+		try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM LogSeason")) {
+			try (ResultSet resultSet = stmt.executeQuery()) {
+
+				while (resultSet.next()) {
+					LogSeason logSeason = new LogSeason(
+							resultSet.getInt("id"),
+							resultSet.getString("name"),
+							resultSet.getInt("columns"),
+							resultSet.getInt("rows")
+					);
+					logSeasons.add(logSeason);
+				}
+			}
+		} catch (SQLException e) {
+			Logger.error(e);
+		}
+		return logSeasons;
+	}
+
+	@Override
+	public LogSeason getLogSeason(int id) {
+		try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM LogSeason WHERE id = ?")) {
+			stmt.setInt(1, id);
+
+			try (ResultSet resultSet = stmt.executeQuery()) {
+				if (resultSet.next()) {
+					LogSeason logSeason = new LogSeason(
+							resultSet.getInt("id"),
+							resultSet.getString("name"),
+							resultSet.getInt("columns"),
+							resultSet.getInt("rows")
+					);
+					logSeason.getLogItems().addAll(getAllPlayoutItems(logSeason));
+					return logSeason;
+				}
+			}
+		} catch (SQLException e) {
+			Logger.error(e);
+		}
+		return null;
+	}
+
+	private List<LogItem> getAllPlayoutItems(LogSeason season) {
+		List<LogItem> logItems = new ArrayList<>();
+		try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM LogItem WHERE logSeason = ?")) {
+			stmt.setInt(1, season.getId());
+			try (ResultSet resultSet = stmt.executeQuery()) {
+
+				while (resultSet.next()) {
+					LogItem logItem = new LogItem(
+							UUID.fromString(resultSet.getString("uuid")),
+							resultSet.getString("name"),
+							resultSet.getString("color"),
+							resultSet.getInt("page"),
+							resultSet.getInt("position"),
+							season
+					);
+					logItem.getPlayOutItems().addAll(getAllPlayoutItems(logItem));
+					logItems.add(logItem);
+				}
+			}
+		} catch (SQLException e) {
+			Logger.error(e);
+		}
+		return logItems;
+	}
+
+	private List<PlayOutItem> getAllPlayoutItems(LogItem item) {
+		List<PlayOutItem> playOutItems = new ArrayList<>();
+		try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM PlayOutItem WHERE uuid = ? AND logSeason = ?")) {
+			stmt.setString(1, item.getUuid().toString());
+			stmt.setInt(2, item.getLogSeason().getId());
+
+			try (ResultSet resultSet = stmt.executeQuery()) {
+
+				while (resultSet.next()) {
+					PlayOutItem playOutItem = new PlayOutItem(
+							UUID.fromString(resultSet.getString("uuid")),
+							item.getLogSeason(),
+							resultSet.getLong("time")
+					);
+					playOutItems.add(playOutItem);
+				}
+			}
+		} catch (SQLException e) {
+			Logger.error(e);
+		}
+		return playOutItems;
+	}
+
+	@Override
+	public void deleteSession(int id) {
+		try (PreparedStatement deletePlayoutItems = connection.prepareStatement("DELETE FROM PlayOutItem WHERE uuid IN (SELECT uuid FROM LogItem l WHERE l.logSeason = ?)")) {
+			deletePlayoutItems.setInt(1, id);
+			deletePlayoutItems.execute();
+
+			try (PreparedStatement deleteLogItems = connection.prepareStatement("DELETE FROM LogItem WHERE logSeason = ?")) {
+				deleteLogItems.setInt(1, id);
+				deleteLogItems.execute();
+			}
+
+			try (PreparedStatement deleteLogSeason = connection.prepareStatement("DELETE FROM LogSeason WHERE id = ?")) {
+				deleteLogSeason.setInt(1, id);
+				deleteLogSeason.execute();
+			}
+		} catch (SQLException e) {
+			Logger.error(e);
+		}
+	}
+
+	@Override
+	public void close() throws RuntimeException {
+		if (connection != null) {
+			try {
+				connection.close();
+			} catch (SQLException e) {
+				throw new RuntimeException(e);
+			}
+		}
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/viewcontroller/MainViewControllerListener.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/viewcontroller/MainViewControllerListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..25925457e94eb9cbe3a89c2d1d0f32fdac06c50d
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/viewcontroller/MainViewControllerListener.java
@@ -0,0 +1,46 @@
+package de.tobias.playpad.plugin.playout.viewcontroller;
+
+import de.thecodelabs.utils.ui.NVCStage;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.plugin.MainWindowListener;
+import de.tobias.playpad.plugin.playout.PlayoutLogPlugin;
+import de.tobias.playpad.plugin.playout.Strings;
+import de.tobias.playpad.settings.keys.KeyCollection;
+import de.tobias.playpad.view.main.MenuType;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+import de.tobias.playpad.viewcontroller.main.MenuToolbarViewController;
+import javafx.scene.control.MenuItem;
+
+public class MainViewControllerListener implements MainWindowListener {
+	private MenuItem menuItem;
+
+	@Override
+	public void onInit(IMainViewController iMainViewController) {
+		iMainViewController.performLayoutDependedAction((oldToolbar, newToolbar) -> {
+			if (menuItem == null) {
+				menuItem = new MenuItem(Localization.getString(Strings.MENU_ITEM_LOG));
+				menuItem.setOnAction(event -> {
+					PlayoutLogViewController playoutLogViewController = new PlayoutLogViewController(newToolbar.getContainingWindow());
+					playoutLogViewController.getStageContainer().ifPresent(NVCStage::showAndWait);
+				});
+			}
+
+			if (oldToolbar != null) {
+				oldToolbar.removeMenuItem(menuItem);
+			}
+
+			newToolbar.addMenuItem(menuItem, MenuType.EXTENSION);
+			loadMenuKeyBinding();
+		});
+	}
+
+	@Override
+	public void loadMenuKeyBinding() {
+		final KeyCollection keyCollection = PlayPadPlugin.getInstance().getGlobalSettings().getKeyCollection();
+		final MenuToolbarViewController menuToolbarController = PlayPadPlugin.getInstance().getMainViewController().getMenuToolbarController();
+		menuToolbarController.setKeyBindingForMenu(menuItem, keyCollection.getKey(PlayoutLogPlugin.KEY_COLLECTION_PLAYOUT));
+
+		menuItem.setDisable(false);
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/viewcontroller/PlayoutLogStatusIconListener.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/viewcontroller/PlayoutLogStatusIconListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..3c42a5a69d38568960db805798ba6c751bef2649
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/viewcontroller/PlayoutLogStatusIconListener.java
@@ -0,0 +1,35 @@
+package de.tobias.playpad.plugin.playout.viewcontroller;
+
+import de.thecodelabs.utils.ui.icon.FontAwesomeType;
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.tobias.playpad.plugin.MainWindowListener;
+import de.tobias.playpad.plugin.playout.log.LogSeason;
+import de.tobias.playpad.plugin.playout.log.LogSessionListener;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+
+public class PlayoutLogStatusIconListener implements LogSessionListener, MainWindowListener {
+	private FontIcon logIcon;
+
+	@Override
+	public void playoutLogStarted(LogSeason logSeason) {
+		logIcon.setVisible(true);
+	}
+
+	@Override
+	public void playoutLogStopped(LogSeason logSeason) {
+		logIcon.setVisible(false);
+	}
+
+	@Override
+	public void onInit(IMainViewController mainViewControllerListener) {
+		// LogIcon
+		logIcon = new FontIcon(FontAwesomeType.LIST);
+		logIcon.setVisible(false);
+		mainViewControllerListener.performLayoutDependedAction((oldToolbar, newToolbar) -> {
+			if (oldToolbar != null) {
+				oldToolbar.removeToolbarItem(logIcon);
+			}
+			newToolbar.addToolbarItem(logIcon);
+		});
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/viewcontroller/PlayoutLogViewController.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/viewcontroller/PlayoutLogViewController.java
new file mode 100644
index 0000000000000000000000000000000000000000..479c4e5f6620f30c1277cd5a71dcba24f606056f
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/viewcontroller/PlayoutLogViewController.java
@@ -0,0 +1,217 @@
+package de.tobias.playpad.plugin.playout.viewcontroller;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.dataformat.csv.CsvMapper;
+import com.fasterxml.jackson.dataformat.csv.CsvSchema;
+import com.fasterxml.jackson.module.scala.DefaultScalaModule;
+import com.itextpdf.text.DocumentException;
+import de.thecodelabs.logger.Logger;
+import de.thecodelabs.storage.proxy.SettingsProxy;
+import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.ui.NVCStage;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.plugin.playout.Strings;
+import de.tobias.playpad.plugin.playout.export.CsvPlayoutLogExport;
+import de.tobias.playpad.plugin.playout.export.PlayoutLogPdfExport;
+import de.tobias.playpad.plugin.playout.log.LogSeason;
+import de.tobias.playpad.plugin.playout.log.LogSeasons;
+import de.tobias.playpad.plugin.playout.storage.PlayoutLogSettings;
+import de.tobias.playpad.project.Project;
+import de.tobias.playpad.project.ProjectSettings;
+import javafx.beans.InvalidationListener;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.*;
+import javafx.stage.FileChooser;
+import javafx.stage.Modality;
+import javafx.stage.Stage;
+import javafx.stage.Window;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Optional;
+
+public class PlayoutLogViewController extends NVC {
+
+	@FXML
+	private TextField nameTextField;
+	@FXML
+	private ListView<LogSeason> logList;
+	@FXML
+	private Button startButton;
+	@FXML
+	private Button exportButton;
+	@FXML
+	private Button exportCsvButton;
+	@FXML
+	private Button deleteButton;
+	@FXML
+	private Button finishButton;
+	@FXML
+	private CheckBox autoStartCheckbox;
+
+	public PlayoutLogViewController(Window owner) {
+		load("view/dialog", "PlayoutLogDialog", Localization.getBundle());
+
+		NVCStage stage = applyViewControllerToStage();
+		stage.initOwner(owner);
+		stage.initModality(Modality.WINDOW_MODAL);
+		addCloseKeyShortcut(stage::close);
+	}
+
+	@Override
+	public void init() {
+		updateListView();
+
+		if (LogSeasons.getCurrentSession() != null) { // Running
+			startButton.setText(Localization.getString(Strings.PLAYOUT_LOG_DIALOG_BUTTON_STOP));
+			nameTextField.setDisable(true);
+			nameTextField.setText(LogSeasons.getCurrentSession().getName());
+		} else {
+			startButton.setText(Localization.getString(Strings.PLAYOUT_LOG_DIALOG_BUTTON_START));
+			nameTextField.setDisable(false);
+		}
+
+		logList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
+
+		autoStartCheckbox.setSelected(SettingsProxy.getSettings(PlayoutLogSettings.class).autoStartLogging());
+		autoStartCheckbox.selectedProperty().addListener((observable, oldValue, newValue) ->
+				SettingsProxy.getSettings(PlayoutLogSettings.class).autoStartLogging(newValue));
+
+		startButton.disableProperty().bind(nameTextField.textProperty().isEmpty());
+
+		exportButton.setDisable(true);
+		exportCsvButton.setDisable(true);
+		logList.getSelectionModel().getSelectedItems().addListener((InvalidationListener) observable -> {
+			exportButton.setDisable(logList.getSelectionModel().getSelectedItems().size() != 1);
+			exportCsvButton.setDisable(logList.getSelectionModel().getSelectedItems().isEmpty());
+		});
+		deleteButton.disableProperty().bind(logList.getSelectionModel().selectedItemProperty().isNull());
+	}
+
+	private void updateListView() {
+		logList.getItems().setAll(LogSeasons.getAllLogSeasonsLazy());
+	}
+
+	@Override
+	public void initStage(Stage stage) {
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
+
+		stage.setTitle(Localization.getString(Strings.UI_DIALOG_PLAYOUT_LOG_TITLE));
+		stage.setMinWidth(450);
+		stage.setMinHeight(600);
+
+		stage.initModality(Modality.WINDOW_MODAL);
+
+		PlayPadPlugin.styleable().applyStyle(stage);
+	}
+
+	@FXML
+	private void startButtonHandler(ActionEvent event) {
+		if (LogSeasons.getCurrentSession() == null) { // Start
+			if (nameTextField.getText().isEmpty()) {
+				return;
+			}
+
+			if (LogSeasons.getAllLogSeasonsLazy().stream().anyMatch(item -> item.getName().equals(nameTextField.getText()))) {
+				showErrorMessage(Localization.getString("PlayoutLogDialog.Error.NameExists"));
+				return;
+			}
+
+			final Project currentProject = PlayPadPlugin.getInstance().getCurrentProject();
+			final ProjectSettings settings = currentProject.getSettings();
+
+			LogSeason logSeason = LogSeasons.createLogSeason(nameTextField.getText(), settings.getColumns(), settings.getRows());
+			logSeason.createProjectSnapshot(currentProject);
+
+			startButton.setText(Localization.getString(Strings.PLAYOUT_LOG_DIALOG_BUTTON_STOP));
+			nameTextField.setDisable(false);
+
+			updateListView();
+		} else { // Stop
+			LogSeasons.stop();
+			startButton.setText(Localization.getString(Strings.PLAYOUT_LOG_DIALOG_BUTTON_START));
+			nameTextField.setDisable(false);
+			nameTextField.setText("");
+		}
+	}
+
+	@FXML
+	private void exportButtonHandler(ActionEvent event) {
+		getSelectedLogSeason().ifPresent(season -> { // Lazy Season
+			FileChooser fileChooser = new FileChooser();
+			FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter("PDF", "*.pdf");
+			fileChooser.getExtensionFilters().add(extensionFilter);
+
+			File file = fileChooser.showSaveDialog(getContainingWindow());
+			if (file != null) {
+				try {
+					PlayoutLogPdfExport.createPdfFile(file.toPath(), LogSeasons.getLogSeason(season.getId()));
+				} catch (IOException | DocumentException e) {
+					Logger.error(e);
+				}
+			}
+		});
+	}
+
+	@FXML
+	private void exportMultipleCsvHandler(ActionEvent event) {
+		FileChooser fileChooser = new FileChooser();
+		FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter("CSV", "*.csv");
+		fileChooser.getExtensionFilters().add(extensionFilter);
+
+		File file = fileChooser.showSaveDialog(getContainingWindow());
+		if (file == null) {
+			return;
+		}
+		Path path = file.toPath();
+
+		final LogSeason[] logSeasons = logList.getSelectionModel().getSelectedItems()
+				.parallelStream()
+				.map(logSeason -> LogSeasons.getLogSeason(logSeason.getId()))
+				.toArray(LogSeason[]::new);
+
+		final CsvPlayoutLogExport.CsvColumn[] export = CsvPlayoutLogExport.export(logSeasons);
+
+		// create mapper and schema
+		CsvMapper mapper = new CsvMapper();
+		mapper.registerModule(new DefaultScalaModule());
+		mapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true);
+
+		CsvSchema schema = CsvSchema.builder()
+				.addColumn("Name")
+				.addColumn("Zaehler")
+				.addColumn("Sessions")
+				.addColumn("Erstes Datum")
+				.addColumn("Letztes Datum")
+				.build();
+		schema = schema.withColumnSeparator(';').withHeader();
+
+		// output writer
+		ObjectWriter objectWriter = mapper.writer(schema);
+		try {
+			objectWriter.writeValue(Files.newBufferedWriter(path), export);
+		} catch (IOException e) {
+			Logger.error(e);
+		}
+	}
+
+	@FXML
+	private void deleteButtonHandler(ActionEvent event) {
+		logList.getSelectionModel().getSelectedItems().forEach(season -> LogSeasons.deleteSession(season.getId()));
+		updateListView();
+	}
+
+	@FXML
+	private void finishButtonHandler(ActionEvent event) {
+		getStageContainer().ifPresent(NVCStage::close);
+	}
+
+	private Optional<LogSeason> getSelectedLogSeason() {
+		return Optional.ofNullable(logList.getSelectionModel().getSelectedItem());
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/resources/lang/playoutlog_de.properties b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/resources/lang/playoutlog_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..2d840cd91667ae81b3a289a8fff8186b4e8101db
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/resources/lang/playoutlog_de.properties
@@ -0,0 +1,12 @@
+UI.Dialog.PlayoutLog.Title=PlayoutLog
+main.menuitem.log=Playout Log...
+
+PlayoutLogDialog.Label.Headline=PlayOut Log
+PlayoutLogDialog.Checkbox.AutoStart=Automatisch starten bei Programmstart
+PlayoutLogDialog.Button.Start=Starten
+PlayoutLogDialog.Button.Stop=Stoppen
+PlayoutLogDialog.Button.Export=PDF Exportieren...
+PlayoutLogDialog.Button.ExportAll=CSV Exportieren...
+PlayoutLogDialog.Button.Delete=L\u00F6schen
+
+PlayoutLogDialog.Error.NameExists=Dieser Name ist bereits verwendet. W\u00E4hlen Sie bitte einen anderen Namen.
\ No newline at end of file
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/resources/plugin.yml b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/resources/plugin.yml
new file mode 100644
index 0000000000000000000000000000000000000000..074e1226a55ef3266d31a89be11b2b40fd56f8b5
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/resources/plugin.yml
@@ -0,0 +1,6 @@
+main: "de.tobias.playpad.plugin.playout.PlayoutLogPlugin"
+name: "PlayoutLogPlugin"
+artifactId: "${pom.artifactId}"
+groupId: "${pom.groupId}"
+version: "${pom.version}"
+build: 8
diff --git a/PlayWall/src/main/resources/view/dialog/PlayoutLogDialog.fxml b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/resources/view/dialog/PlayoutLogDialog.fxml
similarity index 64%
rename from PlayWall/src/main/resources/view/dialog/PlayoutLogDialog.fxml
rename to PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/resources/view/dialog/PlayoutLogDialog.fxml
index 018321ac305f98f31af170a6d4ada8cf1754d6cc..211b26b3c27587df3670aec8cf5467ea07f69630 100644
--- a/PlayWall/src/main/resources/view/dialog/PlayoutLogDialog.fxml
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/resources/view/dialog/PlayoutLogDialog.fxml
@@ -1,38 +1,44 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-
 <?import javafx.geometry.Insets?>
 <?import javafx.scene.control.*?>
 <?import javafx.scene.layout.*?>
 <VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" spacing="14.0"
-      xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
+      xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
     <children>
-        <Label styleClass="headline" text="PlayOut Log"/>
+        <Label styleClass="headline" text="%PlayoutLogDialog.Label.Headline"/>
         <HBox spacing="14.0">
             <children>
                 <TextField fx:id="nameTextField" maxWidth="1.7976931348623157E308" prefWidth="300.0" promptText="Name"
                            HBox.hgrow="ALWAYS"/>
                 <Button fx:id="startButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false"
-                        onAction="#startButtonHandler" prefWidth="100.0" text="Starten" HBox.hgrow="ALWAYS"/>
+                        onAction="#startButtonHandler" prefWidth="100.0" text="%PlayoutLogDialog.Button.Start"
+                        HBox.hgrow="ALWAYS"/>
             </children>
         </HBox>
         <HBox maxWidth="1.7976931348623157E308" spacing="14.0" VBox.vgrow="ALWAYS">
             <children>
                 <ListView fx:id="logList" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="300.0"
-                          HBox.hgrow="ALWAYS"/>
+                          styleClass="dark-list" HBox.hgrow="ALWAYS"/>
                 <VBox maxWidth="1.7976931348623157E308" spacing="14.0" HBox.hgrow="ALWAYS">
                     <children>
                         <Button fx:id="exportButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false"
-                                onAction="#exportButtonHandler" prefWidth="100.0" text="Export..." VBox.vgrow="ALWAYS"/>
+                                onAction="#exportButtonHandler" prefWidth="100.0" text="%PlayoutLogDialog.Button.Export"
+                                VBox.vgrow="ALWAYS"/>
+                        <Button fx:id="exportCsvButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false"
+                                onAction="#exportMultipleCsvHandler" prefWidth="100.0" text="%PlayoutLogDialog.Button.ExportAll"
+                                VBox.vgrow="ALWAYS"/>
                         <Button fx:id="deleteButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false"
-                                onAction="#deleteButtonHandler" prefWidth="100.0" text="Löschen..."
+                                onAction="#deleteButtonHandler" prefWidth="100.0" text="%PlayoutLogDialog.Button.Delete"
                                 VBox.vgrow="ALWAYS"/>
                     </children>
                 </VBox>
             </children>
         </HBox>
-        <HBox alignment="TOP_RIGHT">
+        <HBox alignment="CENTER_LEFT">
             <children>
+                <CheckBox fx:id="autoStartCheckbox" maxWidth="1.7976931348623157E308" mnemonicParsing="false"
+                          text="%PlayoutLogDialog.Checkbox.AutoStart" HBox.hgrow="ALWAYS"/>
                 <Button fx:id="finishButton" defaultButton="true" mnemonicParsing="false"
                         onAction="#finishButtonHandler" text="Fertig"/>
             </children>
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/scala/de/tobias/playpad/plugin/playout/PlayOutLogInitializer.scala b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/scala/de/tobias/playpad/plugin/playout/PlayOutLogInitializer.scala
new file mode 100644
index 0000000000000000000000000000000000000000..76d5d99b2446352e02a685959c0af5c836259d4f
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/scala/de/tobias/playpad/plugin/playout/PlayOutLogInitializer.scala
@@ -0,0 +1,24 @@
+package de.tobias.playpad.plugin.playout
+
+import java.sql.SQLException
+
+import de.thecodelabs.logger.Logger
+import de.thecodelabs.utils.application.ApplicationUtils
+import de.thecodelabs.utils.application.container.PathType
+import de.tobias.playpad.plugin.playout.log.LogSeasons
+import de.tobias.playpad.plugin.playout.storage.SqlLiteLogSeasonStorageHandler
+
+object PlayOutLogInitializer {
+
+	def init(): Unit = {
+		val app = ApplicationUtils.getApplication
+
+		try {
+			val playOutLogPath = app.getPath(PathType.DOCUMENTS, "logging.db")
+			LogSeasons.setStorageHandler(new SqlLiteLogSeasonStorageHandler(playOutLogPath))
+			Logger.info("Setup LogSeasonStorageHandler in path: {0}", playOutLogPath)
+		} catch {
+			case e: SQLException => Logger.error("Cannot setup LogSeasonStorageHandler ({0})", e.getLocalizedMessage)
+		}
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/scala/de/tobias/playpad/plugin/playout/ProjectListener.scala b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/scala/de/tobias/playpad/plugin/playout/ProjectListener.scala
new file mode 100644
index 0000000000000000000000000000000000000000..b1718d04a72d70a7ea2c4565f7d1584c84597c55
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/scala/de/tobias/playpad/plugin/playout/ProjectListener.scala
@@ -0,0 +1,31 @@
+package de.tobias.playpad.plugin.playout
+
+import java.text.SimpleDateFormat
+
+import de.thecodelabs.logger.Logger
+import de.thecodelabs.storage.proxy.SettingsProxy
+import de.tobias.playpad.plugin.GlobalAdapter
+import de.tobias.playpad.plugin.playout.log.LogSeasons
+import de.tobias.playpad.plugin.playout.storage.PlayoutLogSettings
+import de.tobias.playpad.project.Project
+
+class ProjectListener extends GlobalAdapter {
+
+	private val dateFormatter = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss")
+	private val nameFormat = "%s (%s)"
+
+	override def projectOpened(newProject: Project): Unit = {
+		val autoStart = SettingsProxy.getSettings(classOf[PlayoutLogSettings]).autoStartLogging()
+		if (autoStart) {
+			Logger.info("Start new PlayOutLog session")
+
+			val settings = newProject.getSettings
+
+			val logName = String.format(nameFormat, dateFormatter.format(System.currentTimeMillis), newProject.getProjectReference.getName)
+			val logSeason = LogSeasons.createLogSeason(logName, settings.getColumns, settings.getRows)
+			logSeason.createProjectSnapshot(newProject)
+		}
+	}
+
+	override def projectClosed(currentProject: Project): Unit = LogSeasons.stop()
+}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/scala/de/tobias/playpad/plugin/playout/export/CsvPlayoutLogExport.scala b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/scala/de/tobias/playpad/plugin/playout/export/CsvPlayoutLogExport.scala
new file mode 100644
index 0000000000000000000000000000000000000000..e45923c3930e78e2d9522f2c886d0199344d7a77
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/scala/de/tobias/playpad/plugin/playout/export/CsvPlayoutLogExport.scala
@@ -0,0 +1,85 @@
+package de.tobias.playpad.plugin.playout.export
+
+import java.util.{Date, UUID}
+
+import com.fasterxml.jackson.annotation.{JsonFormat, JsonIgnore, JsonProperty, JsonPropertyOrder}
+import de.tobias.playpad.plugin.playout.log.LogSeason
+
+import scala.jdk.CollectionConverters._
+
+object CsvPlayoutLogExport {
+
+	@JsonPropertyOrder(value = Array("name", "count", "seasonCount", "firstTime", "lastTime"))
+	class CsvColumn
+	(
+		@JsonIgnore
+		var id: UUID,
+		@JsonProperty("Name")
+		var name: String,
+		@JsonProperty("Zaehler")
+		var count: Int,
+		@JsonProperty("Sessions")
+		var seasonCount: Int,
+		@JsonProperty("Erstes Datum")
+		@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm")
+		var firstTime: Date,
+		@JsonProperty("Letztes Datum")
+		@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm")
+		var lastTime: Date
+	) {
+	}
+
+	def export(sessions: Array[LogSeason]): Array[CsvColumn] = {
+		val items = sessions
+			.map(_.getLogItems.asScala)
+			.flatten
+			.distinctBy(_.getUuid)
+			.map(entry => new CsvColumn(entry.getUuid, entry.getName, 0, 0, null, null))
+
+		sessions
+			.map(_.getLogItems.asScala)
+			.flatten
+			.foreach(item => {
+				val entry = items.filter(i => i.id == item.getUuid).head
+				entry.count = entry.count + item.getPlayOutItems.size()
+			})
+
+		sessions
+			.map(_.getLogItems.asScala.distinctBy(_.getUuid))
+			.flatten
+			.foreach(item => {
+				val entry = items.filter(i => i.id == item.getUuid).head
+				entry.seasonCount = entry.seasonCount + 1
+			})
+
+		val timeMapping = sessions
+			.map(_.getLogItems.asScala)
+			.flatten
+			.map(i => i.getPlayOutItems.asScala)
+			.flatten
+			.map(i => i.getPathUuid -> i.getTime)
+
+		items.foreach(item => {
+			timeMapping.filter(i => i._1 == item.id).minByOption(_._2).map(_._2) match {
+				case Some(value) => item.firstTime = new Date(value)
+				case _ =>
+			}
+
+			timeMapping.filter(i => i._1 == item.id).maxByOption(_._2).map(_._2) match {
+				case Some(value) => item.lastTime = new Date(value)
+				case _ =>
+			}
+		})
+
+		items.groupBy(_.name).map((keyValue: (String, Array[CsvColumn])) => {
+			new CsvColumn(
+				null,
+				keyValue._1,
+				keyValue._2.map(i => i.count).sum,
+				keyValue._2.map(i => i.seasonCount).maxOption.getOrElse(0),
+				keyValue._2.map(i => i.firstTime).filter(_ != null).minOption.orNull,
+				keyValue._2.map(i => i.firstTime).filter(_ != null).minOption.orNull
+			)
+		}).toArray
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/pom.xml b/PlayWallPlugins/PlayWallPluginWebAPI/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e806e6397201734c6cce3b69e58ed5de4889969f
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/pom.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>PlayWallPlugins</artifactId>
+        <groupId>de.tobias.playpad</groupId>
+        <version>7.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>PlayWallPluginWebAPI</artifactId>
+
+    <properties>
+        <project.outputDirectory>../../build/${project.version}</project.outputDirectory>
+        <project.artifactName>${project.artifactId}-v${project.version}</project.artifactName>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>de.tobias.playpad</groupId>
+            <artifactId>PlayWallCore</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.sparkjava</groupId>
+            <artifactId>spark-core</artifactId>
+            <version>${spark-core.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>de.thecodelabs</groupId>
+                <artifactId>versionizer-maven-plugin</artifactId>
+                <version>1.0.1</version>
+                <configuration>
+                    <resourceFile>plugin.yml</resourceFile>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>resource-fill</id>
+                        <goals>
+                            <goal>resource-fill</goal>
+                        </goals>
+                        <phase>compile</phase>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!--Scala Plugin-->
+            <plugin>
+                <groupId>net.alchim31.maven</groupId>
+                <artifactId>scala-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>scala-compile-first</id>
+                        <phase>process-resources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                            <goal>compile</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>scala-test-compile</id>
+                        <phase>process-test-resources</phase>
+                        <goals>
+                            <goal>testCompile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <version>3.1.1</version>
+                <configuration>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                    <outputDirectory>${project.outputDirectory}</outputDirectory>
+                    <finalName>${project.artifactName}</finalName>
+                    <appendAssemblyId>false</appendAssemblyId>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>assemble-all</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <distributionManagement>
+        <repository>
+            <id>release</id>
+            <name>TheCodeLabs-releases</name>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
+        </repository>
+        <snapshotRepository>
+            <id>snapshots</id>
+            <name>TheCodeLabs-snapshots</name>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+    <repositories>
+        <repository>
+            <id>release</id>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>snapshots</id>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+</project>
\ No newline at end of file
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin.yml b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin.yml
new file mode 100644
index 0000000000000000000000000000000000000000..20f98f590f65c3d60a2b38426294a052e816413b
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin.yml
@@ -0,0 +1,6 @@
+main: "de.tobias.playpad.plugin.api.WebApiPlugin"
+name: "WebApiPlugin"
+artifactId: "${pom.artifactId}"
+groupId: "${pom.groupId}"
+version: "${pom.version}"
+build: 1
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/WebApiPlugin.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/WebApiPlugin.scala
new file mode 100644
index 0000000000000000000000000000000000000000..35c391df6113a4621a22e58d0b51078b54e185f4
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/WebApiPlugin.scala
@@ -0,0 +1,27 @@
+package de.tobias.playpad.plugin.api
+
+import de.thecodelabs.logger.Logger
+import de.thecodelabs.plugins.{Plugin, PluginDescriptor}
+import de.tobias.playpad.PlayPadPlugin
+import de.tobias.playpad.plugin.api.websocket.WebSocketHandler
+import de.tobias.playpad.plugin.api.websocket.listener.{PadStatusListener, ProjectListener}
+import spark.Spark
+
+class WebApiPlugin extends Plugin {
+	override def startup(pluginDescriptor: PluginDescriptor): Unit = {
+		PlayPadPlugin.getInstance().addPadListener(new PadStatusListener)
+		PlayPadPlugin.getInstance().addGlobalListener(new ProjectListener)
+
+		Logger.debug("Enable Web API Plugin")
+
+		Spark.port(9876)
+		Spark.webSocket("/api", WebSocketHandler.instance)
+		Spark.get("/", (_, _) => "PlayWall API")
+	}
+
+	override def shutdown(): Unit = {
+		Logger.debug("Disable Web API Plugin")
+
+		Spark.stop()
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/MethodExecutable.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/MethodExecutable.scala
new file mode 100644
index 0000000000000000000000000000000000000000..1658952e5f6582f5963388b2b373375fcbc09cbe
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/MethodExecutable.scala
@@ -0,0 +1,9 @@
+package de.tobias.playpad.plugin.api.websocket
+
+import com.google.gson.JsonObject
+import de.tobias.playpad.plugin.api.websocket.message.Message
+import org.eclipse.jetty.websocket.api.Session
+
+trait MethodExecutable {
+	def execute(session: Session, message: Message): JsonObject
+}
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/WebSocketHandler.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/WebSocketHandler.scala
new file mode 100644
index 0000000000000000000000000000000000000000..69b48550f1f043cf02bfea30e3116b3d79c11727
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/WebSocketHandler.scala
@@ -0,0 +1,70 @@
+package de.tobias.playpad.plugin.api.websocket
+
+import java.util.concurrent.ConcurrentLinkedQueue
+
+import com.google.gson.{Gson, JsonObject}
+import de.thecodelabs.logger.Logger
+import de.tobias.playpad.plugin.api.websocket.message.Message
+import de.tobias.playpad.plugin.api.websocket.methods.{PadStatusChangeMethod, ProjectCurrentMethod, ProjectListMethod, ProjectOpenMethod}
+import org.eclipse.jetty.websocket.api.Session
+import org.eclipse.jetty.websocket.api.annotations._
+
+@WebSocket
+class WebSocketHandler {
+
+	private val sessions = new ConcurrentLinkedQueue[Session]
+
+	private val methods: Map[String, MethodExecutable] = Map(
+		"project-list" -> new ProjectListMethod,
+		"project-current" -> new ProjectCurrentMethod,
+		"project-open" -> new ProjectOpenMethod,
+		"pad-status-change" -> new PadStatusChangeMethod
+	)
+
+	@OnWebSocketConnect def connected(session: Session): Unit = {
+		Logger.debug("WebSocket Client connected")
+		sessions.add(session)
+	}
+
+	@OnWebSocketClose def closed(session: Session, statusCode: Int, reason: String): Unit = {
+		Logger.debug("WebSocket Client disconnected")
+		sessions.remove(session)
+	}
+
+	@OnWebSocketMessage def onRead(session: Session, text: String): Unit = {
+		Logger.debug("Read from WebSocket: {0}", text)
+
+		val message: Message = WebSocketHandler.gson.fromJson(text, classOf[Message])
+		val response = methods(message.`type`).execute(session, message)
+
+		if (response != null) {
+			WebSocketHandler.sendResponse(session, message, response)
+		}
+	}
+
+	@OnWebSocketError def onError(session: Session, error: Throwable): Unit = {
+		Logger.error(error)
+	}
+
+	def sendUpdate(message: String, jsonObject: JsonObject): Unit = {
+		jsonObject.addProperty("updateType", message)
+		val payload = WebSocketHandler.gson.toJson(jsonObject)
+
+		sessions.stream()
+			.filter(session => session.isOpen)
+			.forEach(session => session.getRemote.sendString(payload))
+	}
+}
+
+object WebSocketHandler {
+
+	lazy val instance: WebSocketHandler = new WebSocketHandler
+
+	private val gson = new Gson()
+
+	def sendResponse(session: Session, message: Message, response: JsonObject) = {
+		response.addProperty("messageId", message.messageId)
+		response.addProperty("type", message.`type`)
+		session.getRemote.sendString(gson.toJson(response))
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/listener/PadStatusListener.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/listener/PadStatusListener.scala
new file mode 100644
index 0000000000000000000000000000000000000000..ffd31cb462573fa1630bcf9448d4f4eda0b7a387
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/listener/PadStatusListener.scala
@@ -0,0 +1,18 @@
+package de.tobias.playpad.plugin.api.websocket.listener
+
+import com.google.gson.JsonObject
+import de.tobias.playpad.pad.{Pad, PadStatus}
+import de.tobias.playpad.plugin.PadListener
+import de.tobias.playpad.plugin.api.websocket.WebSocketHandler
+
+class PadStatusListener extends PadListener {
+
+	override def onStatusChange(pad: Pad, newValue: PadStatus): Unit = {
+		val payload = new JsonObject
+
+		payload.addProperty("pad", pad.getUuid.toString)
+		payload.addProperty("status", newValue.name())
+
+		WebSocketHandler.instance.sendUpdate("pad-status-changed", payload)
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/listener/ProjectListener.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/listener/ProjectListener.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a0a8a8aae190a554c88884f474c4cda70fb1a4e8
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/listener/ProjectListener.scala
@@ -0,0 +1,14 @@
+package de.tobias.playpad.plugin.api.websocket.listener
+
+import de.tobias.playpad.plugin.GlobalAdapter
+import de.tobias.playpad.plugin.api.websocket.WebSocketHandler
+import de.tobias.playpad.plugin.api.websocket.serialize.ProjectSerializer
+import de.tobias.playpad.profile.Profile
+import de.tobias.playpad.project.Project
+
+class ProjectListener extends GlobalAdapter {
+	override def projectOpened(newProject: Project): Unit = {
+		val jsonObject = ProjectSerializer.serializeProject(newProject, Profile.currentProfile())
+		WebSocketHandler.instance.sendUpdate("project-changed", jsonObject)
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/message/Message.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/message/Message.scala
new file mode 100644
index 0000000000000000000000000000000000000000..32d4188134e58901c4810a585e5cda4abecc071c
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/message/Message.scala
@@ -0,0 +1,11 @@
+package de.tobias.playpad.plugin.api.websocket.message
+
+import com.google.gson.JsonObject
+
+class Message (var `type`: String, var messageId: String, var payload: JsonObject) {
+
+	// gson only
+	def this() {
+		this("", "", null)
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/methods/PadStatusChangeMethod.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/methods/PadStatusChangeMethod.scala
new file mode 100644
index 0000000000000000000000000000000000000000..492583d000d44bdd997507e27fae325436c0b21c
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/methods/PadStatusChangeMethod.scala
@@ -0,0 +1,32 @@
+package de.tobias.playpad.plugin.api.websocket.methods
+
+import java.util.UUID
+
+import com.google.gson.JsonObject
+import de.tobias.playpad.PlayPadPlugin
+import de.tobias.playpad.pad.PadStatus
+import de.tobias.playpad.plugin.api.websocket.MethodExecutable
+import de.tobias.playpad.plugin.api.websocket.message.Message
+import javafx.application.Platform
+import org.eclipse.jetty.websocket.api.Session
+
+class PadStatusChangeMethod extends MethodExecutable {
+	override def execute(session: Session, message: Message): JsonObject = {
+		val padId = UUID.fromString(message.payload.get("pad").getAsString)
+		val newStatus = PadStatus.valueOf(message.payload.get("status").getAsString)
+
+		val currentProject = PlayPadPlugin.getInstance().getCurrentProject
+		val pad = currentProject.getPad(padId)
+
+		Platform.runLater(() => {
+			newStatus match {
+				case PadStatus.PLAY => pad.play()
+				case PadStatus.PAUSE => pad.pause()
+				case PadStatus.STOP => pad.stop()
+				case _ =>
+			}
+		})
+
+		new JsonObject
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/methods/ProjectCurrentMethod.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/methods/ProjectCurrentMethod.scala
new file mode 100644
index 0000000000000000000000000000000000000000..ac5cd11148fc9d3fd31276b49bde39f5664fb631
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/methods/ProjectCurrentMethod.scala
@@ -0,0 +1,21 @@
+package de.tobias.playpad.plugin.api.websocket.methods
+
+import com.google.gson.JsonObject
+import de.tobias.playpad.PlayPadPlugin
+import de.tobias.playpad.plugin.api.websocket.MethodExecutable
+import de.tobias.playpad.plugin.api.websocket.message.Message
+import de.tobias.playpad.plugin.api.websocket.serialize.ProjectSerializer
+import de.tobias.playpad.profile.Profile
+import org.eclipse.jetty.websocket.api.Session
+
+class ProjectCurrentMethod extends MethodExecutable {
+	override def execute(session: Session, message: Message): JsonObject = {
+		val currentProject = PlayPadPlugin.getInstance().getCurrentProject
+
+		if (currentProject == null) {
+			new JsonObject
+		} else {
+			ProjectSerializer.serializeProject(currentProject, Profile.currentProfile)
+		}
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/methods/ProjectListMethod.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/methods/ProjectListMethod.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a1e29d6d5a4e93cb17edf922c775482959994b56
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/methods/ProjectListMethod.scala
@@ -0,0 +1,27 @@
+package de.tobias.playpad.plugin.api.websocket.methods
+
+import com.google.gson.{JsonArray, JsonObject}
+import de.tobias.playpad.plugin.api.websocket.MethodExecutable
+import de.tobias.playpad.plugin.api.websocket.message.Message
+import de.tobias.playpad.project.ref.ProjectReferenceManager
+import org.eclipse.jetty.websocket.api.Session
+
+import scala.jdk.CollectionConverters._
+
+class ProjectListMethod extends MethodExecutable {
+	override def execute(session: Session, message: Message): JsonObject = {
+		val projectList = new JsonArray()
+
+		ProjectReferenceManager.getProjects.asScala
+    		.map(project => {
+				val jsonObject = new JsonObject()
+				jsonObject.addProperty("id", project.getUuid.toString)
+				jsonObject.addProperty("name", project.getName)
+				jsonObject
+			}).foreach((i: JsonObject) => projectList.add(i))
+
+		val response = new JsonObject()
+		response.add("projects", projectList)
+		response
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/methods/ProjectOpenMethod.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/methods/ProjectOpenMethod.scala
new file mode 100644
index 0000000000000000000000000000000000000000..150f1f5a1ef0338b06114efa8506b978b9c74544
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/methods/ProjectOpenMethod.scala
@@ -0,0 +1,21 @@
+package de.tobias.playpad.plugin.api.websocket.methods
+
+import java.util.UUID
+
+import com.google.gson.JsonObject
+import de.tobias.playpad.PlayPadPlugin
+import de.tobias.playpad.plugin.api.websocket.MethodExecutable
+import de.tobias.playpad.plugin.api.websocket.message.Message
+import de.tobias.playpad.project.ref.ProjectReferenceManager
+import javafx.application.Platform
+import org.eclipse.jetty.websocket.api.Session
+
+class ProjectOpenMethod extends MethodExecutable {
+	override def execute(session: Session, message: Message): JsonObject = {
+		val requestedId = UUID.fromString(message.payload.get("id").getAsString)
+
+		val reference = ProjectReferenceManager.getProject(requestedId)
+		Platform.runLater(() => PlayPadPlugin.getInstance().openProject(reference, null))
+		null
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/serialize/ProjectSerializer.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/serialize/ProjectSerializer.scala
new file mode 100644
index 0000000000000000000000000000000000000000..3c1e157137bf1ed7d405a784bdf87510581443a8
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/serialize/ProjectSerializer.scala
@@ -0,0 +1,71 @@
+package de.tobias.playpad.plugin.api.websocket.serialize
+
+import com.google.gson.{JsonArray, JsonObject}
+import de.tobias.playpad.design.modern.ModernColor
+import de.tobias.playpad.profile.Profile
+import de.tobias.playpad.project.Project
+
+object ProjectSerializer {
+
+	def serializeProject(project: Project, profile: Profile): JsonObject = {
+		val result = new JsonObject
+
+		result.addProperty("id", project.getProjectReference.getUuid.toString)
+		result.addProperty("name", project.getProjectReference.getName)
+		result.addProperty("columns", project.getSettings.getColumns)
+		result.addProperty("rows", project.getSettings.getRows)
+
+		val pageArray = new JsonArray()
+		project.getPages.forEach(page => {
+			val pageObject = new JsonObject
+
+			pageObject.addProperty("id", page.getId.toString)
+			pageObject.addProperty("name", page.getName)
+			pageObject.addProperty("position", page.getPosition)
+
+			val padArray = new JsonArray()
+			page.getPads.forEach(pad => {
+				val padObject = new JsonObject
+				padObject.addProperty("id", pad.getUuid.toString)
+				padObject.addProperty("name", pad.getName)
+				padObject.addProperty("status", pad.getStatus.name)
+
+				padObject.addProperty("position", pad.getPosition)
+				padObject.addProperty("page", pad.getPage.getPosition)
+
+				val padDesign = new JsonObject
+				padDesign.add("normal", serializeDesign(pad.getPadSettings.getDesign.getBackgroundColor))
+				padDesign.add("play", serializeDesign(pad.getPadSettings.getDesign.getPlayColor))
+				padObject.add("design", padDesign)
+
+				padArray.add(padObject)
+			})
+			pageObject.add("pads", padArray)
+
+			pageArray.add(pageObject)
+		})
+		result.add("pages", pageArray)
+
+		val globalDesign = new JsonObject
+		globalDesign.add("normal", serializeDesign(profile.getProfileSettings.getDesign.getBackgroundColor))
+		globalDesign.add("play", serializeDesign(profile.getProfileSettings.getDesign.getPlayColor))
+		result.add("design", globalDesign)
+
+		result
+	}
+
+	private def serializeDesign(color: ModernColor): JsonObject = {
+		val json = new JsonObject
+
+		color.getCurrentModernColor.ifPresent(c => {
+			json.addProperty("hi", c.getColors.getHi)
+			json.addProperty("low", c.getColors.getLow)
+			json.addProperty("font", c.getColors.getFont)
+			json.addProperty("button", c.getColors.getButton)
+			json.addProperty("playbarBackground", c.getColors.getPlaybar.getBackground)
+			json.addProperty("playbarTrack", c.getColors.getPlaybar.getTrack)
+		})
+
+		json
+	}
+}
diff --git a/PlayWallPlugins/pom.xml b/PlayWallPlugins/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6707940ede504d7c632906e0d0b24f603cba0a62
--- /dev/null
+++ b/PlayWallPlugins/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>de.tobias.playpad</groupId>
+        <artifactId>PlayWallDesktop</artifactId>
+        <version>7.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>PlayWallPlugins</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>PlayWallPluginAwake</module>
+        <module>PlayWallPluginEqualizer</module>
+        <module>PlayWallPluginLaunchpad</module>
+        <module>PlayWallPluginMedia</module>
+        <module>PlayWallPluginNativeAudio</module>
+        <module>PlayWallPluginPlayoutLog</module>
+        <module>PlayWallPluginWebAPI</module>
+    </modules>
+
+</project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 6a92993de0f9f8d568be733070e210da5766a9d9..0c64706ede144c84101f32b34fcc26f4fb2bd99a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
 
     <groupId>de.tobias.playpad</groupId>
     <artifactId>PlayWallDesktop</artifactId>
-    <version>6.2.0-SNAPSHOT</version>
+    <version>7.0.0</version>
     <packaging>pom</packaging>
 
     <properties>
@@ -17,12 +17,17 @@
         <core.version>${project.version}</core.version>
         <components.version>${project.version}</components.version>
 
-        <jlibs.version>2.0.5</jlibs.version>
-        <libPlugins.version>2.2.0</libPlugins.version>
-        <versionizer-api.version>1.1.0</versionizer-api.version>
+        <jlibs.version>2.0.6</jlibs.version>
+        <libPlugins.version>2.2.1</libPlugins.version>
+        <versionizer-api.version>1.1.1</versionizer-api.version>
 
         <jlayer.version>1.0.1</jlayer.version>
 
+        <itextpdf.version>5.5.13</itextpdf.version>
+        <jackson-dataformat-csv.version>2.9.9</jackson-dataformat-csv.version>
+
+        <spark-core.version>[2.9.0,)</spark-core.version>
+
         <jna.version>5.2.0</jna.version>
 
         <scala-library.version>2.13.0</scala-library.version>
@@ -44,11 +49,7 @@
         <module>PlayWall</module>
         <module>PlayWallCore</module>
         <module>PlayWallComponents</module>
-        <module>PlayWallPluginAwake</module>
-        <module>PlayWallPluginEqualizer</module>
-        <module>PlayWallPluginLaunchpad</module>
-        <module>PlayWallPluginMedia</module>
-        <module>PlayWallPluginNativeAudio</module>
+        <module>PlayWallPlugins</module>
     </modules>
 
     <dependencyManagement>
@@ -122,12 +123,12 @@
         <repository>
             <id>release</id>
             <name>TheCodeLabs-releases</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-release</url>
         </repository>
         <snapshotRepository>
             <id>snapshots</id>
             <name>TheCodeLabs-snapshots</name>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
         </snapshotRepository>
     </distributionManagement>
 
@@ -145,7 +146,7 @@
         </pluginRepository>
         <pluginRepository>
             <id>release</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-plugins-release</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-plugins-release</url>
             <releases>
                 <enabled>true</enabled>
             </releases>
@@ -155,7 +156,7 @@
         </pluginRepository>
         <pluginRepository>
             <id>snapshots</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-plugins-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-plugins-snapshots</url>
             <releases>
                 <enabled>false</enabled>
             </releases>
@@ -167,6 +168,11 @@
 
 
     <repositories>
+        <repository>
+            <id>jcenter</id>
+            <url>https://jcenter.bintray.com/</url>
+        </repository>
+
         <repository>
             <id>scala</id>
             <name>Scala Tools</name>
@@ -181,7 +187,7 @@
 
         <repository>
             <id>release</id>
-            <url>https://maven.thecodelabs.de/artifactory/Releases</url>
+            <url>https://maven.thecodedev.de/artifactory/Releases</url>
             <releases>
                 <enabled>true</enabled>
             </releases>
@@ -191,7 +197,7 @@
         </repository>
         <repository>
             <id>snapshots</id>
-            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+            <url>https://maven.thecodedev.de/artifactory/TheCodeLabs-snapshots</url>
             <releases>
                 <enabled>false</enabled>
             </releases>