Browse Source

Merge pull request #24 from Seil0/dev

"toothless dragon" 0.7.0
pull/25/head
Jannik 4 years ago committed by GitHub
parent
commit
53f68c9a69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      .classpath
  2. 8
      .settings/org.eclipse.jdt.core.prefs
  3. 2
      README.md
  4. 28
      pom.xml
  5. 142
      src/main/java/com/cemu_UI/uiElements/JFXOkayCancelDialog.java
  6. 98
      src/main/java/com/cemu_UI/uiElements/JFXTextAreaInfoDialog.java
  7. 160
      src/main/java/kellerkinder/HomeFlix/application/Main.java
  8. 558
      src/main/java/kellerkinder/HomeFlix/application/MainWindowController.java
  9. 300
      src/main/java/kellerkinder/HomeFlix/controller/DBController.java
  10. 64
      src/main/java/kellerkinder/HomeFlix/controller/OMDbAPIController.java
  11. 8
      src/main/java/kellerkinder/HomeFlix/controller/UpdateController.java
  12. 2
      src/main/java/kellerkinder/HomeFlix/datatypes/FilmTabelDataType.java
  13. 1
      src/main/java/kellerkinder/HomeFlix/datatypes/SourceDataType.java
  14. 86
      src/main/java/kellerkinder/HomeFlix/player/Player.java
  15. 276
      src/main/java/kellerkinder/HomeFlix/player/PlayerController.java
  16. 189
      src/main/java/org/kellerkinder/Alerts/JFX2BtnCancelAlert.java
  17. 113
      src/main/java/org/kellerkinder/Alerts/JFXInfoAlert.java
  18. 109
      src/main/resources/fxml/MainWindow.fxml
  19. 38
      src/main/resources/fxml/PlayerWindow.fxml
  20. BIN
      src/main/resources/icons/ic_fullscreen_black_24dp_1x.png
  21. BIN
      src/main/resources/icons/ic_fullscreen_exit_black_24dp_1x.png
  22. BIN
      src/main/resources/icons/ic_pause_black_24dp_1x.png
  23. BIN
      src/main/resources/icons/ic_play_arrow_black_24dp_1x.png
  24. BIN
      src/main/resources/icons/ic_stop_black_24dp_1x.png
  25. 8
      src/main/resources/locals/HomeFlix-Local_de_DE.properties
  26. 8
      src/main/resources/locals/HomeFlix-Local_en_US.properties

7
.classpath

@ -17,11 +17,16 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-9">
<attributes>
<attribute name="module" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

8
.settings/org.eclipse.jdt.core.prefs

@ -1,5 +1,13 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=9
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=9
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=9

2
README.md

