diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index 573656f6b552ab704fd9f1ad893286475dda5049..c1500a33cb5596556ab38560f449acbae8fbe473 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -16,6 +16,7 @@
     <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginAwake" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginAwake/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginAwake/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginEqualizer" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginEqualizer/src/main/resources" charset="UTF-8" />
@@ -32,6 +33,7 @@
     <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/resources" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginWebAPI" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources" charset="UTF-8" />
     <file url="PROJECT" charset="UTF-8" />
   </component>
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 71a1574f2f6df494b2028c78bb51cb89fc3ba39e..ae20783ca82797f27ca5b049467c233d031158e8 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -7,6 +7,7 @@
       <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$/PlayWallPlugins/PlayWallPluginAwake/PlayWallPluginAwake.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginAwake/PlayWallPluginAwake.iml" />
+      <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginContentPlayer/PlayWallPluginContentPlayer.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginContentPlayer/PlayWallPluginContentPlayer.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" />
diff --git a/PlayWall/pom.xml b/PlayWall/pom.xml
index ccb9aec7567cc8e913e7b5c597793d72e9e1183f..e339a9b3049ae791a35ba7f8a2a48e8804854d16 100644
--- a/PlayWall/pom.xml
+++ b/PlayWall/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallDesktop</artifactId>
-        <version>7.0.2</version>
+        <version>7.1.0</version>
     </parent>
 
     <artifactId>PlayWall</artifactId>
diff --git a/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java b/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java
index f3f434f50447c73577d67fdb21460933fcb5ea93..a8590e8ec2ffe39a877e882a444c9b82085d98f3 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java
@@ -26,6 +26,8 @@ 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.viewcontroller.option.GlobalSettingsTabViewController;
+import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController;
 import javafx.application.Application;
 import javafx.application.Platform;
 import javafx.scene.image.Image;