@ -18,7 +18,7 @@ sqlite-jdbc: https://github.com/xerial/sqlite-jdbc
apache commons io : https://commons.apache.org/proper/commons-io/
## screenshots
![Screenshot](https://github.com/Seil0/Seil0.github.io/blob/master/pictures/Project-HomeFlix_MainWindow.png)
![Screenshot](https://github.com/Seil0/Seil0.github.io/blob/master/images/Project-HomeFlix_MainWindow.png)
Project-HomeFlix © 2016-2018 Kellerkinder ([Seil0](https://github.com/Seil0), [Windoofs](https://github.com/Windoofs))
www.kellerkinder.xyz

28
pom.xml

@ -4,7 +4,7 @@
<groupId>org.kellerkinder</groupId>
<artifactId>Project-HomeFlix</artifactId>
<version>0.6.0</version>
<version>0.7.0</version>
<packaging>jar</packaging>
<name>Project-HomeFlix</name>
@ -19,7 +19,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<version>4.12</version>
<scope>test</scope>
</dependency>
@ -32,7 +32,7 @@
<dependency>
<groupId>com.jfoenix</groupId>
<artifactId>jfoenix</artifactId>
<version>9.0.2</version>
<version>9.0.3</version>
</dependency>
<dependency>
@ -50,13 +50,13 @@
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.10.0</version>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.10.0</version>
<version>2.11.0</version>
</dependency>
</dependencies>
@ -78,21 +78,21 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<version>3.1.1</version>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>kellerkinder.HomeFlix.application.Main</mainClass>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>kellerkinder.HomeFlix.application.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>

142
src/main/java/com/cemu_UI/uiElements/JFXOkayCancelDialog.java

@ -1,142 +0,0 @@
/**
* cemu_UI
*
* Copyright 2017 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.cemu_UI.uiElements;
import java.util.ResourceBundle;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialogLayout;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
public class JFXOkayCancelDialog {
private String headingText;
private String bodyText;
private String dialogBtnStyle;
private String okayText;
private String cancelText;
private int dialogWidth;
private int dialogHeight;
private EventHandler<ActionEvent> okayAction;
private EventHandler<ActionEvent> cancelAction;
private Pane pane;
/**
* Creates a new JFoenix Dialog to show some information with okay and cancel option
* @param headingText Heading Text, just the heading
* @param bodyText body Text, all other text belongs here
* @param dialogBtnStyle Style of the okay button
* @param dialogWidth dialog width
* @param dialogHeight dialog height
* @param okayAction action which is performed if the okay button is clicked
* @param cancelAction action which is performed if the cancel button is clicked
* @param pane pane to which the dialog belongs
*/
public JFXOkayCancelDialog(String headingText, String bodyText, String dialogBtnStyle, int dialogWidth,
int dialogHeight, EventHandler<ActionEvent> okayAction, EventHandler<ActionEvent> cancelAction, Pane pane,
ResourceBundle bundle) {
this.headingText = headingText;
this.bodyText = bodyText;
this.dialogBtnStyle = dialogBtnStyle;
this.dialogWidth = dialogWidth;
this.dialogHeight = dialogHeight;
this.okayAction = okayAction;
this.cancelAction = cancelAction;
this.pane = pane;
okayText = bundle.getString("okayBtnText");
cancelText = bundle.getString("cancelBtnText");
}
public void show() {
JFXDialogLayout content = new JFXDialogLayout();
content.setHeading(new Text(headingText));
content.setBody(new Text(bodyText));
StackPane stackPane = new StackPane();
stackPane.autosize();
JFXDialog dialog = new JFXDialog(stackPane, content, JFXDialog.DialogTransition.LEFT, true);
JFXButton okayBtn = new JFXButton(okayText);
okayBtn.addEventHandler(ActionEvent.ACTION, (e)-> {
dialog.close();
});
okayBtn.addEventHandler(ActionEvent.ACTION, okayAction);
okayBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
okayBtn.setPrefHeight(32);
okayBtn.setStyle(dialogBtnStyle);
JFXButton cancelBtn = new JFXButton(cancelText);
cancelBtn.addEventHandler(ActionEvent.ACTION, (e)-> {
dialog.close();
});
cancelBtn.addEventHandler(ActionEvent.ACTION, cancelAction);
cancelBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
cancelBtn.setPrefHeight(32);
cancelBtn.setStyle(dialogBtnStyle);
content.setActions(cancelBtn, okayBtn);
content.setPrefSize(dialogWidth, dialogHeight);
pane.getChildren().add(stackPane);
AnchorPane.setTopAnchor(stackPane, (pane.getHeight()-content.getPrefHeight())/2);
AnchorPane.setLeftAnchor(stackPane, (pane.getWidth()-content.getPrefWidth())/2);
dialog.show();
}
public String getOkayText() {
return okayText;
}
public void setOkayText(String okayText) {
this.okayText = okayText;
}
public String getCancelText() {
return cancelText;
}
public void setCancelText(String cancelText) {
this.cancelText = cancelText;
}
public EventHandler<ActionEvent> getOkayAction() {
return okayAction;
}
public void setOkayAction(EventHandler<ActionEvent> okayAction) {
this.okayAction = okayAction;
}
public EventHandler<ActionEvent> getCancelAction() {
return cancelAction;
}
public void setCancelAction(EventHandler<ActionEvent> cancelAction) {
this.cancelAction = cancelAction;
}
}

98
src/main/java/com/cemu_UI/uiElements/JFXTextAreaInfoDialog.java

@ -1,98 +0,0 @@
/**
* cemu_UI
*
* Copyright 2017 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.cemu_UI.uiElements;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialogLayout;
import com.jfoenix.controls.JFXTextArea;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
public class JFXTextAreaInfoDialog {
private String headingText;
private String bodyText;
private String dialogBtnStyle;
private int dialogWidth;
private int dialogHeight;
private JFXTextArea textArea;
private Pane pane;
/**
* Creates a new JFoenix Dialog to show some information
* @param headingText Heading Text, just the heading
* @param bodyText body Text, all other text belongs here
* @param dialogBtnStyle Style of the okay button
* @param dialogWidth dialog width
* @param dialogHeight dialog height
* @param pane pane to which the dialog belongs
*/
public JFXTextAreaInfoDialog(String headingText, String bodyText, String dialogBtnStyle, int dialogWidth, int dialogHeight, Pane pane) {
this.headingText = headingText;
this.bodyText = bodyText;
this.dialogBtnStyle = dialogBtnStyle;
this.dialogWidth = dialogWidth;
this.dialogHeight = dialogHeight;
this.pane = pane;
}
public void show() {
textArea = new JFXTextArea(bodyText);
JFXDialogLayout content = new JFXDialogLayout();
content.setHeading(new Text(headingText));
content.setBody(textArea);
content.setPrefSize(dialogWidth, dialogHeight);
StackPane stackPane = new StackPane();
stackPane.autosize();
JFXDialog dialog = new JFXDialog(stackPane, content, JFXDialog.DialogTransition.LEFT, true);
JFXButton button = new JFXButton("Okay");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
dialog.close();
}
});
button.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
button.setPrefHeight(32);
button.setStyle(dialogBtnStyle);
content.setActions(button);
pane.getChildren().add(stackPane);
AnchorPane.setTopAnchor(stackPane, (pane.getHeight() - content.getPrefHeight()) / 2);
AnchorPane.setLeftAnchor(stackPane, (pane.getWidth() - content.getPrefWidth()) / 2);
dialog.show();
}
public JFXTextArea getTextArea() {
return textArea;
}
public void setTextArea(JFXTextArea textArea) {
this.textArea = textArea;
}
}