@@ -37,21 +39,24 @@ import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.function.Consumer;
+import java.util.function.Supplier;
 
 public class PlayPadImpl implements PlayPad {
 
-	private Application.Parameters parameters;
+	private final Application.Parameters parameters;
 
-	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 final List<MainWindowListener> mainViewListeners = new ArrayList<>();
+	private final List<SettingsListener> settingsListeners = new ArrayList<>();
+	private final List<PadListener> padListeners = new ArrayList<>();
+	private final List<GlobalListener> globalListeners = new ArrayList<>();
+	private final List<Supplier<ProfileSettingsTabViewController>> additionalProfileSettingsTabs = new ArrayList<>();
+	private final List<Supplier<GlobalSettingsTabViewController>> additionalGlobalSettingsTabs = new ArrayList<>();
 
 	private MainViewController mainViewController;
 	private Image stageIcon;
 	private Project currentProject;
 
-	private Module module;
+	private final Module module;
 
 	private UpdateService updateService;
 	protected GlobalSettings globalSettings;
@@ -242,6 +247,26 @@ public class PlayPadImpl implements PlayPad {
 		return updateService;
 	}
 
+	@Override
+	public void addAdditionalProfileSettingsTab(Supplier<ProfileSettingsTabViewController> tab) {
+		additionalProfileSettingsTabs.add(tab);
+	}
+
+	@Override
+	public List<Supplier<ProfileSettingsTabViewController>> getAdditionalProfileSettingsTabs() {
+		return additionalProfileSettingsTabs;
+	}
+
+	@Override
+	public void addGlobalSettingsTab(Supplier<GlobalSettingsTabViewController> tab) {
+		additionalGlobalSettingsTabs.add(tab);
+	}
+
+	@Override
+	public List<Supplier<GlobalSettingsTabViewController>> getGlobalSettingsTabs() {
+		return additionalGlobalSettingsTabs;
+	}
+
 	/*
 	Getter / Setter
 	 */
diff --git a/PlayWall/src/main/java/de/tobias/playpad/PlayPadMain.java b/PlayWall/src/main/java/de/tobias/playpad/PlayPadMain.java
index 47696ffe718bf872dd71584a00689ac476f8d041..79b2b7b6aae33c837fff88e2546954a85186fb52 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/PlayPadMain.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/PlayPadMain.java
@@ -18,6 +18,7 @@ import de.tobias.playpad.profile.ref.ProfileReferenceManager;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.ref.ProjectReferenceManager;
 import de.tobias.playpad.update.VersionUpdater;
+import de.tobias.playpad.util.ListSerializer;
 import de.tobias.playpad.util.UUIDSerializer;
 import de.tobias.playpad.viewcontroller.SplashScreenViewController;
 import io.github.openunirest.http.Unirest;
@@ -36,6 +37,7 @@ import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
 import java.util.UUID;
 
 /*
@@ -65,6 +67,7 @@ public class PlayPadMain extends Application {
 
 		// Register UserDefaults Serializer
 		UserDefaults.registerLoader(new UUIDSerializer(), UUID.class);
+		UserDefaults.registerLoader(new ListSerializer(), ArrayList.class);
 
 		ApplicationUtils.addAppListener(PlayPadMain::applicationWillStart);
 		App app = ApplicationUtils.registerMainApplication(PlayPadMain.class);
@@ -89,6 +92,7 @@ public class PlayPadMain extends Application {
 	@Override
 	public void init() {
 		App app = ApplicationUtils.getApplication();
+		Logger.info("Running on Java: " + System.getProperty("java.version") + " (" + System.getProperty("java.vendor") + ")");
 		Logger.info("Run Path: {0}", SystemUtils.getRunPath());
 
 		// Init SSLContext
diff --git a/PlayWall/src/main/java/de/tobias/playpad/Strings.java b/PlayWall/src/main/java/de/tobias/playpad/Strings.java
index b28adcf21884f13366e14acc1b2f28b5a7ad0b00..e71f1944b156d2853018669b92e0ba6366fa9595 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/Strings.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/Strings.java
@@ -173,6 +173,7 @@ public class Strings {
 
 	// UI - Window - PadSettings
 	public static final String UI_WINDOW_PAD_SETTINGS_GENERAL_TITLE = "UI.Window.PadSettings.General.Title";
+	public static final String UI_WINDOW_PAD_SETTINGS_PLAYLIST_TITLE = "UI.Window.PadSettings.Playlist.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";
diff --git a/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignAnimator.java b/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignAnimator.java
index d7ebadfc7f1e14ae7e77ffa5cad5ae4d618f71e5..ffd70e7b8b949a039aeb21718fdd335de4193f16 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignAnimator.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignAnimator.java
@@ -1,7 +1,7 @@
 package de.tobias.playpad.design;
 
 import de.tobias.playpad.pad.view.IPadView;
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import de.tobias.playpad.util.FadeableColor;
 import de.tobias.playpad.view.PseudoClasses;
 import javafx.animation.KeyFrame;
@@ -23,7 +23,7 @@ public class ModernDesignAnimator {
 
 	private static HashMap<Integer, Timeline> timelines = new HashMap<>();
 
-	public static void animateFade(IPadViewController padViewController, FadeableColor startColor, FadeableColor endColor, Duration duration) {
+	public static void animateFade(AbstractPadViewController padViewController, FadeableColor startColor, FadeableColor endColor, Duration duration) {
 		ObjectProperty<FadeableColor> backgroundColor = new SimpleObjectProperty<>();
 
 		Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(0), new KeyValue(backgroundColor, startColor)),
@@ -32,7 +32,7 @@ public class ModernDesignAnimator {
 		animate(padViewController, timeline, backgroundColor);
 	}
 
-	public static void animateWarn(IPadViewController padViewController, FadeableColor startColor, FadeableColor endColor, Duration duration) {
+	public static void animateWarn(AbstractPadViewController padViewController, FadeableColor startColor, FadeableColor endColor, Duration duration) {
 		ObjectProperty<FadeableColor> backgroundColor = new SimpleObjectProperty<>();
 
 		Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(0), new KeyValue(backgroundColor, startColor)),
@@ -45,7 +45,7 @@ public class ModernDesignAnimator {
 		animate(padViewController, timeline, backgroundColor);
 	}
 
-	private static void animate(IPadViewController padViewController, Timeline timeline, ObjectProperty<FadeableColor> objectProperty) {
+	private static void animate(AbstractPadViewController padViewController, Timeline timeline, ObjectProperty<FadeableColor> objectProperty) {
 		int index = padViewController.getPad().getPosition();
 
 		if (timelines.containsKey(index)) {
@@ -68,7 +68,7 @@ public class ModernDesignAnimator {
 		timelines.put(index, timeline);
 	}
 
-	public static void stopAnimation(IPadViewController controller) {
+	public static void stopAnimation(AbstractPadViewController controller) {
 		int index = controller.getPad().getPosition();
 
 		if (timelines.containsKey(index)) {
@@ -76,7 +76,7 @@ public class ModernDesignAnimator {
 		}
 	}
 
-	public static void warnFlash(IPadViewController controller) {
+	public static void warnFlash(AbstractPadViewController controller) {
 		final IPadView view = controller.getView();
 		try {
 			while (!Thread.interrupted()) {
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 ef01fa96ae6a41cef3f5c94a11d706aa28e51410..a3aa32c486a7ef02b1d297b042edbfe8249baafb 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
@@ -21,9 +21,9 @@ import java.util.Deque;
 public class DesktopMainLayoutFactory extends MainLayoutFactory {
 
 	private DesktopMenuToolbarViewController desktopMenuToolbarViewController;
-	private ObjectProperty<DesktopEditMode> editMode = new SimpleObjectProperty<>(DesktopEditMode.PLAY);
+	private final ObjectProperty<DesktopEditMode> editMode = new SimpleObjectProperty<>(DesktopEditMode.PLAY);
 
-	private Deque<IPadView> recyclingStack;
+	private final Deque<IPadView> recyclingStack;
 
 	public DesktopMainLayoutFactory(String type) {
 		super(type);
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 fc6d030e7c7ca0032590d9df3395200e4f7c1371..aacddf3f434ca9ed7d05381521cfaeb3d870b95b 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
@@ -26,6 +26,7 @@ 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.ProjectSettings;
+import de.tobias.playpad.project.ProjectSettingsValidator;
 import de.tobias.playpad.project.page.Page;
 import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.project.ref.ProjectReferenceManager;
@@ -65,6 +66,7 @@ import javafx.scene.control.MenuBar;
 import javafx.scene.control.MenuItem;
 import javafx.scene.control.TextField;
 import javafx.scene.control.*;
+import javafx.scene.input.KeyCode;
 import javafx.scene.input.KeyCombination;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.HBox;
@@ -155,7 +157,7 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 	private transient DesktopColorPickerView colorPickerView;
 	private transient PadRemoveMouseListener padRemoveMouseListener;
 
-	private DesktopMainLayoutFactory connect;
+	private final DesktopMainLayoutFactory connect;
 
 	DesktopMenuToolbarViewController(IMainViewController controller, DesktopMainLayoutFactory connect) {
 		super("Header", "view/main/desktop", Localization.getBundle());
@@ -303,8 +305,7 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 
 		int index = 1; // Für Tastenkombination
 		for (MainLayoutFactory connect : mainLayouts.getComponents()) {
-			if(connect.getType().equals(profileSettings.getMainLayoutType()))
-			{
+			if (connect.getType().equals(profileSettings.getMainLayoutType())) {
 				continue;
 			}
 
@@ -324,7 +325,7 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 
 			layoutMenu.getItems().add(item);
 			index++;
-	}
+		}
 	}
 
 	@Override
@@ -699,6 +700,34 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 		}
 	}
 
+	@FXML
+	void addColumnToProject() {
+		ProjectSettingsValidator projectSettingsValidator = new ProjectSettingsValidator(mainViewController.getScreen());
+		final int maxValue = projectSettingsValidator.maxValue(ProjectSettingsValidator.Dimension.COLUMNS);
+		if (maxValue < openProject.getSettings().getColumns() + 1) {
+			showErrorMessage(Localization.getString("Error.Screen.TooMuch", maxValue));
+			return;
+		}
+
+		openProject.addColumn();
+		mainViewController.createPadViews();
+		mainViewController.showPage(mainViewController.getPage());
+	}
+
+	@FXML
+	void addRowToProject() {
+		ProjectSettingsValidator projectSettingsValidator = new ProjectSettingsValidator(mainViewController.getScreen());
+		final int maxValue = projectSettingsValidator.maxValue(ProjectSettingsValidator.Dimension.ROWS);
+		if (maxValue < openProject.getSettings().getRows() + 1) {
+			showErrorMessage(Localization.getString("Error.Screen.TooMuch", maxValue));
+			return;
+		}
+
+		openProject.addRow();
+		mainViewController.createPadViews();
+		mainViewController.showPage(mainViewController.getPage());
+	}
+
 	@FXML
 	void alwaysOnTopItemHandler(ActionEvent event) {
 		boolean selected = alwaysOnTopItem.isSelected();
@@ -728,6 +757,12 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro
 		NotificationPane pane = mainViewController.getNotificationPane();
 		pane.setOnShown(e -> searchField.requestFocus());
 		pane.show("", box);
+
+		searchField.setOnKeyPressed(e -> {
+			if (e.getCode() == KeyCode.ESCAPE) {
+				pane.hide();
+			}
+		});
 	}
 
 	@FXML
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 94c9d6cb155705a2eb67eb7b6bcef255ef71517f..ff626503c43c96606ff23dbf7dea99e14cc0ce81 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
@@ -2,11 +2,13 @@ package de.tobias.playpad.layout.desktop;
 
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.thecodelabs.utils.ui.icon.FontIconType;
 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.ProjectSettings;
 import de.tobias.playpad.project.page.Page;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import de.tobias.playpad.viewcontroller.main.MenuToolbarViewController;
@@ -20,17 +22,21 @@ import javafx.stage.Stage;
 
 import java.util.Optional;
 
-public class DesktopPageEditButtonView extends HBox implements EventHandler<ActionEvent> {
+public class DesktopPageEditButtonView extends HBox {
 
-	private Page page;
-	private Button leftMoveButton;
-	private Button rightMoveButton;
-	private Button editTextButton;
-	private Button cloneButton;
-	private Button deleteButton;
+	private static class EditButton extends Button {
+		private EditButton(FontIconType icon, EventHandler<ActionEvent> onAction, String tooltip) {
+			super("", new FontIcon(icon));
+			setOnAction(onAction);
+			setTooltip(new Tooltip(tooltip));
+			setFocusTraversable(false);
+		}
+	}
 
-	private transient MenuToolbarViewController controller;
-	private transient IMainViewController mainViewController;
+	private final Page page;
+
+	private final transient MenuToolbarViewController controller;
+	private final transient IMainViewController mainViewController;
 
 	DesktopPageEditButtonView(MenuToolbarViewController controller, IMainViewController mainViewController, Page page) {
 		this.page = page;
@@ -38,112 +44,98 @@ public class DesktopPageEditButtonView extends HBox implements EventHandler<Acti
 		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_LEFT_MOVE)));
-		leftMoveButton.setFocusTraversable(false);
+		Button leftMoveButton = new EditButton(FontAwesomeType.ARROW_LEFT, this::onLeftButton, Localization.getString(Strings.TOOLTIP_PAGE_LEFT_MOVE));
+		Button rightMoveButton = new EditButton(FontAwesomeType.ARROW_RIGHT, this::onRightButton, Localization.getString(Strings.TOOLTIP_PAGE_RIGHT_MOVE));
+		Button editTextButton = new EditButton(FontAwesomeType.EDIT, this::onRenameButton, Localization.getString(Strings.TOOLTIP_PAGE_RENAME));
+		Button cloneButton = new EditButton(FontAwesomeType.COPY, this::onCloneButton, Localization.getString(Strings.TOOLTIP_PAGE_CLONE));
+		Button deleteButton = new EditButton(FontAwesomeType.TRASH, this::onDeleteButton, Localization.getString(Strings.TOOLTIP_PAGE_DELETE));
 
-		rightMoveButton = new Button("", new FontIcon(FontAwesomeType.ARROW_RIGHT));
-		rightMoveButton.setOnAction(this);
-		rightMoveButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_RIGHT_MOVE)));
-		rightMoveButton.setFocusTraversable(false);
+		getChildren().addAll(leftMoveButton, rightMoveButton, editTextButton, cloneButton, deleteButton);
+		setSpacing(7);
+	}
 
-		editTextButton = new Button("", new FontIcon(FontAwesomeType.EDIT));
-		editTextButton.setOnAction(this);
-		editTextButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_RENAME)));
-		editTextButton.setFocusTraversable(false);
+	private void onLeftButton(ActionEvent event) {
+		final Project project = page.getProject();
+		if (page.getPosition() > 0) {
+			final Page leftPage = project.getPage(page.getPosition() - 1);
 
-		cloneButton = new Button("", new FontIcon(FontAwesomeType.COPY));
-		cloneButton.setOnAction(this);
-		cloneButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_CLONE)));
-		cloneButton.setFocusTraversable(false);
+			final int leftIndex = leftPage.getPosition();
+			final int rightIndex = page.getPosition();
 
-		deleteButton = new Button("", new FontIcon(FontAwesomeType.TRASH));
-		deleteButton.setOnAction(this);
-		deleteButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_DELETE)));
-		deleteButton.setFocusTraversable(false);
+			project.setPage(rightIndex, leftPage);
+			project.setPage(leftIndex, page);
 
-		getChildren().addAll(leftMoveButton, rightMoveButton, editTextButton, cloneButton, deleteButton);
-		setSpacing(7);
+			if (mainViewController.getMenuToolbarController() != null)
+				mainViewController.getMenuToolbarController().initPageButtons();
+			mainViewController.showPage(leftIndex);
+		}
+		event.consume();
 	}
 
-	@Override
-	public void handle(ActionEvent event) {
-		if (event.getSource() == leftMoveButton) {
-			Project project = page.getProject();
-			if (page.getPosition() > 0) {
-				Page leftPage = project.getPage(page.getPosition() - 1);
+	private void onRightButton(ActionEvent event) {
+		final Project project = page.getProject();
+		if (page.getPosition() < project.getPages().size()) {
+			final Page rightPage = project.getPage(page.getPosition() + 1);
 
-				int leftIndex = leftPage.getPosition();
-				int rightIndex = page.getPosition();
+			final int rightIndex = rightPage.getPosition();
+			final int leftIndex = page.getPosition();
 
-				project.setPage(rightIndex, leftPage);
-				project.setPage(leftIndex, page);
+			project.setPage(leftIndex, rightPage);
+			project.setPage(rightIndex, page);
 
-				IMainViewController controller = PlayPadPlugin.getInstance().getMainViewController();
-				if (controller.getMenuToolbarController() != null)
-					controller.getMenuToolbarController().initPageButtons();
-				controller.showPage(leftIndex);
-			}
-			event.consume();
-		} else if (event.getSource() == rightMoveButton) {
-			Project project = page.getProject();
-			if (page.getPosition() < project.getPages().size()) {
-				Page rightPage = project.getPage(page.getPosition() + 1);
+			if (mainViewController.getMenuToolbarController() != null)
+				mainViewController.getMenuToolbarController().initPageButtons();
+			mainViewController.showPage(rightIndex);
+		}
+		event.consume();
+	}
 
-				int rightIndex = rightPage.getPosition();
-				int leftIndex = page.getPosition();
+	private void onRenameButton(ActionEvent event) {
+		showPageNameDialog(page);
+	}
 
-				project.setPage(leftIndex, rightPage);
-				project.setPage(rightIndex, page);
+	private void onCloneButton(ActionEvent event) {
+		final Page clone = page.copy();
 
-				IMainViewController controller = PlayPadPlugin.getInstance().getMainViewController();
-				if (controller.getMenuToolbarController() != null)
-					controller.getMenuToolbarController().initPageButtons();
-				controller.showPage(rightIndex);
-			}
-			event.consume();
-		} else if (event.getSource() == editTextButton) {
-			showPageNameDialog(page);
+		// Show Rename dialog for cloned page
+		boolean success = showPageNameDialog(clone);
 
-			event.consume();
-		} else if (event.getSource() == cloneButton) {
-			Page clone = page.copy();
+		if (!success) {
+			return;
+		}
 
-			// Show Rename dialog for cloned page
-			boolean success = showPageNameDialog(clone);
+		Project project = page.getProject();
+		boolean added = project.addPage(clone);
 
-			if (!success) {
-				return;
-			}
+		if (!added) {
+			mainViewController.showErrorMessage(Localization.getString(Strings.ERROR_PROJECT_PAGE_COUNT, ProjectSettings.MAX_PAGES));
+			return;
+		}
 
-			Project project = page.getProject();
-			project.addPage(clone);
+		controller.initPageButtons();
+		mainViewController.showPage(clone);
+	}
+
+	private void onDeleteButton(ActionEvent event) {
+		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.initOwner(controller.getContainingWindow());
+		alert.initModality(Modality.WINDOW_MODAL);
+		Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
+		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
+		Optional<ButtonType> result = alert.showAndWait();
+		result.filter(r -> r == ButtonType.OK).ifPresent(r ->
+		{
+			Project project = page.getProject();
+			project.removePage(page);
+			PlayPadMain.getProgramInstance().getMainViewController().showPage(0);
 			controller.initPageButtons();
-			mainViewController.showPage(clone);
+			controller.highlightPageButton(0); // Show first page
 			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.initOwner(controller.getContainingWindow());
-			alert.initModality(Modality.WINDOW_MODAL);
-			Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
-			stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
-
-			Optional<ButtonType> result = alert.showAndWait();
-			result.filter(r -> r == ButtonType.OK).ifPresent(r ->
-			{
-				Project project = page.getProject();
-				project.removePage(page);
-				PlayPadMain.getProgramInstance().getMainViewController().showPage(0);
-				controller.initPageButtons();
-				controller.highlightPageButton(0); // Show first page
-				event.consume();
-			});
-		}
+		});
 	}
 
 	private boolean showPageNameDialog(Page page) {
diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/listener/PadNewContentListener.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/listener/PadNewContentListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..fedd12aea0879dbda04f8cc41b28c335c4807a8e
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/listener/PadNewContentListener.java
@@ -0,0 +1,100 @@
+package de.tobias.playpad.layout.desktop.listener;
+
+import de.thecodelabs.utils.application.ApplicationUtils;
+import de.thecodelabs.utils.util.Localization;
+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.content.PadContentFactory;
+import de.tobias.playpad.pad.content.PadContentRegistry;
+import de.tobias.playpad.registry.NoSuchComponentException;
+import de.tobias.playpad.settings.GlobalSettings;
+import javafx.event.ActionEvent;
+import javafx.scene.Node;
+import javafx.stage.FileChooser;
+import javafx.stage.Window;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.List;
+
+public class PadNewContentListener {
+
+	private final Pad pad;
+
+	public PadNewContentListener(Pad pad) {
+		this.pad = pad;
+	}
+
+	public List<File> showMediaOpenFileChooser(ActionEvent event, String[] supportedFileTypes, boolean multiSelect) {
+		GlobalSettings settings = PlayPadPlugin.getInstance().getGlobalSettings();
+		if (pad.getProject() != null && settings.isLiveMode() && settings.isLiveModeFile() && pad.getProject().getActivePlayers() > 0) {
+			return Collections.emptyList();
+		}
+
+		final FileChooser chooser = new FileChooser();
+		final FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter(Localization.getString(Strings.FILE_FILTER_MEDIA), supportedFileTypes);
+		chooser.getExtensionFilters().add(extensionFilter);
+
+		// Last Folder
+		final Object openFolder = ApplicationUtils.getApplication().getUserDefaults().getData(DesktopPadViewController.OPEN_FOLDER);
+		if (openFolder != null) {
+			File folder = new File(openFolder.toString());
+			if (folder.exists()) {
+				chooser.setInitialDirectory(folder);
+			}
+		}
+
+		final List<File> selectedFiles;
+		final Window window = ((Node) event.getTarget()).getScene().getWindow();
+		if (multiSelect) {
+			selectedFiles = chooser.showOpenMultipleDialog(window);
+		} else {
+			selectedFiles = Collections.singletonList(chooser.showOpenDialog(window));
+		}
+
+		if (selectedFiles != null && !selectedFiles.isEmpty()) {
+			ApplicationUtils.getApplication().getUserDefaults().setData(DesktopPadViewController.OPEN_FOLDER, selectedFiles.get(0).getParent());
+		}
+		return selectedFiles;
+	}
+
+	public void onNew(ActionEvent event, PadContentFactory.PadContentTypeChooser padContentTypeChooser) throws NoSuchComponentException {
+		final PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents();
+		final List<File> files = showMediaOpenFileChooser(event, registry.getSupportedFileTypes(), false);
+
+		if (files != null) {
+			final Path path = files.get(0).toPath();
+
+			final List<PadContentFactory> connects = registry.getPadContentConnectsForFile(path);
+			if (!connects.isEmpty()) {
+				if (connects.size() > 1) { // Multiple content types possible
+					padContentTypeChooser.showOptions(connects, padContent ->
+					{
+						if (padContent != null) {
+							setNewPadContent(path, padContent);
+						}
+					});
+				} else {
+					PadContentFactory padContent = connects.iterator().next();
+					setNewPadContent(path, padContent);
+				}
+			}
+		}
+	}
+
+	private void setNewPadContent(Path path, PadContentFactory connect) {
+		if (pad.getContent() == null || !pad.getContent().getType().equals(connect.getType())) {
+			this.pad.setContentType(connect.getType());
+		}
+
+		if (pad.isPadVisible()) {
+			pad.getController().getView().showBusyView(true);
+		}
+
+		pad.setPath(path);
+	}
+
+}
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 86347f6aa5f964cc26359dbbe7d49bbfdc102ad5..fff46f264a0632184ab597a851d5eba90fcf7b47 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
@@ -7,7 +7,10 @@ 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.content.Playlistable;
+import de.tobias.playpad.pad.drag.ContentDragOption;
 import de.tobias.playpad.pad.drag.PadDragMode;
+import de.tobias.playpad.pad.drag.PlaylistDragOption;
 import de.tobias.playpad.pad.view.IPadView;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.project.Project;
@@ -26,18 +29,21 @@ import javafx.scene.layout.Pane;
 import javafx.scene.paint.Color;
 
 import java.io.File;
+import java.nio.file.Path;
+import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Set;
+import java.util.List;
+import java.util.stream.Collectors;
 
 public class DesktopPadDragListener implements EventHandler<DragEvent> {
 
-	private static final String PADINDEX_DATATYPE = "de.tobias.playpad.padindex";
-	private static final DataFormat dataFormat = new DataFormat(PADINDEX_DATATYPE);
+	private static final String PAD_INDEX_DATATYPE = "de.tobias.playpad.pad_index";
+	private static final DataFormat dataFormat = new DataFormat(PAD_INDEX_DATATYPE);
 
-	private Pad currentPad;
-	private final Pane padView; // Node der PadView
+	private final Pad currentPad;
+	private final Pane padViewNode; // Node der PadView
 
-	private DesktopMainLayoutFactory connect;
+	private final DesktopMainLayoutFactory connect;
 
 	private PadDragOptionView padHud;
 	private FileDragOptionView fileHud;
@@ -46,21 +52,21 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> {
 		this.currentPad = currentPad;
 		this.connect = connect;
 
-		this.padView = view.getRootNode();
+		this.padViewNode = view.getRootNode();
 	}
 
 	public void addListener() {
-		this.padView.setOnDragOver(this::dragOver);
-		this.padView.setOnDragExited(event -> dragExited());
-		this.padView.setOnDragDropped(this::dragDropped);
-		this.padView.setOnDragDetected(this::dragDetacted);
+		this.padViewNode.setOnDragOver(this::dragOver);
+		this.padViewNode.setOnDragExited(event -> dragExited());
+		this.padViewNode.setOnDragDropped(this::dragDropped);
+		this.padViewNode.setOnDragDetected(this::dragDetected);
 	}
 
 	void removeListener() {
-		this.padView.setOnDragOver(null);
-		this.padView.setOnDragExited(null);
-		this.padView.setOnDragDropped(null);
-		this.padView.setOnDragDetected(null);
+		this.padViewNode.setOnDragOver(null);
+		this.padViewNode.setOnDragExited(null);
+		this.padViewNode.setOnDragDropped(null);
+		this.padViewNode.setOnDragDetected(null);
 	}
 
 	@Override
@@ -75,52 +81,67 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> {
 	}
 
 	private void dragOver(DragEvent event) {
-		if (Profile.currentProfile().getProfileSettings().isLocked()) {
+		if (Profile.currentProfile().getProfileSettings().isLocked() || checkLiveMode()) {
 			return;
 		}
 
 		if (event.getGestureSource() != this && event.getDragboard().hasFiles()) {
-			File file = event.getDragboard().getFiles().get(0);
-			if (file.isFile()) {
-				// Check Live Mode
-				if (checkLiveMode()) {
-					return;
-				}
+			handleFileDropOver(event);
+		} else if (event.getDragboard().hasContent(dataFormat)) {
+			handlePadDragOver(event);
+		}
+		event.consume();
+	}
+
+	@SuppressWarnings("java:S1066")
+	private void handleFileDropOver(DragEvent event) {
+		final File file = event.getDragboard().getFiles().get(0);
+		if (file.isFile()) {
 
-				// Build In Filesupport
-				PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents();
-				Set<PadContentFactory> connects = registry.getPadContentConnectsForFile(file.toPath());
+			final List<Path> paths = event.getDragboard().getFiles().stream().map(File::toPath).collect(Collectors.toList());
 
-				if (!connects.isEmpty()) {
-					if (fileHud == null) {
-						fileHud = new FileDragOptionView(padView);
-					}
-					fileHud.showDropOptions(connects);
+			// built-in file support
+			final PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents();
+			final List<PadContentFactory> supportedContentTypes = registry.getPadContentConnectsForFiles(paths);
 
-					event.acceptTransferModes(TransferMode.LINK);
-					return;
+			if (currentPad.getContent() != null && currentPad.getContent().isPadLoading()) {
+				return;
+			}
+
+			final List<ContentDragOption> contentDragOptions = new ArrayList<>(supportedContentTypes);
+
+			if (currentPad.getContent() instanceof Playlistable) {
+				if (supportedContentTypes.stream().anyMatch(factory -> factory.getType().equals(currentPad.getContent().getType()))) {
+					contentDragOptions.add(new PlaylistDragOption());
 				}
 			}
-		}
 
-		// Drag and Drop von Pads
-		if (event.getDragboard().hasContent(dataFormat)) {
-			PadIndex index = (PadIndex) event.getDragboard().getContent(dataFormat);
-			if (!currentPad.getPadIndex().equals(index)) {
+			if (!contentDragOptions.isEmpty()) {
+				if (fileHud == null) {
+					fileHud = new FileDragOptionView(padViewNode);
+				}
+				fileHud.showOptions(contentDragOptions);
+
+				event.acceptTransferModes(TransferMode.LINK);
+			}
+		}
+	}
 
-				Collection<PadDragMode> connects = PlayPadPlugin.getRegistries().getDragModes().getComponents();
+	private void handlePadDragOver(DragEvent event) {
+		PadIndex index = (PadIndex) event.getDragboard().getContent(dataFormat);
+		if (!currentPad.getPadIndex().equals(index)) {
 
-				if (!connects.isEmpty()) {
-					if (padHud == null) {
-						padHud = new PadDragOptionView(padView);
-					}
-					padHud.showDropOptions(connects);
+			Collection<PadDragMode> connects = PlayPadPlugin.getRegistries().getDragModes().getComponents();
 
-					event.acceptTransferModes(TransferMode.MOVE);
+			if (!connects.isEmpty()) {
+				if (padHud == null) {
+					padHud = new PadDragOptionView(padViewNode);
 				}
+				padHud.showDropOptions(connects);
+
+				event.acceptTransferModes(TransferMode.MOVE);
 			}
 		}
-		event.consume();
 	}
 
 	private void dragExited() {
@@ -134,79 +155,83 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> {
 
 	// Drag Content ist los gelassen am Ziel
 	private void dragDropped(DragEvent event) {
-		Project project = PlayPadPlugin.getInstance().getCurrentProject();
+		final Project project = PlayPadPlugin.getInstance().getCurrentProject();
 
-		Dragboard db = event.getDragboard();
+		final Dragboard dragboard = event.getDragboard();
 		boolean success = false;
 
 		// File Handling
-		if (db.hasFiles()) {
-			File file = db.getFiles().get(0);
-
-			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 (dragboard.hasFiles()) {
+			success = handleFileDragDropped(dragboard);
+		}
 
-				if (currentPad.getContent() == null || !currentPad.getContent().getType().equals(connect.getType())) {
-					currentPad.setContentType(connect.getType());
-				}
+		// Pad DnD
+		if (dragboard.hasContent(dataFormat)) {
+			success = handlePadDragDropped(project, dragboard);
+		}
+		// Event Completion
+		event.setDropCompleted(success);
+		event.consume();
+	}
 
-				if (currentPad.isPadVisible()) {
-					currentPad.getController().getView().showBusyView(true);
-				}
+	private boolean handleFileDragDropped(Dragboard dragboard) {
+		final ContentDragOption dragOption = fileHud.getSelectedConnect();
+		if (dragOption != null) {
+			// stop pad if playing
+			if (currentPad.getContent() != null && currentPad.getStatus().equals(PadStatus.PLAY)) {
+				currentPad.getContent().stop();
+				currentPad.stop();
+			}
 
-				this.currentPad.setPath(file.toPath());
+			dragOption.handleDrop(currentPad, dragboard.getFiles());
 
-				if (currentPad.getController() != null) {
-					IPadView padView = currentPad.getController().getView();
-					padView.setContentView(currentPad);
-					padView.addDefaultElements(currentPad);
-				}
+			if (currentPad.getController() != null) {
+				final IPadView padView = currentPad.getController().getView();
+				padView.setContentView(currentPad);
+				padView.addDefaultElements(currentPad);
 			}
+
+			return true;
 		}
+		return false;
+	}
 
-		// Pad DnD
-		if (db.hasContent(dataFormat)) {
-			Object data = db.getContent(dataFormat);
-			if (data instanceof PadIndex) {
-				PadIndex srcIndex = (PadIndex) data;
-				PadIndex newIndex = currentPad.getPadIndex(); // Lister ist auf Ziel Pad, daher ist der Index von currentPad
-
-				// Drag handle
-				PadDragMode mode = padHud.getSelectedPadDragMode();
-				success = mode.handle(srcIndex, newIndex, project);
-				padHud.hide();
-
-				// Update der Pad Views nach dem DnD
-				IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController();
-				mainViewController.showPage(mainViewController.getPage());
-
-				if (project.getProjectReference().isSync()) {
-					CommandManager.execute(Commands.PAD_MOVE);
-				}
+	private boolean handlePadDragDropped(Project project, Dragboard dragboard) {
+		boolean success = false;
+
+		Object data = dragboard.getContent(dataFormat);
+		if (data instanceof PadIndex) {
+			PadIndex srcIndex = (PadIndex) data;
+			PadIndex newIndex = currentPad.getPadIndex(); // Lister ist auf Ziel Pad, daher ist der Index von currentPad
+
+			// Drag handle
+			PadDragMode mode = padHud.getSelectedPadDragMode();
+			success = mode.handle(srcIndex, newIndex, project);
+			padHud.hide();
+
+			// Update der Pad Views nach dem DnD
+			IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController();
+			mainViewController.showPage(mainViewController.getPage());
+
+			if (project.getProjectReference().isSync()) {
+				CommandManager.execute(Commands.PAD_MOVE);
 			}
 		}
-		// Event Completion
-		event.setDropCompleted(success);
-		event.consume();
+		return success;
 	}
 
-	private void dragDetacted(MouseEvent event) {
+	private void dragDetected(MouseEvent event) {
 		if (connect.getEditMode() == DesktopEditMode.DRAG) {
 			if (checkLiveMode()) {
 				return;
 			}
 
-			Dragboard dragboard = padView.startDragAndDrop(TransferMode.MOVE);
+			Dragboard dragboard = padViewNode.startDragAndDrop(TransferMode.MOVE);
 
 			// Create Snapshot
 			SnapshotParameters parameters = new SnapshotParameters();
 			parameters.setFill(Color.TRANSPARENT);
-			WritableImage snapshot = padView.snapshot(parameters, null);
+			WritableImage snapshot = padViewNode.snapshot(parameters, null);
 			for (int x = 0; x < snapshot.getWidth(); x++) {
 				for (int y = 0; y < snapshot.getHeight(); y++) {
 					Color oldColor = snapshot.getPixelReader().getColor(x, y).darker().darker();
@@ -229,9 +254,7 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> {
 	private boolean checkLiveMode() {
 		GlobalSettings globalSettings = PlayPadPlugin.getInstance().getGlobalSettings();
 		if (currentPad.getProject() != null) {
-			if (globalSettings.isLiveMode() && globalSettings.isLiveModeFile() && currentPad.getProject().getActivePlayers() > 0) {
-				return true;
-			}
+			return globalSettings.isLiveMode() && globalSettings.isLiveModeFile() && currentPad.getProject().getActivePlayers() > 0;
 		}
 		return false;
 	}
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 6d0b659e2464756bf60529e5533697aa164c9611..e1489f3445343db9ef7b1b3a46be0e6030a8f690 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
@@ -14,30 +14,37 @@ import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.pad.content.PadContent;
 import de.tobias.playpad.pad.content.PadContentFactory;
 import de.tobias.playpad.pad.content.PadContentRegistry;
+import de.tobias.playpad.pad.content.Playlistable;
 import de.tobias.playpad.pad.content.play.Pauseable;
 import de.tobias.playpad.pad.view.IPadContentView;
 import de.tobias.playpad.pad.view.IPadView;
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.project.page.PadIndex;
 import de.tobias.playpad.registry.NoSuchComponentException;
+import de.tobias.playpad.util.NodeWalker;
 import de.tobias.playpad.view.EmptyPadView;
 import de.tobias.playpad.view.PseudoClasses;
+import de.tobias.playpad.view.pad.*;
 import javafx.beans.property.Property;
 import javafx.css.PseudoClass;
 import javafx.geometry.Pos;
 import javafx.scene.Node;
+import javafx.scene.Parent;
 import javafx.scene.control.Button;
 import javafx.scene.control.Label;
 import javafx.scene.control.ProgressBar;
 import javafx.scene.layout.*;
 import javafx.scene.paint.Color;
 
+import static de.tobias.playpad.view.pad.PadStyleClasses.*;
+
 public class DesktopPadView implements IPadView {
 
 	private Label indexLabel;
 	private Label loopLabel;
 	private Label triggerLabel;
+	private Label playlistLabel;
 	private Label errorLabel;
 
 	private HBox infoBox;
@@ -51,6 +58,7 @@ public class DesktopPadView implements IPadView {
 	private ProgressBar playBar;
 	private Button playButton;
 	private Button pauseButton;
+	private Button nextButton;
 	private Button stopButton;
 	private Button newButton;
 	private Button settingsButton;
@@ -60,10 +68,10 @@ 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
+	// Reference to its controller
+	private final transient DesktopPadViewController controller;
 
 	public DesktopPadView(DesktopMainLayoutFactory connect) {
 		controller = new DesktopPadViewController(this, connect);
@@ -71,31 +79,25 @@ public class DesktopPadView implements IPadView {
 	}
 
 	private void setupView() {
-		superRoot = new StackPane();
-		root = new VBox();
+		superRoot = new PadStackPane(STYLE_CLASS_PAD, STYLE_CLASS_PAD_INDEX);
+		root = new PadVBox(STYLE_CLASS_PAD_BUTTON_ROOT);
 		busyView = new BusyView(superRoot);
 
-		cueInLayer = new Label();
+		cueInLayer = PadLabel.empty(STYLE_CLASS_PAD_CUE_IN, STYLE_CLASS_PAD_CUE_IN_INDEX);
 		cueInLayer.prefHeightProperty().bind(root.heightProperty());
-		cueInContainer = new VBox(cueInLayer);
-
-		indexLabel = new Label();
-
-		loopLabel = new Label(); // Active über Visible
-		loopLabel.setGraphic(new FontIcon(FontAwesomeType.REPEAT));
-
-		triggerLabel = new Label();
-		triggerLabel.setGraphic(new FontIcon(FontAwesomeType.EXTERNAL_LINK));
+		VBox cueInContainer = new VBox(cueInLayer);
 
-		errorLabel = new Label();
-		errorLabel.setGraphic(new FontIcon(FontAwesomeType.WARNING));
+		indexLabel = PadLabel.empty(STYLE_CLASS_PAD_INFO, STYLE_CLASS_PAD_INFO_INDEX);
+		timeLabel = PadLabel.empty(STYLE_CLASS_PAD_INFO, STYLE_CLASS_PAD_INFO_INDEX);
 
-		timeLabel = new Label();
+		loopLabel = new PadLabel(new FontIcon(FontAwesomeType.REPEAT));
+		triggerLabel = new PadLabel(new FontIcon(FontAwesomeType.EXTERNAL_LINK));
+		playlistLabel = PadLabel.empty(STYLE_CLASS_PAD_INFO, STYLE_CLASS_PAD_INFO_INDEX);
+		errorLabel = new PadLabel(new FontIcon(FontAwesomeType.WARNING));
 
-		infoBox = new HBox(); // childern in addDefaultButton()
-		infoBox.setSpacing(5);
+		infoBox = new PadHBox(5);
 
-		preview = new HBox();
+		preview = PadHBox.deepStyled(STYLE_CLASS_PAD_TITLE, STYLE_CLASS_PAD_TITLE_INDEX);
 		HBox.setHgrow(preview, Priority.ALWAYS);
 		VBox.setVgrow(preview, Priority.ALWAYS);
 
@@ -103,25 +105,16 @@ public class DesktopPadView implements IPadView {
 		timeLabel.setMaxWidth(Double.MAX_VALUE);
 		timeLabel.setAlignment(Pos.CENTER_RIGHT);
 
-		playBar = new ProgressBar(0);
+		playBar = new PadProgressBar(0, STYLE_CLASS_PAD_PLAYBAR, STYLE_CLASS_PAD_PLAYBAR_INDEX);
 		playBar.prefWidthProperty().bind(root.widthProperty());
 
 		// Buttons
-		playButton = new Button("", new FontIcon(FontAwesomeType.PLAY));
-		playButton.setFocusTraversable(false);
-		playButton.setOnAction(controller);
-		pauseButton = new Button("", new FontIcon(FontAwesomeType.PAUSE));
-		pauseButton.setFocusTraversable(false);
-		pauseButton.setOnAction(controller);
-		stopButton = new Button("", new FontIcon(FontAwesomeType.STOP));
-		stopButton.setFocusTraversable(false);
-		stopButton.setOnAction(controller);
-		newButton = new Button("", new FontIcon(FontAwesomeType.FOLDER_OPEN));
-		newButton.setFocusTraversable(false);
-		newButton.setOnAction(controller);
-		settingsButton = new Button("", new FontIcon(FontAwesomeType.GEAR));
-		settingsButton.setFocusTraversable(false);
-		settingsButton.setOnAction(controller);
+		playButton = new PadButton(new FontIcon(FontAwesomeType.PLAY), controller);
+		pauseButton = new PadButton(new FontIcon(FontAwesomeType.PAUSE), controller);
+		nextButton = new PadButton(new FontIcon(FontAwesomeType.STEP_FORWARD), controller);
+		stopButton = new PadButton(new FontIcon(FontAwesomeType.STOP), controller);
+		newButton = new PadButton(new FontIcon(FontAwesomeType.FOLDER_OPEN), controller);
+		settingsButton = new PadButton(new FontIcon(FontAwesomeType.GEAR), controller);
 
 		// Not Found Label
 		notFoundLabel = new FontIcon(FontAwesomeType.EXCLAMATION_TRIANGLE);
@@ -129,11 +122,10 @@ public class DesktopPadView implements IPadView {
 		notFoundLabel.setOpacity(0.75);
 		notFoundLabel.setSize(80);
 		notFoundLabel.setMouseTransparent(true);
-
 		notFoundLabel.setVisible(false);
 
 		// Button HBOX
-		buttonBox = new HBox(); // childern in addDefaultButton()
+		buttonBox = new PadHBox(STYLE_CLASS_PAD_BUTTON_BOX);
 
 		root.getChildren().addAll(infoBox, preview, playBar, buttonBox);
 		superRoot.getChildren().addAll(cueInContainer, root, notFoundLabel);
@@ -160,13 +152,11 @@ public class DesktopPadView implements IPadView {
 					PadContentFactory connect = registry.getFactory(content.getType());
 
 					previewContent = connect.getPadContentPreview(pad, preview);
-					Node node = previewContent.getNode();
-
-					node.getStyleClass().addAll("pad-title", "pad" + pad.getPadIndex() + "-title");
+					Parent node = previewContent.getNode();
 
-					// Copy Pseudoclasses
+					// Copy Pseudo classes
 					for (PseudoClass pseudoClass : superRoot.getPseudoClassStates()) {
-						node.pseudoClassStateChanged(pseudoClass, true);
+						NodeWalker.getAllNodes(node).forEach(element -> element.pseudoClassStateChanged(pseudoClass, true));
 					}
 
 					preview.getChildren().setAll(node);
@@ -177,16 +167,11 @@ public class DesktopPadView implements IPadView {
 			}
 		}
 		EmptyPadView view = new EmptyPadView(preview);
-		if (pad != null) {
-			view.getStyleClass().addAll("pad-title", "pad" + pad.getPadIndex() + "-title");
-		} else {
-			view.getStyleClass().addAll("pad-title");
-		}
 		preview.getChildren().setAll(view);
 	}
 
 	@Override
-	public IPadViewController getViewController() {
+	public AbstractPadViewController getViewController() {
 		return controller;
 	}
 
@@ -209,31 +194,10 @@ public class DesktopPadView implements IPadView {
 		this.indexLabel.setText(text);
 	}
 
-	ProgressBar getPlayBar() {
-		return playBar;
-	}
-
 	@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);
-		triggerLabel.getGraphic().pseudoClassStateChanged(pseudoClass, active);
-		errorLabel.getGraphic().pseudoClassStateChanged(pseudoClass, active);
-
-		if (preview != null) {
-			preview.getChildren().forEach(i -> i.pseudoClassStateChanged(pseudoClass, active));
-		}
-
-		playBar.pseudoClassStateChanged(pseudoClass, active);
-
-		playButton.getGraphic().pseudoClassStateChanged(pseudoClass, active);
-		pauseButton.getGraphic().pseudoClassStateChanged(pseudoClass, active);
-		stopButton.getGraphic().pseudoClassStateChanged(pseudoClass, active);
-		newButton.getGraphic().pseudoClassStateChanged(pseudoClass, active);
-		settingsButton.getGraphic().pseudoClassStateChanged(pseudoClass, active);
+		NodeWalker.getAllNodes(getRootNode())
+				.forEach(node -> node.pseudoClassStateChanged(pseudoClass, active));
 	}
 
 	@Override
@@ -254,6 +218,10 @@ public class DesktopPadView implements IPadView {
 		return pauseButton;
 	}
 
+	Button getNextButton() {
+		return nextButton;
+	}
+
 	Button getStopButton() {
 		return stopButton;
 	}
@@ -278,8 +246,7 @@ public class DesktopPadView implements IPadView {
 		triggerLabel.setVisible(hasTriggerItems);
 	}
 
-	void
-	setTime(String time) {
+	void setTime(String time) {
 		if (time == null) {
 			timeLabel.setText("");
 		} else {
@@ -293,18 +260,23 @@ public class DesktopPadView implements IPadView {
 			if (pad.getContent() != null) {
 				if (pad.getContent() instanceof Pauseable) {
 					if (pad.getStatus() == PadStatus.PLAY) {
-						buttonBox.getChildren().setAll(pauseButton, stopButton, newButton, settingsButton);
+						if (pad.getContent() instanceof Playlistable) {
+							buttonBox.getChildren().setAll(pauseButton, nextButton, stopButton, settingsButton);
+						} else {
+							buttonBox.getChildren().setAll(pauseButton, stopButton, settingsButton);
+						}
 					} else {
-						buttonBox.getChildren().setAll(playButton, stopButton, newButton, settingsButton);
+						buttonBox.getChildren().setAll(playButton, stopButton, settingsButton);
 					}
 				} else {
-					buttonBox.getChildren().setAll(playButton, stopButton, newButton, settingsButton);
+					buttonBox.getChildren().setAll(playButton, stopButton, settingsButton);
 				}
 			} else {
 				buttonBox.getChildren().setAll(newButton, settingsButton);
 			}
+			applyStyleClasses(pad.getPadIndex());
 		}
-		infoBox.getChildren().setAll(indexLabel, loopLabel, triggerLabel, errorLabel, timeLabel);
+		infoBox.getChildren().setAll(indexLabel, loopLabel, triggerLabel, playlistLabel, errorLabel, timeLabel);
 
 		// Buttons unten Full Width
 		buttonBox.prefWidthProperty().bind(superRoot.widthProperty());
@@ -325,64 +297,18 @@ 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");
-		loopLabel.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon");
-		triggerLabel.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon");
-		errorLabel.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon");
-
-		preview.getChildren().forEach(i -> i.getStyleClass().addAll("pad-title", "pad" + index + "-title"));
-
-		playBar.getStyleClass().addAll("pad-playbar", "pad" + index + "-playbar");
-
-		playButton.getStyleClass().addAll("pad-button", "pad" + index + "-button");
-		pauseButton.getStyleClass().addAll("pad-button", "pad" + index + "-button");
-		stopButton.getStyleClass().addAll("pad-button", "pad" + index + "-button");
-		newButton.getStyleClass().addAll("pad-button", "pad" + index + "-button");
-		settingsButton.getStyleClass().addAll("pad-button", "pad" + index + "-button");
-
-		playButton.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon");
-		pauseButton.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon");
-		stopButton.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon");
-		newButton.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon");
-		settingsButton.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon");
-
-		buttonBox.getStyleClass().add("pad-button-box");
-		root.getStyleClass().add("pad-root");
+		NodeWalker.getAllNodes(getRootNode())
+				.stream()
+				.filter(node -> node instanceof PadIndexable)
+				.forEach(node -> ((PadIndexable) node).setIndex(index));
 	}
 
 	@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"));
-		loopLabel.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad"));
-		triggerLabel.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad"));
-		errorLabel.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad"));
-
-		preview.getChildren().forEach(i -> i.getStyleClass().removeIf(c -> c.startsWith("pad")));
-
-		playBar.getStyleClass().removeIf(c -> c.startsWith("pad"));
-
-		playButton.getStyleClass().removeIf(c -> c.startsWith("pad"));
-		pauseButton.getStyleClass().removeIf(c -> c.startsWith("pad"));
-		stopButton.getStyleClass().removeIf(c -> c.startsWith("pad"));
-		newButton.getStyleClass().removeIf(c -> c.startsWith("pad"));
-		settingsButton.getStyleClass().removeIf(c -> c.startsWith("pad"));
-
-		playButton.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad"));
-		pauseButton.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad"));
-		stopButton.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad"));
-		newButton.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad"));
-		settingsButton.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad"));
-
-		buttonBox.getStyleClass().remove("pad-button-box");
-		root.getStyleClass().remove("pad-root");
+		NodeWalker.getAllNodes(getRootNode())
+				.stream()
+				.filter(node -> node instanceof PadIndexable)
+				.forEach(node -> ((PadIndexable) node).setIndex(null));
 	}
 
 	@Override
@@ -406,6 +332,10 @@ public class DesktopPadView implements IPadView {
 		setContentView(null);
 	}
 
+	public Label getPlaylistLabel() {
+		return playlistLabel;
+	}
+
 	@Override
 	public void setPlaybarVisible(boolean visible) {
 		playBar.setVisible(visible);
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 21700d33e55e8d33b0dd52bc5e10075c6f48b331..fd9acc77f4555699721cdea533a759b8a673a3fd 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,22 +1,19 @@
 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;
 import de.tobias.playpad.PlayPadPlugin;
-import de.tobias.playpad.Strings;
 import de.tobias.playpad.layout.desktop.DesktopEditMode;
 import de.tobias.playpad.layout.desktop.DesktopMainLayoutFactory;
+import de.tobias.playpad.layout.desktop.listener.PadNewContentListener;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.pad.TimeMode;
-import de.tobias.playpad.pad.content.PadContentFactory;
-import de.tobias.playpad.pad.content.PadContentRegistry;
+import de.tobias.playpad.pad.content.Playlistable;
 import de.tobias.playpad.pad.content.play.Durationable;
 import de.tobias.playpad.pad.listener.*;
 import de.tobias.playpad.pad.view.IPadView;
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.profile.ProfileSettings;
 import de.tobias.playpad.registry.NoSuchComponentException;
@@ -27,29 +24,21 @@ import de.tobias.playpad.viewcontroller.option.pad.PadSettingsViewController;
 import javafx.beans.value.ChangeListener;
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
-import javafx.scene.Node;
-import javafx.stage.FileChooser;
-import javafx.stage.FileChooser.ExtensionFilter;
-import javafx.stage.Stage;
 import javafx.util.Duration;
 
-import java.io.File;
-import java.nio.file.Path;
-import java.util.Set;
-
-public class DesktopPadViewController implements IPadViewController, EventHandler<ActionEvent> {
+public class DesktopPadViewController extends AbstractPadViewController implements EventHandler<ActionEvent> {
 
 	public static final String OPEN_FOLDER = "openFolder";
 	private static final String DURATION_FORMAT = "%d:%02d";
 
-	private DesktopPadView padView;
+	private final DesktopPadView padView;
 	private Pad pad;
 
-	private PadLockedListener padLockedListener;
-	private PadStatusListener padStatusListener;
-	private PadContentListener padContentListener;
-	private PadDurationListener padDurationListener;
-	private IPadPositionListener padPositionListener;
+	private final PadLockedListener padLockedListener;
+	private final PadStatusListener padStatusListener;
+	private final PadContentListener padContentListener;
+	private final PadDurationListener padDurationListener;
+	private final IPadPositionListener padPositionListener;
 
 	private DesktopPadDragListener padDragListener;
 
@@ -95,6 +84,8 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 			padView.loopLabelVisibleProperty().bind(pad.getPadSettings().loopProperty());
 			padView.setTriggerLabelActive(pad.getPadSettings().hasTriggerItems());
 
+			updatePlaylistLabelBinding(pad);
+
 			// Update Listener
 			padContentListener.setPad(pad);
 			padPositionListener.setPad(pad);
@@ -103,9 +94,9 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 			pad.contentProperty().addListener(padContentListener);
 			pad.statusProperty().addListener(padStatusListener);
 
-			// Inital Listener call with new data
+			// Initial Listener call with new data
 			padContentListener.changed(null, null, pad.getContent()); // Add Duration listener
-			padStatusListener.changed(null, null, pad.getStatus());
+			padStatusListener.changed(null, null, pad.getStatus()); // Show correct pseudo classes ...
 
 			// Add Drag and Drop Listener
 			padDragListener = new DesktopPadDragListener(pad, padView, connect);
@@ -128,6 +119,9 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 			padView.setTriggerLabelActive(false);
 			padView.loopLabelVisibleProperty().unbind();
 
+			padView.getPlaylistLabel().textProperty().unbind();
+			padView.getPlaylistLabel().setText("");
+
 			// Remove Bindings & Listener
 			pad.contentProperty().removeListener(padContentListener);
 			pad.statusProperty().removeListener(padStatusListener);
@@ -163,6 +157,8 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 				onPlay();
 			} else if (event.getSource() == padView.getPauseButton()) {
 				onPause();
+			} else if (event.getSource() == padView.getNextButton()) {
+				onNext();
 			} else if (event.getSource() == padView.getStopButton()) {
 				onStop();
 			} else if (event.getSource() == padView.getNewButton()) {
@@ -190,72 +186,21 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 		}
 	}
 
-	private void onStop() {
-		if (pad.getContent() != null) {
-			pad.setStatus(PadStatus.STOP);
+	private void onNext() {
+		if (pad.getContent() instanceof Playlistable) {
+			((Playlistable) pad.getContent()).next();
 		}
 	}
 
-	private void onNew(ActionEvent event) throws NoSuchComponentException {
-		GlobalSettings settings = PlayPadPlugin.getInstance().getGlobalSettings();
-		if (pad.getProject() != null) {
-			if (settings.isLiveMode() && settings.isLiveModeFile() && pad.getProject().getActivePlayers() > 0) {
-				return;
-			}
-		}
-
-		FileChooser chooser = new FileChooser();
-		PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents();
-
-		// File Extension
-		ExtensionFilter extensionFilter = new ExtensionFilter(Localization.getString(Strings.FILE_FILTER_MEDIA),
-				registry.getSupportedFileTypes());
-		chooser.getExtensionFilters().add(extensionFilter);
-
-		// Last Folder
-		Object openFolder = ApplicationUtils.getApplication().getUserDefaults().getData(OPEN_FOLDER);
-		if (openFolder != null) {
-			File folder = new File(openFolder.toString());
-			if (folder.exists()) {
-				chooser.setInitialDirectory(folder);
-			}
-		}
-
-		File file = chooser.showOpenDialog(((Node) event.getTarget()).getScene().getWindow());
-		if (file != null) {
-			Path path = file.toPath();
-
-			Set<PadContentFactory> connects = registry.getPadContentConnectsForFile(file.toPath());
-			if (!connects.isEmpty()) {
-				if (connects.size() > 1) { // Multiple content types possible
-					FileDragOptionView hud = new FileDragOptionView(padView.getRootNode());
-					hud.showDropOptions(connects, connect ->
-					{
-						if (connect != null) {
-							setNewPadContent(path, connect);
-							hud.hide();
-						}
-					});
-				} else {
-					PadContentFactory connect = connects.iterator().next();
-					setNewPadContent(path, connect);
-				}
-			}
-
-			ApplicationUtils.getApplication().getUserDefaults().setData(OPEN_FOLDER, path.getParent().toString());
+	private void onStop() {
+		if (pad.getContent() != null) {
+			pad.setStatus(PadStatus.STOP);
 		}
 	}
 
-	private void setNewPadContent(Path path, PadContentFactory connect) {
-		if (pad.getContent() == null || !pad.getContent().getType().equals(connect.getType())) {
-			this.pad.setContentType(connect.getType());
-		}
-
-		if (pad.isPadVisible()) {
-			pad.getController().getView().showBusyView(true);
-		}
-
-		pad.setPath(path);
+	public void onNew(ActionEvent event) throws NoSuchComponentException {
+		final PadNewContentListener listener = new PadNewContentListener(pad);
+		listener.onNew(event, new FileDragOptionView(padView.getRootNode()));
 	}
 
 	private void onSettings() {
@@ -263,15 +208,11 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 		IMainViewController mvc = PlayPadPlugin.getInstance().getMainViewController();
 
 		if (mvc != null) {
-			if (pad.getProject() != null) {
-				if (settings.isLiveMode() && settings.isLiveModeSettings() && pad.getProject().getActivePlayers() > 0) {
-					return;
-				}
+			if (pad.getProject() != null && settings.isLiveMode() && settings.isLiveModeSettings() && pad.getProject().getActivePlayers() > 0) {
+				return;
 			}
 
-			Stage owner = mvc.getStage();
-
-			PadSettingsViewController padSettingsViewController = new PadSettingsViewController(pad, owner);
+			PadSettingsViewController padSettingsViewController = new PadSettingsViewController(pad, mvc);
 			padSettingsViewController.getStageContainer().ifPresent(nvcStage -> nvcStage.addCloseHook(() -> {
 				if (padView != null && pad != null)
 					padView.setTriggerLabelActive(pad.getPadSettings().hasTriggerItems());
@@ -394,7 +335,7 @@ public class DesktopPadViewController implements IPadViewController, EventHandle
 			padView.getSettingsButton().setDisable(true);
 		}
 
-		// Alles Desktivieren, wenn nicht Play Mode
+		// Alles Deaktivieren, wenn nicht Play Mode
 		if (connect.getEditMode() != DesktopEditMode.PLAY) {
 			padView.getPlayButton().setDisable(true);
 			padView.getPauseButton().setDisable(true);
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 c094f0df8c0058df0096424b0d132f1bfdd4f122..3c220b8ba255b641ea8355d2cc818418e90e1a5f 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
@@ -14,12 +14,14 @@ import de.tobias.playpad.pad.content.PadContent;
 import de.tobias.playpad.pad.content.PadContentFactory;
 import de.tobias.playpad.pad.view.IPadContentView;
 import de.tobias.playpad.pad.view.IPadView;
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.project.page.PadIndex;
 import de.tobias.playpad.registry.NoSuchComponentException;
+import de.tobias.playpad.util.NodeWalker;
 import de.tobias.playpad.view.EmptyPadView;
 import de.tobias.playpad.view.PseudoClasses;
+import de.tobias.playpad.view.pad.*;
 import javafx.beans.property.Property;
 import javafx.css.PseudoClass;
 import javafx.geometry.Pos;
@@ -29,11 +31,14 @@ import javafx.scene.control.ProgressBar;
 import javafx.scene.layout.*;
 import javafx.scene.paint.Color;
 
+import static de.tobias.playpad.view.pad.PadStyleClasses.*;
+
 public class TouchPadView implements IPadView {
 
 	private Label indexLabel;
 	private Label loopLabel;
 	private Label triggerLabel;
+	private Label playlistLabel;
 	private Label errorLabel;
 
 	private HBox infoBox;
@@ -50,10 +55,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
+	private final transient TouchPadViewController controller; // Reference to its controller
 
 	public TouchPadView() {
 		controller = new TouchPadViewController(this);
@@ -61,31 +65,25 @@ public class TouchPadView implements IPadView {
 	}
 
 	private void setupView() {
-		superRoot = new StackPane();
-		root = new VBox();
+		superRoot = new PadStackPane(STYLE_CLASS_PAD, STYLE_CLASS_PAD_INDEX);
+		root = new PadVBox(STYLE_CLASS_PAD_BUTTON_ROOT);
 		busyView = new BusyView(superRoot);
 
-		cueInLayer = new Label();
+		cueInLayer = PadLabel.empty(STYLE_CLASS_PAD_CUE_IN, STYLE_CLASS_PAD_CUE_IN_INDEX);
 		cueInLayer.prefHeightProperty().bind(root.heightProperty());
-		cueInContainer = new VBox(cueInLayer);
-
-		indexLabel = new Label();
-
-		loopLabel = new Label(); // Active über Visible
-		loopLabel.setGraphic(new FontIcon(FontAwesomeType.REPEAT));
+		VBox cueInContainer = new VBox(cueInLayer);
 
-		triggerLabel = new Label();
-		triggerLabel.setGraphic(new FontIcon(FontAwesomeType.EXTERNAL_LINK));
+		indexLabel = PadLabel.empty(STYLE_CLASS_PAD_INFO, STYLE_CLASS_PAD_INFO_INDEX);
+		timeLabel = PadLabel.empty(STYLE_CLASS_PAD_INFO, STYLE_CLASS_PAD_INFO_INDEX);
 
-		errorLabel = new Label();
-		errorLabel.setGraphic(new FontIcon(FontAwesomeType.WARNING));
+		loopLabel = new PadLabel(new FontIcon(FontAwesomeType.REPEAT));
+		triggerLabel = new PadLabel(new FontIcon(FontAwesomeType.EXTERNAL_LINK));
+		playlistLabel = PadLabel.empty(STYLE_CLASS_PAD_INFO, STYLE_CLASS_PAD_INFO_INDEX);
+		errorLabel = new PadLabel(new FontIcon(FontAwesomeType.WARNING));
 
-		timeLabel = new Label();
+		infoBox = new PadHBox(5);
 
-		infoBox = new HBox(); // childern in addDefaultButton()
-		infoBox.setSpacing(5);
-
-		preview = new HBox();
+		preview = PadHBox.deepStyled(STYLE_CLASS_PAD_TITLE, STYLE_CLASS_PAD_TITLE_INDEX);
 		HBox.setHgrow(preview, Priority.ALWAYS);
 		VBox.setVgrow(preview, Priority.ALWAYS);
 
@@ -93,16 +91,15 @@ public class TouchPadView implements IPadView {
 		timeLabel.setMaxWidth(Double.MAX_VALUE);
 		timeLabel.setAlignment(Pos.CENTER_RIGHT);
 
-		playBar = new ProgressBar(0);
+		playBar = new PadProgressBar(0, STYLE_CLASS_PAD_PLAYBAR, STYLE_CLASS_PAD_PLAYBAR_INDEX);
 		playBar.prefWidthProperty().bind(root.widthProperty());
 
 		// Not Found Label
 		notFoundLabel = new FontIcon(FontAwesomeType.EXCLAMATION_TRIANGLE);
-		notFoundLabel.getStyleClass().add("pad-notfound");
+		notFoundLabel.getStyleClass().clear();
 		notFoundLabel.setOpacity(0.5);
 		notFoundLabel.setSize(50);
 		notFoundLabel.setMouseTransparent(true);
-
 		notFoundLabel.setVisible(false);
 
 		root.getChildren().addAll(infoBox, preview, playBar);
@@ -135,8 +132,6 @@ public class TouchPadView implements IPadView {
 					previewContent = connect.getPadContentPreview(pad, preview);
 					Node node = previewContent.getNode();
 
-					node.getStyleClass().addAll("pad-title", "pad" + pad.getPadIndex() + "-title");
-
 					// Copy Pseudoclasses
 					for (PseudoClass pseudoClass : superRoot.getPseudoClassStates()) {
 						node.pseudoClassStateChanged(pseudoClass, true);
@@ -150,16 +145,11 @@ public class TouchPadView implements IPadView {
 			}
 		}
 		EmptyPadView view = new EmptyPadView(preview);
-		if (pad != null) {
-			view.getStyleClass().addAll("pad-title", "pad" + pad.getPadIndex() + "-title");
-		} else {
-			view.getStyleClass().addAll("pad-title");
-		}
 		preview.getChildren().setAll(view);
 	}
 
 	@Override
-	public IPadViewController getViewController() {
+	public AbstractPadViewController getViewController() {
 		return controller;
 	}
 
@@ -188,19 +178,8 @@ 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);
-		triggerLabel.getGraphic().pseudoClassStateChanged(pseudoClass, active);
-		errorLabel.getGraphic().pseudoClassStateChanged(pseudoClass, active);
-
-		if (preview != null) {
-			preview.getChildren().forEach(i -> i.pseudoClassStateChanged(pseudoClass, active));
-		}
-
-		playBar.pseudoClassStateChanged(pseudoClass, active);
+		NodeWalker.getAllNodes(getRootNode())
+				.forEach(node -> node.pseudoClassStateChanged(pseudoClass, active));
 	}
 
 	@Override
@@ -235,7 +214,7 @@ public class TouchPadView implements IPadView {
 
 	@Override
 	public void addDefaultElements(Pad pad) {
-		infoBox.getChildren().setAll(indexLabel, loopLabel, triggerLabel, errorLabel, timeLabel);
+		infoBox.getChildren().setAll(indexLabel, loopLabel, triggerLabel, playlistLabel, errorLabel, timeLabel);
 
 		// alle Labels in der InfoBox sollen die gleiche Höhe haben, damit die Icons auf gleicher höhe sind
 		for (Node child : infoBox.getChildren()) {
@@ -247,38 +226,18 @@ 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");
-		loopLabel.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon");
-		triggerLabel.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon");
-		errorLabel.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon");
-
-		preview.getChildren().forEach(i -> i.getStyleClass().addAll("pad-title", "pad" + index + "-title"));
-
-		playBar.getStyleClass().addAll("pad-playbar", "pad" + index + "-playbar");
-
-		root.getStyleClass().add("pad-root");
+		NodeWalker.getAllNodes(getRootNode())
+				.stream()
+				.filter(node -> node instanceof PadIndexable)
+				.forEach(node -> ((PadIndexable) node).setIndex(index));
 	}
 
 	@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"));
-		loopLabel.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad"));
-		triggerLabel.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad"));
-		errorLabel.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad"));
-
-		preview.getChildren().forEach(i -> i.getStyleClass().removeIf(c -> c.startsWith("pad")));
-
-		playBar.getStyleClass().removeIf(c -> c.startsWith("pad"));
-
-		root.getStyleClass().remove("pad-root");
+		NodeWalker.getAllNodes(getRootNode())
+				.stream()
+				.filter(node -> node instanceof PadIndexable)
+				.forEach(node -> ((PadIndexable) node).setIndex(null));
 	}
 
 	@Override
@@ -301,6 +260,10 @@ public class TouchPadView implements IPadView {
 		setContentView(null);
 	}
 
+	public Label getPlaylistLabel() {
+		return playlistLabel;
+	}
+
 	@Override
 	public void setPlaybarVisible(boolean visible) {
 		playBar.setVisible(visible);
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 d6a75430cb0063cd1191e25e9a2499c2f7080f92..c43b9679075c400a0e949b80e2b9ab64e28d4f50 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
@@ -7,7 +7,7 @@ import de.tobias.playpad.pad.TimeMode;
 import de.tobias.playpad.pad.content.play.Durationable;
 import de.tobias.playpad.pad.listener.*;
 import de.tobias.playpad.pad.view.IPadView;
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.profile.ProfileSettings;
 import javafx.beans.value.ChangeListener;
@@ -18,7 +18,7 @@ import javafx.scene.input.MouseEvent;
 import javafx.scene.input.TouchEvent;
 import javafx.util.Duration;
 
-public class TouchPadViewController implements IPadViewController, EventHandler<Event> {
+public class TouchPadViewController extends AbstractPadViewController implements EventHandler<Event> {
 
 	protected static final String CURRENT_PAGE_BUTTON = "current-page-button";
 	private static final String DURATION_FORMAT = "%d:%02d";
@@ -70,11 +70,13 @@ public class TouchPadViewController implements IPadViewController, EventHandler<
 			padView.loopLabelVisibleProperty().bind(pad.getPadSettings().loopProperty());
 			padView.setTriggerLabelActive(pad.getPadSettings().hasTriggerItems());
 
+			updatePlaylistLabelBinding(pad);
+
 			// Update Listener
 			padContentListener.setPad(pad);
 			padPositionListener.setPad(pad);
 
-			// Pad Content Chnage
+			// Pad Content Change
 			pad.contentProperty().addListener(padContentListener);
 			// Pad Status Change
 			pad.statusProperty().addListener(padStatusListener);
@@ -98,6 +100,9 @@ public class TouchPadViewController implements IPadViewController, EventHandler<
 			padView.clearPreviewContent();
 			padView.clearTime();
 
+			padView.getPlaylistLabel().textProperty().unbind();
+			padView.getPlaylistLabel().setText("");
+
 			padView.setTriggerLabelActive(false);
 
 			padView.loopLabelVisibleProperty().unbind();
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 426d058b27de8b181450cc7727dbf0e3c7a0335d..b54079b8e799e072c95b4bbfec191f6a56bdc233 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
@@ -7,9 +7,9 @@ import de.tobias.playpad.audio.AudioRegistry;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.pad.content.play.*;
-import de.tobias.playpad.pad.fade.Fade;
-import de.tobias.playpad.pad.fade.FadeDelegate;
+import de.tobias.playpad.pad.fade.FadeControllerDelegate;
 import de.tobias.playpad.pad.fade.Fadeable;
+import de.tobias.playpad.pad.fade.LogarithmicFadeController;
 import de.tobias.playpad.pad.mediapath.MediaPath;
 import de.tobias.playpad.volume.VolumeManager;
 import javafx.application.Platform;
@@ -24,7 +24,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 
 public class AudioContent extends PadContent implements Pauseable, Durationable, Fadeable,
-		Equalizeable, FadeDelegate, Seekable, SpeedAdjustable {
+		Equalizeable, FadeControllerDelegate, Seekable, SpeedAdjustable {
 
 	private final String type;
 
@@ -33,15 +33,15 @@ public class AudioContent extends PadContent implements Pauseable, Durationable,
 	private ObjectProperty<Duration> durationProperty = new SimpleObjectProperty<>();
 	private ObjectProperty<Duration> positionProperty = new SimpleObjectProperty<>();
 
-	private ChangeListener<Number> volumeListener;
-	private ChangeListener<Number> rateListener;
+	private final ChangeListener<Number> volumeListener;
+	private final ChangeListener<Number> rateListener;
 
-	private Fade fade;
+	private final LogarithmicFadeController fade;
 
 	AudioContent(String type, Pad pad) {
 		super(pad);
 		this.type = type;
-		fade = new Fade(this);
+		fade = new LogarithmicFadeController(this);
 
 		// Pad Volume Listener
 		volumeListener = (a, oldValue, newValue) -> updateVolume();
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 d60a59d949a82adbb94f117600f4d9e6fd95da51..8e5f4339e3e2107bab28ee4ba9c591fcabe1c138 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
@@ -1,16 +1,11 @@
 package de.tobias.playpad.pad.content;
 
 import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.preview.PadTextPreview;
 import de.tobias.playpad.pad.view.IPadContentView;
 import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController;
 import de.tobias.playpad.viewcontroller.option.profile.AudioTabViewController;
-import javafx.geometry.Pos;
-import javafx.scene.Node;
-import javafx.scene.control.Label;
 import javafx.scene.layout.Pane;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.VBox;
-import javafx.scene.text.TextAlignment;
 
 public class AudioPadContentFactory extends PadContentFactory {
 
@@ -33,7 +28,7 @@ public class AudioPadContentFactory extends PadContentFactory {
 	@Override
 	public IPadContentView getPadContentPreview(Pad pad, Pane parentNode) {
 		if (pad.getContent() != null) {
-			return new AudioContentView(pad, parentNode);
+			return new PadTextPreview(pad, parentNode);
 		} else {
 			return null;
 		}
@@ -43,32 +38,4 @@ public class AudioPadContentFactory extends PadContentFactory {
 	public ProfileSettingsTabViewController getSettingsTabViewController(boolean activePlayer) {
 		return new AudioTabViewController(activePlayer);
 	}
-
-	private static class AudioContentView implements IPadContentView {
-
-		private Label nameLabel;
-
-		AudioContentView(Pad pad, Pane parentNode) {
-			nameLabel = new Label();
-			nameLabel.textProperty().bind(pad.nameProperty());
-
-			nameLabel.setWrapText(true);
-			nameLabel.setAlignment(Pos.CENTER);
-			nameLabel.setTextAlignment(TextAlignment.CENTER);
-
-			nameLabel.prefWidthProperty().bind(parentNode.widthProperty());
-			nameLabel.setMaxHeight(Double.MAX_VALUE);
-			VBox.setVgrow(nameLabel, Priority.ALWAYS);
-		}
-
-		@Override
-		public Node getNode() {
-			return nameLabel;
-		}
-
-		@Override
-		public void deInit() {
-			nameLabel.textProperty().unbind();
-		}
-	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/drag/PlaylistDragOption.java b/PlayWall/src/main/java/de/tobias/playpad/pad/drag/PlaylistDragOption.java
new file mode 100644
index 0000000000000000000000000000000000000000..69e86ec2c6f8c2b9c437daffec996dc9aea8213a
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/pad/drag/PlaylistDragOption.java
@@ -0,0 +1,40 @@
+package de.tobias.playpad.pad.drag;
+
+import de.thecodelabs.utils.ui.icon.FontAwesomeType;
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.pad.Pad;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.scene.Node;
+
+import java.io.File;
+import java.util.List;
+
+public class PlaylistDragOption implements ContentDragOption {
+
+	private final StringProperty displayProperty = new SimpleStringProperty(Localization.getString("DndMode.Playlist"));
+
+	@Override
+	public void handleDrop(Pad currentPad, List<File> files) {
+		if (currentPad.isPadVisible()) {
+			currentPad.getController().getView().showBusyView(true);
+		}
+
+		for (File file : files) {
+			currentPad.addPath(file.toPath());
+		}
+	}
+
+	@Override
+	public StringProperty displayProperty() {
+		return displayProperty;
+	}
+
+	@Override
+	public Node getGraphics() {
+		final FontIcon fontIcon = new FontIcon(FontAwesomeType.PLUS_CIRCLE);
+		fontIcon.setSize(30);
+		return fontIcon;
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadContentListener.java b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadContentListener.java
index 0b88a71ca642f337b7c892cf68bc04d3a2efc9ab..20c58f70592345eadb08fc634bcf34a7824951ec 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadContentListener.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadContentListener.java
@@ -3,16 +3,16 @@ package de.tobias.playpad.pad.listener;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.content.PadContent;
 import de.tobias.playpad.pad.content.play.Durationable;
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 
 public class PadContentListener implements ChangeListener<PadContent> {
 
 	private Pad pad;
-	private IPadViewController controller;
+	private final AbstractPadViewController controller;
 
-	public PadContentListener(IPadViewController controller) {
+	public PadContentListener(AbstractPadViewController controller) {
 		this.controller = controller;
 	}
 
@@ -49,5 +49,7 @@ public class PadContentListener implements ChangeListener<PadContent> {
 		} else {
 			controller.getView().setPlaybarVisible(false);
 		}
+
+		controller.updatePlaylistLabelBinding(pad);
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadDurationListener.java b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadDurationListener.java
index ce208522f99ec464cbe6996109ad0a4b3c9210d5..a364fed1a5f5f6996c4885374d1b8acd70faa936 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadDurationListener.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadDurationListener.java
@@ -1,15 +1,15 @@
 package de.tobias.playpad.pad.listener;
 
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 import javafx.util.Duration;
 
 public class PadDurationListener implements ChangeListener<Duration> {
 
-	private IPadViewController controller;
+	private AbstractPadViewController controller;
 
-	public PadDurationListener(IPadViewController controller) {
+	public PadDurationListener(AbstractPadViewController controller) {
 		this.controller = controller;
 	}
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadLockedListener.java b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadLockedListener.java
index 702951b06dab11e634e5c4aec827a06c98638f4e..e94995dda657050904571c0d88dec486b4d62dfa 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadLockedListener.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadLockedListener.java
@@ -1,14 +1,14 @@
 package de.tobias.playpad.pad.listener;
 
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 
 public class PadLockedListener implements ChangeListener<Boolean> {
 
-	private IPadViewController controller;
+	private AbstractPadViewController controller;
 
-	public PadLockedListener(IPadViewController controller) {
+	public PadLockedListener(AbstractPadViewController controller) {
 		this.controller = controller;
 	}
 
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 579fe5a9dfb6fbac7a207b2f67b09cfce5c74800..5326b5f914229d7a4e1b9499bb44c01234d00ecf 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
@@ -13,7 +13,7 @@ import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.pad.content.PadContent;
 import de.tobias.playpad.pad.content.play.Durationable;
 import de.tobias.playpad.pad.fade.Fadeable;
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import de.tobias.playpad.profile.Profile;
 import javafx.beans.value.ObservableValue;
 import javafx.util.Duration;
@@ -21,9 +21,9 @@ import javafx.util.Duration;
 public class PadPositionListener implements Runnable, IPadPositionListener {
 
 	private Pad pad;
-	private IPadViewController controller;
+	private AbstractPadViewController controller;
 
-	public PadPositionListener(IPadViewController controller) {
+	public PadPositionListener(AbstractPadViewController controller) {
 		this.controller = controller;
 	}
 
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 bda5270de706c8c4ecfece808faaa2780eb11170..061cc894962680419298d76f8b326c825afb6770 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
@@ -3,16 +3,16 @@ 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.pad.viewcontroller.AbstractPadViewController;
 import de.tobias.playpad.view.PseudoClasses;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 
 public class PadStatusListener implements ChangeListener<PadStatus> {
 
-	private IPadViewController controller;
+	private AbstractPadViewController controller;
 
-	public PadStatusListener(IPadViewController controller) {
+	public PadStatusListener(AbstractPadViewController controller) {
 		this.controller = controller;
 	}
 
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 7920226aec329f3beaa502e701fb055778ceef76..ca60c2c7bd416bf8da2e0b263172e9affec19ea1 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/server/ServerImpl.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/server/ServerImpl.java
@@ -71,9 +71,9 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 	private static final String PROTOCOL = "https";
 	private static final String WS_PROTOCOL = "wss";
 
-	private String host;
+	private final String host;
 	private WebSocket websocket;
-	private ServerSyncListener syncListener;
+	private final ServerSyncListener syncListener;
 
 	ServerImpl(String host) {
 		this.host = host;
@@ -281,6 +281,7 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> {
 	public void connect(String key) {
 		try {
 			WebSocketFactory webSocketFactory = new WebSocketFactory();
+			webSocketFactory.setConnectionTimeout(5000);
 			if (PlayPadMain.sslContext != null) {
 				webSocketFactory.setSSLContext(PlayPadMain.sslContext);
 			}
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 98290adbcd0df99adf16698fe28258999e072a94..e103e69319bbd4457628bb024cc4f812e00d2c66 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItemFactory.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItemFactory.java
@@ -6,6 +6,7 @@ import de.tobias.playpad.Strings;
 import de.tobias.playpad.tigger.Trigger;
 import de.tobias.playpad.tigger.TriggerItem;
 import de.tobias.playpad.tigger.TriggerItemFactory;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import de.tobias.playpad.viewcontroller.option.pad.trigger.CartTriggerViewController;
 
 public class CartTriggerItemFactory extends TriggerItemFactory {
@@ -20,8 +21,8 @@ public class CartTriggerItemFactory extends TriggerItemFactory {
 	}
 
 	@Override
-	public NVC getSettingsController(TriggerItem item) {
-		return new CartTriggerViewController((CartTriggerItem) item);
+	public NVC getSettingsController(TriggerItem item, IMainViewController mainViewController) {
+		return new CartTriggerViewController((CartTriggerItem) item, mainViewController);
 	}
 
 	@Override
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 434a17a2577ee8aee5a27b1a2850134362e350d0..e6a6a6aa5d3748b2cc348230870c16ac1f5e263b 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/trigger/TriggerDisplayable.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/TriggerDisplayable.java
@@ -10,7 +10,7 @@ import javafx.beans.property.StringProperty;
 
 public class TriggerDisplayable implements Displayable {
 
-	private Trigger trigger;
+	private final Trigger trigger;
 
 	public TriggerDisplayable(Trigger trigger) {
 		this.trigger = trigger;
@@ -21,7 +21,7 @@ public class TriggerDisplayable implements Displayable {
 		return trigger;
 	}
 
-	private StringProperty displayable = new SimpleStringProperty();
+	private final StringProperty displayable = new SimpleStringProperty();
 
 	@Override
 	public StringProperty displayProperty() {
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 73d2447a29858d8ba7ea630749aa89d8cec357dc..fa908a635f0a02ded7f7e3c4518a21a6c5efef05 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItemFactory.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItemFactory.java
@@ -6,6 +6,7 @@ import de.tobias.playpad.Strings;
 import de.tobias.playpad.tigger.Trigger;
 import de.tobias.playpad.tigger.TriggerItem;
 import de.tobias.playpad.tigger.TriggerItemFactory;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import de.tobias.playpad.viewcontroller.option.pad.trigger.VolumeTriggerViewController;
 
 public class VolumeTriggerItemFactory extends TriggerItemFactory {
@@ -20,8 +21,8 @@ public class VolumeTriggerItemFactory extends TriggerItemFactory {
 	}
 
 	@Override
-	public NVC getSettingsController(TriggerItem item) {
-		return new VolumeTriggerViewController((VolumeTriggerItem) item);
+	public NVC getSettingsController(TriggerItem item, IMainViewController mainViewController) {
+		return new VolumeTriggerViewController((VolumeTriggerItem) item, mainViewController);
 	}
 
 	@Override
diff --git a/PlayWall/src/main/java/de/tobias/playpad/util/ListSerializer.java b/PlayWall/src/main/java/de/tobias/playpad/util/ListSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..155d9bdcf0638bd678fb6dae9ab45799963f68e6
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/util/ListSerializer.java
@@ -0,0 +1,35 @@
+package de.tobias.playpad.util;
+
+import de.thecodelabs.storage.settings.UserDefaults;
+import org.dom4j.Element;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ListSerializer implements UserDefaults.Serializer<ArrayList> {
+
+	private static final String LIST_ITEM = "item";
+
+	@Override
+	public ArrayList get(Element element) {
+		ArrayList<Object> list = new ArrayList<>();
+		for (Element child : element.elements(LIST_ITEM)) {
+			final Object o = UserDefaults.loadElement(child);
+			list.add(o);
+		}
+		return list;
+	}
+
+	@Override
+	public void set(Object o, Element element) {
+		if (o instanceof List) {
+			//noinspection unchecked
+			final List<Object> list = (List<Object>) o;
+
+			for (Object item : list) {
+				final Element childElement = element.addElement(LIST_ITEM);
+				UserDefaults.save(childElement, item, null);
+			}
+		}
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/util/NodeWalker.java b/PlayWall/src/main/java/de/tobias/playpad/util/NodeWalker.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a2a2b6a86c8a360606310494a7e11737a612020
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/util/NodeWalker.java
@@ -0,0 +1,37 @@
+package de.tobias.playpad.util;
+
+import javafx.scene.Node;
+import javafx.scene.Parent;
+import javafx.scene.control.Labeled;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class NodeWalker {
+
+	private NodeWalker() {
+	}
+
+	public static List<Node> getAllNodes(Parent root) {
+		List<Node> nodes = new ArrayList<>();
+		nodes.add(root);
+		addAllDescendents(root, nodes);
+		return nodes;
+	}
+
+	private static void addAllDescendents(Parent parent, List<Node> nodes) {
+		for (Node node : parent.getChildrenUnmodifiable()) {
+			nodes.add(node);
+
+			if (node instanceof Labeled) {
+				final Node graphic = ((Labeled) node).getGraphic();
+				if (graphic != null) {
+					nodes.add(graphic);
+				}
+			}
+
+			if (node instanceof Parent)
+				addAllDescendents((Parent) node, nodes);
+		}
+	}
+}
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 e04e34fbe511be49ef008abbdd6963f1219026db..38270ca6887aaa067025135443761d2215c55706 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/view/FileDragOptionView.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/FileDragOptionView.java
@@ -1,6 +1,7 @@
 package de.tobias.playpad.view;
 
 import de.tobias.playpad.pad.content.PadContentFactory;
+import de.tobias.playpad.pad.drag.ContentDragOption;
 import javafx.animation.FadeTransition;
 import javafx.animation.ParallelTransition;
 import javafx.animation.ScaleTransition;
@@ -14,16 +15,16 @@ import javafx.scene.layout.*;
 import javafx.scene.paint.Color;
 import javafx.scene.text.TextAlignment;
 
-import java.util.Set;
+import java.util.Collection;
 import java.util.function.Consumer;
 
-public class FileDragOptionView {
+public class FileDragOptionView implements PadContentFactory.PadContentTypeChooser {
 
-	private HBox optionPane;
-	private Pane parent;
+	private final HBox optionPane;
+	private final Pane parent;
 
-	private Transition inTransition;
-	private Transition outTransition;
+	private final Transition inTransition;
+	private final Transition outTransition;
 
 	public FileDragOptionView(Pane pane) {
 		parent = pane;
@@ -76,9 +77,9 @@ public class FileDragOptionView {
 		return parallelTransition;
 	}
 
-	private PadContentFactory selectedConnect;
+	private ContentDragOption selectedConnect;
 
-	public void showDropOptions(Set<PadContentFactory> options) {
+	public void showOptions(Collection<? extends ContentDragOption> options) {
 		if (!parent.getChildren().contains(optionPane)) {
 			selectedConnect = null;
 
@@ -125,14 +126,16 @@ public class FileDragOptionView {
 
 	}
 
-	public void showDropOptions(Set<PadContentFactory> options, Consumer<PadContentFactory> onFinish) {
-		showDropOptions(options);
+	public void showOptions(Collection<PadContentFactory> options, Consumer<PadContentFactory> onFinish) {
+		showOptions(options);
 
 		for (Node node : optionPane.getChildren()) {
 			if (node instanceof Label) {
 				Label label = (Label) node;
-				label.setOnMouseClicked(ev ->
-						onFinish.accept((PadContentFactory) label.getUserData()));
+				label.setOnMouseClicked(ev -> {
+					onFinish.accept((PadContentFactory) label.getUserData());
+					hide();
+				});
 				label.setOnMouseEntered(e ->
 						label.pseudoClassStateChanged(PseudoClasses.HOVER_CLASS, true));
 				label.setOnMouseExited(e ->
@@ -141,7 +144,7 @@ public class FileDragOptionView {
 		}
 	}
 
-	public PadContentFactory getSelectedConnect() {
+	public ContentDragOption getSelectedConnect() {
 		return selectedConnect;
 	}
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/PadDragOptionView.java b/PlayWall/src/main/java/de/tobias/playpad/view/PadDragOptionView.java
index 205250172cbe517acfb7cb51d1f052de96eae133..7dac34cde41953601b45c78688458d1418ed47ec 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/view/PadDragOptionView.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/PadDragOptionView.java
@@ -100,7 +100,7 @@ public class PadDragOptionView {
 			parent.getChildren().add(optionPane);
 			optionPane.getChildren().clear();
 
-			for (PadDragMode connect : options.stream().sorted().toArray(value -> new PadDragMode[value])) {
+			for (PadDragMode connect : options.stream().sorted().toArray(PadDragMode[]::new)) {
 				Label label = new Label();
 				label.getStyleClass().add("dnd-file-option");
 
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadButton.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadButton.java
new file mode 100644
index 0000000000000000000000000000000000000000..9cfcd183917cda844a14d0875b669c8aed059e66
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadButton.java
@@ -0,0 +1,35 @@
+package de.tobias.playpad.view.pad;
+
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.tobias.playpad.project.page.PadIndex;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.scene.control.Button;
+
+import static de.tobias.playpad.view.pad.PadStyleClasses.*;
+
+public class PadButton extends Button implements PadIndexable {
+
+	private final ObjectProperty<PadIndex> indexProperty;
+
+	public PadButton(FontIcon icon, EventHandler<ActionEvent> value) {
+		super("", icon);
+
+		setFocusTraversable(false);
+		setOnAction(value);
+
+		indexProperty = new SimpleObjectProperty<>();
+		indexProperty.addListener(new StyleIndexListener(this, STYLE_CLASS_PAD_BUTTON, STYLE_CLASS_PAD_BUTTON_INDEX));
+		indexProperty.addListener(new StyleIndexListener(getGraphic(), STYLE_CLASS_PAD_ICON, STYLE_CLASS_PAD_ICON_INDEX));
+	}
+
+	public PadIndex getIndex() {
+		return indexProperty.get();
+	}
+
+	public void setIndex(PadIndex index) {
+		indexProperty.set(index);
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadHBox.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadHBox.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e0c2cdf37be559da5436023d84f375f701aa7e1
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadHBox.java
@@ -0,0 +1,57 @@
+package de.tobias.playpad.view.pad;
+
+import de.tobias.playpad.project.page.PadIndex;
+import javafx.beans.InvalidationListener;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.scene.Node;
+import javafx.scene.layout.HBox;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class PadHBox extends HBox implements PadIndexable {
+
+	private final ObjectProperty<PadIndex> indexProperty;
+	private final List<StyleIndexListener> styleListeners = new LinkedList<>();
+
+	public static PadHBox deepStyled(String... styleClasses) {
+		PadHBox padHBox = new PadHBox(styleClasses);
+
+		padHBox.getChildren().addListener((InvalidationListener) observable -> {
+			for (StyleIndexListener listener : padHBox.styleListeners) {
+				padHBox.indexProperty.removeListener(listener);
+			}
+
+			padHBox.styleListeners.clear();
+
+			for (Node child : padHBox.getChildren()) {
+				StyleIndexListener listener = new StyleIndexListener(child, styleClasses);
+				padHBox.indexProperty.addListener(listener);
+				padHBox.styleListeners.add(listener);
+
+				listener.changed(padHBox.indexProperty, null, padHBox.indexProperty.get());
+			}
+		});
+
+		return padHBox;
+	}
+
+	public PadHBox(String... styleClasses) {
+		this(0, styleClasses);
+	}
+
+	public PadHBox(double spacing, String... styleClasses) {
+		super(spacing);
+		indexProperty = new SimpleObjectProperty<>();
+		indexProperty.addListener(new StyleIndexListener(this, styleClasses));
+	}
+
+	public PadIndex getIndex() {
+		return indexProperty.get();
+	}
+
+	public void setIndex(PadIndex index) {
+		indexProperty.set(index);
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadIndexable.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadIndexable.java
new file mode 100644
index 0000000000000000000000000000000000000000..c50a5cc70ee1604eeeb280636e8b3ae561480790
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadIndexable.java
@@ -0,0 +1,9 @@
+package de.tobias.playpad.view.pad;
+
+import de.tobias.playpad.project.page.PadIndex;
+
+public interface PadIndexable {
+	PadIndex getIndex();
+
+	void setIndex(PadIndex index);
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadLabel.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadLabel.java
new file mode 100644
index 0000000000000000000000000000000000000000..f2aabb08af4bb3c2b1d99ee25576442ef2c4fb90
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadLabel.java
@@ -0,0 +1,57 @@
+package de.tobias.playpad.view.pad;
+
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.tobias.playpad.project.page.PadIndex;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.scene.control.Label;
+
+import static de.tobias.playpad.view.pad.PadStyleClasses.STYLE_CLASS_PAD_ICON;
+import static de.tobias.playpad.view.pad.PadStyleClasses.STYLE_CLASS_PAD_ICON_INDEX;
+
+public class PadLabel extends Label implements PadIndexable {
+
+	private final ObjectProperty<PadIndex> indexProperty;
+	private StyleIndexListener graphicsListener;
+
+	public static PadLabel empty(String... styleClasses) {
+		return new PadLabel("", styleClasses);
+	}
+
+	public PadLabel(FontIcon icon, String... styleClasses) {
+		this("", styleClasses);
+		setGraphic(icon);
+	}
+
+	public PadLabel(String text, String... styleClasses) {
+		super(text);
+
+		indexProperty = new SimpleObjectProperty<>();
+		indexProperty.addListener(new StyleIndexListener(this, styleClasses));
+		initStyleGraphicsListener();
+
+		graphicProperty().addListener(observable -> {
+			if (graphicsListener != null) {
+				indexProperty.removeListener(graphicsListener);
+				graphicsListener = null;
+
+			}
+			initStyleGraphicsListener();
+		});
+	}
+
+	private void initStyleGraphicsListener() {
+		if (getGraphic() != null) {
+			graphicsListener = new StyleIndexListener(getGraphic(), STYLE_CLASS_PAD_ICON, STYLE_CLASS_PAD_ICON_INDEX);
+			indexProperty.addListener(graphicsListener);
+		}
+	}
+
+	public PadIndex getIndex() {
+		return indexProperty.get();
+	}
+
+	public void setIndex(PadIndex index) {
+		indexProperty.set(index);
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadProgressBar.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadProgressBar.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d366b8cfcf4ab58d695c76e24bbe2ada13b6a54
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadProgressBar.java
@@ -0,0 +1,25 @@
+package de.tobias.playpad.view.pad;
+
+import de.tobias.playpad.project.page.PadIndex;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.scene.control.ProgressBar;
+
+public class PadProgressBar extends ProgressBar implements PadIndexable {
+
+	private final ObjectProperty<PadIndex> indexProperty;
+
+	public PadProgressBar(double progress, String... styleClasses) {
+		super(progress);
+		indexProperty = new SimpleObjectProperty<>();
+		indexProperty.addListener(new StyleIndexListener(this, styleClasses));
+	}
+
+	public PadIndex getIndex() {
+		return indexProperty.get();
+	}
+
+	public void setIndex(PadIndex index) {
+		indexProperty.set(index);
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadStackPane.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadStackPane.java
new file mode 100644
index 0000000000000000000000000000000000000000..94d5670789563c8e01f906399bef0187cfc9a5f8
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadStackPane.java
@@ -0,0 +1,24 @@
+package de.tobias.playpad.view.pad;
+
+import de.tobias.playpad.project.page.PadIndex;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.scene.layout.StackPane;
+
+public class PadStackPane extends StackPane implements PadIndexable {
+
+	private final ObjectProperty<PadIndex> indexProperty;
+
+	public PadStackPane(String... styleClasses) {
+		indexProperty = new SimpleObjectProperty<>();
+		indexProperty.addListener(new StyleIndexListener(this, styleClasses));
+	}
+
+	public PadIndex getIndex() {
+		return indexProperty.get();
+	}
+
+	public void setIndex(PadIndex index) {
+		indexProperty.set(index);
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadStyleClasses.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadStyleClasses.java
new file mode 100644
index 0000000000000000000000000000000000000000..b610e4391e05d21ea51949856af096c0bd021648
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadStyleClasses.java
@@ -0,0 +1,37 @@
+package de.tobias.playpad.view.pad;
+
+import de.tobias.playpad.project.page.PadIndex;
+
+public class PadStyleClasses {
+
+	private PadStyleClasses() {
+	}
+
+	public static final String STYLE_CLASS_PAD = "pad";
+	public static final String STYLE_CLASS_PAD_INDEX = "pad${index}";
+
+	public static final String STYLE_CLASS_PAD_BUTTON = "pad-button";
+	public static final String STYLE_CLASS_PAD_BUTTON_INDEX = "pad${index}-button";
+
+	public static final String STYLE_CLASS_PAD_ICON = "pad-icon";
+	public static final String STYLE_CLASS_PAD_ICON_INDEX = "pad${index}-icon";
+
+	public static final String STYLE_CLASS_PAD_INFO = "pad-info";
+	public static final String STYLE_CLASS_PAD_INFO_INDEX = "pad${index}-info";
+
+	public static final String STYLE_CLASS_PAD_TITLE = "pad-title";
+	public static final String STYLE_CLASS_PAD_TITLE_INDEX = "pad${index}-title";
+
+	public static final String STYLE_CLASS_PAD_BUTTON_BOX = "pad-button-box";
+	public static final String STYLE_CLASS_PAD_BUTTON_ROOT = "pad-root";
+
+	public static final String STYLE_CLASS_PAD_PLAYBAR = "pad-playbar";
+	public static final String STYLE_CLASS_PAD_PLAYBAR_INDEX = "pad${index}-playbar";
+
+	public static final String STYLE_CLASS_PAD_CUE_IN = "pad-cue-in";
+	public static final String STYLE_CLASS_PAD_CUE_IN_INDEX = "pad${index}-cue-in";
+
+	public static String replaceIndex(String styleClass, PadIndex index) {
+		return styleClass.replace("${index}", String.valueOf(index));
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadVBox.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadVBox.java
new file mode 100644
index 0000000000000000000000000000000000000000..33d999dc7349e03010453853977619ba086e468d
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadVBox.java
@@ -0,0 +1,29 @@
+package de.tobias.playpad.view.pad;
+
+import de.tobias.playpad.project.page.PadIndex;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.scene.layout.VBox;
+
+public class PadVBox extends VBox implements PadIndexable {
+
+	private final ObjectProperty<PadIndex> indexProperty;
+
+	public PadVBox(String... styleClasses) {
+		this(0, styleClasses);
+	}
+
+	public PadVBox(double spacing, String... styleClasses) {
+		super(spacing);
+		indexProperty = new SimpleObjectProperty<>();
+		indexProperty.addListener(new StyleIndexListener(this, styleClasses));
+	}
+
+	public PadIndex getIndex() {
+		return indexProperty.get();
+	}
+
+	public void setIndex(PadIndex index) {
+		indexProperty.set(index);
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/StyleIndexListener.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/StyleIndexListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..de3acf0ce609fbed673a2aba820c1aef0cf0ffc7
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/StyleIndexListener.java
@@ -0,0 +1,32 @@
+package de.tobias.playpad.view.pad;
+
+import de.tobias.playpad.project.page.PadIndex;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.scene.Node;
+
+public class StyleIndexListener implements ChangeListener<PadIndex> {
+
+	private final Node node;
+	private final String[] styleClasses;
+
+	public StyleIndexListener(Node node, String... styleClasses) {
+		this.node = node;
+		this.styleClasses = styleClasses;
+	}
+
+	@Override
+	public void changed(ObservableValue<? extends PadIndex> observable, PadIndex oldValue, PadIndex newValue) {
+		if (oldValue != null) {
+			for (String styleClass : styleClasses) {
+				node.getStyleClass().remove(PadStyleClasses.replaceIndex(styleClass, oldValue));
+			}
+		}
+
+		if (newValue != null) {
+			for (String styleClass : styleClasses) {
+				node.getStyleClass().add(PadStyleClasses.replaceIndex(styleClass, newValue));
+			}
+		}
+	}
+}
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 7c47592784002e01ae7bf9afed070ee0b959ec4f..4ae03e046bd0f2834543ac709659003d56d92573 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
@@ -28,7 +28,6 @@ import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 
-// TODO Extract into lang file
 public class AboutDialog extends NVC {
 
 	@FXML
@@ -40,6 +39,9 @@ public class AboutDialog extends NVC {
 	@FXML
 	private Label versionLabel;
 
+	@FXML
+	private Label platformLabel;
+
 	@FXML
 	private Label authorLabel;
 
@@ -52,7 +54,7 @@ public class AboutDialog extends NVC {
 	@FXML
 	private Label graphicsLabel;
 
-	private Window owner;
+	private final Window owner;
 
 	public AboutDialog(Window owner) {
 		this.owner = owner;
@@ -68,7 +70,7 @@ public class AboutDialog extends NVC {
 		AnchorPane.setLeftAnchor(icon, 14.0);
 		AnchorPane.setTopAnchor(icon, 14.0);
 
-		icon.setOnMouseClicked((e) -> getStageContainer().ifPresent(NVCStage::close));
+		icon.setOnMouseClicked(e -> getStageContainer().ifPresent(NVCStage::close));
 
 		ApplicationInfo info = ApplicationUtils.getApplication().getInfo();
 		versionLabel.setText(info.getVersion());
@@ -76,6 +78,10 @@ public class AboutDialog extends NVC {
 		graphicsLabel.setText(Localization.getString(Strings.UI_DIALOG_ABOUT_GRAPHICS));
 		libsLabel.setText(Localization.getString(Strings.UI_DIALOG_ABOUT_LIBRARIES));
 
+		platformLabel.setText(String.format("%s (%s) + %s (%s)", System.getProperty("java.version"),
+				System.getProperty("java.vendor"), System.getProperty("javafx.version"),
+				System.getProperty("javafx.runtime.version")));
+
 		Hyperlink websiteLink = new Hyperlink(Localization.getString(Strings.UI_DIALOG_ABOUT_WEBSITE));
 		websiteLink.setPadding(Insets.EMPTY);
 		websiteLink.setFocusTraversable(false);
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 b2bf4ab78fee9e28884c81cd21fb457db7f1f677..ec8f51a3dfc669a93d119794e71e1f9b2d29ee48 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
@@ -363,6 +363,7 @@ public class MainViewController extends NVC implements IMainViewController, Noti
 				}
 			}
 		}
+		Platform.exit();
 		return true;
 	}
 
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 068ecda32cf6bd2f68391253facbedee24e5f5d1..e29db503f32fbff22d8f33dcf471b8423c9238af 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
@@ -36,9 +36,8 @@ public class GlobalSettingsViewController extends NVC implements IGlobalSettings
 	@FXML
 	private Button finishButton;
 
-	private List<GlobalSettingsTabViewController> tabs = new ArrayList<>();
-
-	private Runnable onFinish;
+	private final List<GlobalSettingsTabViewController> tabs = new ArrayList<>();
+	private final Runnable onFinish;
 
 	public GlobalSettingsViewController(Window owner, Runnable onFinish) {
 		load("view/option/global", "GlobalSettingsView", Localization.getBundle());
@@ -53,6 +52,13 @@ public class GlobalSettingsViewController extends NVC implements IGlobalSettings
 		addTab(new KeysTabViewController());
 		addTab(new UpdateTabViewController());
 
+		PlayPadPlugin.getInstance().getGlobalSettingsTabs().forEach(supplier -> {
+			final GlobalSettingsTabViewController globalSettingsTabViewController = supplier.get();
+			if (globalSettingsTabViewController != null) {
+				addTab(globalSettingsTabViewController);
+			}
+		});
+
 		// Show Current Settings
 		loadTabs();
 	}
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 fd2bb3bcd7679c4e777a0b103866730733932f86..604d60b25598cbf48aa1d6d4ade48fa9c854795e 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
@@ -24,7 +24,9 @@ import javafx.fxml.FXML;
 import javafx.scene.control.*;
 
 import java.io.IOException;
+import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 public class UpdateTabViewController extends GlobalSettingsTabViewController {
@@ -56,7 +58,11 @@ public class UpdateTabViewController extends GlobalSettingsTabViewController {
 		GlobalSettings globalSettings = playPad.getGlobalSettings();
 
 		updateChannelComboBox.setValue(globalSettings.getUpdateChannel());
-		openUpdateList.getItems().setAll(playPad.getUpdateService().getRemoteVersions().values());
+		final List<Version> updates = playPad.getUpdateService().getRemoteVersions().values()
+				.stream()
+				.filter(Objects::nonNull)
+				.collect(Collectors.toList());
+		openUpdateList.getItems().setAll(updates);
 		updateButton.setDisable(openUpdateList.getItems().isEmpty());
 
 		ApplicationInfo info = ApplicationUtils.getApplication().getInfo();
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 cd36d822fa42ae26dac33467de7f3b1434e23e7a..4e40233ca501ef4edc4c8f2a3c1aca28d042dadb 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,21 +1,36 @@
 package de.tobias.playpad.viewcontroller.option.pad;
 
+import de.thecodelabs.utils.application.system.NativeApplication;
 import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.Strings;
+import de.tobias.playpad.layout.desktop.listener.PadNewContentListener;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadSettings;
 import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.pad.TimeMode;
+import de.tobias.playpad.pad.content.PadContentFactory;
+import de.tobias.playpad.pad.content.Playlistable;
 import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
 import de.tobias.playpad.viewcontroller.cell.EnumCell;
+import javafx.beans.binding.Bindings;
 import javafx.beans.value.ChangeListener;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.scene.control.*;
+import javafx.scene.layout.VBox;
 import javafx.stage.Stage;
 
+import java.util.Optional;
+
 public class GeneralPadTabViewController extends PadSettingsTabViewController {
 
+	@FXML
+	private VBox mediaRootBox;
+	@FXML
+	private Label pathLabel;
+	@FXML
+	private Button showPathButton;
+
 	@FXML
 	private TextField titleTextField;
 	@FXML
@@ -31,12 +46,24 @@ public class GeneralPadTabViewController extends PadSettingsTabViewController {
 	@FXML
 	private Button deleteButton;
 
-	private Pad pad;
+	private final Pad pad;
 
 	GeneralPadTabViewController(Pad pad) {
 		load("view/option/pad", "GeneralTab", Localization.getBundle());
 		this.pad = pad;
 
+		if (pad.getPath() != null) {
+			pathLabel.setText(pad.getPath().toString());
+		} else {
+			pathLabel.setText(Localization.getString("padSettings.gen.label.media.empty"));
+		}
+		showPathButton.disableProperty().bind(Bindings.isEmpty(pad.getPaths()));
+
+		// Disable media section for playlists
+		if (pad.getContent() instanceof Playlistable) {
+			mediaRootBox.setDisable(true);
+		}
+
 		if (pad.getStatus() == PadStatus.PLAY || pad.getStatus() == PadStatus.PAUSE) {
 			deleteButton.setDisable(true);
 		}
@@ -44,7 +71,6 @@ public class GeneralPadTabViewController extends PadSettingsTabViewController {
 
 	@Override
 	public void init() {
-		// Init Listener
 		ChangeListener<Number> volumeListener = (a, b, c) -> pad.getPadSettings().setVolume(c.doubleValue() / 100.0);
 		volumeSlider.valueProperty().addListener(volumeListener);
 
@@ -71,16 +97,14 @@ public class GeneralPadTabViewController extends PadSettingsTabViewController {
 
 	@Override
 	public void loadSettings(Pad pad) {
-		PadSettings padSettings = pad.getPadSettings();
+		final PadSettings padSettings = pad.getPadSettings();
 
-		// Bindings
 		titleTextField.textProperty().bindBidirectional(pad.nameProperty());
 		repeatCheckBox.selectedProperty().bindBidirectional(padSettings.loopProperty());
 		timeDisplayComboBox.valueProperty().bindBidirectional(padSettings.timeModeProperty());
 
 		volumeSlider.setValue(padSettings.getVolume() * 100);
 
-		// is Custom TimeMode Actvie
 		customTimeDisplayCheckBox.setSelected(padSettings.isCustomTimeMode());
 		if (!padSettings.isCustomTimeMode()) {
 			timeDisplayComboBox.setDisable(true);
@@ -96,7 +120,21 @@ public class GeneralPadTabViewController extends PadSettingsTabViewController {
 		timeDisplayComboBox.valueProperty().unbindBidirectional(padSettings.timeModeProperty());
 	}
 
-	// Listener
+	@FXML
+	private void showPathButtonHandler() {
+		NativeApplication.sharedInstance().showFileInFileViewer(pad.getPath());
+	}
+
+	@FXML
+	private void chooseButtonHandler(ActionEvent event) {
+		final PadNewContentListener listener = new PadNewContentListener(pad);
+		listener.onNew(event, (options, onSelected) -> {
+			ChoiceDialog<PadContentFactory> dialog = new ChoiceDialog<>(null, options);
+			final Optional<PadContentFactory> padContentFactory = dialog.showAndWait();
+			padContentFactory.ifPresent(onSelected);
+		});
+	}
+
 	@FXML
 	private void deleteButtonHandler(ActionEvent event) {
 		pad.clear();
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 739b65fd2c8591af25fbf2d4eb134ffd7b92332b..d7da00b3990912aaa2c9f0c6c3600408fbed1256 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
@@ -10,64 +10,63 @@ 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.mediapath.MediaPath;
+import de.tobias.playpad.pad.content.Playlistable;
 import de.tobias.playpad.registry.NoSuchComponentException;
 import de.tobias.playpad.viewcontroller.IPadSettingsViewController;
 import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
-import javafx.collections.ObservableList;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
-import javafx.scene.Parent;
-import javafx.scene.control.*;
-import javafx.scene.layout.AnchorPane;
+import javafx.scene.control.Button;
+import javafx.scene.control.Tab;
+import javafx.scene.control.TabPane;
 import javafx.stage.Stage;
-import javafx.stage.Window;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 
 public class PadSettingsViewController extends NVC implements IPadSettingsViewController {
 
-	private Pad pad;
+	private final Pad pad;
 
 	@FXML
 	private TabPane tabPane;
-	private List<PadSettingsTabViewController> tabs = new ArrayList<>();
-
-	private Control pathLookupButton;
+	private final List<PadSettingsTabViewController> tabs = new ArrayList<>();
 
 	@FXML
 	private Button finishButton;
 
-	public PadSettingsViewController(Pad pad, Window owner) {
+	public PadSettingsViewController(Pad pad, IMainViewController mainViewController) {
 		load("view/option/pad", "PadSettingsView", Localization.getBundle());
 		this.pad = pad;
 
 		addTab(new GeneralPadTabViewController(pad));
+		if (pad.getContent() instanceof Playlistable) {
+			addTab(new PlaylistTabViewController(pad));
+		}
 		addTab(new DesignPadTabViewController(pad));
 		addTab(new PlayerPadTabViewController(pad));
-		addTab(new TriggerPadTabViewController(pad));
+		addTab(new TriggerPadTabViewController(pad, mainViewController));
 
 		if (pad.getContent() != null) {
 			try {
-				// Get Pad Type specific tab
-				String type = pad.getContent().getType();
-				PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents();
+				final String type = pad.getContent().getType();
+				final PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents();
 
-				PadContentFactory padContentFactory = registry.getFactory(type);
-				PadSettingsTabViewController contentTab = padContentFactory.getSettingsViewController(pad);
+				final PadContentFactory padContentFactory = registry.getFactory(type);
+				final PadSettingsTabViewController contentTab = padContentFactory.getSettingsViewController(pad);
 
-				if (contentTab != null)
+				if (contentTab != null) {
 					addTab(contentTab);
+				}
 			} catch (NoSuchComponentException e) {
 				Logger.error(e);
 			}
 		}
 
-		setupPathLookupButton();
-
 		NVCStage nvcStage = applyViewControllerToStage();
-		nvcStage.initOwner(owner);
+		nvcStage.initOwner(mainViewController.getStage());
 		nvcStage.addCloseHook(this::onFinish);
 		addCloseKeyShortcut(() -> finishButton.fire());
 
@@ -76,57 +75,23 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo
 		setTitle(pad);
 	}
 
-	private void setupPathLookupButton() {
-		PathLookupListener pathLookupListener = new PathLookupListener();
-
-		if (pad.getContent() != null) {
-			final ObservableList<MediaPath> paths = pad.getPaths();
-			if (paths.size() == 1) {
-				Button button = new Button(Localization.getString("padSettings.button.path"));
-
-				MediaPath path = paths.get(0);
-				button.setUserData(path);
-				button.setOnAction(pathLookupListener);
-
-				pathLookupButton = button;
-			} else if (paths.size() > 1) {
-				MenuButton button = new MenuButton(Localization.getString("padSettings.button.path"));
-
-				for (MediaPath path : paths) {
-					MenuItem item = new MenuItem(path.getFileName());
-					button.getItems().add(item);
-
-					item.setUserData(path);
-					item.setOnAction(pathLookupListener);
-				}
-
-				pathLookupButton = button;
-			}
-
-			Parent parent = getParent();
-			if (parent instanceof AnchorPane && pathLookupButton != null) {
-				AnchorPane anchorPane = (AnchorPane) parent;
-				anchorPane.getChildren().add(pathLookupButton);
-
-				AnchorPane.setLeftAnchor(pathLookupButton, 14.0);
-				AnchorPane.setBottomAnchor(pathLookupButton, 14.0);
-			}
-		}
-	}
-
 	private void setTitle(Pad pad) {
 		String title;
 		if (pad.getStatus() != PadStatus.EMPTY) {
-			title = Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_TITLE, pad.getPositionReadable(), pad.getName());
+			try {
+				title = Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_TITLE, pad.getPositionReadable(), pad.getName());
+			} catch (IllegalStateException e) {
+				Logger.error(e);
+				title = Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_TITLE_EMPTY, pad.getPositionReadable());
+			}
 		} else {
 			title = Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_TITLE_EMPTY, pad.getPositionReadable());
 		}
-		getStageContainer().ifPresent(nvcStage -> nvcStage.getStage().setTitle(title));
-	}
-
-	@Override
-	public void init() {
 
+		final Optional<NVCStage> stageContainer = getStageContainer();
+		if (stageContainer.isPresent()) {
+			stageContainer.get().getStage().setTitle(title);
+		}
 	}
 
 	@Override
@@ -134,7 +99,7 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo
 		stage.getIcons().add(PlayPadPlugin.getInstance().getIcon());
 
 		stage.setMinWidth(650);
-		stage.setMinHeight(550);
+		stage.setMinHeight(600);
 
 		PlayPadPlugin.styleable().applyStyle(stage);
 	}
@@ -162,6 +127,7 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo
 	@FXML
 	private void finishButtonHandler(ActionEvent event) {
 		onFinish();
+		getStageContainer().ifPresent(NVCStage::close);
 	}
 
 	/**
@@ -173,7 +139,6 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo
 		for (PadSettingsTabViewController controller : tabs) {
 			controller.saveSettings(pad);
 		}
-		getStageContainer().ifPresent(NVCStage::close);
 		return true;
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PathLookupListener.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PathLookupListener.java
deleted file mode 100644
index 148f385f1de2c8c9018086a80087c4ef6a8ba314..0000000000000000000000000000000000000000
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PathLookupListener.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package de.tobias.playpad.viewcontroller.option.pad;
-
-import de.thecodelabs.utils.application.system.NativeApplication;
-import de.tobias.playpad.pad.mediapath.MediaPath;
-import javafx.event.ActionEvent;
-import javafx.event.EventHandler;
-import javafx.scene.control.Button;
-import javafx.scene.control.MenuItem;
-
-import java.nio.file.Path;
-
-public class PathLookupListener implements EventHandler<ActionEvent> {
-
-	@Override
-	public void handle(ActionEvent event) {
-		Object source = event.getSource();
-		if (source instanceof Button) {
-			// single path
-			Object userData = ((Button) source).getUserData();
-			if (userData instanceof MediaPath) {
-				showPath((MediaPath) userData);
-			}
-		} else if (source instanceof MenuItem) {
-			// multiple path
-			Object userData = ((MenuItem) source).getUserData();
-			if (userData instanceof Path) {
-				showPath((MediaPath) userData);
-			}
-		}
-	}
-
-	private void showPath(MediaPath path) {
-		NativeApplication.sharedInstance().showFileInFileViewer(path.getPath());
-	}
-}
\ No newline at end of file
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 67d71214c4bd6b72e4eab97da3d926de39f302d5..11d394f681a0bb2f852d0907cffd60e927012d4b 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
@@ -4,10 +4,10 @@ import de.thecodelabs.utils.util.Localization;
 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.settings.FadeSettings;
 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.FadeSettingsViewController;
 import de.tobias.playpad.viewcontroller.settings.WarningFeedbackViewController;
 import javafx.fxml.FXML;
 import javafx.scene.control.CheckBox;
@@ -21,7 +21,7 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController {
 	private CheckBox customFadeCheckBox;
 	@FXML
 	private VBox fadeContainer;
-	private FadeViewController fadeViewController;
+	private FadeSettingsViewController fadeViewController;
 
 	@FXML
 	private VBox warningFeedbackContainer;
@@ -42,7 +42,7 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController {
 	@Override
 	public void init() {
 		// Embed ViewController
-		fadeViewController = new FadeViewController();
+		fadeViewController = new FadeSettingsViewController();
 		fadeContainer.getChildren().add(fadeViewController.getParent());
 
 		warningFeedbackViewController = WarningFeedbackViewController.newViewControllerForPad();
@@ -54,12 +54,12 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController {
 			PadSettings padSettings = pad.getPadSettings();
 
 			if (c && !padSettings.isCustomFade())
-				padSettings.setFade(new Fade());
+				padSettings.setFade(new FadeSettings());
 			else if (!c && padSettings.isCustomFade())
 				padSettings.setFade(null);
 
 			if (c)
-				fadeViewController.setFade(padSettings.getFade());
+				fadeViewController.setFadeSettings(padSettings.getFade());
 		});
 
 		warningEnableCheckBox.selectedProperty().addListener((a, b, c) ->
@@ -104,7 +104,7 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController {
 		PadSettings padSettings = pad.getPadSettings();
 
 		if (padSettings.isCustomFade())
-			fadeViewController.setFade(padSettings.getFade());
+			fadeViewController.setFadeSettings(padSettings.getFade());
 
 		customFadeCheckBox.setSelected(padSettings.isCustomFade());
 		if (!padSettings.isCustomFade()) {
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlaylistTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlaylistTabViewController.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a80e87d3169c61af24b9a8fdaf0f233f6cf2979
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlaylistTabViewController.java
@@ -0,0 +1,165 @@
+package de.tobias.playpad.viewcontroller.option.pad;
+
+import de.thecodelabs.utils.application.system.NativeApplication;
+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.Strings;
+import de.tobias.playpad.layout.desktop.listener.PadNewContentListener;
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.content.PadContentFactory;
+import de.tobias.playpad.pad.content.PadContentRegistry;
+import de.tobias.playpad.pad.content.Playlistable;
+import de.tobias.playpad.pad.mediapath.MediaPath;
+import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
+import javafx.beans.binding.Bindings;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.ListView;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+
+public class PlaylistTabViewController extends PadSettingsTabViewController {
+
+	@FXML
+	private ListView<MediaPath> mediaPathListView;
+
+	@FXML
+	private Button addButton;
+	@FXML
+	private Button upButton;
+	@FXML
+	private Button downButton;
+
+	@FXML
+	private Label pathLabel;
+	@FXML
+	private Button deleteButton;
+	@FXML
+	private Button showFileButton;
+
+	private final Pad pad;
+
+	public PlaylistTabViewController(Pad pad) {
+		this.pad = pad;
+		load("view/option/pad", "PlaylistTab", Localization.getBundle());
+
+		mediaPathListView.setItems(pad.getPaths());
+		initButtons();
+	}
+
+	@Override
+	public void init() {
+		addButton.setGraphic(new FontIcon(FontAwesomeType.PLUS));
+		upButton.setGraphic(new FontIcon(FontAwesomeType.ARROW_UP));
+		downButton.setGraphic(new FontIcon(FontAwesomeType.ARROW_DOWN));
+
+		mediaPathListView.setCellFactory(param -> new ListCell<MediaPath>() {
+			@Override
+			protected void updateItem(MediaPath item, boolean empty) {
+				super.updateItem(item, empty);
+				if (!empty) {
+					setText(item.getFileName());
+					final Playlistable playlist = (Playlistable) pad.getContent();
+					if (!playlist.isLoaded(item)) {
+						setGraphic(new FontIcon(FontAwesomeType.WARNING));
+					} else {
+						setGraphic(null);
+					}
+				} else {
+					setText("");
+					setGraphic(null);
+				}
+			}
+		});
+
+		pathLabel.setText(Localization.getString("padSettings.gen.label.media.empty"));
+		mediaPathListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
+			if (newValue != null) {
+				pathLabel.setText(newValue.getPath().toString());
+			} else {
+				pathLabel.setText(Localization.getString("padSettings.gen.label.media.empty"));
+			}
+		});
+	}
+
+	private void initButtons() {
+		upButton.disableProperty()
+				.bind(mediaPathListView.getSelectionModel().selectedItemProperty().isNull()
+						.or(mediaPathListView.getSelectionModel().selectedIndexProperty().isEqualTo(0)));
+		downButton.disableProperty()
+				.bind(mediaPathListView.getSelectionModel().selectedItemProperty().isNull()
+						.or(mediaPathListView.getSelectionModel().selectedIndexProperty().isEqualTo(Bindings.size(mediaPathListView.getItems()).subtract(1))));
+
+		deleteButton.disableProperty().bind(mediaPathListView.getSelectionModel().selectedItemProperty().isNull());
+		showFileButton.disableProperty().bind(mediaPathListView.getSelectionModel().selectedItemProperty().isNull());
+	}
+
+	@Override
+	public String getName() {
+		return Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_PLAYLIST_TITLE);
+	}
+
+	@Override
+	public void loadSettings(Pad pad) {
+		// Not implemented
+	}
+
+	@Override
+	public void saveSettings(Pad pad) {
+		// Not implemented
+	}
+
+	@FXML
+	public void onAddHandler(ActionEvent event) {
+		final PadContentRegistry padContentRegistry = PlayPadPlugin.getRegistries().getPadContents();
+		final PadContentFactory contentFactory = padContentRegistry.getFactory(pad.getContent().getType());
+
+		final PadNewContentListener padNewContentListener = new PadNewContentListener(pad);
+		final List<File> files = padNewContentListener.showMediaOpenFileChooser(event, contentFactory.getSupportedTypes(), true);
+
+		if (files != null) {
+			for (File file : files) {
+				pad.addPath(file.toPath());
+			}
+		}
+	}
+
+	@FXML
+	public void onUpHandler(ActionEvent event) {
+		final int selectedIndex = mediaPathListView.getSelectionModel().getSelectedIndex();
+		Collections.swap(pad.getPaths(), selectedIndex, selectedIndex - 1);
+		mediaPathListView.getSelectionModel().select(selectedIndex - 1);
+		pad.getContent().reorderMedia();
+	}
+
+	@FXML
+	public void onDownAction(ActionEvent event) {
+		final int selectedIndex = mediaPathListView.getSelectionModel().getSelectedIndex();
+		Collections.swap(pad.getPaths(), selectedIndex, selectedIndex + 1);
+		mediaPathListView.getSelectionModel().select(selectedIndex + 1);
+		pad.getContent().reorderMedia();
+	}
+
+	@FXML
+	public void onShowFileHandler(ActionEvent event) {
+		MediaPath mediaPath = mediaPathListView.getSelectionModel().getSelectedItem();
+		NativeApplication.sharedInstance().showFileInFileViewer(mediaPath.getPath());
+	}
+
+	@FXML
+	public void onDeleteHandler(ActionEvent event) {
+		MediaPath mediaPath = mediaPathListView.getSelectionModel().getSelectedItem();
+		pad.removePath(mediaPath);
+
+		if (pad.getPaths().isEmpty()) {
+			pad.clear();
+		}
+	}
+}
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 33fd3432634f564d5718ba8fc85d4fc4725a42b7..d9e1d8fc62dee9745734c99a475b77898a0bf5ea 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
@@ -8,6 +8,7 @@ import de.tobias.playpad.tigger.TriggerPoint;
 import de.tobias.playpad.trigger.TriggerDisplayable;
 import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
 import de.tobias.playpad.viewcontroller.cell.DisplayableTreeCell;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import de.tobias.playpad.viewcontroller.option.pad.trigger.TriggerPointViewController;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
@@ -26,9 +27,11 @@ public class TriggerPadTabViewController extends PadSettingsTabViewController im
 	@FXML
 	private VBox contentView;
 
-	private Pad pad;
+	private final Pad pad;
+	private final IMainViewController mainViewController;
 
-	TriggerPadTabViewController(Pad pad) {
+	TriggerPadTabViewController(Pad pad, IMainViewController mainViewController) {
+		this.mainViewController = mainViewController;
 		load("view/option/pad", "TriggerTab", Localization.getBundle());
 		this.pad = pad;
 	}
@@ -61,7 +64,7 @@ public class TriggerPadTabViewController extends PadSettingsTabViewController im
 
 		if (newValue != null) {
 			TriggerDisplayable triggerWrapper = newValue.getValue();
-			TriggerPointViewController controller = new TriggerPointViewController(triggerWrapper);
+			TriggerPointViewController controller = new TriggerPointViewController(mainViewController, triggerWrapper);
 			contentView.getChildren().setAll(controller.getParent());
 			VBox.setVgrow(controller.getParent(), Priority.ALWAYS);
 		}
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 a5d2f0ea9780c898b90e1ebd98efff2c60d19653..1168ae13aedb828a12ba14ff18c14bad68718a1d 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
@@ -8,6 +8,7 @@ import de.tobias.playpad.pad.PadStatus;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.trigger.CartTriggerItem;
 import de.tobias.playpad.view.main.ProjectPreviewView;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import javafx.beans.InvalidationListener;
 import javafx.fxml.FXML;
 import javafx.geometry.Insets;
@@ -25,17 +26,17 @@ public class CartTriggerViewController extends NVC {
 	@FXML
 	private CheckBox allCartsCheckbox;
 
-	private ProjectPreviewView projectPreviewView;
+	private final ProjectPreviewView projectPreviewView;
 
-	private CartTriggerItem item;
+	private final CartTriggerItem item;
 
-	public CartTriggerViewController(CartTriggerItem item) {
+	public CartTriggerViewController(CartTriggerItem item, IMainViewController mainViewController) {
 		load("view/option/pad/trigger", "CartTrigger", Localization.getBundle());
 		this.item = item;
 
 		Project project = PlayPadMain.getProgramInstance().getCurrentProject();
 		final List<Pad> pads = item.getCarts().stream().map(project::getPad).collect(Collectors.toList());
-		projectPreviewView = new ProjectPreviewView(project, pads);
+		projectPreviewView = new ProjectPreviewView(project, pads, mainViewController.getPage());
 		projectPreviewView.setPadding(new Insets(0, 0, 0, 164));
 		projectPreviewView.selectedProperty().addListener((InvalidationListener) observable -> {
 			item.getCarts().clear();
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 77d5166b7191a5da2d5f2565bd1221da47e830b4..85793e58329cc0793f8919085cf1059bd01cb500 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
@@ -10,6 +10,7 @@ import de.tobias.playpad.registry.NoSuchComponentException;
 import de.tobias.playpad.tigger.TriggerItem;
 import de.tobias.playpad.tigger.TriggerItemFactory;
 import de.tobias.playpad.trigger.TriggerDisplayable;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import javafx.fxml.FXML;
 import javafx.scene.control.Button;
 import javafx.scene.control.ContentDisplay;
@@ -26,14 +27,17 @@ public class TriggerPointViewController extends NVC {
 	@FXML
 	private HBox buttonBox;
 
-	private TriggerDisplayable triggerWrapper;
+	private final IMainViewController mainViewController;
+	private final TriggerDisplayable triggerWrapper;
 
-	public TriggerPointViewController(TriggerDisplayable triggerWrapper) {
+	public TriggerPointViewController(IMainViewController mainViewController, TriggerDisplayable triggerWrapper) {
+		this.mainViewController = mainViewController;
 		load("view/option/pad/trigger", "TriggerPoint", Localization.getBundle());
 		this.triggerWrapper = triggerWrapper;
 
-		for (TriggerItem item : triggerWrapper.getTrigger().getItems())
-			showTriggerItem(item);
+		for (TriggerItem item : triggerWrapper.getTrigger().getItems()) {
+			showTriggerItem(item, mainViewController);
+		}
 	}
 
 	@Override
@@ -42,17 +46,17 @@ public class TriggerPointViewController extends NVC {
 		types.stream().sorted().forEach(item ->
 		{
 			try {
-				TriggerItemFactory conntect = PlayPadPlugin.getRegistries().getTriggerItems().getFactory(item);
-				Button button = new Button(conntect.toString(), new FontIcon(FontAwesomeType.PLUS_CIRCLE));
+				TriggerItemFactory factory = PlayPadPlugin.getRegistries().getTriggerItems().getFactory(item);
+				Button button = new Button(factory.toString(), new FontIcon(FontAwesomeType.PLUS_CIRCLE));
 				button.setContentDisplay(ContentDisplay.TOP);
 				button.setPrefWidth(150);
 
 				button.setOnAction(e ->
 				{
-					TriggerItem triggerItem = conntect.newInstance(triggerWrapper.getTrigger());
+					TriggerItem triggerItem = factory.newInstance(triggerWrapper.getTrigger());
 
 					triggerWrapper.addItem(triggerItem);
-					showTriggerItem(triggerItem);
+					showTriggerItem(triggerItem, mainViewController);
 				});
 				buttonBox.getChildren().add(button);
 			} catch (NoSuchComponentException e) {
@@ -61,17 +65,19 @@ public class TriggerPointViewController extends NVC {
 		});
 	}
 
-	private void showTriggerItem(TriggerItem item) {
+	private void showTriggerItem(TriggerItem item, IMainViewController mainViewController) {
 		try {
 			TriggerItemFactory connect = PlayPadPlugin.getRegistries().getTriggerItems().getFactory(item.getType());
 
 			VBox itemBox = new VBox(14);
-			NVC controller = connect.getSettingsController(item);
+			NVC controller = connect.getSettingsController(item, mainViewController);
 			if (controller != null) {
 				itemBox.getChildren().add(controller.getParent());
 
-				NVC timeViewController = new TriggerTimeViewController(item);
-				itemBox.getChildren().add(timeViewController.getParent());
+				if (triggerWrapper.getTrigger().getTriggerPoint().isTimeAppendable()) {
+					final NVC timeViewController = new TriggerTimeViewController(item);
+					itemBox.getChildren().add(timeViewController.getParent());
+				}
 
 				Button deleteButton = new Button("", new FontIcon(FontAwesomeType.TRASH));
 				HBox hbox = new HBox(itemBox, deleteButton);
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 10a1a70dfb79ad38c6eedcacaa450384a65cdef9..f48a57341e8a354af30dafc4ead00f256d7955f4 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
@@ -8,6 +8,7 @@ import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.trigger.VolumeTriggerItem;
 import de.tobias.playpad.view.main.ProjectPreviewView;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import javafx.beans.InvalidationListener;
 import javafx.fxml.FXML;
 import javafx.geometry.Insets;
@@ -30,20 +31,20 @@ public class VolumeTriggerViewController extends NVC {
 	private Slider durationSlider;
 	@FXML
 	private Label durationLabel;
-	private ProjectPreviewView projectPreviewView;
+	private final ProjectPreviewView projectPreviewView;
 
-	private VolumeTriggerItem item;
+	private final VolumeTriggerItem item;
 
-	public VolumeTriggerViewController(VolumeTriggerItem item) {
+	public VolumeTriggerViewController(VolumeTriggerItem item, IMainViewController mainViewController) {
 		load("view/option/pad/trigger", "VolumeTrigger", Localization.getBundle());
 		this.item = item;
 
 		volumeSlider.setValue(item.getVolume() * 100.0);
 		durationSlider.setValue(item.getDuration().toSeconds());
 
-		Project project = PlayPadMain.getProgramInstance().getCurrentProject();
+		final Project project = PlayPadMain.getProgramInstance().getCurrentProject();
 		final List<Pad> pads = item.getCarts().stream().map(project::getPad).collect(Collectors.toList());
-		projectPreviewView = new ProjectPreviewView(project, pads);
+		projectPreviewView = new ProjectPreviewView(project, pads, mainViewController.getPage());
 		projectPreviewView.setPadding(new Insets(0, 0, 0, 164));
 		projectPreviewView.selectedProperty().addListener((InvalidationListener) observable -> {
 			item.getCarts().clear();
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 384bb2ed2a3fc5a673a82827410e905ca302a45d..7d6e0cb80ec93b40dd5ed01b725a4fe2e49a395b 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
@@ -7,7 +7,7 @@ import de.tobias.playpad.profile.Profile;
 import de.tobias.playpad.profile.ProfileSettings;
 import de.tobias.playpad.viewcontroller.cell.EnumCell;
 import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController;
-import de.tobias.playpad.viewcontroller.settings.FadeViewController;
+import de.tobias.playpad.viewcontroller.settings.FadeSettingsViewController;
 import de.tobias.playpad.viewcontroller.settings.WarningFeedbackViewController;
 import javafx.fxml.FXML;
 import javafx.scene.control.CheckBox;
@@ -32,8 +32,8 @@ public class PlayerTabViewController extends ProfileSettingsTabViewController {
 		load("view/option/profile", "PlayerTab", Localization.getBundle());
 
 		// Player
-		FadeViewController fadeViewController = new FadeViewController();
-		fadeViewController.setFade(Profile.currentProfile().getProfileSettings().getFade());
+		FadeSettingsViewController fadeViewController = new FadeSettingsViewController();
+		fadeViewController.setFadeSettings(Profile.currentProfile().getProfileSettings().getFade());
 		fadeContainer.getChildren().add(fadeViewController.getParent());
 		setAnchor(fadeViewController.getParent(), 0, 0, 0, 0);
 	}
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 1c4b3641862810f6d72a8366aad2936365556fc1..4f0ab95348e67855818b1aaf81a63b5a9010a4e7 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
@@ -40,15 +40,15 @@ public class ProfileSettingsViewController extends NVC implements IProfileSettin
 	@FXML
 	private Button finishButton;
 
-	private List<ProfileSettingsTabViewController> tabs = new ArrayList<>();
+	private final List<ProfileSettingsTabViewController> tabs = new ArrayList<>();
 
-	private Runnable onFinish;
+	private final Runnable onFinish;
 
 	public ProfileSettingsViewController(Window owner, Project project, Runnable onFinish) {
 		load("view/option/profile", "SettingsView", Localization.getBundle());
 		this.onFinish = onFinish;
 
-		boolean activePlayer = project.hasActivePlayers();
+		boolean hasActivePlayers = project.hasActivePlayers();
 
 		addTab(new MappingTabViewController());
 		addTab(new DesignTabViewController());
@@ -58,12 +58,19 @@ public class ProfileSettingsViewController extends NVC implements IProfileSettin
 		PadContentRegistry padContents = PlayPadPlugin.getRegistries().getPadContents();
 		for (String type : padContents.getTypes()) {
 			PadContentFactory component = padContents.getFactory(type);
-			ProfileSettingsTabViewController controller = component.getSettingsTabViewController(activePlayer);
+			ProfileSettingsTabViewController controller = component.getSettingsTabViewController(hasActivePlayers);
 			if (controller != null) {
 				addTab(controller);
 			}
 		}
 
+		PlayPadPlugin.getInstance().getAdditionalProfileSettingsTabs().forEach(supplier -> {
+			ProfileSettingsTabViewController controller = supplier.get();
+			if (controller != null) {
+				addTab(controller);
+			}
+		});
+
 		NVCStage nvcStage = applyViewControllerToStage();
 		nvcStage.initOwner(owner);
 		nvcStage.addCloseHook(this::onFinish);
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 dac32ea109085e1fbd079363f87a73ea1a70f18d..33ed71c972ff750b188f775ae9347caea26d2563 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
@@ -6,6 +6,8 @@ import de.tobias.playpad.Strings;
 import de.tobias.playpad.design.ModernDesignSizeHelper;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.ProjectSettings;
+import de.tobias.playpad.project.ProjectSettingsValidator;
+import de.tobias.playpad.project.ProjectSettingsValidator.ValidationState;
 import de.tobias.playpad.view.PseudoClasses;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import de.tobias.playpad.viewcontroller.option.IProjectReloadTask;
@@ -16,25 +18,16 @@ import javafx.scene.control.Label;
 import javafx.scene.control.TextField;
 import javafx.stage.Screen;
 
-public class GeneralTabViewController extends ProjectSettingsTabViewController implements IProjectReloadTask {
-
-	public static final int DISPLAY_OFFSET = 100;
+import static de.tobias.playpad.project.ProjectSettingsValidator.Dimension;
 
-	private enum ValidationState {
-		NORMAL,
-		TOO_MUCH,
-		TOO_LESS
-	}
-
-	private enum Dimension {
-		COLUMNS,
-		ROWS
-	}
+public class GeneralTabViewController extends ProjectSettingsTabViewController implements IProjectReloadTask {
 
 	private static final String DIGIT_POSITIVE = "^[1-9]\\d*$";
 
-	private Screen mainWindowScreen;
-	private Alertable parentController; // Für Benachrichtungen
+	private final Screen mainWindowScreen;
+	private final Alertable parentController; // Für Benachrichtungen
+
+	private final ProjectSettingsValidator projectSettingsValidator;
 
 	@FXML
 	private TextField columnTextField;
@@ -52,6 +45,8 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 		this.mainWindowScreen = currentScreen;
 		this.parentController = parentController;
 
+		this.projectSettingsValidator = new ProjectSettingsValidator(this.mainWindowScreen);
+
 		if (activePlayer) {
 			rowTextField.setDisable(true);
 			columnTextField.setDisable(true);
@@ -63,7 +58,7 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 		columnTextField.textProperty().addListener((a, b, c) ->
 		{
 			if (c.matches(DIGIT_POSITIVE) && !c.isEmpty()) {
-				ValidationState validationState = validate(Integer.parseInt(c), Dimension.COLUMNS);
+				ValidationState validationState = projectSettingsValidator.validate(Integer.parseInt(c), Dimension.COLUMNS);
 				if (validationState == ValidationState.NORMAL) {
 					columnTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, false);
 					columnErrorLabel.setText("");
@@ -73,22 +68,22 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 					String errorText = "";
 					// Error Message
 					if (validationState == ValidationState.TOO_MUCH) {
-						errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_MUCH, maxValue(Dimension.COLUMNS));
+						errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_MUCH, projectSettingsValidator.maxValue(Dimension.COLUMNS));
 					} else if (validationState == ValidationState.TOO_LESS) {
-						errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, minValue(Dimension.COLUMNS));
+						errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, projectSettingsValidator.minValue(Dimension.COLUMNS));
 					}
 					columnErrorLabel.setText(errorText);
 				}
 			} else {
 				columnTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, true);
-				columnErrorLabel.setText(Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, minValue(Dimension.COLUMNS)));
+				columnErrorLabel.setText(Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, projectSettingsValidator.minValue(Dimension.COLUMNS)));
 			}
 		});
 
 		rowTextField.textProperty().addListener((a, b, c) ->
 		{
 			if (c.matches(DIGIT_POSITIVE) && !c.isEmpty()) {
-				ValidationState validationState = validate(Integer.parseInt(c), Dimension.ROWS);
+				ValidationState validationState = projectSettingsValidator.validate(Integer.parseInt(c), Dimension.ROWS);
 				if (validationState == ValidationState.NORMAL) {
 					rowTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, false);
 					rowErrorLabel.setText("");
@@ -98,49 +93,19 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 					String errorText = "";
 					// Error Message
 					if (validationState == ValidationState.TOO_MUCH) {
-						errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_MUCH, maxValue(Dimension.ROWS));
+						errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_MUCH, projectSettingsValidator.maxValue(Dimension.ROWS));
 					} else if (validationState == ValidationState.TOO_LESS) {
-						errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, minValue(Dimension.ROWS));
+						errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, projectSettingsValidator.minValue(Dimension.ROWS));
 					}
 					rowErrorLabel.setText(errorText);
 				}
 			} else {
 				rowTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, true);
-				rowErrorLabel.setText(Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, minValue(Dimension.ROWS)));
+				rowErrorLabel.setText(Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, projectSettingsValidator.minValue(Dimension.ROWS)));
 			}
 		});
 	}
 
-	private ValidationState validate(int input, Dimension dimension) {
-		if (input < minValue(dimension)) {
-			return ValidationState.TOO_LESS;
-		} else if (input > maxValue(dimension)) {
-			return ValidationState.TOO_MUCH;
-		}
-		return ValidationState.NORMAL;
-	}
-
-	private int minValue(Dimension dimension) {
-		if (dimension == Dimension.COLUMNS) {
-			return ProjectSettings.MIN_COLUMNS;
-		} else if (dimension == Dimension.ROWS) {
-			return ProjectSettings.MIN_ROWS;
-		}
-		return -1;
-	}
-
-	private int maxValue(Dimension dimension) {
-		double width = mainWindowScreen.getVisualBounds().getMaxX() - mainWindowScreen.getVisualBounds().getMinX();
-		double height = mainWindowScreen.getVisualBounds().getMaxY() - mainWindowScreen.getVisualBounds().getMinY();
-
-		if (dimension == Dimension.COLUMNS) {
-			return Math.min((int) (width / ModernDesignSizeHelper.getPadWidth()), ProjectSettings.MAX_COLUMNS);
-		} else if (dimension == Dimension.ROWS) {
-			return Math.min((int) ((height - DISPLAY_OFFSET) / ModernDesignSizeHelper.getPadHeight()), ProjectSettings.MAX_ROWS);
-		}
-		return -1;
-	}
-
 	private boolean screenValid() {
 		double width = mainWindowScreen.getVisualBounds().getMaxX() - mainWindowScreen.getVisualBounds().getMinX();
 		double height = mainWindowScreen.getVisualBounds().getMaxY() - mainWindowScreen.getVisualBounds().getMinY();
@@ -200,8 +165,8 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i
 	@Override
 	public boolean validSettings() {
 		try {
-			return validate(Integer.parseInt(columnTextField.getText()), Dimension.COLUMNS) == ValidationState.NORMAL &&
-					validate(Integer.parseInt(rowTextField.getText()), Dimension.ROWS) == ValidationState.NORMAL;
+			return projectSettingsValidator.validate(Integer.parseInt(columnTextField.getText()), Dimension.COLUMNS) == ValidationState.NORMAL &&
+					projectSettingsValidator.validate(Integer.parseInt(rowTextField.getText()), Dimension.ROWS) == ValidationState.NORMAL;
 		} catch (NumberFormatException e) {
 			return false;
 		}
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 9b2c6957ec97cdbfc6d4050cc662d4330fdbd062..9cab45389cb4dbdc4fa911f4d16fe0c74d5b04c9 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
@@ -35,10 +35,10 @@ public class ProjectSettingsViewController extends NVC implements IProjectSettin
 	@FXML
 	private Button finishButton;
 
-	private List<ProjectSettingsTabViewController> tabs = new ArrayList<>();
-	private Project project;
+	private final List<ProjectSettingsTabViewController> tabs = new ArrayList<>();
+	private final Project project;
 
-	private Runnable onFinish;
+	private final Runnable onFinish;
 
 	public ProjectSettingsViewController(Screen currentScreen, Window owner, Project project, Runnable onFinish) {
 		load("view/option/project", "ProjectSettingsView", Localization.getBundle());
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeSettingsViewController.java
similarity index 70%
rename from PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java
rename to PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeSettingsViewController.java
index 14515382904128e4e49c021e0431c02f4a4981fe..ab32efe2dfe4d81fce1b78dd8a21f3475e14a94d 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeSettingsViewController.java
@@ -3,14 +3,14 @@ package de.tobias.playpad.viewcontroller.settings;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.settings.Fade;
+import de.tobias.playpad.settings.FadeSettings;
 import javafx.fxml.FXML;
 import javafx.scene.control.CheckBox;
 import javafx.scene.control.Label;
 import javafx.scene.control.Slider;
 import javafx.util.Duration;
 
-public class FadeViewController extends NVC {
+public class FadeSettingsViewController extends NVC {
 
 	@FXML
 	private Slider fadeInSlider;
@@ -29,10 +29,12 @@ public class FadeViewController extends NVC {
 	private CheckBox fadeOutPauseCheckBox;
 	@FXML
 	private CheckBox fadeOutStopCheckBox;
+	@FXML
+	private CheckBox fadeOutEofCheckBox;
 
-	private Fade fade;
+	private FadeSettings fade;
 
-	public FadeViewController() {
+	public FadeSettingsViewController() {
 		load("view/settings", "FadeView", Localization.getBundle());
 	}
 
@@ -54,13 +56,14 @@ public class FadeViewController extends NVC {
 			fade.setFadeOut(seconds);
 		});
 
-		fadeInStartCheckBox.selectedProperty().addListener((a, b, c) -> fade.setFadeInStart(c));
-		fadeInPauseCheckBox.selectedProperty().addListener((a, b, c) -> fade.setFadeInPause(c));
-		fadeOutPauseCheckBox.selectedProperty().addListener((a, b, c) -> fade.setFadeOutPause(c));
-		fadeOutStopCheckBox.selectedProperty().addListener((a, b, c) -> fade.setFadeOutStop(c));
+		fadeInStartCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeInStart(newValue));
+		fadeInPauseCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeInPause(newValue));
+		fadeOutPauseCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeOutPause(newValue));
+		fadeOutStopCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeOutStop(newValue));
+		fadeOutEofCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeOutEof(newValue));
 	}
 
-	public void setFade(Fade fade) {
+	public void setFadeSettings(FadeSettings fade) {
 		this.fade = fade;
 
 		if (fade != null) {
@@ -76,6 +79,7 @@ public class FadeViewController extends NVC {
 			fadeInPauseCheckBox.setSelected(fade.isFadeInPause());
 			fadeOutPauseCheckBox.setSelected(fade.isFadeOutPause());
 			fadeOutStopCheckBox.setSelected(fade.isFadeOutStop());
+			fadeOutEofCheckBox.setSelected(fade.isFadeOutEof());
 		}
 	}
 }
diff --git a/PlayWall/src/main/resources/lang/_de.properties b/PlayWall/src/main/resources/lang/_de.properties
index cfbdf22ed322a5aa4e6fe39868cd2e6956349c89..33029a528b99644493e53bcd9b83e304ae7fd03d 100755
--- a/PlayWall/src/main/resources/lang/_de.properties
+++ b/PlayWall/src/main/resources/lang/_de.properties
@@ -144,8 +144,8 @@ Error.Plugins.Missing=Es wurden im Projekt Erweiterungen verwendet, welche momen
 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 {}
+Error.Screen.TooMuch=Maximale Anzahl der Kacheln {}
+Error.Screen.TooLess=Minimale Anzahl der Kacheln {}
 #Mapper
 Mapper.Keyboard.Name=Tastatur
 Mapper.Midi.Name=Midi
@@ -158,6 +158,7 @@ Info.Mapper.PressKey=Dr\u00FCcken Sie eine Taste auf dem Ger\u00E4t.
 UI.Settings.Alert.NewKeyShortcut.Text=Dr\u00FCcken Sie bitte die gew\u00FCnschte Tastenkombination. \nDieses kann aus Buchstaben, Ziffern und/oder den F-Tasten bestehen.
 # UI - Window - PadSettings
 UI.Window.PadSettings.General.Title=Allgemein
+UI.Window.PadSettings.Playlist.Title=Playlist
 UI.Window.PadSettings.Player.Title=Player
 UI.Window.PadSettings.Layout.Title=Layout
 UI.Window.PadSettings.Trigger.Title=Trigger
@@ -208,13 +209,18 @@ UI.Window.Settings.Updates.CurrentVersion={} (Build {})
 TriggerPoint.toString={} ({})
 Trigger.Cart.Name=Kacheln
 Trigger.Volume.Name=Lautst\u00E4rke
+
 # TriggerPoint - Enum
 TriggerPoint.START=Start
-TriggerPoint.EOF_STOP=Ende/Stop
+TriggerPoint.STOP=Stop
+TriggerPoint.EOF=Ende
+TriggerPoint.EOF_STATE=Ende (EoF)
+
 # Drag and Drop Mode
 DnDMode.Replace=Ersetzen
 DnDMode.Duplicate=Duplizieren
 DnDMode.Move=Tauschen
+DndMode.Playlist=Hinzuf\u00FCgen
 # Main Layout
 MainLayout.Desktop=Desktopmodus
 MainLayout.Touch=Touchmodus
diff --git a/PlayWall/src/main/resources/lang/ui_de.properties b/PlayWall/src/main/resources/lang/ui_de.properties
index 1876ec12242853a055acb1e74acccedae6ee242f..f3e03f795141542e4f17f58a3af51a51dfca4be3 100755
--- a/PlayWall/src/main/resources/lang/ui_de.properties
+++ b/PlayWall/src/main/resources/lang/ui_de.properties
@@ -29,6 +29,8 @@ main.menuitem.changelog=Changelog anzeigen...
 main.menuitem.website=Webseite anzeigen...
 main.menuitem.fullScreen=Vollbild
 main.menuitem.searchPad=Kachel suchen...
+main.menuitem.addColumn=Spalte rechts hinzuf\u00FCgen
+main.menuitem.addRow=Reihe unten hinzuf\u00FCgen
 main.label.live=Live
 settings.gen.label.behaviour=Programmstart:
 settings.gen.checkbox.openLastDocument=Automatisch zuletzt geladenes Projekt \u00F6ffnen.
@@ -62,14 +64,16 @@ settings.player.label.modus=Wiedergabemodus:
 settings.player.checkbox.modus=Mehrere Player gleichzeitig wiedergeben
 settings.player.label.warning=Warnhinweise:
 settings.player.label.fade=Ein-/Ausblenden:
-settings.player.label.fadeIn=Einblenden (in s):
-settings.player.label.fadeOut=Ausblenden (in s):
+settings.player.label.fadeIn=Einblenden:
+settings.player.label.fadeOut=Ausblenden:
 settings.player.label.startIn=... nach Start
 settings.player.label.pauseIn=... bei Pause
 settings.player.label.pauseOut=... bei Pause
-settings.player.label.stopOut=... bei Stop/EoF
-settings.player.label.fadeInfo=Wird beim Ein- oder Ausblenden die Dauer auf 0 gesetzt, so findet keine \u00DCberblendung statt. Wenn die Datei zu Ende ist, findet kein Ausblenden statt.
+settings.player.label.stopOut=... bei Stop
+settings.player.label.eofOut=... bei End of File
+settings.player.label.fadeInfo=Wird beim Ein- oder Ausblenden die Dauer auf 0 gesetzt, so findet keine \u00DCberblendung statt.
 settings.player.label.timeDisplay=Zeitanzeige:
+settings.warning.label.time=Warnhinweis ab Restdauer:
 settings.update.label.current=Installierte Version:
 settings.update.label.search=Nach Updates suchen:
 settings.update.label.available=Verf\u00FCgbare Updates:
@@ -114,12 +118,15 @@ midi.button.new=\u00C4ndern
 keyboard.label.key=Taste (Tastatur):
 keyboard.button.new=\u00C4ndern
 padSettings.button.delete=L\u00F6schen
-padSettings.button.path=Pfad zeigen
+padSettings.button.path.show=Im Ordner anzeigen
+padSettings.button.path.choose=Pfad w\u00E4hlen
+padSettings.gen.label.media=Medien:
+padSettings.gen.label.media.empty=<Keine Auswahl>
 padSettings.gen.label.title=Titel:
 padSettings.gen.label.volume=Lautst\u00E4rke:
 padSettings.gen.label.timeDisplay=Zeitanzeige:
 padSettings.gen.checkbox.customSettings=Eigene Einstellungen
-padSettings.checkbox.loop=Wiederholen
+padSettings.label.loop=Wiederholen:
 padSettings.button.finish=Fertig
 padSettings.player.label.warning=Warnhinweise:
 padSettings.player.label.cueIn=Intro Dauer (in s):
@@ -153,7 +160,7 @@ project.import.label.media=Medien:
 project.import.label.name=Name:
 project.import.label.path=Mediendateien:
 project.import.label.sync=
-project.import.checkbox.sync=Cloud-Sychronisation aktivieren
+project.import.checkbox.sync=Cloud-Synchronisation aktivieren
 project.import.checkbox.profile=Profil importieren
 project.import.checkbox.media=Medien importieren
 project.import.button.choose=Ordner ausw\u00E4hlen...
@@ -178,7 +185,6 @@ profile.button.new=Neu
 profile.button.delete=L\u00F6schen
 profile.button.duplicate=Duplizieren
 profile.button.choose=Profil w\u00E4hlen
-warning.label.time=Warnhinweis ab Restdauer: (Sek)
 print.label.page=Seite:
 print.button.cancel=Abbrechen
 print.button.print=Drucken
@@ -227,4 +233,14 @@ 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
+PathMatchDialog.Button.Finish=\u00DCbernehmen
+
+about.label.headline=\u00DCber PlayWall
+about.label.version=Version:
+about.label.author=Autor:
+about.label.graphics=Grafiken:
+about.label.platform=Plattform:
+about.label.website=Webseite:
+about.label.code=Code:
+about.label.libraries=Bibliotheken:
+about.label.thanksgiving=Besonderen Dank an die treuen Betatester Stefan und Robert.
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/view/dialog/About.fxml b/PlayWall/src/main/resources/view/dialog/About.fxml
index 45bfe74d2f4dea2fc9760bf608fad319b3e20dc5..952fc777da80ccb8203515f5a4fa3c99fb2cc648 100644
--- a/PlayWall/src/main/resources/view/dialog/About.fxml
+++ b/PlayWall/src/main/resources/view/dialog/About.fxml
@@ -19,49 +19,56 @@
                 </ImageView>
                 <VBox alignment="CENTER_LEFT" spacing="7.0">
                     <children>
-                        <Label styleClass="about-headline" text="Über PlayWall">
+                        <Label styleClass="about-headline" text="%about.label.headline">
                             <VBox.margin>
                                 <Insets bottom="14.0"/>
                             </VBox.margin>
                         </Label>
                         <HBox spacing="14.0">
                             <children>
-                                <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="Version:" textAlignment="RIGHT"/>
+                                <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="%about.label.version" textAlignment="RIGHT"/>
                                 <Label fx:id="versionLabel" text="1.0.0"/>
                             </children>
                         </HBox>
                         <HBox spacing="14.0">
                             <children>
-                                <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="Autor:" textAlignment="RIGHT"/>
+                                <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="%about.label.author" textAlignment="RIGHT"/>
                                 <Label fx:id="authorLabel" text="Tobias Ullerich"/>
                             </children>
                         </HBox>
                         <HBox spacing="14.0">
                             <children>
-                                <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="Grafiken:"
+                                <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="%about.label.graphics"
                                        textAlignment="RIGHT"/>
                                 <Label fx:id="graphicsLabel" text="Robert Goldmann"/>
                             </children>
                         </HBox>
+                        <HBox spacing="14.0">
+                            <children>
+                                <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="%about.label.platform" textAlignment="RIGHT"/>
+                                <Label fx:id="platformLabel" text="controlsfx" wrapText="true"/>
+                            </children>
+                        </HBox>
+
                         <HBox fx:id="websiteContainer" spacing="14.0">
                             <children>
-                                <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="Webseite" textAlignment="RIGHT"/>
+                                <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="%about.label.website" textAlignment="RIGHT"/>
                             </children>
                         </HBox>
                         <HBox fx:id="codeContainer" spacing="14.0">
                             <children>
-                                <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="Code:" textAlignment="RIGHT"/>
+                                <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="%about.label.code" textAlignment="RIGHT"/>
                             </children>
                         </HBox>
                         <HBox spacing="14.0">
                             <children>
-                                <Label alignment="CENTER_RIGHT" minWidth="75.0" prefWidth="75.0" text="Libraries:"
+                                <Label alignment="CENTER_RIGHT" minWidth="75.0" prefWidth="75.0" text="%about.label.libraries"
                                        textAlignment="RIGHT"/>
                                 <Label fx:id="libsLabel" text="controlsfx" wrapText="true"/>
                             </children>
                         </HBox>
                         <Label maxWidth="1.7976931348623157E308"
-                               text="Besonderen Dank an die treuen Betatester Stefan und Robert." wrapText="true">
+                               text="%about.label.thanksgiving" wrapText="true">
                             <VBox.margin>
                                 <Insets left="89.0"/>
                             </VBox.margin>
diff --git a/PlayWall/src/main/resources/view/main/desktop/Header.fxml b/PlayWall/src/main/resources/view/main/desktop/Header.fxml
index e18a7a14f0c5dc5fcc12236a2b8e9bd522902747..8383f694f9a847157ff36e78fd1a0264919ff3f3 100644
--- a/PlayWall/src/main/resources/view/main/desktop/Header.fxml
+++ b/PlayWall/src/main/resources/view/main/desktop/Header.fxml
@@ -126,6 +126,10 @@
                             </accelerator>
                         </CheckMenuItem>
                         <SeparatorMenuItem mnemonicParsing="false"/>
+                        <MenuItem mnemonicParsing="false" onAction="#addColumnToProject"
+                                  text="%main.menuitem.addColumn"/>
+                        <MenuItem mnemonicParsing="false" onAction="#addRowToProject" text="%main.menuitem.addRow"/>
+                        <SeparatorMenuItem mnemonicParsing="false"/>
                         <MenuItem fx:id="searchPadMenuItem" mnemonicParsing="false" onAction="#searchPadHandler"
                                   text="%main.menuitem.searchPad"/>
                         <SeparatorMenuItem mnemonicParsing="false"/>
diff --git a/PlayWall/src/main/resources/view/option/pad/GeneralTab.fxml b/PlayWall/src/main/resources/view/option/pad/GeneralTab.fxml
index bbbfc204f67a81ad39794136484871888554f9a3..918175e2602fd5ef7166f7392ed40efcbc8838ca 100644
--- a/PlayWall/src/main/resources/view/option/pad/GeneralTab.fxml
+++ b/PlayWall/src/main/resources/view/option/pad/GeneralTab.fxml
@@ -5,44 +5,70 @@
 <?import javafx.scene.layout.*?>
 <VBox spacing="14.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
     <children>
-        <VBox layoutX="14.0" layoutY="14.0" spacing="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0"
-              AnchorPane.topAnchor="14.0">
+        <VBox fx:id="mediaRootBox" spacing="14.0">
             <children>
-                <HBox alignment="CENTER_LEFT" layoutX="14.0" layoutY="14.0" spacing="14.0">
+                <HBox alignment="CENTER_LEFT" spacing="14.0">
                     <children>
-                        <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="19.0" prefWidth="150.0"
-                               text="%padSettings.gen.label.title" AnchorPane.leftAnchor="14.0"/>
-                        <TextField fx:id="titleTextField" layoutX="125.0" layoutY="14.0" prefWidth="250.0"
-                                   AnchorPane.leftAnchor="127.0"/>
+                        <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%padSettings.gen.label.media"/>
+                        <Label fx:id="pathLabel" text="Label" textOverrun="CENTER_ELLIPSIS"/>
                         <VBox HBox.hgrow="ALWAYS"/>
-                        <Button fx:id="deleteButton" mnemonicParsing="false" onAction="#deleteButtonHandler"
-                                text="%padSettings.button.delete"/>
-                    </children>
-                </HBox>
-                <HBox alignment="CENTER_LEFT" layoutX="14.0" layoutY="48.0" spacing="14.0">
-                    <children>
-                        <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="50.0" prefWidth="150.0"
-                               text="%padSettings.gen.label.volume" AnchorPane.leftAnchor="14.0"/>
-                        <Slider fx:id="volumeSlider" layoutX="122.0" layoutY="54.0" prefWidth="250.0"
-                                showTickLabels="true" showTickMarks="true" snapToTicks="true" value="100.0"
-                                AnchorPane.leftAnchor="127.0"/>
-                        <VBox HBox.hgrow="ALWAYS"/>
-                        <CheckBox fx:id="repeatCheckBox" mnemonicParsing="false" text="%padSettings.checkbox.loop"/>
+                        <Button fx:id="showPathButton" mnemonicParsing="false" onAction="#showPathButtonHandler"
+                                text="%padSettings.button.path.show"/>
                     </children>
                 </HBox>
-                <HBox alignment="CENTER_LEFT" layoutX="14.0" layoutY="84.0" spacing="14.0">
+                <HBox spacing="14.0">
                     <children>
-                        <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="89.0" prefWidth="150.0"
-                               text="%padSettings.gen.label.timeDisplay" AnchorPane.leftAnchor="14.0"/>
-                        <ComboBox fx:id="timeDisplayComboBox" layoutX="127.0" layoutY="84.0" prefWidth="250.0"
-                                  AnchorPane.leftAnchor="127.0"/>
-                        <VBox HBox.hgrow="ALWAYS"/>
-                        <CheckBox fx:id="customTimeDisplayCheckBox" layoutX="406.0" layoutY="88.0"
-                                  mnemonicParsing="false" text="%padSettings.gen.checkbox.customSettings"/>
+                        <Button mnemonicParsing="false" onAction="#chooseButtonHandler"
+                                text="%padSettings.button.path.choose"/>
+                        <Button fx:id="deleteButton" mnemonicParsing="false" onAction="#deleteButtonHandler"
+                                text="%padSettings.button.delete"/>
                     </children>
+                    <padding>
+                        <Insets left="164.0"/>
+                    </padding>
                 </HBox>
+                <Separator prefWidth="200.0"/>
             </children>
         </VBox>
+        <HBox alignment="CENTER_LEFT" spacing="14.0">
+            <children>
+                <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="19.0" prefWidth="150.0"
+                       text="%padSettings.gen.label.title" AnchorPane.leftAnchor="14.0"/>
+                <TextField fx:id="titleTextField" layoutX="125.0" layoutY="14.0" prefWidth="250.0"
+                           AnchorPane.leftAnchor="127.0"/>
+            </children>
+        </HBox>
+        <HBox alignment="CENTER_LEFT" spacing="14.0">
+            <children>
+                <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="89.0" prefWidth="150.0"
+                       text="%padSettings.gen.label.timeDisplay" AnchorPane.leftAnchor="14.0"/>
+                <CheckBox fx:id="customTimeDisplayCheckBox" layoutX="406.0" layoutY="88.0" mnemonicParsing="false"
+                          text="%padSettings.gen.checkbox.customSettings"/>
+            </children>
+        </HBox>
+        <HBox>
+            <children>
+                <ComboBox fx:id="timeDisplayComboBox" prefWidth="250.0"/>
+            </children>
+            <padding>
+                <Insets left="164.0"/>
+            </padding>
+        </HBox>
+        <Separator prefWidth="200.0"/>
+        <HBox alignment="CENTER_LEFT" spacing="14.0">
+            <children>
+                <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%padSettings.label.loop"/>
+                <CheckBox fx:id="repeatCheckBox" mnemonicParsing="false" text="%settings.checkbox.activate"/>
+            </children>
+        </HBox>
+        <HBox alignment="CENTER_LEFT" spacing="14.0">
+            <children>
+                <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="50.0" prefWidth="150.0"
+                       text="%padSettings.gen.label.volume" AnchorPane.leftAnchor="14.0"/>
+                <Slider fx:id="volumeSlider" layoutX="122.0" layoutY="54.0" prefWidth="250.0" showTickLabels="true"
+                        showTickMarks="true" snapToTicks="true" value="100.0" AnchorPane.leftAnchor="127.0"/>
+            </children>
+        </HBox>
     </children>
     <padding>
         <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/>
diff --git a/PlayWall/src/main/resources/view/option/pad/PlaylistTab.fxml b/PlayWall/src/main/resources/view/option/pad/PlaylistTab.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..6f25be3e5792c953ce621d4ae05e0ca0db5b8c8f
--- /dev/null
+++ b/PlayWall/src/main/resources/view/option/pad/PlaylistTab.fxml
@@ -0,0 +1,51 @@
+<?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" spacing="14.0"
+      xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
+    <children>
+        <VBox spacing="14.0">
+            <children>
+                <ListView fx:id="mediaPathListView" prefWidth="250.0" VBox.vgrow="ALWAYS"/>
+                <HBox spacing="14.0">
+                    <children>
+                        <Button fx:id="addButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false"
+                                onAction="#onAddHandler" HBox.hgrow="ALWAYS"/>
+                        <Button fx:id="upButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false"
+                                onAction="#onUpHandler" HBox.hgrow="ALWAYS"/>
+                        <Button fx:id="downButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false"
+                                onAction="#onDownAction" HBox.hgrow="ALWAYS"/>
+                    </children>
+                </HBox>
+            </children>
+        </VBox>
+        <VBox spacing="14.0">
+            <children>
+                <HBox spacing="14.0">
+                    <children>
+                        <Label fx:id="pathLabel" textOverrun="CENTER_ELLIPSIS"/>
+                    </children>
+                </HBox>
+                <HBox spacing="14.0">
+                    <children>
+                        <Button fx:id="showFileButton" mnemonicParsing="false" onAction="#onShowFileHandler"
+                                text="%padSettings.button.path.show"/>
+                        <Button fx:id="deleteButton" mnemonicParsing="false" onAction="#onDeleteHandler"
+                                text="%padSettings.button.delete"/>
+                    </children>
+                </HBox>
+            </children>
+            <HBox.margin>
+                <Insets/>
+            </HBox.margin>
+            <padding>
+                <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/>
+            </padding>
+        </VBox>
+    </children>
+    <padding>
+        <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/>
+    </padding>
+</HBox>
diff --git a/PlayWall/src/main/resources/view/settings/FadeView.fxml b/PlayWall/src/main/resources/view/settings/FadeView.fxml
index 41b62886108419caa49806c4e3d2b6b21080ad40..94c88e46b71d49e1d6329457922e436f8c375690 100644
--- a/PlayWall/src/main/resources/view/settings/FadeView.fxml
+++ b/PlayWall/src/main/resources/view/settings/FadeView.fxml
@@ -51,6 +51,8 @@
                                           text="%settings.player.label.pauseOut"/>
                                 <CheckBox fx:id="fadeOutStopCheckBox" mnemonicParsing="false"
                                           text="%settings.player.label.stopOut"/>
+                                <CheckBox fx:id="fadeOutEofCheckBox" mnemonicParsing="false"
+                                          text="%settings.player.label.eofOut"/>
                             </children>
                         </HBox>
                     </children>
diff --git a/PlayWall/src/main/resources/view/settings/WarningFeedbackSettingsView.fxml b/PlayWall/src/main/resources/view/settings/WarningFeedbackSettingsView.fxml
index 115ed50e46fbf3987e97541afe8bd1782b246400..27801c98ba344874f9658e81722cee69720e32e0 100644
--- a/PlayWall/src/main/resources/view/settings/WarningFeedbackSettingsView.fxml
+++ b/PlayWall/src/main/resources/view/settings/WarningFeedbackSettingsView.fxml
@@ -10,7 +10,7 @@
         <HBox alignment="CENTER_LEFT" spacing="14.0">
             <children>
                 <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="14.0" prefWidth="150.0"
-                       text="%warning.label.time" textAlignment="RIGHT" wrapText="true" AnchorPane.leftAnchor="14.0"/>
+                       text="%settings.warning.label.time" textAlignment="RIGHT" wrapText="true" AnchorPane.leftAnchor="14.0"/>
                 <Slider fx:id="warningFeedbackTimeSlider" blockIncrement="0.1" majorTickUnit="1.0" max="10.0"
                         minorTickCount="9" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="5.0"
                         HBox.hgrow="ALWAYS"/>
diff --git a/PlayWall/src/main/sass/components/dark-list.scss b/PlayWall/src/main/sass/components/dark-list.scss
new file mode 100644
index 0000000000000000000000000000000000000000..080f181297955b8f85c6922e539e69705d001645
--- /dev/null
+++ b/PlayWall/src/main/sass/components/dark-list.scss
@@ -0,0 +1,23 @@
+@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;
+		}
+
+		&:odd {
+			-fx-background-color: -fx-base;
+		}
+	}
+}
\ No newline at end of file
diff --git a/PlayWall/src/main/sass/components/list.scss b/PlayWall/src/main/sass/components/list.scss
index 1ea1f4bc53dc52ac2bfb04568b503e2d64412451..45bcf857eb7c9f26a7ae5cf1a91c174cf92f75df 100644
--- a/PlayWall/src/main/sass/components/list.scss
+++ b/PlayWall/src/main/sass/components/list.scss
@@ -1,19 +1,22 @@
 @import "variables";
 
-.dark-list {
+.list-view {
 	-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-padding: 4px;
 		-fx-text-fill: #FFFFFF;
 		-fx-opacity: 1;
 
 		&:filled {
 			-fx-border-width: 0px 0px 1px 0px;
-			-fx-border-color: #00000044;
+		}
+
+		&:odd:filled {
+			-fx-background-color: derive(-fx-hover-base, -10%);
 		}
 	}
 
diff --git a/PlayWall/src/main/sass/modern.scss b/PlayWall/src/main/sass/modern.scss
index 7046c6af039f7e778946349465614c6b1a8e9f6b..bb353f6186cc4e1be629a85988ceb1745bdb2908 100644
--- a/PlayWall/src/main/sass/modern.scss
+++ b/PlayWall/src/main/sass/modern.scss
@@ -12,6 +12,7 @@
 @import "components/menu";
 @import "components/toggle-button";
 @import "components/list";
+@import "components/dark-list";
 @import "components/progress-bar";
 @import "components/dialog";
 @import "components/treeview";
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 aec4ccf9145de83e3b41e86038504f1dbf585ea9..b639f9099419bd956a0b420216f9c01568b2c679 100644
--- a/PlayWall/src/main/scala/de/tobias/playpad/design/ModernCartDesignHandlerImpl.scala
+++ b/PlayWall/src/main/scala/de/tobias/playpad/design/ModernCartDesignHandlerImpl.scala
@@ -4,7 +4,7 @@ import de.thecodelabs.utils.application.ApplicationUtils
 import de.tobias.playpad.design.modern.model.{ModernCartDesign, ModernGlobalDesign}
 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.pad.viewcontroller.AbstractPadViewController
 import de.tobias.playpad.util.Minifier
 import de.tobias.playpad.view.PseudoClasses
 import javafx.util.Duration
@@ -47,7 +47,7 @@ class ModernCartDesignHandlerImpl extends ModernCartDesignHandler {
 		expressionParser.parseExpression(string, new TemplateParserContext("${", "}")).getValue(context, classOf[String])
 	}
 
-	override def handleWarning(design: ModernCartDesign, controller: IPadViewController, warning: Duration, globalDesign: ModernGlobalDesign): Unit = {
+	override def handleWarning(design: ModernCartDesign, controller: AbstractPadViewController, warning: Duration, globalDesign: ModernGlobalDesign): Unit = {
 		if (globalDesign.isWarnAnimation) {
 			val playColor = design.getPlayColor
 			val backgroundColor = design.getBackgroundColor
@@ -71,5 +71,5 @@ class ModernCartDesignHandlerImpl extends ModernCartDesignHandler {
 		}
 	}
 
-	override def stopWarning(design: ModernCartDesign, controller: IPadViewController): Unit = ModernDesignAnimator.stopAnimation(controller)
+	override def stopWarning(design: ModernCartDesign, controller: AbstractPadViewController): Unit = ModernDesignAnimator.stopAnimation(controller)
 }
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 ca1ade7277a8ba8e726e3d3b1844575ea2b47f0b..3eea45b74878a931b801b72ea341ce13375be7d2 100644
--- a/PlayWall/src/main/scala/de/tobias/playpad/design/ModernGlobalDesignHandlerImpl.scala
+++ b/PlayWall/src/main/scala/de/tobias/playpad/design/ModernGlobalDesignHandlerImpl.scala
@@ -1,14 +1,11 @@
 package de.tobias.playpad.design
 
-import java.nio.file.Files
-import java.util.function.Consumer
-
 import de.thecodelabs.utils.application.ApplicationUtils
 import de.thecodelabs.utils.application.container.PathType
 import de.tobias.playpad.design.modern.model.{ModernCartDesign, ModernGlobalDesign}
 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.pad.viewcontroller.AbstractPadViewController
 import de.tobias.playpad.project.Project
 import de.tobias.playpad.util.Minifier
 import de.tobias.playpad.view.{ColorPickerView, PseudoClasses}
@@ -22,6 +19,8 @@ import org.springframework.expression.common.TemplateParserContext
 import org.springframework.expression.spel.standard.SpelExpressionParser
 import org.springframework.expression.spel.support.StandardEvaluationContext
 
+import java.nio.file.Files
+import java.util.function.Consumer
 import scala.jdk.CollectionConverters._
 
 class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with ColorModeHandler {
@@ -93,7 +92,7 @@ class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with Color
 		expressionParser.parseExpression(string, new TemplateParserContext("${", "}")).getValue(context, classOf[String])
 	}
 
-	override def handleWarning(design: ModernGlobalDesign, controller: IPadViewController, warning: Duration): Unit = {
+	override def handleWarning(design: ModernGlobalDesign, controller: AbstractPadViewController, warning: Duration): Unit = {
 		if (design.isWarnAnimation) {
 			warnAnimation(design, controller, warning)
 		} else {
@@ -101,7 +100,7 @@ class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with Color
 		}
 	}
 
-	private def warnAnimation(design: ModernGlobalDesign, controller: IPadViewController, warning: Duration): Unit = {
+	private def warnAnimation(design: ModernGlobalDesign, controller: AbstractPadViewController, warning: Duration): Unit = {
 		val stopColor = if (design.isFlatDesign) design.getBackgroundColor.toFlatFadeableColor else design.getBackgroundColor.toFadeableColor
 		val playColor = if (design.isFlatDesign) design.getPlayColor.toFlatFadeableColor else design.getPlayColor.toFadeableColor
 
@@ -118,7 +117,7 @@ class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with Color
 		ModernDesignAnimator.animateWarn(controller, playColor, stopColor, duration)
 	}
 
-	override def stopWarning(design: ModernGlobalDesign, controller: IPadViewController): Unit = ModernDesignAnimator.stopAnimation(controller)
+	override def stopWarning(design: ModernGlobalDesign, controller: AbstractPadViewController): 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/PluginLoadingTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/PluginLoadingTask.scala
index 0d415d80d9cd6c21276953546d84d47c187b770e..7b4d7bacf7a75ff8a6ee3ad8e67cd9a523ed6ffc 100644
--- a/PlayWall/src/main/scala/de/tobias/playpad/initialize/PluginLoadingTask.scala
+++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/PluginLoadingTask.scala
@@ -1,4 +1,5 @@
 package de.tobias.playpad.initialize
+
 import java.io.IOException
 import java.nio.file.{Path, Paths}
 
@@ -8,6 +9,8 @@ import de.thecodelabs.utils.application.ApplicationUtils
 import de.thecodelabs.utils.application.container.PathType
 import de.tobias.playpad.PlayPadImpl
 import de.tobias.playpad.plugin.ModernPluginManager
+import javafx.application.Platform
+import org.controlsfx.dialog.ExceptionDialog
 
 class PluginLoadingTask extends PlayPadInitializeTask {
 	override def name(): String = "Plugins"
@@ -34,6 +37,11 @@ class PluginLoadingTask extends PlayPadInitializeTask {
 			case e: Exception =>
 				Logger.error("Unable to load plugins")
 				Logger.error(e)
+
+				Platform.runLater(() => {
+					val dialog = new ExceptionDialog(e)
+					dialog.showAndWait()
+				})
 		}
 	}
 
diff --git a/PlayWallComponents/pom.xml b/PlayWallComponents/pom.xml
index e43eab12219cb2353d7a74809fcba74d74097769..014e6b86de1ac4bfcd3f2e4f69af6c276f1567f9 100644
--- a/PlayWallComponents/pom.xml
+++ b/PlayWallComponents/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallDesktop</artifactId>
-        <version>7.0.2</version>
+        <version>7.1.0</version>
     </parent>
 
     <artifactId>PlayWallComponents</artifactId>
diff --git a/PlayWallCore/pom.xml b/PlayWallCore/pom.xml
index e2f7f2d2f67a8ed6af95a543b09d75d003aaec2c..e88205b628d36d178dd5d0938e379c960fd4d7ea 100644
--- a/PlayWallCore/pom.xml
+++ b/PlayWallCore/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallDesktop</artifactId>
-        <version>7.0.2</version>
+        <version>7.1.0</version>
     </parent>
 
     <artifactId>PlayWallCore</artifactId>
@@ -29,10 +29,38 @@
         <dependency>
             <groupId>de.thecodelabs</groupId>
             <artifactId>libPlugins-core</artifactId>
+            <version>${libPlugins.version}</version>
+            <classifier>java8</classifier>
+            <exclusions>
+                <exclusion>
+                    <groupId>de.thecodelabs</groupId>
+                    <artifactId>libUtils</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>de.thecodelabs</groupId>
+                    <artifactId>libStorage</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>de.thecodelabs</groupId>
             <artifactId>libPlugins-versionizer</artifactId>
+            <version>${libPlugins.version}</version>
+            <classifier>java8</classifier>
+            <exclusions>
+                <exclusion>
+                    <groupId>de.thecodelabs</groupId>
+                    <artifactId>libUtils</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>de.thecodelabs</groupId>
+                    <artifactId>libStorage</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>de.thecodelabs.versionizer</groupId>
+                    <artifactId>api</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>de.thecodelabs.versionizer</groupId>
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java b/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java
index 14d50ffae9ec046ee3cdb1b70fa00542ec112b81..c480828c5d48c0712eab670dbd4a3d2ed05ede89 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java
@@ -14,12 +14,15 @@ import de.tobias.playpad.project.ProjectReader.ProjectReaderDelegate.ProfileAbor
 import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.settings.GlobalSettings;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
+import de.tobias.playpad.viewcontroller.option.GlobalSettingsTabViewController;
+import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController;
 import javafx.scene.image.Image;
 import org.dom4j.DocumentException;
 
 import java.io.IOException;
 import java.util.List;
 import java.util.function.Consumer;
+import java.util.function.Supplier;
 
 /**
  * Hauptfunktionen für Listener und zur Programmsteuerung für Plugins.
@@ -138,4 +141,15 @@ public interface PlayPad {
 
 	UpdateService getUpdateService();
 
+	/*
+	Settings Views
+	 */
+
+	void addAdditionalProfileSettingsTab(Supplier<ProfileSettingsTabViewController> tab);
+
+	List<Supplier<ProfileSettingsTabViewController>> getAdditionalProfileSettingsTabs();
+
+	void addGlobalSettingsTab(Supplier<GlobalSettingsTabViewController> tab);
+
+	List<Supplier<GlobalSettingsTabViewController>> getGlobalSettingsTabs();
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/audio/AudioCapability.java b/PlayWallCore/src/main/java/de/tobias/playpad/audio/AudioCapability.java
index c8db038e85e1b12b53a665a4fd4995b5c97d30fe..5fb29e5373d451e77f55ec95885e075859ce859e 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/audio/AudioCapability.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/audio/AudioCapability.java
@@ -11,10 +11,10 @@ public class AudioCapability {
 	public static final AudioCapability EQUALIZER = new AudioCapability("EQUALIZER", Equalizeable.class);
 	public static final AudioCapability SOUNDCARD = new AudioCapability("SOUNDCARD", Soundcardable.class);
 
-	private String nameKey;
-	private Class<? extends AudioFeature> clazz;
+	private final String nameKey;
+	private final Class<? extends AudioFeature> clazz;
 
-	private static List<AudioCapability> audioCapabilityList;
+	private static final List<AudioCapability> audioCapabilityList;
 
 	static {
 		audioCapabilityList = new ArrayList<>();
diff --git a/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java
similarity index 90%
rename from PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java
rename to PlayWallCore/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java
index d06dbc7a7c6619d5dedb9389c9124e680fe0bb53..91939942841248f3799c5dcf7b6b9e738b5b9831 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java
@@ -2,7 +2,7 @@ package de.tobias.playpad.design;
 
 public class ModernDesignSizeHelper {
 
-	private static final double MIN_WIDTH = 165;
+	private static final double MIN_WIDTH = 140;
 	private static final double MIN_HEIGHT = 115;
 
 	private ModernDesignSizeHelper() {
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernCartDesignHandler.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernCartDesignHandler.java
index 0f34344711461d7ef8a26a175053fc2be731f27b..200ead1fd6e412137370b6393167bb1092adc90d 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernCartDesignHandler.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernCartDesignHandler.java
@@ -2,7 +2,7 @@ package de.tobias.playpad.design.modern;
 
 import de.tobias.playpad.design.modern.model.ModernCartDesign;
 import de.tobias.playpad.design.modern.model.ModernGlobalDesign;
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import javafx.util.Duration;
 
 public interface ModernCartDesignHandler {
@@ -12,9 +12,9 @@ public interface ModernCartDesignHandler {
 	/*
 	 * Wird in einem neuen Thread aufgerufen
 	 */
-	void handleWarning(ModernCartDesign design, IPadViewController controller, Duration warning, ModernGlobalDesign globalDesign);
+	void handleWarning(ModernCartDesign design, AbstractPadViewController controller, Duration warning, ModernGlobalDesign globalDesign);
 
-	default void stopWarning(ModernCartDesign design, IPadViewController controller) {
+	default void stopWarning(ModernCartDesign design, AbstractPadViewController controller) {
 	}
 
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernGlobalDesignHandler.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernGlobalDesignHandler.java
index 1c6930dd44d0737bfce2454d18f96ba131652aff..bca1e4aa9cee672852326f41dffe582e115f10e4 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernGlobalDesignHandler.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernGlobalDesignHandler.java
@@ -1,7 +1,7 @@
 package de.tobias.playpad.design.modern;
 
 import de.tobias.playpad.design.modern.model.ModernGlobalDesign;
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import javafx.stage.Stage;
@@ -16,8 +16,8 @@ public interface ModernGlobalDesignHandler {
 	/*
 	 * Wird in einem neuen Thread aufgerufen
 	 */
-	void handleWarning(ModernGlobalDesign design, IPadViewController controller, Duration warning);
+	void handleWarning(ModernGlobalDesign design, AbstractPadViewController controller, Duration warning);
 
-	default void stopWarning(ModernGlobalDesign design, IPadViewController controller) {
+	default void stopWarning(ModernGlobalDesign design, AbstractPadViewController controller) {
 	}
 }
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 2a0fd4c28cda491ab99634c36b4f2ac2ac967598..cbefe4d2a0c9c95ce5607e7bcd510b7311212ea9 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java
@@ -13,7 +13,7 @@ import de.tobias.playpad.pad.listener.trigger.PadTriggerContentListener;
 import de.tobias.playpad.pad.listener.trigger.PadTriggerDurationListener;
 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.pad.viewcontroller.AbstractPadViewController;
 import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.ProjectSettings;
 import de.tobias.playpad.project.page.PadIndex;
@@ -78,7 +78,7 @@ public class Pad {
 	// Utils
 	private transient boolean eof;
 
-	private transient IPadViewController controller;
+	private transient AbstractPadViewController controller;
 	private transient Project project;
 	private transient PadUpdateListener padListener;
 
@@ -323,6 +323,10 @@ public class Pad {
 			createMediaPath(path);
 		} else {
 			setPath(path, 0);
+
+			while (mediaPaths.size() > 1) {
+				mediaPaths.remove(mediaPaths.size() - 1);
+			}
 		}
 	}
 
@@ -350,6 +354,13 @@ public class Pad {
 		addPath(mediaPath);
 	}
 
+	public void addPath(Path path) {
+		if (mediaPaths.isEmpty()) {
+			setName(PathUtils.getFilenameWithoutExtension(path.getFileName()));
+		}
+		createMediaPath(path);
+	}
+
 	public void addPath(MediaPath mediaPath) {
 		mediaPaths.add(mediaPath);
 
@@ -364,6 +375,7 @@ public class Pad {
 	}
 
 	public void removePath(MediaPath path) {
+		getContent().unloadMedia(path);
 		mediaPaths.remove(path);
 	}
 
@@ -374,6 +386,12 @@ public class Pad {
 		}
 	}
 
+	public void clearPaths() {
+		while (!mediaPaths.isEmpty()) {
+			removePath(mediaPaths.get(0));
+		}
+	}
+
 	/**
 	 * Get the status of the pad.
 	 *
@@ -556,11 +574,11 @@ public class Pad {
 		return controller != null;
 	}
 
-	public IPadViewController getController() {
+	public AbstractPadViewController getController() {
 		return controller;
 	}
 
-	public void setController(IPadViewController controller) {
+	public void setController(AbstractPadViewController controller) {
 		this.controller = controller;
 	}
 
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 f85ef7e4c280e323aebcc5ea805e94a0cd5e5dd2..a935edd4808ae2d9f1c92c99286591e429334cd8 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java
@@ -7,7 +7,7 @@ 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;
-import de.tobias.playpad.settings.Fade;
+import de.tobias.playpad.settings.FadeSettings;
 import de.tobias.playpad.tigger.Trigger;
 import de.tobias.playpad.tigger.TriggerPoint;
 import javafx.beans.binding.BooleanBinding;
@@ -31,7 +31,7 @@ public class PadSettings {
 	private DoubleProperty speedProperty = new SimpleDoubleProperty(1.0);
 	private BooleanProperty loopProperty = new SimpleBooleanProperty(false);
 	private ObjectProperty<TimeMode> timeModeProperty = new SimpleObjectProperty<>();
-	private ObjectProperty<Fade> fadeProperty = new SimpleObjectProperty<>();
+	private ObjectProperty<FadeSettings> fadeProperty = new SimpleObjectProperty<>();
 	private ObjectProperty<Duration> warningProperty = new SimpleObjectProperty<>();
 	private ObjectProperty<Duration> cueInProperty = new SimpleObjectProperty<>();
 
@@ -137,18 +137,18 @@ public class PadSettings {
 	 *
 	 * @return Fade
 	 */
-	public Fade getFade() {
+	public FadeSettings getFade() {
 		if (fadeProperty.isNull().get() && Profile.currentProfile() != null) {
 			return Profile.currentProfile().getProfileSettings().getFade();
 		}
 		return fadeProperty.get();
 	}
 
-	public void setFade(Fade fade) {
+	public void setFade(FadeSettings fade) {
 		this.fadeProperty.set(fade);
 	}
 
-	public ObjectProperty<Fade> fadeProperty() {
+	public ObjectProperty<FadeSettings> fadeProperty() {
 		return fadeProperty;
 	}
 
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 c4a44e1d72c09c8ae1ae8bdd3103f4f68447045f..82e70e61fcdcf7c06ccc037ad6296898528be82b 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java
@@ -1,9 +1,10 @@
 package de.tobias.playpad.pad;
 
+import de.thecodelabs.logger.Logger;
 import de.thecodelabs.storage.settings.UserDefaults;
 import de.tobias.playpad.design.modern.model.ModernCartDesign;
 import de.tobias.playpad.design.modern.serializer.ModernCartDesignSerializer;
-import de.tobias.playpad.settings.Fade;
+import de.tobias.playpad.settings.FadeSettings;
 import de.tobias.playpad.tigger.Trigger;
 import de.tobias.playpad.tigger.TriggerPoint;
 import javafx.util.Duration;
@@ -50,7 +51,7 @@ public class PadSettingsSerializer {
 		if (settingsElement.element(TIME_MODE_ELEMENT) != null)
 			padSettings.setTimeMode(TimeMode.valueOf(settingsElement.element(TIME_MODE_ELEMENT).getStringValue()));
 		if (settingsElement.element(FADE_ELEMENT) != null)
-			padSettings.setFade(Fade.load(settingsElement.element(FADE_ELEMENT)));
+			padSettings.setFade(FadeSettings.load(settingsElement.element(FADE_ELEMENT)));
 		if (settingsElement.element(WARNING_ELEMENT) != null) {
 			try {
 				Duration duration = Duration.valueOf(settingsElement.element(WARNING_ELEMENT).getStringValue().replace(" ", ""));
@@ -92,9 +93,13 @@ public class PadSettingsSerializer {
 		Element triggersElement = settingsElement.element(TRIGGERS_ELEMENT);
 		if (triggersElement != null) {
 			for (Element triggerElement : triggersElement.elements(TRIGGER_ELEMENT)) {
-				Trigger trigger = new Trigger();
-				trigger.load(triggerElement);
-				padSettings.getTriggers().put(trigger.getTriggerPoint(), trigger);
+				try {
+					Trigger trigger = new Trigger();
+					trigger.load(triggerElement);
+					padSettings.getTriggers().put(trigger.getTriggerPoint(), trigger);
+				} catch (IllegalArgumentException e) {
+					Logger.error(e);
+				}
 			}
 		}
 		padSettings.updateTrigger(); // Add missing trigger points
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 bf50a0b447c04de9dd77eadb9a9ee6834ca224bc..6c6d943e9f88741e9891794bf5a68fa3d712a7df 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
@@ -40,6 +40,10 @@ public abstract class PadContent {
 
 	public abstract boolean isPadLoaded();
 
+	public boolean isPadLoading() {
+		return false;
+	}
+
 	/**
 	 * Load media files.
 	 */
@@ -64,6 +68,9 @@ public abstract class PadContent {
 	 */
 	public abstract void unloadMedia(MediaPath mediaPath);
 
+	public void reorderMedia() {
+	}
+
 	public abstract void updateVolume();
 
 	@Override
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentFactory.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentFactory.java
index 5b34c1653f0bd0836507fc4a7af1a4082c48dbd2..611654dc50e21a013911b95a49e9024936c9b14b 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentFactory.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentFactory.java
@@ -2,16 +2,24 @@ package de.tobias.playpad.pad.content;
 
 import de.thecodelabs.utils.io.PathUtils;
 import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.drag.ContentDragOption;
 import de.tobias.playpad.pad.view.IPadContentView;
 import de.tobias.playpad.registry.Component;
 import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
 import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController;
 import javafx.scene.layout.Pane;
 
+import java.io.File;
 import java.nio.file.Path;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Consumer;
 
-// COMMENT PadContentFactory
-public abstract class PadContentFactory extends Component implements Comparable<PadContentFactory> {
+public abstract class PadContentFactory extends Component implements ContentDragOption {
+
+	public interface PadContentTypeChooser {
+		void showOptions(Collection<PadContentFactory> options, Consumer<PadContentFactory> onSelected);
+	}
 
 	public PadContentFactory(String type) {
 		super(type);
@@ -31,11 +39,6 @@ public abstract class PadContentFactory extends Component implements Comparable<
 
 	public abstract String[] getSupportedTypes();
 
-	@Override
-	public int compareTo(PadContentFactory o) {
-		return getType().compareTo(o.getType());
-	}
-
 	public static boolean isFileTypeSupported(Path path, PadContentFactory connect) {
 		String extension = PathUtils.getFileExtension(path);
 		for (String ex : connect.getSupportedTypes()) {
@@ -45,4 +48,26 @@ public abstract class PadContentFactory extends Component implements Comparable<
 		}
 		return false;
 	}
+
+	// Generic Drag Option for all content types
+
+	@Override
+	public void handleDrop(Pad currentPad, List<File> files) {
+		if (currentPad.getContent() == null || !currentPad.getContent().getType().equals(getType())) {
+			currentPad.setContentType(getType());
+		}
+
+		if (currentPad.isPadVisible()) {
+			currentPad.getController().getView().showBusyView(true);
+		}
+
+		if (currentPad.getContent() instanceof Playlistable) {
+			currentPad.clearPaths();
+			for (File file : files) {
+				currentPad.addPath(file.toPath());
+			}
+		} else {
+			currentPad.setPath(files.get(0).toPath());
+		}
+	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentRegistry.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentRegistry.java
index 20e7f45d2ef3f798555acda8d0062c9cad47c5f5..a2614a95f34e7f86294ff57beb87777c818e8bcb 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentRegistry.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentRegistry.java
@@ -12,17 +12,30 @@ public class PadContentRegistry extends ComponentRegistry<PadContentFactory> {
 		super(name);
 	}
 
-	public Set<PadContentFactory> getPadContentConnectsForFile(Path path) throws NoSuchComponentException {
-		Set<PadContentFactory> connects = new HashSet<>();
+	public List<PadContentFactory> getPadContentConnectsForFile(Path paths) throws NoSuchComponentException {
+		return getPadContentConnectsForFiles(Collections.singletonList(paths));
+	}
+
+	public List<PadContentFactory> getPadContentConnectsForFiles(List<Path> paths) throws NoSuchComponentException {
+		final Set<PadContentFactory> connects = new HashSet<>();
 		for (String type : getTypes()) {
 			PadContentFactory connect = getFactory(type);
 			for (String extension : connect.getSupportedTypes()) {
-				if (path.getFileName().toString().toLowerCase().matches("." + extension)) {
+				if (isExtensionMatchingAllFiles(extension, paths)) {
 					connects.add(connect);
 				}
 			}
 		}
-		return connects;
+		return new ArrayList<>(connects);
+	}
+
+	private boolean isExtensionMatchingAllFiles(String extension, List<Path> paths) {
+		for (Path path : paths) {
+			if (!path.getFileName().toString().toLowerCase().matches("." + extension)) {
+				return false;
+			}
+		}
+		return true;
 	}
 
 	public String[] getSupportedFileTypes() throws NoSuchComponentException {
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/Playlistable.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/Playlistable.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d15d9ad02184a18dc076b6cce7d739f8eba9552
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/Playlistable.java
@@ -0,0 +1,16 @@
+package de.tobias.playpad.pad.content;
+
+import de.tobias.playpad.pad.mediapath.MediaPath;
+import javafx.beans.property.IntegerProperty;
+
+public interface Playlistable {
+	int getCurrentPlayingMediaIndex();
+
+	IntegerProperty currentPlayingMediaIndexProperty();
+
+	boolean hasNext();
+
+	void next();
+
+	boolean isLoaded(MediaPath mediaPath);
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/drag/ContentDragOption.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/drag/ContentDragOption.java
new file mode 100644
index 0000000000000000000000000000000000000000..8af2e6d82227376781157fc2f9bd46b9073ce53f
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/drag/ContentDragOption.java
@@ -0,0 +1,17 @@
+package de.tobias.playpad.pad.drag;
+
+import de.tobias.playpad.Displayable;
+import de.tobias.playpad.pad.Pad;
+
+import java.io.File;
+import java.util.List;
+
+public interface ContentDragOption extends Displayable, Comparable<ContentDragOption> {
+
+	void handleDrop(Pad currentPad, List<File> files);
+
+	@Override
+	default int compareTo(ContentDragOption o) {
+		return displayProperty().get().compareTo(o.displayProperty().get());
+	}
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/AbstractFadeController.java
similarity index 59%
rename from PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java
rename to PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/AbstractFadeController.java
index de3828da7264143b30c1c0a49f94b58407d4919a..3923a9e07e8f171ce6b4c2ea714d6ed273136694 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/AbstractFadeController.java
@@ -4,19 +4,14 @@ import javafx.animation.Transition;
 import javafx.util.Duration;
 
 /**
- * Fade utils.
- *
- * @author tobias
- * @since 6.0.0
+ * @since 7.1.0
  */
-public class Fade {
+public abstract class AbstractFadeController {
 
-	private FadeDelegate fadeDelegate;
 	private Transition currentFadeTransition;
+	protected final FadeControllerDelegate fadeDelegate;
 
-	private double velocity = 1;
-
-	public Fade(FadeDelegate fadeDelegate) {
+	public AbstractFadeController(FadeControllerDelegate fadeDelegate) {
 		this.fadeDelegate = fadeDelegate;
 	}
 
@@ -58,15 +53,7 @@ public class Fade {
 
 			@Override
 			protected void interpolate(double frac) {
-				double diff = Math.abs(to - from);
-				if (from < to) { // Fade In
-					double fade = fadeInVolumeMultiplier(frac, velocity);
-					fadeDelegate.onFadeLevelChange(from + fade * diff);
-				} else { // Fade Out
-					double fade = fadeOutVolumeMultiplier(frac, velocity);
-					double newValue = to + fade * diff;
-					fadeDelegate.onFadeLevelChange(newValue);
-				}
+				AbstractFadeController.this.interpolate(this, frac, from, to);
 			}
 		};
 		currentFadeTransition.setOnFinished(e ->
@@ -79,12 +66,5 @@ public class Fade {
 		currentFadeTransition.play();
 	}
 
-	private double fadeInVolumeMultiplier(double time, double velocity) {
-		return Math.pow(Math.E, velocity * (time - 1)) * time;
-	}
-
-	private double fadeOutVolumeMultiplier(double time, double velocity) {
-		return Math.pow(Math.E, -velocity * time) * (1 - time);
-	}
-
+	protected abstract void interpolate(Transition transition, double frac, double from, double to);
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/FadeDelegate.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/FadeControllerDelegate.java
similarity index 87%
rename from PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/FadeDelegate.java
rename to PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/FadeControllerDelegate.java
index 3c7e49855c636f54ebf577814245059aa478524d..b86b6751aa985583cbb1a7c6a38642cff624df06 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/FadeDelegate.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/FadeControllerDelegate.java
@@ -6,7 +6,7 @@ package de.tobias.playpad.pad.fade;
  * @author tobias
  * @since 6.0.0
  */
-public interface FadeDelegate {
+public interface FadeControllerDelegate {
 
 	/**
 	 * If the fade level is changed, the delegate performs this method. The faded object should update.
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fadeable.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fadeable.java
index a0f5444cd47f4548471c82f34bad43b006f693dc..7e343f61b3d67bcd1b92703ec14cc2837c259835 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fadeable.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fadeable.java
@@ -7,6 +7,10 @@ public interface Fadeable {
 
 	void fadeIn();
 
+	default void fadeOut() {
+		fadeOut(null);
+	}
+
 	void fadeOut(Runnable runnable);
 
 	boolean isFadeActive();
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/LinearFadeController.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/LinearFadeController.java
new file mode 100644
index 0000000000000000000000000000000000000000..3287ca97157df9df9aac614b43ccd21baa49e94a
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/LinearFadeController.java
@@ -0,0 +1,26 @@
+package de.tobias.playpad.pad.fade;
+
+import javafx.animation.Transition;
+
+/**
+ * A fade controller implementation, that handles fade scala linear.
+ *
+ * @author tobias
+ * @since 7.1.0
+ */
+public class LinearFadeController extends AbstractFadeController {
+
+	public LinearFadeController(FadeControllerDelegate fadeDelegate) {
+		super(fadeDelegate);
+	}
+
+	@Override
+	protected void interpolate(Transition transition, double frac, double from, double to) {
+		double diff = Math.abs(to - from);
+		if (from < to) { // Fade In
+			fadeDelegate.onFadeLevelChange(diff * frac);
+		} else { // Fade Out
+			fadeDelegate.onFadeLevelChange(from - (diff * frac));
+		}
+	}
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/LogarithmicFadeController.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/LogarithmicFadeController.java
new file mode 100644
index 0000000000000000000000000000000000000000..effbc279899291ec7edb57cea9b6c2b018a686ea
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/LogarithmicFadeController.java
@@ -0,0 +1,40 @@
+package de.tobias.playpad.pad.fade;
+
+import javafx.animation.Transition;
+
+/**
+ * A fade controller implementation, that handles fade scala logarithmic for dB.
+ *
+ * @author tobias
+ * @since 6.0.0
+ */
+public class LogarithmicFadeController extends AbstractFadeController {
+
+	private static final double VELOCITY = 1;
+
+	public LogarithmicFadeController(FadeControllerDelegate fadeDelegate) {
+		super(fadeDelegate);
+	}
+
+	@Override
+	protected void interpolate(Transition transition, double frac, double from, double to) {
+		double diff = Math.abs(to - from);
+		if (from < to) { // Fade In
+			double fade = computeFadeInMultiplier(frac);
+			fadeDelegate.onFadeLevelChange(from + fade * diff);
+		} else { // Fade Out
+			double fade = computeFadeOutMultiplier(frac);
+			double newValue = to + fade * diff;
+			fadeDelegate.onFadeLevelChange(newValue);
+		}
+	}
+
+	protected double computeFadeInMultiplier(double frac) {
+		return Math.pow(Math.E, VELOCITY * (frac - 1)) * frac;
+	}
+
+	protected double computeFadeOutMultiplier(double frac) {
+		return Math.pow(Math.E, -VELOCITY * frac) * (1 - frac);
+	}
+
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeContentListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeContentListener.java
index ad414c8d8250053b5a3ec2f279c3b3bfd676e57c..0d7436b3405d2f89be63feebeaf36f55fe213889 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeContentListener.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeContentListener.java
@@ -7,9 +7,12 @@ import de.tobias.playpad.pad.fade.Fadeable;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 
+/**
+ * Remove end of file fade listener on old pad content and register on new pad content
+ */
 public class PadFadeContentListener implements ChangeListener<PadContent> {
 
-	private Pad pad;
+	private final Pad pad;
 
 	public PadFadeContentListener(Pad pad) {
 		this.pad = pad;
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeDurationListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeDurationListener.java
index d9eee37384b5f462200ec2e45f18b1e9b630e56e..214f832d81b61a8449170e5443a83a1fa32c57de 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeDurationListener.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeDurationListener.java
@@ -1,6 +1,7 @@
 package de.tobias.playpad.pad.fade.listener;
 
 import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.content.Playlistable;
 import de.tobias.playpad.pad.content.play.Durationable;
 import de.tobias.playpad.pad.fade.Fadeable;
 import javafx.beans.value.ChangeListener;
@@ -9,7 +10,7 @@ import javafx.util.Duration;
 
 public class PadFadeDurationListener implements ChangeListener<Duration> {
 
-	private Pad pad;
+	private final Pad pad;
 
 	public PadFadeDurationListener(Pad pad) {
 		this.pad = pad;
@@ -17,15 +18,27 @@ public class PadFadeDurationListener implements ChangeListener<Duration> {
 
 	@Override
 	public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
-		if (pad.getPadSettings().getFade().isFadeOutStop()) {
+		if (pad.getPadSettings().getFade().isFadeOutEof()) {
 			final Duration fadeDuration = pad.getPadSettings().getFade().getFadeOut();
 
+			// Do not fade out if looping is enabled
+			if (pad.getPadSettings().isLoop()) {
+				return;
+			}
+
+			// Do not fade out if the playlist has a next entry
+			if (pad.getContent() instanceof Playlistable && ((Playlistable) pad.getContent()).hasNext()) {
+				return;
+			}
+			
 			if (pad.getContent() instanceof Durationable) {
-				Durationable durationable = (Durationable) pad.getContent();
-				if (durationable.getPosition() != null && durationable.getDuration() != null) {
-					if (durationable.getPosition().add(fadeDuration).greaterThan(durationable.getDuration())) {
-						fadeOut();
-					}
+				final Durationable durationable = (Durationable) pad.getContent();
+
+				final Duration position = durationable.getPosition();
+				final Duration duration = durationable.getDuration();
+
+				if (position != null && duration != null && position.add(fadeDuration).greaterThan(duration)) {
+					fadeOut();
 				}
 			}
 		}
@@ -33,11 +46,10 @@ public class PadFadeDurationListener implements ChangeListener<Duration> {
 
 	private void fadeOut() {
 		if (pad.getContent() instanceof Fadeable) {
-			Fadeable fadeable = (Fadeable) pad.getContent();
+			final Fadeable fadeable = (Fadeable) pad.getContent();
 			if (!fadeable.isFadeActive()) {
-				fadeable.fadeOut(null);
+				fadeable.fadeOut();
 			}
-
 		}
 	}
 }
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 f0ea7b10a3a826fcc3c1fa104c978859abd93270..5067bad2fd287937bc336e5362a57ad854d7b609 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
@@ -51,7 +51,7 @@ public class PadStatusControlListener implements ChangeListener<PadStatus> {
 				}
 
 				if (pad.getContent() instanceof Fadeable) {
-					if (padSettings.getFade().isFadeInStart() || (oldValue == PadStatus.PAUSE && padSettings.getFade().isFadeInPause())) {
+					if ((oldValue != PadStatus.PAUSE && padSettings.getFade().isFadeInStart()) || (oldValue == PadStatus.PAUSE && padSettings.getFade().isFadeInPause())) {
 						((Fadeable) pad.getContent()).fadeIn();
 					}
 				}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerDurationListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerDurationListener.java
index 56eb71c98416217a5bd385a176f4690b084aa86d..834121676c93bc610e53b4ed255d8c06536991ae 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerDurationListener.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerDurationListener.java
@@ -15,29 +15,29 @@ import javafx.util.Duration;
 
 public class PadTriggerDurationListener implements ChangeListener<Duration> {
 
-	private Pad pad;
+	private final Pad pad;
 
 	public PadTriggerDurationListener(Pad pad) {
 		this.pad = pad;
 	}
 
 	@Override
-	public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
+	public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration currentTime) {
 		PadContent content = pad.getContent();
 		if (content instanceof Durationable) {
 			Duration totalDuration = ((Durationable) content).getDuration();
 			if (totalDuration != null) {
-				Duration leftTime = totalDuration.subtract(newValue);
-
 				IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController();
 				Profile currentProfile = Profile.currentProfile();
 				PadSettings padSettings = pad.getPadSettings();
 
-				// Execute Triggers
-				Trigger startTrigger = padSettings.getTrigger(TriggerPoint.START);
-				startTrigger.handle(pad, newValue, pad.getProject(), mainViewController, currentProfile);
+				// Execute Start Triggers
+				final Trigger startTrigger = padSettings.getTrigger(TriggerPoint.START);
+				startTrigger.handle(pad, currentTime, pad.getProject(), mainViewController, currentProfile);
 
-				Trigger endTrigger = padSettings.getTrigger(TriggerPoint.EOF_STOP);
+				// Execute End Trigger
+				final Duration leftTime = totalDuration.subtract(currentTime);
+				final Trigger endTrigger = padSettings.getTrigger(TriggerPoint.EOF);
 				endTrigger.handle(pad, leftTime, pad.getProject(), mainViewController, currentProfile);
 			}
 		}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerStatusListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerStatusListener.java
index 4517436191751b721ca5cc1ee98b18254fc2a196..94459f05e67e68795cc885c73be904a798fced97 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerStatusListener.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerStatusListener.java
@@ -14,7 +14,7 @@ import javafx.util.Duration;
 
 public class PadTriggerStatusListener implements ChangeListener<PadStatus> {
 
-	private Pad pad;
+	private final Pad pad;
 
 	public PadTriggerStatusListener(Pad pad) {
 		this.pad = pad;
@@ -26,12 +26,12 @@ public class PadTriggerStatusListener implements ChangeListener<PadStatus> {
 			PadSettings padSettings = pad.getPadSettings();
 
 			// Execute Trigger
-			if (newValue == PadStatus.PLAY) { // TRIGGER FÜR START
+			if (newValue == PadStatus.PLAY) {
 				executeTrigger(padSettings.getTriggers().get(TriggerPoint.START));
-			} else if (newValue == PadStatus.STOP || (oldValue == PadStatus.PLAY && newValue == PadStatus.READY)) { // TRIGGER FÜR STOP
-				executeTrigger(padSettings.getTriggers().get(TriggerPoint.EOF_STOP));
-			} else if (oldValue == PadStatus.PLAY && newValue == PadStatus.READY && pad.isEof()) { // TRIGGER FÜR EOF
-				executeTrigger(padSettings.getTriggers().get(TriggerPoint.EOF_STOP));
+			} else if (newValue == PadStatus.STOP) {
+				executeTrigger(padSettings.getTriggers().get(TriggerPoint.STOP));
+			} else if (oldValue == PadStatus.PLAY && newValue == PadStatus.READY && pad.isEof()) {
+				executeTrigger(padSettings.getTriggers().get(TriggerPoint.EOF_STATE));
 			}
 		} else {
 			pad.setIgnoreTrigger(false);
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 2287d7e5ac335b679cbf05975645bbd2e0737b97..64b1eb68e81f22260754f63fd089efdc97fcc12b 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
@@ -19,8 +19,8 @@ import java.util.UUID;
  */
 public class MediaPath {
 
-	private UUID id;
-	private StringProperty fileName;
+	private final UUID id;
+	private final StringProperty fileName;
 	private Pad pad;
 
 	public MediaPath(UUID id, Path path, Pad pad) {
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/preview/PadTextPreview.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/preview/PadTextPreview.java
new file mode 100644
index 0000000000000000000000000000000000000000..714792cb845c075ea42c739964af5f1b44ef8fa7
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/preview/PadTextPreview.java
@@ -0,0 +1,40 @@
+package de.tobias.playpad.pad.preview;
+
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.view.IPadContentView;
+import javafx.geometry.Pos;
+import javafx.scene.Parent;
+import javafx.scene.control.Label;
+import javafx.scene.layout.Pane;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+import javafx.scene.text.TextAlignment;
+
+public class PadTextPreview implements IPadContentView {
+
+	private final Label nameLabel;
+
+	public PadTextPreview(Pad pad, Pane parentNode) {
+		this.nameLabel = new Label();
+		this.nameLabel.textProperty().bind(pad.nameProperty());
+
+		this.nameLabel.setWrapText(true);
+		this.nameLabel.setAlignment(Pos.CENTER);
+		this.nameLabel.setTextAlignment(TextAlignment.CENTER);
+
+		this.nameLabel.prefWidthProperty().bind(parentNode.widthProperty());
+		this.nameLabel.setMaxHeight(Double.MAX_VALUE);
+
+		VBox.setVgrow(nameLabel, Priority.ALWAYS);
+	}
+
+	@Override
+	public Parent getNode() {
+		return nameLabel;
+	}
+
+	@Override
+	public void deInit() {
+		nameLabel.textProperty().unbind();
+	}
+}
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 c91aa9c7651afdc804ed1e961bf8cf80a1744338..62c5c08f19d5f9dfae5feddd12b5020c1a0e4be6 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
@@ -1,6 +1,6 @@
 package de.tobias.playpad.pad.view;
 
-import javafx.scene.Node;
+import javafx.scene.Parent;
 
 // TODO Rename to ContentView
 
@@ -17,7 +17,7 @@ public interface IPadContentView {
 	 *
 	 * @return GUI Element
 	 */
-	Node getNode();
+	Parent getNode();
 
 	/**
 	 * Deinitialisiert die View. Hier können mögliche Bindings und Listener entfernt werden.
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 51c6ae1b2d7450bf0cd0c191d822bc7f43be7beb..fd2be672d536176e22eb2a1097acca69a666be8e 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
@@ -1,9 +1,10 @@
 package de.tobias.playpad.pad.view;
 
 import de.tobias.playpad.pad.Pad;
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import de.tobias.playpad.project.page.PadIndex;
 import javafx.css.PseudoClass;
+import javafx.scene.control.Label;
 import javafx.scene.layout.Pane;
 
 /**
@@ -33,7 +34,7 @@ public interface IPadView {
 	 *
 	 * @return ViewController des Pad
 	 */
-	IPadViewController getViewController();
+	AbstractPadViewController getViewController();
 
 	/**
 	 * Gibt das oberste GUI Element des Pads zurück, welche im MainView verwendet wird.
@@ -106,6 +107,8 @@ public interface IPadView {
 	 */
 	void setPlaybarVisible(boolean visible);
 
+	Label getPlaylistLabel();
+
 	/**
 	 * Fügt die Standart Elemente der PadView hinzu. Die GUI Element sind Abhängig vom Pad, und welchen Content es hat.
 	 *
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/viewcontroller/AbstractPadViewController.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/viewcontroller/AbstractPadViewController.java
new file mode 100644
index 0000000000000000000000000000000000000000..e1cbb5372b4768424ceae0a0f1cee17adf0a6527
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/viewcontroller/AbstractPadViewController.java
@@ -0,0 +1,71 @@
+package de.tobias.playpad.pad.viewcontroller;
+
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.content.Playlistable;
+import de.tobias.playpad.pad.listener.IPadPositionListener;
+import de.tobias.playpad.pad.view.IPadView;
+import javafx.beans.binding.Bindings;
+import javafx.beans.value.ChangeListener;
+import javafx.util.Duration;
+
+/**
+ * Schnittstellen um mit einem PadViewController zu kommunizieren.
+ *
+ * @author tobias
+ * @since 5.1.0
+ */
+public abstract class AbstractPadViewController {
+
+	/**
+	 * Gibt das Pad zurück, welches er verwaltet. (Das Datenmodel)
+	 *
+	 * @return Pad
+	 */
+	public abstract Pad getPad();
+
+	/**
+	 * Gibt die View des Controllers zurück.
+	 *
+	 * @return View
+	 */
+	public abstract IPadView getView();
+
+	/**
+	 * Setzt ein Pad für ein View. Hier werden die Datein mittels ViewController der View bekannt gemacht.
+	 *
+	 * @param pad Neues Pad
+	 */
+	public abstract void setupPad(Pad pad);
+
+	/**
+	 * Entfertn des Verbundene Pad von der View.
+	 */
+	public abstract void removePad();
+
+	public abstract void updateTimeLabel();
+
+	public abstract void updateButtonDisable();
+
+	public abstract IPadPositionListener getPadPositionListener();
+
+	public abstract ChangeListener<Duration> getPadDurationListener();
+
+	public void updatePlaylistLabelBinding(Pad pad) {
+		if (pad.getContent() instanceof Playlistable) {
+			final Playlistable content = (Playlistable) pad.getContent();
+			getView().getPlaylistLabel().textProperty().bind(Bindings.createStringBinding(() -> {
+				final int currentPlayingMediaIndex = content.getCurrentPlayingMediaIndex();
+				final int totalCount = pad.getPaths().size();
+
+				if (currentPlayingMediaIndex < 0) {
+					return "- / " + totalCount;
+				} else {
+					return (currentPlayingMediaIndex + 1) + " / " + totalCount;
+				}
+			}, content.currentPlayingMediaIndexProperty(), pad.getPaths()));
+		} else {
+			getView().getPlaylistLabel().textProperty().unbind();
+			getView().getPlaylistLabel().setText("");
+		}
+	}
+}
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/viewcontroller/IPadViewController.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/viewcontroller/IPadViewController.java
deleted file mode 100644
index 6c010518809856910286625e81179040dfcb5c13..0000000000000000000000000000000000000000
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/viewcontroller/IPadViewController.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package de.tobias.playpad.pad.viewcontroller;
-
-import de.tobias.playpad.pad.Pad;
-import de.tobias.playpad.pad.listener.IPadPositionListener;
-import de.tobias.playpad.pad.view.IPadView;
-import javafx.beans.value.ChangeListener;
-import javafx.util.Duration;
-
-/**
- * Schnittstellen um mit einem PadViewController zu kommunizieren.
- *
- * @author tobias
- * @since 5.1.0
- */
-public interface IPadViewController {
-
-	/**
-	 * Gibt das Pad zurück, welches er verwaltet. (Das Datenmodel)
-	 *
-	 * @return Pad
-	 */
-	Pad getPad();
-
-	/**
-	 * Gibt die View des Controllers zurück.
-	 *
-	 * @return View
-	 */
-	IPadView getView();
-
-	/**
-	 * Setzt ein Pad für ein View. Hier werden die Datein mittels ViewController der View bekannt gemacht.
-	 *
-	 * @param pad Neues Pad
-	 */
-	void setupPad(Pad pad);
-
-	/**
-	 * Entfertn des Verbundene Pad von der View.
-	 */
-	void removePad();
-
-	void updateTimeLabel();
-
-	void updateButtonDisable();
-
-	IPadPositionListener getPadPositionListener();
-
-	ChangeListener<Duration> getPadDurationListener();
-}
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 6a7710569a56500cac8e246091f31523071c9190..40505787027f23d67c65d616d4ab9b889c0b347b 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPluginManager.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPluginManager.java
@@ -2,8 +2,8 @@ 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;
+import de.thecodelabs.plugins.versionizer.PluginArtifact;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
 import de.tobias.playpad.PlayPadPlugin;
@@ -25,10 +25,10 @@ public class ModernPluginManager {
 
 	private static final String PLUGIN_INFO_TXT = "pluginInfo.txt";
 
-	private PluginManager pluginManager;
-	private Set<Path> deletedPlugins;
+	private final PluginManager pluginManager;
+	private final Set<Path> deletedPlugins;
 
-	private Set<Module> modules;
+	private final Set<Module> modules;
 
 	private static ModernPluginManager instance;
 
@@ -59,14 +59,14 @@ public class ModernPluginManager {
 
 	public void loadFile(Path path) {
 		if (path.endsWith("classes")) {
-			pluginManager.addFile(path);
+			pluginManager.addPluginFile(path);
 		} else {
-			pluginManager.addFolder(path);
+			pluginManager.addPluginsOfDirectory(path);
 		}
 		pluginManager.loadPlugins();
 
 		// Registriert Funktionen aus Plugin (Module)
-		for (Plugin p : pluginManager.getPlugins()) {
+		for (Plugin p : pluginManager.getLoadedPlugins()) {
 			if (p instanceof PlayPadPluginStub) {
 				modules.add(((PlayPadPluginStub) p).getModule());
 			}
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 4900d036b2a09c0e936c85cbc6e5b52bebea9964..7e50c4dc4866467c22a06cc7372e830b28cd36e7 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/profile/Profile.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/profile/Profile.java
@@ -17,9 +17,7 @@ import org.dom4j.DocumentException;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
 
 public class Profile {
 
@@ -30,11 +28,13 @@ public class Profile {
 	private static Profile currentProfile;
 
 	// Settings
-	private ProfileReference ref;
+	private final ProfileReference ref;
 
 	private ProfileSettings profileSettings;
 	private MappingCollection mappings;
 
+	private Map<String, Object> customSettings;
+
 	/**
 	 * Use {@link ProfileReferenceManager#addProfile(ProfileReference)} instead
 	 *
@@ -44,6 +44,7 @@ public class Profile {
 		this.ref = ref;
 		this.profileSettings = new ProfileSettings();
 		this.mappings = new MappingCollection();
+		this.customSettings = new HashMap<>();
 	}
 
 	public static Mapping createMappingWithDefaultActions() {
@@ -84,6 +85,14 @@ public class Profile {
 		return profileSettings;
 	}
 
+	public Object getCustomSettings(String name) {
+		return customSettings.get(name);
+	}
+
+	public void addCustomSettings(String name, Object settings) {
+		customSettings.put(name, settings);
+	}
+
 	public static Profile load(ProfileReference ref) throws DocumentException, IOException, ProfileNotFoundException {
 		if (ref == null) {
 			throw new IllegalArgumentException("Profile is null");
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 a2039d5c3d0b27febb982aff03ae0d02e0bcd698..0b20a03f7e516161a6507e746031236a4c02c80e 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java
@@ -8,7 +8,7 @@ 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;
-import de.tobias.playpad.settings.Fade;
+import de.tobias.playpad.settings.FadeSettings;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.SimpleBooleanProperty;
@@ -66,7 +66,7 @@ public class ProfileSettings {
 	private boolean windowAlwaysOnTop = false;
 
 	@Key
-	private Fade fade = new Fade();
+	private FadeSettings fade = new FadeSettings();
 	@Key
 	private TimeMode playerTimeDisplayMode = TimeMode.REST;
 
@@ -115,7 +115,7 @@ public class ProfileSettings {
 		return windowAlwaysOnTop;
 	}
 
-	public Fade getFade() {
+	public FadeSettings getFade() {
 		return fade;
 	}
 
@@ -168,7 +168,7 @@ public class ProfileSettings {
 		this.windowAlwaysOnTop = windowAlwaysOnTop;
 	}
 
-	public void setFade(Fade fade) {
+	public void setFade(FadeSettings fade) {
 		this.fade = fade;
 	}
 
@@ -247,7 +247,7 @@ public class ProfileSettings {
 			}
 
 			if (root.element(FADE_ELEMENT) != null) {
-				Fade fade = Fade.load(root.element(FADE_ELEMENT));
+				FadeSettings fade = FadeSettings.load(root.element(FADE_ELEMENT));
 				profileSettings.setFade(fade);
 			}
 
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 bd70c1dfa78b1a6c1b50f3216ef46d1fdc0fb8b2..eedc4bcac8b6176a772fb4b133d1ac2a7d3682f6 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/project/Project.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/Project.java
@@ -199,7 +199,6 @@ public class Project {
 		notFoundMediaProperty.set(getPads(p -> p.getStatus() == PadStatus.NOT_FOUND).size());
 	}
 
-
 	@Override
 	public String toString() {
 		return projectReference.getName() + " (" + projectReference.getUuid() + ")";
@@ -281,4 +280,14 @@ public class Project {
 		}
 		return null;
 	}
+
+	public void addColumn() {
+		settings.setColumns(settings.getColumns() + 1);
+		pages.forEach(Page::addColumn);
+	}
+
+	public void addRow() {
+		settings.setRows(settings.getRows() + 1);
+		pages.forEach(Page::addRow);
+	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSettingsValidator.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSettingsValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..c750722448fe4573b004fead310a1634075d4b83
--- /dev/null
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSettingsValidator.java
@@ -0,0 +1,55 @@
+package de.tobias.playpad.project;
+
+import de.tobias.playpad.design.ModernDesignSizeHelper;
+import javafx.stage.Screen;
+
+public class ProjectSettingsValidator {
+	public static final int DISPLAY_OFFSET = 100;
+
+	public enum ValidationState {
+		NORMAL,
+		TOO_MUCH,
+		TOO_LESS
+	}
+
+	public enum Dimension {
+		COLUMNS,
+		ROWS
+	}
+
+	public ProjectSettingsValidator(Screen mainWindowScreen) {
+		this.mainWindowScreen = mainWindowScreen;
+	}
+
+	private final Screen mainWindowScreen;
+
+	public ValidationState validate(int input, Dimension dimension) {
+		if (input < minValue(dimension)) {
+			return ValidationState.TOO_LESS;
+		} else if (input > maxValue(dimension)) {
+			return ValidationState.TOO_MUCH;
+		}
+		return ValidationState.NORMAL;
+	}
+
+	public int minValue(Dimension dimension) {
+		if (dimension == Dimension.COLUMNS) {
+			return ProjectSettings.MIN_COLUMNS;
+		} else if (dimension == Dimension.ROWS) {
+			return ProjectSettings.MIN_ROWS;
+		}
+		return -1;
+	}
+
+	public int maxValue(Dimension dimension) {
+		double width = mainWindowScreen.getVisualBounds().getMaxX() - mainWindowScreen.getVisualBounds().getMinX();
+		double height = mainWindowScreen.getVisualBounds().getMaxY() - mainWindowScreen.getVisualBounds().getMinY();
+
+		if (dimension == Dimension.COLUMNS) {
+			return Math.min((int) (width / ModernDesignSizeHelper.getPadWidth()), ProjectSettings.MAX_COLUMNS);
+		} else if (dimension == Dimension.ROWS) {
+			return Math.min((int) ((height - DISPLAY_OFFSET) / ModernDesignSizeHelper.getPadHeight()), ProjectSettings.MAX_ROWS);
+		}
+		return -1;
+	}
+}
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 36d9b1d04b488322ad2d1449ca2025ea244e268b..24f207894be9dc118cf8c20439094e3ab46ce851 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
@@ -192,12 +192,17 @@ public class Page {
 	public Pad getPad(int x, int y) {
 		ProjectSettings settings = projectReference.getSettings();
 		if (x < settings.getColumns() && y < settings.getRows()) {
-			int id = y * settings.getColumns() + x;
-			return getPad(id);
+			int position = getPadPosition(x, y);
+			return getPad(position);
 		}
 		return null;
 	}
 
+	private int getPadPosition(int x, int y) {
+		ProjectSettings settings = projectReference.getSettings();
+		return y * settings.getColumns() + x;
+	}
+
 	/**
 	 * Set a pad to a new id. It overwrites the old pad. If the pad argument is null, it only removes the old pad.
 	 *
@@ -244,6 +249,40 @@ public class Page {
 		pads.removeIf(p -> p.getUuid().equals(uuid));
 	}
 
+	public void addColumn() {
+		final int columns = getProject().getSettings().getColumns() - 1;
+		final int rows = getProject().getSettings().getRows();
+
+		for (int i = 0; i < rows; i++) {
+			insertPadAndShiftSuccessor(columns, i, rows * columns);
+		}
+	}
+
+	public void addRow() {
+		final int columns = getProject().getSettings().getColumns();
+		final int rows = getProject().getSettings().getRows() - 1;
+
+		for (int i = 0; i < columns; i++) {
+			insertPadAndShiftSuccessor(columns, i, rows * columns);
+		}
+	}
+
+	/**
+	 * Insert a pad into given (x, y). Moves all other pads one position ahead.
+	 *
+	 * @param x            x
+	 * @param y            y
+	 * @param lastPadIndex index of the last pad on the page
+	 */
+	private void insertPadAndShiftSuccessor(int x, int y, int lastPadIndex) {
+		int position = getPadPosition(x, y);
+		// Going backwards to avoid overwriting the next pad when updating the position of the current one.
+		for (int i = lastPadIndex - 1; i >= position; i--) {
+			getPad(i).setPosition(i + 1);
+		}
+		getPad(position);
+	}
+
 	@Override
 	public String toString() {
 		return "Page [positionProperty=" + positionProperty + "]";
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/registry/Component.java b/PlayWallCore/src/main/java/de/tobias/playpad/registry/Component.java
index 8c645af1e6e2119ed09f38d44926e05531039ba0..6f42120f2074321041352844c3e100bbb0271ff4 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/registry/Component.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/registry/Component.java
@@ -12,8 +12,8 @@ import javafx.scene.Node;
  */
 public class Component implements Displayable {
 
-	private String type;
-	private StringProperty displayProperty;
+	private final String type;
+	private final StringProperty displayProperty;
 	private FontIcon graphics;
 
 	public Component(String type) {
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java b/PlayWallCore/src/main/java/de/tobias/playpad/settings/FadeSettings.java
similarity index 80%
rename from PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java
rename to PlayWallCore/src/main/java/de/tobias/playpad/settings/FadeSettings.java
index 4b30a96f2101acc9136fb218a92918d1edea5a69..d545281b29f8fc47aa42e0619e001a5d69b6073c 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/settings/FadeSettings.java
@@ -14,7 +14,7 @@ import org.dom4j.Element;
  * @see PadSettings#getFade()
  * @since 6.0.0
  */
-public class Fade {
+public class FadeSettings {
 
 	private Duration fadeIn;
 	private Duration fadeOut;
@@ -23,11 +23,12 @@ public class Fade {
 	private boolean fadeInPause;
 	private boolean fadeOutPause;
 	private boolean fadeOutStop;
+	private boolean fadeOutEof;
 
 	/**
 	 * Erstellt ein neues Fade mit den Default Werten. (Fade Dauer: 0 sec)
 	 */
-	public Fade() {
+	public FadeSettings() {
 		this(Duration.ONE, Duration.ONE);
 	}
 
@@ -37,8 +38,8 @@ public class Fade {
 	 * @param fadeIn  Fade In Dauer
 	 * @param fadeOut Fade Out Dauer
 	 */
-	public Fade(Duration fadeIn, Duration fadeOut) {
-		this(fadeIn, fadeOut, false, true, true, true);
+	public FadeSettings(Duration fadeIn, Duration fadeOut) {
+		this(fadeIn, fadeOut, false, true, true, true, false);
 	}
 
 	/**
@@ -51,13 +52,14 @@ public class Fade {
 	 * @param fadeOutPause Fade vor Pause
 	 * @param fadeOutStop  Fade vor Stop
 	 */
-	public Fade(Duration fadeIn, Duration fadeOut, boolean fadeInStart, boolean fadeInPause, boolean fadeOutPause, boolean fadeOutStop) {
+	public FadeSettings(Duration fadeIn, Duration fadeOut, boolean fadeInStart, boolean fadeInPause, boolean fadeOutPause, boolean fadeOutStop, boolean fadeOutEof) {
 		this.fadeIn = fadeIn;
 		this.fadeOut = fadeOut;
 		this.fadeInStart = fadeInStart;
 		this.fadeInPause = fadeInPause;
 		this.fadeOutPause = fadeOutPause;
 		this.fadeOutStop = fadeOutStop;
+		this.fadeOutEof = fadeOutEof;
 	}
 
 	public Duration getFadeIn() {
@@ -108,6 +110,14 @@ public class Fade {
 		this.fadeOutStop = fadeOutStop;
 	}
 
+	public boolean isFadeOutEof() {
+		return fadeOutEof;
+	}
+
+	public void setFadeOutEof(boolean fadeOutEof) {
+		this.fadeOutEof = fadeOutEof;
+	}
+
 	/*
 	 * Serialize
 	 */
@@ -116,6 +126,7 @@ public class Fade {
 	private static final String FADE_IN = "FadeIn";
 
 	private static final String ON_STOP_ATTR = "onStop";
+	private static final String ON_EOF_ATTR = "onEof";
 	private static final String ON_PAUSE_ATTR = "onPause";
 	private static final String ON_START_ATTR = "onStart";
 
@@ -129,16 +140,17 @@ public class Fade {
 		fadeOutElement.addText(fadeOut.toString());
 		fadeOutElement.addAttribute(ON_PAUSE_ATTR, String.valueOf(fadeOutPause));
 		fadeOutElement.addAttribute(ON_STOP_ATTR, String.valueOf(fadeOutStop));
+		fadeOutElement.addAttribute(ON_EOF_ATTR, String.valueOf(fadeOutEof));
 	}
 
-	public static Fade load(Element container) {
+	public static FadeSettings load(Element container) {
 		try {
-			Fade fade = new Fade();
+			FadeSettings fade = new FadeSettings();
 
 			Element fadeInElement = container.element(FADE_IN);
-			if (fadeInElement.attributeValue(ON_PAUSE_ATTR) != null)
+			if (fadeInElement.attributeValue(ON_START_ATTR) != null)
 				fade.setFadeInStart(Boolean.parseBoolean(fadeInElement.attributeValue(ON_START_ATTR)));
-			if (fadeInElement.attributeValue(ON_STOP_ATTR) != null)
+			if (fadeInElement.attributeValue(ON_PAUSE_ATTR) != null)
 				fade.setFadeInPause(Boolean.parseBoolean(fadeInElement.attributeValue(ON_PAUSE_ATTR)));
 			fade.setFadeIn(Duration.valueOf(fadeInElement.getStringValue().replace(" ", "")));
 
@@ -147,6 +159,8 @@ public class Fade {
 				fade.setFadeOutPause(Boolean.parseBoolean(fadeOutElement.attributeValue(ON_PAUSE_ATTR)));
 			if (fadeOutElement.attributeValue(ON_STOP_ATTR) != null)
 				fade.setFadeOutStop(Boolean.parseBoolean(fadeOutElement.attributeValue(ON_STOP_ATTR)));
+			if (fadeOutElement.attributeValue(ON_EOF_ATTR) != null)
+				fade.setFadeOutEof(Boolean.parseBoolean(fadeOutElement.attributeValue(ON_EOF_ATTR)));
 			fade.setFadeOut(Duration.valueOf(fadeOutElement.getStringValue().replace(" ", "")));
 			return fade;
 		} catch (Exception e) {
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 2f65d793a5a5e39a17060ed14d72f6d2b0cfe773..ba284a16cccbe20166ac9c86c41fbb9a822dc5e5 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java
@@ -71,7 +71,7 @@ public class Trigger {
 		try {
 			triggerPoint = TriggerPoint.valueOf(element.attributeValue(POINT_ATTR));
 		} catch (Exception e) {
-			Logger.error(e);
+			throw new IllegalArgumentException("Trigger Point " + element.attributeValue(POINT_ATTR) + " not exists");
 		}
 
 		for (Element itemElement : element.elements(ITEM_ELEMENT)) {
@@ -104,18 +104,22 @@ public class Trigger {
 		return triggerPoint.name() + " (" + items.size() + ")";
 	}
 
-	public void handle(Pad pad, Duration duration, Project project, IMainViewController mainViewController, Profile currentProfile) {
+	public void handle(Pad pad, Duration currentDuration, Project project, IMainViewController mainViewController, Profile currentProfile) {
 		for (TriggerItem item : items) {
 			if (triggerPoint == TriggerPoint.START) {
-				handleStartPoint(pad, duration, project, mainViewController, currentProfile, item);
-			} else if ((triggerPoint == TriggerPoint.EOF_STOP)) {
-				handleEndPoint(pad, duration, project, mainViewController, currentProfile, item);
+				handleStartPoint(pad, currentDuration, project, mainViewController, currentProfile, item);
+			} else if (triggerPoint == TriggerPoint.STOP) {
+				handleEndPoint(pad, currentDuration, project, mainViewController, currentProfile, item);
+			} else if (triggerPoint == TriggerPoint.EOF) {
+				handleEndPoint(pad, currentDuration, project, mainViewController, currentProfile, item);
+			} else if (triggerPoint == TriggerPoint.EOF_STATE) {
+				item.performAction(pad, project, mainViewController, currentProfile);
 			}
 		}
 	}
 
 	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)
+		// Wenn Trigger noch nicht gespielt 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);
@@ -126,7 +130,7 @@ public class Trigger {
 
 	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
+			// Mitten drin, wenn die Zeit die gespielt 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
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerItemFactory.java b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerItemFactory.java
index 9590d921a24a86a84453ff83acbcce147cb69c91..118dc56017638413688062a0bd742f59ffc05dec 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerItemFactory.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerItemFactory.java
@@ -2,6 +2,7 @@ package de.tobias.playpad.tigger;
 
 import de.thecodelabs.utils.ui.NVC;
 import de.tobias.playpad.registry.Component;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
 
 public abstract class TriggerItemFactory extends Component {
 
@@ -11,6 +12,6 @@ public abstract class TriggerItemFactory extends Component {
 
 	public abstract TriggerItem newInstance(Trigger trigger);
 
-	public abstract NVC getSettingsController(TriggerItem item);
+	public abstract NVC getSettingsController(TriggerItem item, IMainViewController mainViewController);
 
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerPoint.java b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerPoint.java
index 30730e5b61922655bbd49ab38a8b6f735967738a..4f1390d9e6ebda63f92fe7647d00ae0fe759df2c 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerPoint.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerPoint.java
@@ -2,7 +2,21 @@ package de.tobias.playpad.tigger;
 
 public enum TriggerPoint {
 
-	START,
-	EOF_STOP
+	START(true),
+	STOP(false),
+	EOF(true),
+	EOF_STATE(false);
 
+	/**
+	 * Defines if a trigger can be run after, before a certain event.
+	 */
+	private final boolean timeAppendable;
+
+	TriggerPoint(boolean timeAppendable) {
+		this.timeAppendable = timeAppendable;
+	}
+
+	public boolean isTimeAppendable() {
+		return timeAppendable;
+	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/view/main/MainLayoutFactory.java b/PlayWallCore/src/main/java/de/tobias/playpad/view/main/MainLayoutFactory.java
index f7cf7399636ec98235da323c9e75f1c23a0631f1..88039dcb374505f9f913fc81b4d72d5c20fdfd63 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/view/main/MainLayoutFactory.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/view/main/MainLayoutFactory.java
@@ -1,7 +1,7 @@
 package de.tobias.playpad.view.main;
 
 import de.tobias.playpad.pad.view.IPadView;
-import de.tobias.playpad.pad.viewcontroller.IPadViewController;
+import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController;
 import de.tobias.playpad.registry.Component;
 import de.tobias.playpad.viewcontroller.main.IMainViewController;
 import de.tobias.playpad.viewcontroller.main.MenuToolbarViewController;
@@ -31,7 +31,7 @@ public abstract class MainLayoutFactory extends Component {
 	 *
 	 * @return Pad
 	 * @see IPadView notwendige Methoden für ein Pad
-	 * @see IPadViewController ViewController zum Pad
+	 * @see AbstractPadViewController ViewController zum Pad
 	 */
 	public abstract IPadView createPadView();
 
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/view/main/ProjectPreviewView.java b/PlayWallCore/src/main/java/de/tobias/playpad/view/main/ProjectPreviewView.java
index 10bba54fef944f0b3dd71fe6a651bf867b4a54f7..2e16c3cb79abe3471b9e6c0c185852f9efb87816 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/view/main/ProjectPreviewView.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/view/main/ProjectPreviewView.java
@@ -6,6 +6,9 @@ import de.tobias.playpad.project.Project;
 import de.tobias.playpad.project.page.Page;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
 import javafx.scene.control.Pagination;
 import javafx.scene.control.ToggleButton;
 import javafx.scene.control.Tooltip;
@@ -15,31 +18,36 @@ import java.util.List;
 
 public class ProjectPreviewView extends Pagination {
 
-	private Project project;
+	private final Project project;
+	private final ObservableList<Pad> selected;
 
-	private ObservableList<Pad> selected;
-
-	public ProjectPreviewView(Project project, List<Pad> preSelect) {
+	public ProjectPreviewView(Project project, List<Pad> preSelect, int initialPage) {
 		super(project.getPages().size());
 		this.project = project;
 		this.selected = FXCollections.observableArrayList(preSelect);
 
-		setPageFactory(index -> {
-			GridPane gridPane = new GridPane();
-			gridPane.setHgap(7);
-			gridPane.setVgap(7);
+		setCurrentPageIndex(initialPage);
+		setPageFactory(this::getPageNode);
+	}
+
+	private Node getPageNode(int index) {
+		GridPane gridPane = new GridPane();
+		gridPane.setHgap(7);
+		gridPane.setVgap(7);
+		gridPane.setAlignment(Pos.CENTER);
 
-			Page page = project.getPage(index);
-			for (int x = 0; x < project.getSettings().getColumns(); x++) {
-				for (int y = 0; y < project.getSettings().getRows(); y++) {
-					final Pad pad = page.getPad(x, y);
-					ToggleButton toggleButton = getToggleButton(preSelect, pad);
+		gridPane.setPadding(new Insets(0, 0, 7, 0));
 
-					gridPane.add(toggleButton, x, y);
-				}
+		final Page page = project.getPage(index);
+		for (int x = 0; x < project.getSettings().getColumns(); x++) {
+			for (int y = 0; y < project.getSettings().getRows(); y++) {
+				final Pad pad = page.getPad(x, y);
+				ToggleButton toggleButton = getToggleButton(selected, pad);
+
+				gridPane.add(toggleButton, x, y);
 			}
-			return gridPane;
-		});
+		}
+		return gridPane;
 	}
 
 	private ToggleButton getToggleButton(List<Pad> preSelect, Pad pad) {
diff --git a/PlayWallPlugins/PlayWallPluginAwake/pom.xml b/PlayWallPlugins/PlayWallPluginAwake/pom.xml
index e8e455aa952bf3696847c5cb239d45bd1817ecc4..ab7412fa66fc468da72597b261d0699a109f60ce 100644
--- a/PlayWallPlugins/PlayWallPluginAwake/pom.xml
+++ b/PlayWallPlugins/PlayWallPluginAwake/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallPlugins</artifactId>
-        <version>7.0.2</version>
+        <version>7.1.0</version>
     </parent>
 
     <artifactId>PlayWallPluginAwake</artifactId>
diff --git a/PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java b/PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java
index aa546a3218fa87200ddeb5090f9b0e7328200391..4c47a3b672cc4a81d24a34c3aa47bb684d19961b 100644
--- a/PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java
+++ b/PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java
@@ -1,8 +1,8 @@
 package de.tobias.playpad.awakeplugin;
 
 import de.thecodelabs.logger.Logger;
-import de.thecodelabs.plugins.PluginArtifact;
 import de.thecodelabs.plugins.PluginDescriptor;
+import de.thecodelabs.plugins.versionizer.PluginArtifact;
 import de.thecodelabs.utils.application.system.NativeApplication;
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/pom.xml b/PlayWallPlugins/PlayWallPluginContentPlayer/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c63bba0cd0555730de475e6b1aa9b82dab82b458
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/pom.xml
@@ -0,0 +1,131 @@
+<?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.1.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>PlayWallPluginContentPlayer</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>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>de.thecodelabs</groupId>
+                <artifactId>versionizer-maven-plugin</artifactId>
+                <version>${versionizer-maven-plugin.version}</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.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+        </repository>
+        <snapshotRepository>
+            <id>snapshots</id>
+            <name>TheCodeLabs-snapshots</name>
+            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+    <repositories>
+        <repository>
+            <id>release</id>
+            <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>snapshots</id>
+            <url>https://maven.thecodelabs.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/PlayWallPluginContentPlayer/src/main/resources/PadContent.xml b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/PadContent.xml
new file mode 100644
index 0000000000000000000000000000000000000000..32da3b2a4dcc9e49a66cbac1a9bb23b5528c2a53
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/PadContent.xml
@@ -0,0 +1,6 @@
+<Actions>
+    <Component id="content_player" name="plugin.content.Player.name" icon="MONITOR_MULTIPLE"
+               class="de.thecodelabs.utils.ui.icon.MaterialDesignIcon"
+               size="30">de.tobias.playpad.plugin.content.pad.ContentPlayerPadContentFactory
+    </Component>
+</Actions>
\ No newline at end of file
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/lang/base.properties b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/lang/base.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/lang/base_de.properties b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/lang/base_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..f349884fe1a09c06e16bd93793838ac6430afbb8
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/lang/base_de.properties
@@ -0,0 +1,17 @@
+plugin.content.Player.name=Content Player
+
+plugin.content.player.settings=Content Player
+plugin.content.player.settings.name=Name:
+plugin.content.player.settings.x=X:
+plugin.content.player.settings.y=Y:
+plugin.content.player.settings.width=Breite:
+plugin.content.player.settings.height=H\u00F6he:
+plugin.content.player.settings.add=Hinzuf\u00FCgen
+plugin.content.player.settings.remove=L\u00F6schen
+plugin.content.player.settings.default_name=Zone
+
+plugin.content.pad.settings.lastFrame.label=Letztes Frame halten
+plugin.content.pad.settings.lastFrame.checkbox=Aktiv
+plugin.content.pad.settings.zone=Zonen
+plugin.content.pad.settings.zone.addAll=Alle anw\u00E4hlen
+plugin.content.pad.settings.zone.removeAll=Alle abw\u00E4hlen
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/plugin.yml b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/plugin.yml
new file mode 100644
index 0000000000000000000000000000000000000000..70a18e12c0441bf59f78ee543ce885c15034c894
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/plugin.yml
@@ -0,0 +1,6 @@
+main: "de.tobias.playpad.plugin.content.ContentPluginMain"
+name: "ContentPlugin"
+artifactId: "${pom.artifactId}"
+groupId: "${pom.groupId}"
+version: "${pom.version}"
+build: 1
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/ContentPadSettings.fxml b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/ContentPadSettings.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..bfd7033978d027d36f881bb9957b7c158056cb89
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/ContentPadSettings.fxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<?import org.controlsfx.control.CheckListView?>
+<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
+    <children>
+        <VBox layoutX="237.0" layoutY="-18.0" spacing="14.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+            <children>
+                <HBox alignment="CENTER_LEFT" spacing="14.0">
+                    <children>
+                        <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.pad.settings.lastFrame.label" />
+                        <CheckBox fx:id="lastFrameCheckbox" mnemonicParsing="false" text="%plugin.content.pad.settings.lastFrame.checkbox" />
+                    </children>
+                </HBox>
+            <HBox spacing="14.0">
+               <children>
+                  <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.pad.settings.zone" />
+                  <CheckListView fx:id="zoneListView" prefHeight="150.0" />
+                  <VBox spacing="14.0">
+                     <children>
+                        <Button fx:id="addAllZonesButton" onAction="#onAddAllZonesHandler" mnemonicParsing="false" text="%plugin.content.pad.settings.zone.addAll" />
+                        <Button fx:id="removeAllZonesButton" onAction="#onRemoveAllZonesHandler" mnemonicParsing="false" text="%plugin.content.pad.settings.zone.removeAll" />
+                     </children>
+                  </VBox>
+               </children>
+            </HBox>
+            </children>
+            <padding>
+                <Insets bottom="14.0" left="14.0" right="14.0" top="14.0" />
+            </padding>
+        </VBox>
+    </children>
+</AnchorPane>
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/PlayerView.fxml b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/PlayerView.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..3428c4ea773b6b4a8e3838f54f9373d77107c718
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/PlayerView.fxml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+<?import javafx.scene.layout.Pane?>
+<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" />
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/ZoneSettings.fxml b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/ZoneSettings.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..64036902597eb22c98b1b9881eee56e6aad82a12
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/ZoneSettings.fxml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import de.thecodelabs.utils.ui.scene.input.NumberTextField?>
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
+    <children>
+      <VBox layoutY="345.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
+         <children>
+              <ListView fx:id="listView" prefWidth="250.0" VBox.vgrow="ALWAYS" />
+              <HBox prefHeight="30.0" prefWidth="200.0" spacing="14.0">
+                  <children>
+                      <Button fx:id="addButton" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#onAddHandle" text="%plugin.content.player.settings.add" HBox.hgrow="ALWAYS" />
+                      <Button fx:id="removeButton" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#onRemoveHandle" text="%plugin.content.player.settings.remove" HBox.hgrow="ALWAYS" />
+                  </children>
+               <padding>
+                  <Insets bottom="14.0" left="14.0" right="14.0" top="14.0" />
+               </padding>
+              </HBox>
+         </children>
+      </VBox>
+        <VBox layoutX="200.0" prefHeight="400.0" prefWidth="401.0" spacing="14.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="250.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+            <children>
+                <HBox alignment="CENTER_LEFT" spacing="14.0">
+                    <children>
+                        <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.player.settings.name" />
+                        <TextField fx:id="nameTextField" />
+                    </children>
+                </HBox>
+                <HBox alignment="CENTER_LEFT" spacing="14.0">
+                    <children>
+                        <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.player.settings.x" />
+                        <NumberTextField fx:id="xTextField" />
+                    </children>
+                </HBox>
+                <HBox alignment="CENTER_LEFT" spacing="14.0">
+                    <children>
+                        <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.player.settings.y" />
+                        <NumberTextField fx:id="yTextField" />
+                    </children>
+                </HBox>
+                <HBox alignment="CENTER_LEFT" spacing="14.0">
+                    <children>
+                        <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.player.settings.width" />
+                        <NumberTextField fx:id="widthTextField" />
+                    </children>
+                </HBox>
+                <HBox alignment="CENTER_LEFT" spacing="14.0">
+                    <children>
+                        <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.player.settings.height" />
+                        <NumberTextField fx:id="heightTextField" />
+                    </children>
+                </HBox>
+            </children>
+            <padding>
+                <Insets bottom="14.0" left="14.0" right="14.0" top="14.0" />
+            </padding>
+        </VBox>
+    </children>
+</AnchorPane>
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/ContentPluginMain.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/ContentPluginMain.scala
new file mode 100644
index 0000000000000000000000000000000000000000..2756703ed75e039767b9c5ba3e09324f46653b98
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/ContentPluginMain.scala
@@ -0,0 +1,60 @@
+package de.tobias.playpad.plugin.content
+
+import de.thecodelabs.plugins.PluginDescriptor
+import de.thecodelabs.storage.settings.{Storage, StorageTypes}
+import de.thecodelabs.utils.util.Localization
+import de.tobias.playpad.PlayPadPlugin
+import de.tobias.playpad.plugin.content.player.ContentPlayerViewController
+import de.tobias.playpad.plugin.content.settings.{ZoneConfiguration, ZoneSettingsViewController}
+import de.tobias.playpad.plugin.{Module, PlayPadPluginStub, SettingsListener}
+import de.tobias.playpad.profile.{Profile, ProfileListener}
+import javafx.application.Platform
+
+class ContentPluginMain extends PlayPadPluginStub with SettingsListener with ProfileListener {
+
+	private var module: Module = _
+
+	override def startup(descriptor: PluginDescriptor): Unit = {
+		module = new Module(descriptor.getName, descriptor.getArtifactId)
+
+		val localization = Localization.loadBundle("lang/base", getClass.getClassLoader)
+		Localization.addResourceBundle(localization)
+
+		PlayPadPlugin.getRegistries.getPadContents.loadComponentsFromFile("PadContent.xml", getClass.getClassLoader, module, localization)
+		PlayPadPlugin.getInstance().addAdditionalProfileSettingsTab(() => new ZoneSettingsViewController)
+
+		PlayPadPlugin.getInstance().addSettingsListener(this)
+		Profile.registerListener(this)
+	}
+
+	override def shutdown(): Unit = {
+		ContentPluginMain.playerViewController.getStageContainer.ifPresent(container => container.forceClose())
+	}
+
+	override def getModule: Module = module
+
+	override def onLoad(profile: Profile): Unit = {
+		val path = profile.getRef.getCustomFilePath("Zones.json")
+		val zoneConfiguration = Storage.load(path, StorageTypes.JSON, classOf[ZoneConfiguration])
+		profile.addCustomSettings(ContentPluginMain.zoneConfigurationKey, zoneConfiguration)
+	}
+
+	override def onSave(profile: Profile): Unit = {
+		val path = profile.getRef.getCustomFilePath("Zones.json")
+		val zoneConfigurationObject = profile.getCustomSettings(ContentPluginMain.zoneConfigurationKey)
+		if (zoneConfigurationObject != null) {
+			Storage.save(path, StorageTypes.JSON, zoneConfigurationObject)
+		}
+	}
+
+	override def reloadSettings(oldProfile: Profile, currentProfile: Profile): Unit = {
+		val zoneConfiguration = currentProfile.getCustomSettings(ContentPluginMain.zoneConfigurationKey).asInstanceOf[ZoneConfiguration]
+		Platform.runLater(() => ContentPluginMain.playerViewController.configurePlayers(zoneConfiguration))
+	}
+}
+
+object ContentPluginMain {
+	lazy val playerViewController: ContentPlayerViewController = new ContentPlayerViewController
+
+	val zoneConfigurationKey = "ZoneConfiguration"
+}
\ No newline at end of file
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerMediaContainer.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerMediaContainer.scala
new file mode 100644
index 0000000000000000000000000000000000000000..3c298dcbfb2fcf167ef3d682cf03bb71c3d6c9da
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerMediaContainer.scala
@@ -0,0 +1,57 @@
+package de.tobias.playpad.plugin.content.pad
+
+import de.tobias.playpad.pad.PadStatus
+import de.tobias.playpad.pad.mediapath.MediaPath
+import de.tobias.playpad.plugin.content.ContentPluginMain
+import de.tobias.playpad.plugin.content.util._
+import javafx.scene.media.MediaPlayer
+import javafx.util.Duration
+
+class ContentPlayerMediaContainer(val content: ContentPlayerPadContent, val path: MediaPath, val mediaPlayer: MediaPlayer) {
+	def play(): Unit = {
+		content._durationProperty.bind(mediaPlayer.totalDurationProperty())
+		content._positionProperty.bind(mediaPlayer.currentTimeProperty())
+		ContentPluginMain.playerViewController.showMediaPlayer(content.getPad.getPadIndex, mediaPlayer, content.getSelectedZones)
+
+		mediaPlayer.seek(Duration.ZERO)
+		mediaPlayer.play()
+
+		content.getPad.setEof(false)
+		content.currentPlayingMediaIndexProperty().set(content.getMediaPlayers.indexOf(this))
+	}
+
+	def resume(): Unit = {
+		mediaPlayer.play()
+	}
+
+	def pause(): Unit = {
+		mediaPlayer.pause()
+	}
+
+	def next(): Unit = {
+		stop()
+
+		val players = content.getMediaPlayers
+		val index = players.indexOf(this)
+		content.currentPlayingMediaIndexProperty().set(index)
+
+		if (index + 1 < players.length) {
+			players(index + 1).play()
+		} else if (content.getPad.getPadSettings.isLoop) {
+			players.head.play()
+		} else {
+			content.getPad.setStatus(PadStatus.STOP)
+		}
+	}
+
+	def stop(): Unit = {
+		mediaPlayer.stop()
+		ContentPluginMain.playerViewController.disconnectMediaPlayer(mediaPlayer, content.getSelectedZones)
+
+		content._durationProperty.bind(content.totalDurationBinding())
+		content._positionProperty.unbind()
+		content._positionProperty.set(Duration.ZERO)
+	}
+
+	override def toString: String = f"MediaPlayerContainer: $path"
+}
\ No newline at end of file
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContent.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContent.scala
new file mode 100644
index 0000000000000000000000000000000000000000..c1db519a17b8119362c64e7385ba26d91f2b9a40
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContent.scala
@@ -0,0 +1,322 @@
+package de.tobias.playpad.plugin.content.pad
+
+import de.thecodelabs.logger.Logger
+import de.tobias.playpad.pad.content.play.{Durationable, Pauseable}
+import de.tobias.playpad.pad.content.{PadContent, Playlistable}
+import de.tobias.playpad.pad.fade.{Fadeable, LinearFadeController}
+import de.tobias.playpad.pad.mediapath.MediaPath
+import de.tobias.playpad.pad.{Pad, PadStatus}
+import de.tobias.playpad.plugin.content.ContentPluginMain
+import de.tobias.playpad.plugin.content.settings.{Zone, ZoneConfiguration}
+import de.tobias.playpad.plugin.content.util._
+import de.tobias.playpad.profile.Profile
+import de.tobias.playpad.volume.VolumeManager
+import javafx.application.Platform
+import javafx.beans.binding.{Bindings, ObjectBinding}
+import javafx.beans.property._
+import javafx.collections.{FXCollections, ObservableList}
+import javafx.scene.media.{Media, MediaPlayer}
+import javafx.util.Duration
+
+import java.nio.file.Files
+import java.util
+import java.util.Optional
+import java.util.stream.Collectors
+import scala.jdk.CollectionConverters._
+
+class ContentPlayerPadContent(val pad: Pad, val `type`: String) extends PadContent(pad) with Pauseable with Durationable with Playlistable with Fadeable {
+
+	private val mediaPlayers: ObservableList[ContentPlayerMediaContainer] = FXCollections.observableArrayList()
+	private val currentRunningIndexProperty: IntegerProperty = new SimpleIntegerProperty(-1)
+
+	private[pad] val _durationProperty = new SimpleObjectProperty[Duration]
+	private[pad] val _positionProperty = new SimpleObjectProperty[Duration]
+
+	private var showingLastFrame: Boolean = false
+	private var isPause: Boolean = false
+
+	private val fadeController = new LinearFadeController(value => {
+		if (getCurrentPlayingMediaIndex >= 0) {
+			ContentPluginMain.playerViewController
+				.setFadeValue(mediaPlayers(getCurrentPlayingMediaIndex).mediaPlayer, getSelectedZones, value)
+		}
+	})
+
+	override def getType: String = `type`
+
+	override def getCurrentPlayingMediaIndex: Int = currentRunningIndexProperty.get()
+
+	override def currentPlayingMediaIndexProperty(): IntegerProperty = currentRunningIndexProperty
+
+	def getMediaPlayers: ObservableList[ContentPlayerMediaContainer] = mediaPlayers
+
+	override def hasNext: Boolean = getCurrentPlayingMediaIndex + 1 < mediaPlayers.length
+
+	/*
+	Control Methods
+	 */
+
+	override def play(): Unit = {
+		if (isPause) {
+			mediaPlayers(getCurrentPlayingMediaIndex).resume()
+		} else {
+			ContentPluginMain.playerViewController.addActivePadToList(getPad.getPadIndex, getSelectedZones)
+
+			getPad.setEof(false)
+			mediaPlayers.head.play()
+		}
+		showingLastFrame = false
+		isPause = false
+	}
+
+	override def pause(): Unit = {
+		isPause = true
+		mediaPlayers(getCurrentPlayingMediaIndex).pause()
+	}
+
+	override def next(): Unit = {
+		mediaPlayers(getCurrentPlayingMediaIndex).next()
+	}
+
+	override def stop(): Boolean = {
+		isPause = false
+		mediaPlayers(getCurrentPlayingMediaIndex).stop()
+		currentRunningIndexProperty.set(-1)
+
+		ContentPluginMain.playerViewController.removeActivePadFromList(getPad.getPadIndex, getSelectedZones)
+		true
+	}
+
+	def onEof(): Unit = {
+		if (isFadeActive) {
+			ContentPluginMain.playerViewController.removeActivePadFromList(getPad.getPadIndex, getSelectedZones)
+			return
+		}
+
+		if (shouldShowLastFrame() && !showingLastFrame // Only is settings is enabled and not already in last frame state
+			&& !pad.getPadSettings.isLoop // Only go to last frame state, is looping is disabled
+		) {
+			getPad.setStatus(PadStatus.PAUSE)
+			showingLastFrame = true
+			return
+		}
+
+		showingLastFrame = false
+
+		if (getPad.isEof) {
+			mediaPlayers(getCurrentPlayingMediaIndex).next()
+			return
+		}
+	}
+
+	/*
+	Durationable
+	 */
+
+	override def getDuration: Duration = _durationProperty.get()
+
+	override def getPosition: Duration = _positionProperty.get()
+
+	override def durationProperty(): ReadOnlyObjectProperty[Duration] = _durationProperty
+
+	override def positionProperty(): ReadOnlyObjectProperty[Duration] = _positionProperty
+
+	def totalDurationBinding(): ObjectBinding[Duration] = {
+		Bindings.createObjectBinding(() => mediaPlayers.stream()
+			.map(player => player.mediaPlayer.getTotalDuration)
+			.filter(duration => duration != null)
+			.reduce(Duration.ZERO, (o1: Duration, o2: Duration) => o1.add(o2)),
+			mediaPlayers.stream().map(player => {
+				if (player.mediaPlayer != null) {
+					player.mediaPlayer.totalDurationProperty()
+				} else {
+					null
+				}
+			})
+				.filter(o => o != null)
+				.toArray(size => new Array[ReadOnlyObjectProperty[Duration]](size)): _*)
+	}
+
+	/*
+	Fadeable
+	 */
+
+	override def fadeIn(): Unit = {
+		val fadeIn = getPad.getPadSettings.getFade.getFadeIn
+		if (fadeIn.toMillis > 0) {
+			fadeController.fadeIn(fadeIn)
+		}
+	}
+
+	override def fadeOut(onFinish: Runnable): Unit = {
+		val fadeOut = getPad.getPadSettings.getFade.getFadeOut
+		if (fadeOut.toMillis > 0) {
+			fadeController.fadeOut(fadeOut, () => {
+				if (onFinish != null) onFinish.run()
+
+				if (getPad.getStatus == PadStatus.PLAY) {
+					getPad.setStatus(PadStatus.STOP)
+				}
+			})
+		}
+		else {
+			onFinish.run()
+		}
+	}
+
+	override def isFadeActive: Boolean = fadeController.isFading
+
+	override def fade(from: Double, to: Double, duration: Duration, onFinish: Runnable): Unit = {
+		fadeController.fade(from, to, duration, onFinish)
+	}
+
+	/*
+	Loading
+	 */
+
+	override def isPadLoaded: Boolean = {
+		mediaPlayers.isNotEmpty && !mediaPlayers.stream().anyMatch(player => player.mediaPlayer.getStatus == MediaPlayer.Status.UNKNOWN)
+	}
+
+	override def isLoaded(mediaPath: MediaPath): Boolean = {
+		val loadedOptional: Optional[Boolean] = mediaPlayers.stream()
+			.filter(item => item.path == mediaPath)
+			.findFirst()
+			.map(container => container.mediaPlayer.getStatus != MediaPlayer.Status.UNKNOWN)
+		loadedOptional.orElse(false)
+	}
+
+
+	override def isPadLoading: Boolean = mediaPlayers.stream().anyMatch(player => player.mediaPlayer.getStatus == MediaPlayer.Status.UNKNOWN)
+
+	/**
+	 * Load media files.
+	 */
+	override def loadMedia(): Unit = {
+		mediaPlayers.clear()
+		getPad.getPaths.forEach(loadMedia(_))
+	}
+
+	/**
+	 * Load media file.
+	 *
+	 * @param mediaPath specify media path
+	 */
+	override def loadMedia(mediaPath: MediaPath): Unit = {
+		val path = mediaPath.getPath
+		if (Files.notExists(path)) {
+			Platform.runLater(() => getPad.setStatus(PadStatus.NOT_FOUND))
+			return
+		}
+
+		val media = new Media(path.toUri.toString)
+		val mediaPlayer = new MediaPlayer(media)
+
+		mediaPlayer.setOnReady(() => {
+			getPad.setStatus(PadStatus.READY)
+
+			_durationProperty.bind(totalDurationBinding())
+			_positionProperty.set(Duration.ZERO)
+
+			Platform.runLater(() => {
+				if (getPad.isPadVisible) {
+					getPad.getController.getView.showBusyView(false)
+				}
+			})
+		})
+
+		mediaPlayer.errorProperty().addListener((_, _, newValue) => Platform.runLater(() => {
+			Logger.error(newValue)
+			pad.setStatus(PadStatus.ERROR)
+		}))
+		mediaPlayer.setOnError(() => Platform.runLater(() => {
+			if (getPad.isPadVisible) {
+				getPad.getController.getView.showBusyView(false)
+			}
+			Logger.error(mediaPlayer.getError)
+			pad.setStatus(PadStatus.ERROR)
+		}))
+
+		mediaPlayer.setOnEndOfMedia(() => {
+			getPad.setEof(true)
+			onEof()
+		})
+
+		mediaPlayers.add(new ContentPlayerMediaContainer(this, mediaPath, mediaPlayer))
+	}
+
+	/**
+	 * Unload media files.
+	 */
+	override def unloadMedia(): Unit = {
+		if ((getPad.getStatus eq PadStatus.PLAY) || (getPad.getStatus eq PadStatus.PAUSE)) getPad.setStatus(PadStatus.STOP)
+
+		mediaPlayers.clear()
+
+		Platform.runLater(() => {
+			if (getPad != null) {
+				getPad.setStatus(PadStatus.EMPTY)
+			}
+		})
+	}
+
+	/**
+	 * Unload media file.
+	 *
+	 * @param mediaPath specify media path
+	 */
+	override def unloadMedia(mediaPath: MediaPath): Unit = {
+		val index = mediaPlayers.indexWhere(item => item.path.getId == mediaPath.getId)
+
+		if (index >= 0) {
+			val playerContainer = mediaPlayers(index)
+			playerContainer.stop()
+			mediaPlayers.remove(index)
+		}
+	}
+
+	override def reorderMedia(): Unit = {
+		val paths = pad.getPaths
+		mediaPlayers.sort((o1, o2) => Integer.compare(paths.indexOf(o1.path), paths.indexOf(o2.path)))
+	}
+
+	/*
+	 Volume
+	 */
+
+	override def updateVolume(): Unit = {
+		val volume = VolumeManager.getInstance.computeVolume(getPad)
+		mediaPlayers.forEach(player => player.mediaPlayer.setVolume(volume))
+	}
+
+	/**
+	 * Create a copy of the PadContent instance
+	 *
+	 * @param pad target pad
+	 * @return copied content
+	 */
+	override def copy(pad: Pad): PadContent = {
+		val clone = new ContentPlayerPadContent(pad, getType)
+		clone.loadMedia()
+		clone
+	}
+
+	/*
+	Custom Settings
+	 */
+
+	def shouldShowLastFrame(): Boolean = {
+		pad.getPadSettings.getCustomSettings.getOrDefault(ContentPlayerPadContentFactory.lastFrame, false).asInstanceOf[Boolean]
+	}
+
+	def getSelectedZones: Seq[Zone] = {
+		val zoneConfiguration = Profile.currentProfile().getCustomSettings(ContentPluginMain.zoneConfigurationKey).asInstanceOf[ZoneConfiguration]
+
+		val customSettings = pad.getPadSettings.getCustomSettings
+		val selectedZoneNames = customSettings.getOrDefault(
+			ContentPlayerPadContentFactory.zones,
+			zoneConfiguration.zones.stream().map(zone => zone.getName).collect(Collectors.toList())
+		).asInstanceOf[util.List[String]]
+		zoneConfiguration.zones.asScala.filter(zone => selectedZoneNames.contains(zone.getName)).toSeq
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContentFactory.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContentFactory.scala
new file mode 100644
index 0000000000000000000000000000000000000000..d08958d5da016d424a9204a12317b8fbade30f93
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContentFactory.scala
@@ -0,0 +1,25 @@
+package de.tobias.playpad.plugin.content.pad
+
+import de.tobias.playpad.pad.Pad
+import de.tobias.playpad.pad.content.{PadContent, PadContentFactory}
+import de.tobias.playpad.pad.view.IPadContentView
+import de.tobias.playpad.viewcontroller.PadSettingsTabViewController
+import javafx.scene.layout.Pane
+
+class ContentPlayerPadContentFactory(val `type`: String) extends PadContentFactory(`type`) {
+
+	override def newInstance(pad: Pad): PadContent = new ContentPlayerPadContent(pad, getType)
+
+	override def getPadContentPreview(pad: Pad, parentNode: Pane): IPadContentView = new ContentPlayerPadPreview(pad, parentNode)
+
+	override def getSettingsViewController(pad: Pad): PadSettingsTabViewController = new ContentPlayerPadContentSettingsViewController(pad)
+
+	override def getSupportedTypes: Array[String] = ContentPlayerPadContentFactory.FILE_EXTENSION
+}
+
+object ContentPlayerPadContentFactory {
+	private val FILE_EXTENSION = Array("*.mp4", "*.mov")
+
+	val lastFrame = "ContentLastFrame"
+	val zones = "zones"
+}
\ No newline at end of file
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContentSettingsViewController.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContentSettingsViewController.scala
new file mode 100644
index 0000000000000000000000000000000000000000..14d5e0ee477047de962dfd5959c2ee67d0a9c1c8
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContentSettingsViewController.scala
@@ -0,0 +1,73 @@
+package de.tobias.playpad.plugin.content.pad
+
+import java.util
+
+import de.thecodelabs.utils.util.Localization
+import de.tobias.playpad.pad.Pad
+import de.tobias.playpad.plugin.content.ContentPluginMain
+import de.tobias.playpad.plugin.content.settings.{Zone, ZoneConfiguration}
+import de.tobias.playpad.profile.Profile
+import de.tobias.playpad.viewcontroller.PadSettingsTabViewController
+import javafx.beans.binding.Bindings
+import javafx.fxml.FXML
+import javafx.scene.control.{Button, CheckBox}
+import org.controlsfx.control.CheckListView
+
+import scala.jdk.CollectionConverters._
+
+class ContentPlayerPadContentSettingsViewController(val pad: Pad) extends PadSettingsTabViewController {
+
+	@FXML
+	var lastFrameCheckbox: CheckBox = _
+	@FXML
+	var zoneListView: CheckListView[Zone] = _
+
+	@FXML
+	var addAllZonesButton: Button = _
+	@FXML
+	var removeAllZonesButton: Button = _
+
+	load("view", "ContentPadSettings", Localization.getBundle)
+
+	override def init(): Unit = {
+		val zoneConfiguration = Profile.currentProfile().getCustomSettings(ContentPluginMain.zoneConfigurationKey).asInstanceOf[ZoneConfiguration]
+		zoneListView.getItems.addAll(zoneConfiguration.zones)
+
+		addAllZonesButton.disableProperty().bind(Bindings.equal(Bindings.size(zoneListView.getCheckModel.getCheckedIndices), zoneListView.getItems.size()))
+		removeAllZonesButton.disableProperty().bind(Bindings.isEmpty(zoneListView.getCheckModel.getCheckedIndices))
+	}
+
+	override def getName: String = Localization.getString("plugin.content.player.settings")
+
+	override def loadSettings(pad: Pad): Unit = {
+		val customSettings = pad.getPadSettings.getCustomSettings
+		val lastFrameOption = customSettings.get(ContentPlayerPadContentFactory.lastFrame)
+		if (lastFrameOption != null) {
+			lastFrameCheckbox.setSelected(lastFrameOption.toString.toBoolean)
+		}
+
+		pad.getContent match {
+			case content: ContentPlayerPadContent =>
+				content.getSelectedZones.foreach(item => zoneListView.getCheckModel.check(item))
+			case _ =>
+		}
+	}
+
+	override def saveSettings(pad: Pad): Unit = {
+		val customSettings = pad.getPadSettings.getCustomSettings
+		customSettings.put(ContentPlayerPadContentFactory.lastFrame, lastFrameCheckbox.isSelected)
+
+		val selectedZoneNames = zoneListView.getCheckModel.getCheckedItems.asScala.map(zone => zone.getName)
+		customSettings.put(ContentPlayerPadContentFactory.zones, new util.ArrayList(selectedZoneNames.asJavaCollection))
+	}
+
+	@FXML
+	def onAddAllZonesHandler(): Unit = {
+		zoneListView.getCheckModel.checkAll()
+	}
+
+	@FXML
+	def onRemoveAllZonesHandler(): Unit = {
+		zoneListView.getCheckModel.clearChecks()
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadPreview.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadPreview.scala
new file mode 100644
index 0000000000000000000000000000000000000000..6ff298194c1ec57c2f6e7262b8c1c96db6498476
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadPreview.scala
@@ -0,0 +1,68 @@
+package de.tobias.playpad.plugin.content.pad
+
+import de.thecodelabs.utils.io.PathUtils
+import de.tobias.playpad.pad.Pad
+import de.tobias.playpad.pad.view.IPadContentView
+import javafx.beans.binding.Bindings
+import javafx.collections.ListChangeListener
+import javafx.geometry.{Insets, Pos}
+import javafx.scene.Parent
+import javafx.scene.control.Label
+import javafx.scene.layout.{Pane, Priority, VBox}
+import javafx.scene.text.TextAlignment
+
+class ContentPlayerPadPreview(pad: Pad, parent: Pane) extends VBox with IPadContentView {
+
+	val nameLabel: Label = new Label()
+	val subTitleLabel: Label = new Label()
+
+	setupLabel(nameLabel)
+	setupLabel(subTitleLabel)
+
+	getChildren.addAll(nameLabel, subTitleLabel)
+	setSpacing(3)
+	setPadding(new Insets(7))
+
+	getStyleClass.addListener(new ListChangeListener[String] {
+		override def onChanged(c: ListChangeListener.Change[_ <: String]): Unit = {
+			while (c.next()) {
+				if (c.wasRemoved()) {
+					nameLabel.getStyleClass.removeAll(c.getRemoved)
+					subTitleLabel.getStyleClass.removeAll(c.getRemoved)
+				}
+
+				if (c.wasAdded()) {
+					nameLabel.getStyleClass.addAll(c.getAddedSubList)
+					subTitleLabel.getStyleClass.addAll(c.getAddedSubList)
+				}
+			}
+		}
+	})
+
+	nameLabel.textProperty.bind(pad.nameProperty)
+	pad.getContent match {
+		case content: ContentPlayerPadContent =>
+			subTitleLabel.textProperty().bind(Bindings.createStringBinding(() => {
+				if (content.getCurrentPlayingMediaIndex < 0) "" else PathUtils.getFilenameWithoutExtension(pad.getPaths.get(content.getCurrentPlayingMediaIndex).getPath.getFileName)
+			}, content.currentPlayingMediaIndexProperty()))
+		case _ =>
+	}
+
+	private def setupLabel(label: Label): Unit = {
+		label.setWrapText(true)
+		label.setAlignment(Pos.CENTER)
+		label.setTextAlignment(TextAlignment.CENTER)
+
+		label.prefWidthProperty.bind(parent.widthProperty)
+		label.setMaxHeight(Double.MaxValue)
+
+		VBox.setVgrow(label, Priority.ALWAYS)
+	}
+
+	override def getNode: Parent = this
+
+	override def deInit(): Unit = {
+		nameLabel.textProperty().unbind()
+		subTitleLabel.textProperty().unbind()
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/player/ContentPlayerViewController.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/player/ContentPlayerViewController.scala
new file mode 100644
index 0000000000000000000000000000000000000000..c659e296cd880469fcae5e27ca2f5b193fad0258
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/player/ContentPlayerViewController.scala
@@ -0,0 +1,118 @@
+package de.tobias.playpad.plugin.content.player
+
+import de.thecodelabs.logger.Logger
+import de.thecodelabs.utils.ui.size.IgnoreStageSizing
+import de.thecodelabs.utils.ui.{NVC, NVCStage}
+import de.tobias.playpad.PlayPadPlugin
+import de.tobias.playpad.plugin.content.settings.{Zone, ZoneConfiguration}
+import de.tobias.playpad.project.page.PadIndex
+import javafx.geometry.Insets
+import javafx.scene.layout._
+import javafx.scene.media.MediaPlayer
+import javafx.scene.paint.Color
+import javafx.stage.{Stage, StageStyle}
+
+import scala.collection.mutable.ListBuffer
+
+@IgnoreStageSizing
+class ContentPlayerViewController extends NVC {
+
+	private val mediaStacks: ListBuffer[MediaPlayerStack] = ListBuffer.empty
+
+	load("view", "PlayerView")
+	private val stageContainer: NVCStage = applyViewControllerToStage
+	stageContainer.addCloseHook(() => false)
+
+	Logger.debug("Create Player View Controller")
+
+	override def init(): Unit = {
+		val parent = getParent.asInstanceOf[Pane]
+		parent.setBackground(new Background(new BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY)))
+	}
+
+	override def initStage(stage: Stage): Unit = {
+		super.initStage(stage)
+		stage.initStyle(StageStyle.UNDECORATED)
+		stage.setAlwaysOnTop(true)
+
+		stage.getScene.setFill(Color.BLACK)
+		stage.getIcons.add(PlayPadPlugin.getInstance().getIcon)
+	}
+
+	def showMediaPlayer(padIndex: PadIndex, mediaPlayer: MediaPlayer, zones: Seq[Zone]): Unit = {
+		val iterator = this.mediaStacks.iterator
+		while (iterator.hasNext) {
+			val mediaPlayerStack = iterator.next()
+			if (zones.contains(mediaPlayerStack.zone)) {
+				mediaPlayerStack.showMediaPlayer(padIndex, mediaPlayer)
+			}
+		}
+	}
+
+	def disconnectMediaPlayer(mediaPlayer: MediaPlayer, zones: Seq[Zone]): Unit = {
+		val iterator = this.mediaStacks.iterator
+		while (iterator.hasNext) {
+			val mediaPlayerStack = iterator.next()
+			if (zones.contains(mediaPlayerStack.zone)) {
+				mediaPlayerStack.disconnectMediaPlayer(mediaPlayer)
+			}
+		}
+	}
+
+	def configurePlayers(configuration: ZoneConfiguration): Unit = {
+		if (configuration.zones.isEmpty) {
+			closeStage()
+			return
+		}
+
+		val parent = getParent.asInstanceOf[Pane]
+		parent.getChildren.clear()
+
+		mediaStacks.clear()
+		configuration.zones.forEach(player => {
+			val mediaPlayerStack = new MediaPlayerStack(player)
+			mediaStacks.addOne(mediaPlayerStack)
+			parent.getChildren.add(mediaPlayerStack)
+		})
+
+		showStage()
+
+		getStageContainer.ifPresent(container => {
+			val stage = container.getStage
+
+			import scala.jdk.CollectionConverters._
+			val zones = configuration.zones.asScala
+			val maxWidth = zones.map(player => player.x + player.width).max
+			val maxHeight = zones.map(player => player.y + player.height).max
+
+			stage.setX(0)
+			stage.setY(0)
+			stage.setWidth(maxWidth)
+			stage.setHeight(maxHeight)
+		})
+	}
+
+	def addActivePadToList(padIndex: PadIndex, zones: Seq[Zone]): Unit = getMediaStacks(zones)
+		.foreach(mediaStack => mediaStack.addActivePad(padIndex))
+
+	def removeActivePadFromList(padIndex: PadIndex, zones: Seq[Zone]): Unit = getMediaStacks(zones)
+		.foreach(mediaStack => mediaStack.removeActivePad(padIndex))
+
+	def highlight(zone: Zone, on: Boolean): Unit = {
+		if (getMediaStack(zone).isEmpty) {
+			return
+		}
+		getMediaStack(zone).head.highlight(on)
+	}
+
+	def setFadeValue(mediaPlayer: MediaPlayer, zones: Seq[Zone], value: Double): Unit = getMediaStacks(zones)
+		.foreach(mediaStack => mediaStack.setFadeValue(mediaPlayer, value))
+
+	private def getMediaStack(zone: Zone): ListBuffer[MediaPlayerStack] = {
+		getMediaStacks(List(zone))
+	}
+
+	private def getMediaStacks(zones: Seq[Zone]): ListBuffer[MediaPlayerStack] = {
+		mediaStacks.filter(mediaPlayer => zones.contains(mediaPlayer.zone))
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/player/MediaPlayerStack.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/player/MediaPlayerStack.scala
new file mode 100644
index 0000000000000000000000000000000000000000..15d3872130e3fe4b1d32c3ff3d67f11329a70c6d
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/player/MediaPlayerStack.scala
@@ -0,0 +1,78 @@
+package de.tobias.playpad.plugin.content.player
+
+import java.util.stream.Collectors
+
+import de.thecodelabs.logger.Logger
+import de.tobias.playpad.plugin.content.settings.Zone
+import de.tobias.playpad.project.page.PadIndex
+import javafx.geometry.Insets
+import javafx.scene.layout.{Background, BackgroundFill, CornerRadii, StackPane}
+import javafx.scene.media.{MediaPlayer, MediaView}
+import javafx.scene.paint.Color
+
+import scala.collection.mutable
+import scala.collection.mutable.ListBuffer
+
+class MediaPlayerStack(val zone: Zone) extends StackPane {
+
+	private var activePlayers: ListBuffer[PadIndex] = ListBuffer.empty
+	val mediaViews: mutable.Map[MediaPlayer, MediaView] = new mutable.HashMap[MediaPlayer, MediaView]()
+
+	setLayoutX(zone.x)
+	setLayoutY(zone.y)
+	setMinWidth(zone.width)
+	setMaxWidth(zone.width)
+	setMinHeight(zone.height)
+	setMaxHeight(zone.height)
+
+	def addActivePad(padIndex: PadIndex): Unit = activePlayers.addOne(padIndex)
+
+	def removeActivePad(padIndex: PadIndex): Unit = activePlayers = activePlayers.filter(element => element != padIndex)
+
+	def showMediaPlayer(padIndex: PadIndex, mediaPlayer: MediaPlayer): Unit = {
+		if (!mediaViews.contains(mediaPlayer)) {
+			val mediaView = new MediaView(mediaPlayer)
+			mediaView.setFitWidth(zone.width)
+			mediaView.setFitHeight(zone.height)
+			mediaViews.put(mediaPlayer, mediaView)
+		}
+
+		val mediaView = mediaViews(mediaPlayer)
+		mediaView.setUserData(padIndex)
+		mediaView.setOpacity(1.0)
+
+		if (!getChildren.contains(mediaView)) {
+			val index = activePlayers.indexOf(padIndex)
+			try {
+				getChildren.add(index, mediaView)
+			} catch {
+				case e: Exception =>
+					Logger.error(e)
+					getChildren.add(mediaView)
+			}
+		}
+	}
+
+	def disconnectMediaPlayer(mediaPlayer: MediaPlayer): Unit = {
+		if (mediaViews.contains(mediaPlayer)) {
+			getChildren.remove(mediaViews(mediaPlayer))
+		}
+	}
+
+	def setFadeValue(mediaPlayer: MediaPlayer, value: Double): Unit = {
+		if (mediaViews.contains(mediaPlayer)) {
+			val mediaView = mediaViews(mediaPlayer)
+			mediaView.setOpacity(value)
+		}
+	}
+
+	def highlight(on: Boolean): Unit = {
+		if (on) {
+			setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)))
+		} else {
+			setBackground(null)
+		}
+	}
+
+	override def toString: String = f"MediaPlayerStack: ${getChildren.stream().map(view => f"MediaView: ${view.getUserData}").collect(Collectors.joining(", "))}"
+}
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/settings/ZoneConfiguration.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/settings/ZoneConfiguration.scala
new file mode 100644
index 0000000000000000000000000000000000000000..956a0183c9eafa8245a6565558bf85aeaa176e4c
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/settings/ZoneConfiguration.scala
@@ -0,0 +1,43 @@
+package de.tobias.playpad.plugin.content.settings
+
+import java.util
+import java.util.{List => JavaList}
+
+import de.thecodelabs.storage.settings.annotation.{FilePath, Key}
+import de.tobias.playpad.Displayable
+import javafx.beans.property.{SimpleStringProperty, StringProperty}
+
+@FilePath("players.json")
+class ZoneConfiguration {
+	@Key
+	var zones: JavaList[Zone] = new util.ArrayList[Zone]()
+}
+
+class Zone extends Displayable {
+	@Key
+	private var name: String = _
+	@Key
+	var x: Double = _
+	@Key
+	var y: Double = _
+	@Key
+	var width: Double = _
+	@Key
+	var height: Double = _
+
+	def getName: String = name
+
+	def setName(name: String): Unit = {
+		this.name = name
+		_displayProperty.set(name)
+	}
+
+	private val _displayProperty: StringProperty = new SimpleStringProperty(name)
+
+	override def displayProperty(): StringProperty = {
+		_displayProperty.set(name)
+		_displayProperty
+	}
+
+	override def toString: String = name
+}
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/settings/ZoneSettingsViewController.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/settings/ZoneSettingsViewController.scala
new file mode 100644
index 0000000000000000000000000000000000000000..bae668ff818ef49c8b463df091ccea02bffdb6f4
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/settings/ZoneSettingsViewController.scala
@@ -0,0 +1,134 @@
+package de.tobias.playpad.plugin.content.settings
+
+import de.thecodelabs.utils.ui.scene.input.NumberTextField
+import de.thecodelabs.utils.util.Localization
+import de.tobias.playpad.plugin.content.ContentPluginMain
+import de.tobias.playpad.profile.{Profile, ProfileSettings}
+import de.tobias.playpad.project.Project
+import de.tobias.playpad.viewcontroller.main.IMainViewController
+import de.tobias.playpad.viewcontroller.option.{IProfileReloadTask, ProfileSettingsTabViewController}
+import javafx.application.Platform
+import javafx.fxml.FXML
+import javafx.scene.control.{Button, ListCell, ListView, TextField}
+
+class ZoneSettingsViewController extends ProfileSettingsTabViewController with IProfileReloadTask {
+
+	@FXML
+	var listView: ListView[Zone] = _
+
+	@FXML
+	var nameTextField: TextField = _
+	@FXML
+	var xTextField: NumberTextField = _
+	@FXML
+	var yTextField: NumberTextField = _
+	@FXML
+	var widthTextField: NumberTextField = _
+	@FXML
+	var heightTextField: NumberTextField = _
+
+	@FXML
+	var addButton: Button = _
+	@FXML
+	var removeButton: Button = _
+
+	load("view", "ZoneSettings", Localization.getBundle)
+
+	override def init(): Unit = {
+		listView.setCellFactory((_: ListView[Zone]) => new ListCell[Zone] {
+			override def updateItem(item: Zone, empty: Boolean): Unit = {
+				super.updateItem(item, empty)
+				if (!empty) {
+					textProperty().bind(item.displayProperty())
+				} else {
+					textProperty().unbind()
+					setText("")
+				}
+			}
+		})
+		listView.getSelectionModel.selectedItemProperty().addListener((_, oldValue, newValue) => {
+			val playerViewController = ContentPluginMain.playerViewController
+
+			if (oldValue != null) {
+				saveSettingsToZone(oldValue)
+				playerViewController.highlight(oldValue, on = false)
+			}
+			if (newValue != null) {
+				showSettingsOfZone(newValue)
+				playerViewController.highlight(newValue, on = true)
+			} else {
+				clearTextFields()
+			}
+		})
+	}
+
+	private def saveSettingsToZone(zone: Zone): Unit = {
+		zone.setName(nameTextField.getText)
+		zone.x = xTextField.getText.toDouble
+		zone.y = yTextField.getText.toDouble
+		zone.width = widthTextField.getText.toDouble
+		zone.height = heightTextField.getText.toDouble
+	}
+
+	private def showSettingsOfZone(zone: Zone): Unit = {
+		nameTextField.setText(zone.getName)
+		xTextField.setText(zone.x.toInt.toString)
+		yTextField.setText(zone.y.toInt.toString)
+		widthTextField.setText(zone.width.toInt.toString)
+		heightTextField.setText(zone.height.toInt.toString)
+	}
+
+	private def clearTextFields(): Unit = {
+		nameTextField.setText("")
+		xTextField.setText("")
+		yTextField.setText("")
+		widthTextField.setText("")
+		heightTextField.setText("")
+	}
+
+	// Actions
+	@FXML
+	def onAddHandle(): Unit = {
+		val newConfiguration = new Zone
+		newConfiguration.setName(Localization.getString("plugin.content.player.settings.default_name"))
+
+		getZoneConfiguration.zones.add(newConfiguration)
+		listView.getItems.add(newConfiguration)
+	}
+
+	@FXML
+	def onRemoveHandle(): Unit = {
+		val selectedItem = listView.getSelectionModel.getSelectedItem
+		if (selectedItem != null) {
+			listView.getItems.remove(selectedItem)
+			getZoneConfiguration.zones.remove(selectedItem)
+		}
+	}
+
+	override def loadSettings(settings: Profile): Unit = {
+		listView.getItems.setAll(getZoneConfiguration.zones)
+	}
+
+	override def saveSettings(settings: Profile): Unit = {
+		val selectedItem = listView.getSelectionModel.getSelectedItem
+		if (selectedItem != null) {
+			saveSettingsToZone(selectedItem)
+		}
+	}
+
+	override def needReload(): Boolean = {
+		true
+	}
+
+	override def validSettings(): Boolean = {
+		true
+	}
+
+	override def name(): String = Localization.getString("plugin.content.player.settings")
+
+
+	override def getTask(settings: ProfileSettings, project: Project, controller: IMainViewController): Runnable = () =>
+		Platform.runLater(() => ContentPluginMain.playerViewController.configurePlayers(getZoneConfiguration))
+
+	private def getZoneConfiguration: ZoneConfiguration = Profile.currentProfile().getCustomSettings(ContentPluginMain.zoneConfigurationKey).asInstanceOf[ZoneConfiguration]
+}
diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/util/package.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/util/package.scala
new file mode 100644
index 0000000000000000000000000000000000000000..22836f6b9326accde9478b56a7e65861ff3e5fb3
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/util/package.scala
@@ -0,0 +1,31 @@
+package de.tobias.playpad.plugin.content
+
+import javafx.collections.ObservableList
+
+package object util {
+
+	implicit class ObservableListExtension[E >: Null](list: ObservableList[E]) {
+		def head: E = {
+			if (list.isEmpty) {
+				return null
+			}
+
+			list.get(0)
+		}
+
+		def apply(index: Int): E = list.get(index)
+
+		def length: Long = list.size()
+
+		def isNotEmpty: Boolean = !list.isEmpty
+
+		def indexWhere(predicate: E => Boolean): Int = {
+			for (i <- 0 until list.size()) {
+				if (predicate(list.get(i))) {
+					return i
+				}
+			}
+			-1
+		}
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginEqualizer/pom.xml b/PlayWallPlugins/PlayWallPluginEqualizer/pom.xml
index 1256a10cbe09899239a41d8c2bc2fe2f6d3135a0..2e1be5a7b2293b617048c7d311c779003afabad2 100644
--- a/PlayWallPlugins/PlayWallPluginEqualizer/pom.xml
+++ b/PlayWallPlugins/PlayWallPluginEqualizer/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallPlugins</artifactId>
-        <version>7.0.2</version>
+        <version>7.1.0</version>
     </parent>
 
     <artifactId>PlayWallPluginEqualizer</artifactId>
diff --git a/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerPluginImpl.java b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerPluginImpl.java
index 6ff24f83ac9122fa073da85a772a97ff6be76307..f65d2d28af1b7df25ed6f40c6a92f36a323deb95 100644
--- a/PlayWallPlugins/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,8 +1,8 @@
 package de.tobias.playpad.equalizerplugin.impl;
 
 import de.thecodelabs.logger.Logger;
-import de.thecodelabs.plugins.PluginArtifact;
 import de.thecodelabs.plugins.PluginDescriptor;
+import de.thecodelabs.plugins.versionizer.PluginArtifact;
 import de.thecodelabs.utils.application.ApplicationUtils;
 import de.thecodelabs.utils.application.container.PathType;
 import de.thecodelabs.utils.ui.NVCStage;
diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/pom.xml b/PlayWallPlugins/PlayWallPluginLaunchpad/pom.xml
index 698c86e1e9d034551a033d3dc323d9baa21fcdd0..796dc9ad10ed73ebf34dfecdd5c6b6f3e798b3cd 100644
--- a/PlayWallPlugins/PlayWallPluginLaunchpad/pom.xml
+++ b/PlayWallPlugins/PlayWallPluginLaunchpad/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallPlugins</artifactId>
-        <version>7.0.2</version>
+        <version>7.1.0</version>
     </parent>
 
     <artifactId>PlayWallPluginLaunchpad</artifactId>
diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java
index 3c153f971bccd8dc41be1b3c7cd99470d0c89286..0a62f947c6504e42134e4e139aaff43886478acf 100644
--- a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java
+++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java
@@ -2,8 +2,8 @@ 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.thecodelabs.plugins.versionizer.PluginArtifact;
 import de.tobias.playpad.launchpadplugin.midi.mk2.LaunchPadMK2;
 import de.tobias.playpad.launchpadplugin.midi.s.LaunchPadS;
 import de.tobias.playpad.plugin.Module;
diff --git a/PlayWallPlugins/PlayWallPluginMedia/pom.xml b/PlayWallPlugins/PlayWallPluginMedia/pom.xml
index c28080c20e25e6f0b6f8fd0c6a0963c3a47891fa..f420120ac351928558988fd3c347cec1302a364b 100644
--- a/PlayWallPlugins/PlayWallPluginMedia/pom.xml
+++ b/PlayWallPlugins/PlayWallPluginMedia/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallPlugins</artifactId>
-        <version>7.0.2</version>
+        <version>7.1.0</version>
     </parent>
 
     <artifactId>PlayWallPluginMedia</artifactId>
diff --git a/PlayWallPlugins/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
index 4a9a5ec7b072aa401cb87eea1093050a199b6539..d9c10d492f3725b1bd743b09aab267bfe581046f 100644
--- a/PlayWallPlugins/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
@@ -9,7 +9,7 @@ import javafx.collections.ListChangeListener;
 import javafx.collections.SetChangeListener;
 import javafx.css.PseudoClass;
 import javafx.geometry.Pos;
-import javafx.scene.Node;
+import javafx.scene.Parent;
 import javafx.scene.control.Label;
 import javafx.scene.layout.Pane;
 import javafx.scene.layout.Priority;
@@ -91,7 +91,7 @@ public class ImagePadContentFactory extends PadContentFactory {
 		}
 
 		@Override
-		public Node getNode() {
+		public Parent getNode() {
 			return stackPane;
 		}
 
diff --git a/PlayWallPlugins/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
index 0565647dc30745ffb5da019f0910176bad972704..3fa00ae758861e8750be5612b857fe3cc9f2b35b 100644
--- a/PlayWallPlugins/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
@@ -2,8 +2,8 @@ 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.plugins.versionizer.PluginArtifact;
 import de.thecodelabs.utils.ui.icon.FontAwesomeType;
 import de.thecodelabs.utils.ui.icon.FontIcon;
 import de.thecodelabs.utils.ui.scene.HUD;
diff --git a/PlayWallPlugins/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
index a8aca757db9af4a5e11da5973d0ffcd899ef1c37..14e2269f4a819ec63df0519285189c2c69be1cae 100644
--- a/PlayWallPlugins/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
@@ -3,18 +3,13 @@ package de.tobias.playpad.plugin.media.video;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.content.PadContent;
 import de.tobias.playpad.pad.content.PadContentFactory;
+import de.tobias.playpad.pad.preview.PadTextPreview;
 import de.tobias.playpad.pad.view.IPadContentView;
 import de.tobias.playpad.plugin.media.main.impl.MediaPluginImpl;
 import de.tobias.playpad.plugin.media.main.impl.MediaSettingsTabViewController;
 import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
 import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController;
-import javafx.geometry.Pos;
-import javafx.scene.Node;
-import javafx.scene.control.Label;
 import javafx.scene.layout.Pane;
-import javafx.scene.layout.Priority;
-import javafx.scene.layout.VBox;
-import javafx.scene.text.TextAlignment;
 
 public class VideoPadContentFactory extends PadContentFactory {
 
@@ -31,7 +26,7 @@ public class VideoPadContentFactory extends PadContentFactory {
 
 	@Override
 	public IPadContentView getPadContentPreview(Pad pad, Pane parentNode) {
-		return new VideoContentView(pad, parentNode);
+		return new PadTextPreview(pad, parentNode);
 	}
 
 	@Override
@@ -50,31 +45,4 @@ public class VideoPadContentFactory extends PadContentFactory {
 		return FILE_EXTENSION;
 	}
 
-	private class VideoContentView implements IPadContentView {
-
-		private Label nameLabel;
-
-		VideoContentView(Pad pad, Pane parentNode) {
-			nameLabel = new Label();
-			nameLabel.textProperty().bind(pad.nameProperty());
-
-			nameLabel.setWrapText(true);
-			nameLabel.setAlignment(Pos.CENTER);
-			nameLabel.setTextAlignment(TextAlignment.CENTER);
-
-			nameLabel.prefWidthProperty().bind(parentNode.widthProperty());
-			nameLabel.setMaxHeight(Double.MAX_VALUE);
-			VBox.setVgrow(nameLabel, Priority.ALWAYS);
-		}
-
-		@Override
-		public Node getNode() {
-			return nameLabel;
-		}
-
-		@Override
-		public void deInit() {
-			nameLabel.textProperty().unbind();
-		}
-	}
 }
diff --git a/PlayWallPlugins/PlayWallPluginNativeAudio/pom.xml b/PlayWallPlugins/PlayWallPluginNativeAudio/pom.xml
index 8e54821dac703bc7ec4685f5dd50a199f56fb10a..b2c4941c26d77e0b6aa485cf423b606017803b0e 100644
--- a/PlayWallPlugins/PlayWallPluginNativeAudio/pom.xml
+++ b/PlayWallPlugins/PlayWallPluginNativeAudio/pom.xml
@@ -8,7 +8,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallPlugins</artifactId>
-        <version>7.0.2</version>
+        <version>7.1.0</version>
     </parent>
 
     <properties>
diff --git a/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java
index e0e75d8214d02545871f708dc5f0cacfe6bf9019..399cc42c4f02033e6d3efca1d96c4daaf987bc5b 100644
--- a/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java
+++ b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java
@@ -26,11 +26,11 @@ public class NativeAudioWinHandler extends AudioHandler implements Soundcardable
 	static final String SOUND_CARD = "SoundCard";
 
 	private NativeAudio audioHandler;
-	private ObjectProperty<Duration> durationProperty;
-	private ObjectProperty<Duration> positionProperty;
+	private final ObjectProperty<Duration> durationProperty;
+	private final ObjectProperty<Duration> positionProperty;
 
 	private static Thread positionThread;
-	private static List<NativeAudioWinHandler> playedHandlers = new ArrayList<>();
+	private static final List<NativeAudioWinHandler> playedHandlers = new ArrayList<>();
 	private static final int SLEEP_TIME_POSITION = 50;
 
 	static {
diff --git a/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/plugin/NativeAudioPathType.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/plugin/NativeAudioPathType.java
index 771db0fe9805a4aab1d286d97bd42c8acb9a61c8..1cba1f2a019dd1a84584c7d0bb785a252f822d1e 100644
--- a/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/plugin/NativeAudioPathType.java
+++ b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/plugin/NativeAudioPathType.java
@@ -7,7 +7,7 @@ public enum NativeAudioPathType implements ContainerPathType {
 
 	AUDIO(PathType.LIBRARY.getFolder() + "/Audio");
 
-	private String folder;
+	private final String folder;
 
 	NativeAudioPathType(String folder) {
 		this.folder = folder;
diff --git a/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/NativeAudioPluginImpl.scala b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/NativeAudioPluginImpl.scala
index 040c23f86adb8eb5eb4a08c1a3426e22c8e99607..c273ca5d167c831fa94c23bcc5e148ac9658a893 100644
--- a/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/NativeAudioPluginImpl.scala
+++ b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/NativeAudioPluginImpl.scala
@@ -1,6 +1,7 @@
 package de.tobias.playpad.plugin
 
-import de.thecodelabs.plugins.{PluginArtifact, PluginDescriptor}
+import de.thecodelabs.plugins.PluginDescriptor
+import de.thecodelabs.plugins.versionizer.PluginArtifact
 import de.thecodelabs.utils.util.OS
 import de.thecodelabs.utils.util.OS.OSType
 import de.tobias.playpad.plugin.loader.{MacAudioImplLoader, WindowsAudioImplLoader}
diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/pom.xml b/PlayWallPlugins/PlayWallPluginPlayoutLog/pom.xml
index d03d7fa22d7222e5f75363e91ca9d6ae54ee068a..2239ae0009ea855a08acdffc80c1756c3c5bc091 100644
--- a/PlayWallPlugins/PlayWallPluginPlayoutLog/pom.xml
+++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallPlugins</artifactId>
-        <version>7.0.2</version>
+        <version>7.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
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
index 278ec6c4523045ae4784801f2b38d254efc57e0d..afa5ff76555f3a0eea4d166affb042e78d45424a 100644
--- 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
@@ -2,8 +2,8 @@ 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.plugins.versionizer.PluginArtifact;
 import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.PlayPadPlugin;
 import de.tobias.playpad.plugin.Module;
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/pom.xml b/PlayWallPlugins/PlayWallPluginWebAPI/pom.xml
index 85bc644f9a1801eb33e7e8b2ccee08592c3a1de8..d0b4ab9b7c8d5cd258d926eec7f1858becfd855b 100644
--- a/PlayWallPlugins/PlayWallPluginWebAPI/pom.xml
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>PlayWallPlugins</artifactId>
         <groupId>de.tobias.playpad</groupId>
-        <version>7.0.2</version>
+        <version>7.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettings.java b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettings.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5b35f5f180fa76bf0c1f9681e96c9b03f30f4c5
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettings.java
@@ -0,0 +1,28 @@
+package de.tobias.playpad.plugin.api.websocket.settings;
+
+import de.thecodelabs.storage.settings.annotation.FilePath;
+import de.thecodelabs.storage.settings.annotation.Key;
+
+@FilePath("webapi.json")
+public class WebApiSettings {
+	@Key
+	private boolean enabled = false;
+	@Key
+	private int port = 9876;
+
+	public boolean isEnabled() {
+		return enabled;
+	}
+
+	public void setEnabled(boolean enabled) {
+		this.enabled = enabled;
+	}
+
+	public int getPort() {
+		return port;
+	}
+
+	public void setPort(int port) {
+		this.port = port;
+	}
+}
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base.properties b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base_de.properties b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..0b7b9cf8475b89313f3289e30aef44a2c86136a8
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base_de.properties
@@ -0,0 +1,5 @@
+webapi.settings=WebAPI
+webapi.settings.enable=WebAPI
+webapi.settings.enabled=Aktiv
+webapi.settings.port=Port
+webapi.settings.restart=\u00C4nderungen an den Einstellungen werden erst mit einem Neustart von PlayWall wirksam.
\ No newline at end of file
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..473dba8d1a6441e62fed11fa04b87a6be18397b3
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import de.thecodelabs.utils.ui.scene.input.NumberTextField?>
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.CheckBox?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.layout.HBox?>
+<?import javafx.scene.layout.VBox?>
+<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>
+        <HBox alignment="CENTER_LEFT" spacing="14.0">
+            <children>
+                <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%webapi.settings.enable"/>
+                <CheckBox fx:id="activeCheckbox" mnemonicParsing="false" text="%webapi.settings.enabled"/>
+            </children>
+        </HBox>
+        <HBox alignment="CENTER_LEFT" spacing="14.0">
+            <children>
+                <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%webapi.settings.port"/>
+                <NumberTextField fx:id="portTextField"/>
+            </children>
+        </HBox>
+        <Label text="%webapi.settings.restart">
+            <padding>
+                <Insets left="164.0"/>
+            </padding>
+        </Label>
+    </children>
+    <padding>
+        <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/>
+    </padding>
+</VBox>
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
index 2eb1c9a7579ed7a3b0e3f5a3abceeacdf219753b..0d4d7321ee3a880471919572daaea62d1da8517d 100644
--- 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
@@ -1,17 +1,27 @@
 package de.tobias.playpad.plugin.api
 
+import java.nio.file.{Files, Path}
+
 import de.thecodelabs.logger.Logger
-import de.thecodelabs.plugins.{PluginArtifact, PluginDescriptor}
+import de.thecodelabs.plugins.PluginDescriptor
+import de.thecodelabs.plugins.versionizer.PluginArtifact
+import de.thecodelabs.storage.settings.{Storage, StorageTypes}
+import de.thecodelabs.utils.application.ApplicationUtils
+import de.thecodelabs.utils.application.container.PathType
+import de.thecodelabs.utils.util.Localization
 import de.tobias.playpad.PlayPadPlugin
 import de.tobias.playpad.plugin.api.websocket.WebSocketHandler
 import de.tobias.playpad.plugin.api.websocket.listener.{PadStatusListener, ProjectListener}
+import de.tobias.playpad.plugin.api.websocket.settings.{WebApiSettings, WebApiSettingsViewController}
 import de.tobias.playpad.plugin.{Module, PlayPadPluginStub}
-import spark.Spark
+import spark.{Request, Response, Spark}
 
 class WebApiPlugin extends PlayPadPluginStub with PluginArtifact {
 
 	private var module: Module = _
 
+	private var webApiSettings: WebApiSettings = _
+
 	override def startup(descriptor: PluginDescriptor): Unit = {
 		module = new Module(descriptor.getName, descriptor.getArtifactId)
 
@@ -20,16 +30,34 @@ class WebApiPlugin extends PlayPadPluginStub with PluginArtifact {
 
 		Logger.debug("Enable Web API Plugin")
 
-		Spark.port(9876)
-		Spark.webSocket("/api", WebSocketHandler.instance)
-		Spark.get("/", (_, _) => "PlayWall API")
+		val settingsPath = WebApiPlugin.getWebApiSettingsPath
+		if (Files.exists(settingsPath)) {
+			webApiSettings = Storage.load(StorageTypes.JSON, classOf[WebApiSettings])
+		}
+		if (webApiSettings == null) {
+			webApiSettings = new WebApiSettings
+		}
+
+		if (webApiSettings.isEnabled) {
+			Spark.port(webApiSettings.getPort)
+			Spark.webSocket("/api", WebSocketHandler.instance)
+			Spark.get("/", (_: Request, _: Response) => "PlayWall API")
+			Logger.info(f"Start WebAPI on port ${webApiSettings.getPort}")
+		}
+
+		PlayPadPlugin.getInstance().addGlobalSettingsTab(() => new WebApiSettingsViewController(webApiSettings))
+		Localization.addResourceBundle("plugin/webapi/lang/base", getClass.getClassLoader)
 	}
 
 	override def shutdown(): Unit = {
-		Logger.debug("Disable Web API Plugin")
-
 		Spark.stop()
+		Logger.debug("Disable Web API Plugin")
 	}
 
 	override def getModule: Module = module
+
 }
+
+object WebApiPlugin {
+	def getWebApiSettingsPath: Path = ApplicationUtils.getApplication.getPath(PathType.CONFIGURATION, "webapi.json")
+}
\ No newline at end of file
diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettingsViewController.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettingsViewController.scala
new file mode 100644
index 0000000000000000000000000000000000000000..4f86d86df6e85433d7bd38a2dfb21fcb99361fdd
--- /dev/null
+++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettingsViewController.scala
@@ -0,0 +1,81 @@
+package de.tobias.playpad.plugin.api.websocket.settings
+
+import java.nio.file.Files
+
+import de.thecodelabs.logger.Logger
+import de.thecodelabs.storage.settings.{Storage, StorageTypes}
+import de.thecodelabs.utils.ui.scene.input.NumberTextField
+import de.thecodelabs.utils.util.Localization
+import de.tobias.playpad.plugin.api.WebApiPlugin
+import de.tobias.playpad.settings.GlobalSettings
+import de.tobias.playpad.viewcontroller.option.GlobalSettingsTabViewController
+import javafx.fxml.FXML
+import javafx.scene.control.CheckBox
+
+class WebApiSettingsViewController(val webApiSettings: WebApiSettings) extends GlobalSettingsTabViewController {
+
+	load("plugin/webapi/view", "WebApiSettings", Localization.getBundle)
+
+	@FXML
+	var activeCheckbox: CheckBox = _
+
+	@FXML
+	var portTextField: NumberTextField = _
+
+	/**
+	 * Lädt alle Einstellungen vom Model in die GUI.
+	 *
+	 * @param settings Aktuelles GlobalSettings
+	 */
+	override def loadSettings(settings: GlobalSettings): Unit = {
+		activeCheckbox.setSelected(webApiSettings.isEnabled)
+		portTextField.setText(webApiSettings.getPort.toString)
+	}
+
+	/**
+	 * Speichert alle Änderungen in das Model.
+	 *
+	 * @param settings Aktuelles GlobalSettings
+	 */
+	override def saveSettings(settings: GlobalSettings): Unit = {
+		webApiSettings.setEnabled(activeCheckbox.isSelected)
+		webApiSettings.setPort(portTextField.getText.toInt)
+
+		saveToFile()
+	}
+
+	/**
+	 * Gibt <code>true</code> zurück, wenn im Hauptprogramm etwas neu geladen werden muss.
+	 *
+	 * @return <code>true</code> Benötigt Reload
+	 */
+	override def needReload(): Boolean = {
+		false
+	}
+
+	/**
+	 * Prüft ob die eingetragen Einstellungen erlaubt sind. Bei falschen Eingaben können die Einstellungen nicht
+	 * geschlossen werden.
+	 *
+	 * @return <code>true</code> Einstellungen erlaubt. <code>false</code> Einstellungen fehlerhaft.
+	 */
+	override def validSettings(): Boolean = {
+		true
+	}
+
+	/**
+	 * Gibt den Namen für den Tab zurück.
+	 *
+	 * @return Display Name des Tabs.
+	 */
+	override def name(): String = Localization.getString("webapi.settings")
+
+	private def saveToFile(): Unit = {
+		val settingsPath = WebApiPlugin.getWebApiSettingsPath
+		if (Files.notExists(settingsPath)) {
+			Files.createDirectories(settingsPath.getParent)
+		}
+		Storage.save(StorageTypes.JSON, webApiSettings)
+		Logger.info(f"Save WebAPI settings to $settingsPath")
+	}
+}
diff --git a/PlayWallPlugins/pom.xml b/PlayWallPlugins/pom.xml
index e633d8b643444f5319297ee50360e08d1722198a..53ba5f57847adeeca8830e9ac4dd854bcd0c0426 100644
--- a/PlayWallPlugins/pom.xml
+++ b/PlayWallPlugins/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>de.tobias.playpad</groupId>
         <artifactId>PlayWallDesktop</artifactId>
-        <version>7.0.2</version>
+        <version>7.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -20,6 +20,7 @@
         <module>PlayWallPluginNativeAudio</module>
         <module>PlayWallPluginPlayoutLog</module>
         <module>PlayWallPluginWebAPI</module>
+        <module>PlayWallPluginContentPlayer</module>
     </modules>
 
 </project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 08781928dbc439dbf7103ba7a058b26b6301fa27..a876b2e40959b81847e79506ba84b7540809bed2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
 
     <groupId>de.tobias.playpad</groupId>
     <artifactId>PlayWallDesktop</artifactId>
-    <version>7.0.2</version>
+    <version>7.1.0</version>
     <packaging>pom</packaging>
 
     <properties>
@@ -22,7 +22,7 @@
         <components.version>${project.version}</components.version>
 
         <jlibs.version>2.0.6</jlibs.version>
-        <libPlugins.version>2.2.1</libPlugins.version>
+        <libPlugins.version>3.0.6</libPlugins.version>
         <versionizer-api.version>1.2.0</versionizer-api.version>
 
         <jlayer.version>1.0.1</jlayer.version>
@@ -66,13 +66,6 @@
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
-            <dependency>
-                <groupId>de.thecodelabs</groupId>
-                <artifactId>libPlugins</artifactId>
-                <version>${libPlugins.version}</version>
-                <type>pom</type>
-                <scope>import</scope>
-            </dependency>
         </dependencies>
     </dependencyManagement>