160
src/main/java/kellerkinder/HomeFlix/application/Main.java

@ -19,31 +19,31 @@
* MA 02110-1301, USA.
*
*/
package kellerkinder.HomeFlix.application;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.Optional;
import java.util.ResourceBundle;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.kellerkinder.Alerts.JFX2BtnCancelAlert;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonType;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class Main extends Application {
private Stage primaryStage;
private Scene scene;
private AnchorPane pane;
@ -54,30 +54,30 @@ public class Main extends Application {
private static String osArch = System.getProperty("os.arch");
private static String osVers = System.getProperty("os.version");
private static String javaVers = System.getProperty("java.version");
private static String javaVend= System.getProperty("java.vendor");
private String dirWin = userHome + "/Documents/HomeFlix"; //Windows: C:/Users/"User"/Documents/HomeFlix
private String dirLinux = userHome + "/HomeFlix"; //Linux: /home/"User"/HomeFlix
private static String javaVend = System.getProperty("java.vendor");
private static String local = System.getProperty("user.language") + "_" + System.getProperty("user.country");
private String dirWin = userHome + "/Documents/HomeFlix"; // Windows: C:/Users/"User"/Documents/HomeFlix
private String dirLinux = userHome + "/HomeFlix"; // Linux: /home/"User"/HomeFlix
private File directory;
private File configFile;
private File posterCache;
private String path;
private String FONT_FAMILY = "System";
private String local = System.getProperty("user.language")+"_"+System.getProperty("user.country");
private double FONT_SIZE = 17;
private ResourceBundle bundle;
private static Logger LOGGER;
@Override
public void start(Stage primaryStage) throws IOException {
LOGGER.info("OS: " + osName + " " + osVers + " " + osArch);
LOGGER.info("Java: " + javaVend + " " + javaVers);
LOGGER.info("User: " + userName + " " + userHome);
this.primaryStage = primaryStage;
this.primaryStage = primaryStage;
mainWindow();
}
/**
* initialize the mainWindowController, GUI and load the saved settings or call addFirstSource
* initialize the primaryStage and set the file/directory paths
*/
private void mainWindow(){
try {
FXMLLoader loader = new FXMLLoader();
@ -88,12 +88,18 @@ public class Main extends Application {
primaryStage.setResizable(false);
primaryStage.setTitle("Project HomeFlix");
primaryStage.getIcons().add(new Image(Main.class.getResourceAsStream("/icons/Homeflix_Icon_64x64.png"))); //adds application icon
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
public void handle(WindowEvent we) {
System.exit(1);
}
});
mainWindowController = loader.getController(); //Link of FXMLController and controller class
mainWindowController.setMain(this); //call setMain
// get OS and the specific paths
if (osName.equals("Windows")) {
if (osName.contains("Windows")) {
directory = new File(dirWin);
configFile = new File(dirWin + "/config.xml");
posterCache = new File(dirWin + "/posterCache");
@ -103,33 +109,27 @@ public class Main extends Application {
posterCache = new File(dirLinux + "/posterCache");
}
// generate window
scene = new Scene(pane); // create new scene, append pane to scene
scene.getStylesheets().add(getClass().getResource("/css/MainWindow.css").toExternalForm());
primaryStage.setScene(scene); // append scene to stage
primaryStage.show(); // show stage
// startup checks
if (!configFile.exists()) {
directory.mkdir();
mainWindowController.addSource(firstStart(), "local");
directory.mkdir();
addFirstSource();
mainWindowController.setColor("ee3523");
mainWindowController.setSize(FONT_SIZE);
mainWindowController.setFontSize(17.0);
mainWindowController.setAutoUpdate(false);
mainWindowController.setLocal(local);
mainWindowController.saveSettings();
try {
Runtime.getRuntime().exec("java -jar ProjectHomeFlix.jar"); // start again (preventing Bugs) TODO is this really needed
System.exit(0); // finishes it self
} catch (Exception e) {
LOGGER.error("error while restarting HomeFlix", e);
}
}
if (!posterCache.exists()) {
posterCache.mkdir();
}
// generate window
scene = new Scene(pane); // create new scene, append pane to scene
scene.getStylesheets().add(getClass().getResource("/css/MainWindow.css").toExternalForm());
primaryStage.setScene(scene); // append scene to stage
primaryStage.show(); // show stage
// init here as it loads the games to the mwc and the gui, therefore the window must exist
mainWindowController.init();
mainWindowController.getDbController().init();
@ -137,10 +137,13 @@ public class Main extends Application {
LOGGER.error(e);
}
}
// Method for first Start
private String firstStart(){
switch (System.getProperty("user.language") + "_" + System.getProperty("user.country")) {
/**
* we need to get the path for the first source from the user and add it to
* sources.json, if the user ends the file-/directory-chooser the program will exit
*/
private void addFirstSource() {
switch (local) {
case "en_US":
bundle = ResourceBundle.getBundle("locals.HomeFlix-Local", Locale.US); // us_english
break;
@ -152,30 +155,61 @@ public class Main extends Application {
break;
}
Alert alert = new Alert(AlertType.CONFIRMATION); //new alert with file-chooser
alert.setTitle("Project HomeFlix");
alert.setHeaderText(bundle.getString("firstStartHeader"));
alert.setContentText(bundle.getString("firstStartContent"));
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
DirectoryChooser directoryChooser = new DirectoryChooser();
File selectedDirectory =
directoryChooser.showDialog(primaryStage);
path = selectedDirectory.getAbsolutePath();
} else {
path = "";
}
return path;
JFX2BtnCancelAlert selectFirstSource = new JFX2BtnCancelAlert(bundle.getString("addSourceHeader"),
bundle.getString("addSourceBody"),
"-fx-button-type: RAISED; -fx-background-color: #ee3523; -fx-text-fill: BLACK;",
bundle.getString("addDirectory"), bundle.getString("addStreamSource"),
bundle.getString("cancelBtnText"), primaryStage);
// directory action
EventHandler<ActionEvent> btn1Action = new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
DirectoryChooser directoryChooser = new DirectoryChooser();
directoryChooser.setTitle(bundle.getString("addDirectory"));
File selectedFolder = directoryChooser.showDialog(primaryStage);
if (selectedFolder != null && selectedFolder.exists()) {
mainWindowController.addSource(selectedFolder.getPath(), "local");
selectFirstSource.getAlert().close();
} else {
LOGGER.error("The selected folder dosen't exist!");
System.exit(1);
}
}
};
// streaming action
EventHandler<ActionEvent> btn2Action = new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("addStreamSource");
File selectedFile = fileChooser.showOpenDialog(getPrimaryStage());
if (selectedFile != null && selectedFile.exists()) {
mainWindowController.addSource(selectedFile.getPath(), "stream");
selectFirstSource.getAlert().close();
} else {
LOGGER.error("The selected file dosen't exist!");
System.exit(1);
}
}
};
selectFirstSource.setBtn1Action(btn1Action);
selectFirstSource.setBtn2Action(btn2Action);
selectFirstSource.showAndWait();
}
/**
* set the log file location and initialize the logger
* launch the GUI
* @param args arguments given at the start
*/
public static void main(String[] args) {
if(System.getProperty("os.name").equals("Windows")){
if (System.getProperty("os.name").equals("Windows")) {
System.setProperty("logFilename", userHome + "/Documents/HomeFlix/app.log");
File logFile = new File(userHome + "/Documents/HomeFlix/app.log");
logFile.delete();
}else{
} else {
System.setProperty("logFilename", userHome + "/HomeFlix/app.log");
File logFile = new File(userHome + "/HomeFlix/app.log");
logFile.delete();
@ -188,22 +222,10 @@ public class Main extends Application {
return primaryStage;
}
public void setPrimaryStage(Stage primaryStage) {
this.primaryStage = primaryStage;
}
public AnchorPane getPane( ) {
public AnchorPane getPane() {
return pane;
}
public String getFONT_FAMILY() {
return FONT_FAMILY;
}
public void setFONT_FAMILY(String FONT_FAMILY) {
this.FONT_FAMILY = FONT_FAMILY;
}
public File getDirectory() {
return directory;
}

558
src/main/java/kellerkinder/HomeFlix/application/MainWindowController.java

@ -1,6 +1,6 @@
/**
* Project-HomeFlix
*
*
* Copyright 2016-2018 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
@ -19,7 +19,6 @@
* MA 02110-1301, USA.
*
*/
package kellerkinder.HomeFlix.application;
import java.awt.Desktop;
@ -33,19 +32,17 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.math.BigInteger;
import java.util.ArrayList;
import java.net.URLConnection;
import java.util.Locale;
import java.util.Properties;
import java.util.ResourceBundle;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.kellerkinder.Alerts.JFXInfoAlert;
import com.cemu_UI.uiElements.JFXInfoDialog;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
@ -65,8 +62,6 @@ import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
@ -74,7 +69,6 @@ import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableColumn.SortType;
@ -83,9 +77,7 @@ import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
@ -97,16 +89,18 @@ import kellerkinder.HomeFlix.controller.DBController;
import kellerkinder.HomeFlix.controller.OMDbAPIController;
import kellerkinder.HomeFlix.controller.UpdateController;
import kellerkinder.HomeFlix.datatypes.SourceDataType;
import kellerkinder.HomeFlix.player.Player;
import kellerkinder.HomeFlix.datatypes.FilmTabelDataType;
public class MainWindowController {
@FXML
private AnchorPane mainAnchorPane;
@FXML
private AnchorPane tableModeAnchorPane;
@FXML
private ScrollPane settingsScrollPane;
@FXML
private ScrollPane textScrollPane;
@ -127,82 +121,65 @@ public class MainWindowController {
@FXML
private JFXButton playbtn;
@FXML
private JFXButton openfolderbtn;
@FXML
private JFXButton returnBtn;
@FXML
private JFXButton forwardBtn;
@FXML
private JFXButton aboutBtn;
@FXML
private JFXButton settingsBtn;
@FXML
private JFXButton updateBtn;
@FXML
private JFXButton addDirectoryBtn;
@FXML
private JFXButton addStreamSourceBtn;
@FXML
private JFXButton aboutBtn;
@FXML
private JFXButton settingsBtn;
@FXML
private JFXButton debugBtn;
@FXML
public JFXButton updateBtn;
@FXML
private JFXButton addDirectoryBtn;
@FXML
private JFXButton addStreamSourceBtn;
@FXML
private JFXHamburger menuHam;
@FXML
private JFXToggleButton autoUpdateToggleBtn;
@FXML
private JFXTextField searchTextField;
@FXML
public JFXColorPicker colorPicker;
@FXML
public ChoiceBox<String> languageChoisBox = new ChoiceBox<>();
private JFXHamburger menuHam;
@FXML
public ChoiceBox<String> branchChoisBox = new ChoiceBox<>();
private JFXToggleButton autoUpdateToggleBtn;
@FXML
private JFXToggleButton autoplayToggleBtn;
@FXML
public JFXSlider fontsizeSlider;
@FXML
private Label homeflixSettingsLbl;
@FXML
private Label mainColorLbl;
private JFXTextField searchTextField;
@FXML
private JFXColorPicker colorPicker;
@FXML
private ChoiceBox<String> languageChoisBox = new ChoiceBox<>();
@FXML
private ChoiceBox<String> branchChoisBox = new ChoiceBox<>();
@FXML
private JFXSlider fontsizeSlider;
@FXML
private Label homeflixSettingsLbl;
@FXML
private Label mainColorLbl;
@FXML
private Label fontsizeLbl;
@FXML
private Label languageLbl;
@FXML
private Label languageLbl;
@FXML
private Label updateLbl;
@FXML
private Label branchLbl;
@FXML
private Label sourcesLbl;
@FXML
private Label versionLbl;
@FXML
@FXML
private ImageView posterImageView;
private ImageView imv1;
private ImageView imv1;
@FXML
private TreeItem<FilmTabelDataType> filmRoot = new TreeItem<>(new FilmTabelDataType("", "", "", "", false, false, imv1));
@ -216,46 +193,44 @@ public class MainWindowController {
private TreeTableColumn<FilmTabelDataType, String> columnEpisode = new TreeTableColumn<>("Episode");
@FXML
private TreeTableColumn<FilmTabelDataType, ImageView> columnFavorite = new TreeTableColumn<>("Favorite");
@FXML
private TreeItem<SourceDataType> sourceRoot =new TreeItem<>(new SourceDataType("", ""));
@FXML
private TableColumn<SourceDataType, String> sourceColumn;
@FXML
private TableColumn<SourceDataType, String> modeColumn;
@FXML
private TreeItem<SourceDataType> sourceRoot = new TreeItem<>(new SourceDataType("", ""));
@FXML
private TableColumn<SourceDataType, String> sourceColumn;
@FXML
private TableColumn<SourceDataType, String> modeColumn;
private boolean menuTrue = false;
private boolean settingsTrue = false;
private boolean autoUpdate = false;
private boolean useBeta = false;
private static final Logger LOGGER = LogManager.getLogger(MainWindowController.class.getName());
private boolean autoplay = false;
private static final Logger LOGGER = LogManager.getLogger(MainWindowController.class.getName());
private int hashA = -647380320;
private String version = "0.6.0";
private String buildNumber = "141";
private String versionName = "plasma vampire";
private final String version = "0.7.0";
private final String buildNumber = "151";
private final String versionName = "toothless dragon";
private String dialogBtnStyle;
private String color;
private String title;
private String streamUrl;
private String ratingSortType;
private String local;
private String omdbAPIKey;
// text strings
private String errorPlay;
private String errorLoad;
private String errorSave;
private String infoText;
private String vlcNotInstalled;
public double size;
private double fontSize;
private int last;
private int indexTable;
private int indexList;
private int next;
private ResourceBundle bundle;
private FilmTabelDataType currentTableFilm = new FilmTabelDataType("", "", "", "", false, false, null);
private ObservableList<String> languages = FXCollections.observableArrayList("English (en_US)", "Deutsch (de_DE)");
private ObservableList<String> branches = FXCollections.observableArrayList("stable", "beta");
private ObservableList<FilmTabelDataType> filterData = FXCollections.observableArrayList();
@ -267,9 +242,8 @@ public class MainWindowController {
private ImageView skip_next_black = new ImageView(new Image("icons/ic_skip_next_black_18dp_1x.png"));
private ImageView play_arrow_white = new ImageView(new Image("icons/ic_play_arrow_white_18dp_1x.png"));
private ImageView play_arrow_black = new ImageView(new Image("icons/ic_play_arrow_black_18dp_1x.png"));
private DirectoryChooser directoryChooser = new DirectoryChooser();
private MenuItem like = new MenuItem("like");
private MenuItem dislike = new MenuItem("dislike"); //TODO one option (like or dislike)
private MenuItem like = new MenuItem("like");
private MenuItem dislike = new MenuItem("dislike"); // TODO one option (like or dislike)
private ContextMenu menu = new ContextMenu(like, dislike);
private Properties props = new Properties();
@ -290,12 +264,14 @@ public class MainWindowController {
omdbAPIController = new OMDbAPIController(this, dbController, this.main);
}
// call all initialize methods
void init() {
LOGGER.info("Initializing Project-HomeFlix build " + buildNumber);
loadSettings();
checkAutoUpdate();
initTabel();
initActions();
initUI();
initActions();
}
// Initialize the tables (treeTableViewfilm and sourcesTable)
@ -326,18 +302,18 @@ public class MainWindowController {
filmsTreeTable.getColumns().add(columnFavorite);
filmsTreeTable.getColumns().add(columnSeason);
filmsTreeTable.getColumns().add(columnEpisode);
filmsTreeTable.getColumns().get(0).setVisible(false); //hide columnStreamUrl (important)
// context menu for treeTableViewfilm
filmsTreeTable.getColumns().get(0).setVisible(false); // hide columnStreamUrl (important)
// context menu for treeTableViewfilm
filmsTreeTable.setContextMenu(menu);
// sourcesTreeTable
sourceColumn.setCellValueFactory(cellData -> cellData.getValue().pathProperty());
modeColumn.setCellValueFactory(cellData -> cellData.getValue().modeProperty());
sourcesTable.setItems(sourcesList);
// sourcesTreeTable
sourceColumn.setCellValueFactory(cellData -> cellData.getValue().pathProperty());
modeColumn.setCellValueFactory(cellData -> cellData.getValue().modeProperty());
sourcesTable.setItems(sourcesList);
}
//Initializing the actions
// Initializing the actions
private void initActions() {
HamburgerBackArrowBasicTransition burgerTask = new HamburgerBackArrowBasicTransition(menuHam);
@ -364,7 +340,7 @@ public class MainWindowController {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
ObservableList<FilmTabelDataType> helpData;
filterData.removeAll(filterData);
filterData.clear();
filmRoot.getChildren().removeAll(filmRoot.getChildren());
helpData = filmsList;
@ -412,9 +388,9 @@ public class MainWindowController {
fontsizeSlider.valueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) {
setSize(fontsizeSlider.getValue());
if (title != null) {
dbController.readCache(streamUrl);
setFontSize(fontsizeSlider.getValue());
if (!getCurrentTitle().isEmpty()) {
dbController.readCache(getCurrentStreamUrl());
}
// ta1.setFont(Font.font("System", size));
saveSettings();
@ -424,8 +400,8 @@ public class MainWindowController {
like.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
dbController.like(streamUrl);
dbController.refresh(streamUrl, indexList);
dbController.like(getCurrentStreamUrl());
dbController.refresh(getCurrentStreamUrl(), indexList);
refreshTable();
}
});
@ -433,59 +409,41 @@ public class MainWindowController {
dislike.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
dbController.dislike(streamUrl);
dbController.refresh(streamUrl, indexList);
dbController.dislike(getCurrentStreamUrl());
dbController.refresh(getCurrentStreamUrl(), indexList);
refreshTable();
}
});
/**
* FIXME fix bug when sort by ASCENDING, wrong order
* FIXME when sorting, series are expanded
*/
columnFavorite.sortTypeProperty().addListener(new ChangeListener<SortType>() {
@Override
public void changed(ObservableValue<? extends SortType> paramObservableValue, SortType paramT1, SortType paramT2) {
LOGGER.info("NAME Clicked -- sortType = " + paramT1 + ", SortType=" + paramT2);
ArrayList<Integer> fav_true = new ArrayList<Integer>();
ArrayList<Integer> fav_false = new ArrayList<Integer>();
ObservableList<FilmTabelDataType> helpData;
filterData.removeAll(filterData);
// treeTableViewfilm.getSelectionModel().clearSelection(selected);
filmRoot.getChildren().removeAll(filmRoot.getChildren());
helpData = filmsList;
for (int i = 0; i < helpData.size(); i++) {
if (helpData.get(i).getFavorite() == true) {
fav_true.add(i);
} else {
fav_false.add(i);
}
}
if (paramT2.toString().equals("DESCENDING")) {
LOGGER.info("Absteigend"); // Debug, delete?
for (int i = 0; i < fav_true.size(); i++) {
filterData.add(helpData.get(fav_true.get(i)));
}
for (int i = 0; i < fav_false.size(); i++) {
filterData.add(helpData.get(fav_false.get(i)));
filmRoot.getChildren().clear();
filterData.clear();
if (paramT2.equals(SortType.DESCENDING)) {
for (FilmTabelDataType film : filmsList) {
if (film.getFavorite()) {
filterData.add(0, film);
} else {
filterData.add(film);
}
}
} else {
for (int i = 0; i < fav_false.size(); i++) {
filterData.add(helpData.get(fav_false.get(i)));
}
for (int i = 0; i < fav_true.size(); i++) {
filterData.add(helpData.get(fav_true.get(i)));
// System.out.println("ascending");
for (FilmTabelDataType film : filmsList) {
if (!film.getFavorite()) {
filterData.add(0, film);
} else {
filterData.add(film);
}
}
}
LOGGER.info(filterData.size()); // Debug, delete?
for (int i = 0; i < filterData.size(); i++) {
// LOGGER.info(filterData.get(i).getTitle()+"; "+filterData.get(i).getRating()); // Debugging
// add filtered data to root node after search
filmRoot.getChildren().add(new TreeItem<FilmTabelDataType>(filterData.get(i)));
}
addDataUI(filterData);
}
});
@ -493,22 +451,25 @@ public class MainWindowController {
filmsTreeTable.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
@Override
public void changed(ObservableValue<?> observable, Object oldVal, Object newVal) {
indexTable = filmsTreeTable.getSelectionModel().getSelectedIndex(); // get selected item
last = indexTable - 1;
next = indexTable + 1;
title = columnTitle.getCellData(indexTable); // get name of selected item
streamUrl = columnStreamUrl.getCellData(indexTable); // get file path of selected item
if (filmsTreeTable.getSelectionModel().getSelectedItem() == null) {
return;
}
for (FilmTabelDataType helpData : filmsList) {
if (helpData.getStreamUrl().equals(streamUrl)) {
indexList = filmsList.indexOf(helpData);
currentTableFilm = filmsTreeTable.getSelectionModel().getSelectedItem().getValue(); // set the current film object
indexTable = filmsTreeTable.getSelectionModel().getSelectedIndex(); // get selected items table index
for (FilmTabelDataType film : filmsList) {
if (film.equals(currentTableFilm)) {
indexList = filmsList.indexOf(film); // get selected items list index
}
}
if (filmsList.get(indexList).getCached()) {
LOGGER.info("loading from cache: " + title);
dbController.readCache(streamUrl);
} else {
last = indexTable - 1;
next = indexTable + 1;
if (currentTableFilm.getCached() || dbController.searchCache(getCurrentStreamUrl())) {
LOGGER.info("loading from cache: " + getCurrentTitle());
dbController.readCache(getCurrentStreamUrl());
} else {
omdbAPIController = new OMDbAPIController(mainWindowController, dbController, main);
Thread omdbAPIThread = new Thread(omdbAPIController);
omdbAPIThread.setName("OMDbAPI");
@ -520,15 +481,13 @@ public class MainWindowController {
// initialize UI elements
private void initUI() {
debugBtn.setDisable(true); // debugging button for tests
debugBtn.setVisible(false);
versionLbl.setText("Version: " + version + " (Build: " + buildNumber + ")");
fontsizeSlider.setValue(getSize());
fontsizeSlider.setValue(getFontSize());
colorPicker.setValue(Color.valueOf(getColor()));
updateBtn.setFont(Font.font("System", 12));
autoUpdateToggleBtn.setSelected(isAutoUpdate());
autoplayToggleBtn.setSelected(isAutoplay());
languageChoisBox.setItems(languages);
branchChoisBox.setItems(branches);
@ -544,48 +503,67 @@ public class MainWindowController {
@FXML
private void playbtnclicked() {
// TODO rework when #19 is coming
if (System.getProperty("os.name").contains("Linux")) {
String line;
String output = "";
Process p;
try {
p = Runtime.getRuntime().exec("which vlc");
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
output = line;
if (currentTableFilm.getStreamUrl().contains("_rootNode")) {
LOGGER.info("rootNode found, getting last watched episode");
currentTableFilm = dbController.getLastWatchedEpisode(currentTableFilm.getTitle());
}
if (isSupportedFormat(currentTableFilm)) {
new Player(mainWindowController);
} else {
LOGGER.error("using fallback player!");
if (System.getProperty("os.name").contains("Linux")) {
String line;
String output = "";
Process p;
try {
p = Runtime.getRuntime().exec("which vlc");
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
output = line;
}
LOGGER.info(output);
input.close();
} catch (IOException e1) {
e1.printStackTrace();
}
LOGGER.info(output);
input.close();
} catch (IOException e1) {
e1.printStackTrace();
}
if (output.contains("which: no vlc") || output == "") {
JFXInfoDialog vlcInfoDialog = new JFXInfoDialog("Info", vlcNotInstalled, dialogBtnStyle, 350, 200, main.getPane());
vlcInfoDialog.show();
} else {
if (output.contains("which: no vlc") || output == "") {
JFXInfoAlert vlcInfoAlert = new JFXInfoAlert("Info", vlcNotInstalled, dialogBtnStyle, main.getPrimaryStage());
vlcInfoAlert.showAndWait();
} else {
try {
new ProcessBuilder("vlc", getCurrentStreamUrl()).start();
} catch (IOException e) {
LOGGER.warn("An error has occurred while opening the file!", e);
}
}
} else if (System.getProperty("os.name").contains("Windows") || System.getProperty("os.name").contains("Mac OS X")) {
try {
Runtime.getRuntime().exec(new String[] { "vlc", streamUrl }); // TODO switch to ProcessBuilder
Desktop.getDesktop().open(new File(getCurrentStreamUrl()));
} catch (IOException e) {
showErrorMsg(errorPlay, e);
LOGGER.warn("An error has occurred while opening the file!", e);
}
} else {
LOGGER.error(System.getProperty("os.name") + ", OS is not supported, please contact a developer! ");
}
} else if (System.getProperty("os.name").contains("Windows") || System.getProperty("os.name").contains("Mac OS X")) {
try {
Desktop.getDesktop().open(new File(streamUrl));
} catch (IOException e) {
showErrorMsg(errorPlay, e);
}
} else {
LOGGER.error(System.getProperty("os.name") + ", OS is not supported, please contact a developer! ");
}
}
/**
* check if a film is supported by the HomeFlixPlayer or not
* this is the case if the mime type is mp4
* @param entry the film you want to check
* @return true if so, false if not
*/
private boolean isSupportedFormat(FilmTabelDataType film) {
String mimeType = URLConnection.guessContentTypeFromName(film.getStreamUrl());
return mimeType != null && (mimeType.contains("mp4") || mimeType.contains("vp6"));
}
@FXML
private void openfolderbtnclicked() {
String dest = new File(streamUrl).getParentFile().getAbsolutePath();
String dest = new File(getCurrentStreamUrl()).getParentFile().getAbsolutePath();
if (!System.getProperty("os.name").contains("Linux")) {
try {
Desktop.getDesktop().open(new File(dest));
@ -609,8 +587,8 @@ public class MainWindowController {
private void aboutBtnAction() {
String bodyText = "cemu_UI by @Seil0 \nVersion: " + version + " (Build: " + buildNumber + ") \""
+ versionName + "\" \n" + infoText;
JFXInfoDialog aboutDialog = new JFXInfoDialog("Project HomeFlix", bodyText, dialogBtnStyle, 350, 200, main.getPane());
aboutDialog.show();
JFXInfoAlert infoAlert = new JFXInfoAlert("Project HomeFlix", bodyText, dialogBtnStyle, main.getPrimaryStage());
infoAlert.showAndWait();
}
@FXML
@ -625,17 +603,13 @@ public class MainWindowController {
}
}
@FXML
private void debugBtnclicked(){
//for testing
}
@FXML
private void addDirectoryBtnAction(){
File selectedFolder = directoryChooser.showDialog(null);
DirectoryChooser directoryChooser = new DirectoryChooser();
directoryChooser.setTitle(bundle.getString("addDirectory"));
File selectedFolder = directoryChooser.showDialog(main.getPrimaryStage());
if (selectedFolder != null && selectedFolder.exists()) {
addSource(selectedFolder.getPath(), "local");
dbController.refreshDataBase();
mainWindowController.addSource(selectedFolder.getPath(), "local");
} else {
LOGGER.error("The selected folder dosen't exist!");
}
@ -644,7 +618,7 @@ public class MainWindowController {
@FXML
private void addStreamSourceBtnAction(){
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open Resource File");
fileChooser.setTitle("addStreamSource");
File selectedFile = fileChooser.showOpenDialog(main.getPrimaryStage());
if (selectedFile != null && selectedFile.exists()) {
addSource(selectedFile.getPath(), "stream");
@ -670,7 +644,7 @@ public class MainWindowController {
@FXML
private void autoUpdateToggleBtnAction(){
if (autoUpdate) {
if (isAutoUpdate()) {
setAutoUpdate(false);
} else {
setAutoUpdate(true);
@ -678,6 +652,16 @@ public class MainWindowController {
saveSettings();
}
@FXML
private void autoplayToggleBtnAction(){
if (isAutoplay()) {
setAutoplay(false);
} else {
setAutoplay(true);
}
saveSettings();
}
// refresh the selected child of the root node
private void refreshTable() {
filmRoot.getChildren().get(indexTable).setValue(filmsList.get(indexList));
@ -686,32 +670,32 @@ public class MainWindowController {
/**
* add data from films-list to films-table
*/
public void addDataUI() {