/** * Project-HomeFlix * * Copyright 2016-2019 <@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 kellerkinder.HomeFlix.application; import java.awt.Desktop; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.Writer; import java.math.BigInteger; import java.net.URLConnection; import java.time.LocalDate; import java.util.Locale; import java.util.ResourceBundle; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.Collectors; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.kellerkinder.Alerts.JFXInfoAlert; import com.eclipsesource.json.Json; import com.eclipsesource.json.JsonArray; import com.eclipsesource.json.JsonObject; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXColorPicker; import com.jfoenix.controls.JFXHamburger; import com.jfoenix.controls.JFXSlider; import com.jfoenix.controls.JFXTextField; import com.jfoenix.controls.JFXToggleButton; import com.jfoenix.transitions.hamburger.HamburgerBackArrowBasicTransition; import javafx.animation.TranslateTransition; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.Node; import javafx.scene.control.ChoiceBox; import javafx.scene.control.ContextMenu; import javafx.scene.control.Label; import javafx.scene.control.MenuItem; import javafx.scene.control.ScrollPane; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeTableColumn; import javafx.scene.control.TreeTableColumn.SortType; import javafx.scene.control.TreeTableView; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.input.MouseEvent; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.FontWeight; import javafx.scene.text.Text; import javafx.scene.text.TextFlow; import javafx.stage.DirectoryChooser; import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.util.Duration; import kellerkinder.HomeFlix.controller.DBController; import kellerkinder.HomeFlix.controller.OMDbAPIController; import kellerkinder.HomeFlix.controller.UpdateController; import kellerkinder.HomeFlix.controller.XMLController; import kellerkinder.HomeFlix.datatypes.FilmTabelDataType; import kellerkinder.HomeFlix.datatypes.PosterModeElement; import kellerkinder.HomeFlix.datatypes.SourceDataType; import kellerkinder.HomeFlix.player.Player; public class MainWindowController { // general/settings fxml elements @FXML private AnchorPane mainAnchorPane; @FXML private ScrollPane settingsScrollPane; @FXML private JFXHamburger menuHam; @FXML private HBox topHBox; @FXML private VBox sideMenuVBox; @FXML private TableView sourcesTable; @FXML private JFXButton aboutBtn; @FXML private JFXButton settingsBtn; @FXML private JFXButton updateBtn; @FXML private JFXButton addDirectoryBtn; @FXML private JFXButton addStreamSourceBtn; @FXML private JFXToggleButton autoUpdateToggleBtn; @FXML private JFXToggleButton autoplayToggleBtn; @FXML private JFXColorPicker colorPicker; @FXML private ChoiceBox languageChoisBox = new ChoiceBox<>(); @FXML private ChoiceBox 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 updateLbl; @FXML private Label branchLbl; @FXML private Label sourcesLbl; @FXML private Label versionLbl; @FXML private TreeItem sourceRoot = new TreeItem<>(new SourceDataType("", "")); @FXML private TableColumn sourceColumn; @FXML private TableColumn modeColumn; // table-mode @FXML private AnchorPane tableModeAnchorPane; @FXML private JFXTextField searchTextField; @FXML private TreeTableView filmsTreeTable; @FXML private TreeTableColumn columnStreamUrl; @FXML private TreeTableColumn columnTitle; @FXML private TreeTableColumn columnFavorite; @FXML private TreeTableColumn columnSeason; @FXML private TreeTableColumn columnEpisode; @FXML private TreeItem filmRoot = new TreeItem<>(new FilmTabelDataType("", "", "", "", false, null, null)); @FXML private ScrollPane textScrollPane; @FXML private TextFlow textFlow; @FXML private ImageView posterImageView; @FXML private JFXButton playbtn; @FXML private JFXButton openfolderbtn; @FXML private JFXButton returnBtn; @FXML private JFXButton forwardBtn; // poster-mode @FXML private ScrollPane posterModeScrollPane; @FXML private AnchorPane posterModeAnchorPane; private int xPos = -200; private int yPos = 17; private int xNextElement = 0; private DBController dbController; private UpdateController updateController; private XMLController xmlController; private Stage primaryStage; private static final Logger LOGGER = LogManager.getLogger(MainWindowController.class.getName()); private boolean menuTrue = false; private final String version = "0.7.0"; private final String buildNumber = "169"; private final String versionName = "toothless dragon"; private String btnStyle; private final int hashA = -647380320; private int last; private int indexTable; private int indexList; private int next; private FilmTabelDataType currentTableFilm = new FilmTabelDataType("", "", "", "", false, null, null); private ObservableList languages = FXCollections.observableArrayList("English (en_US)", "Deutsch (de_DE)"); private ObservableList branches = FXCollections.observableArrayList("stable", "beta"); private ObservableList filterData = FXCollections.observableArrayList(); private ObservableList filmsList = FXCollections.observableArrayList(); private ObservableList posterEmenents = FXCollections.observableArrayList(); private static ObservableList sourcesList = FXCollections.observableArrayList(); 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 LocalDate lastValidCache = LocalDate.now().minusDays(30); // current date - 30 days is the last valid cache date public MainWindowController() { // the constructor } @FXML public void initialize() { xmlController = new XMLController(); dbController = DBController.getInstance(); } public void init() { LOGGER.info("Initializing Project-HomeFlix build " + buildNumber); xmlController.loadSettings(); // load settings checkAutoUpdate(); // initialize the GUI and the DBController primaryStage = (Stage) mainAnchorPane.getScene().getWindow(); // set primary stage for dialogs initTabel(); initUI(); initActions(); dbController.init(); refreshAllFilms(); // load sources list in gui addSourceToTable(); // posterModeStartup(); // TODO testing DO NOT USE THIS!! } // Initialize general UI elements private void initUI() { versionLbl.setText("Version: " + version + " (Build: " + buildNumber + ")"); fontsizeSlider.setValue(XMLController.getFontSize()); colorPicker.setValue(Color.valueOf(XMLController.getColor())); updateBtn.setFont(Font.font("System", 12)); autoUpdateToggleBtn.setSelected(XMLController.isAutoUpdate()); autoplayToggleBtn.setSelected(XMLController.isAutoplay()); languageChoisBox.setItems(languages); branchChoisBox.setItems(branches); if (XMLController.isUseBeta()) { branchChoisBox.getSelectionModel().select(1); } else { branchChoisBox.getSelectionModel().select(0); } setLocalUI(); applyColor(); } /** * Initialize the tables (treeTableViewfilm and sourcesTable) only needed for * Tabel-Mode */ private void initTabel() { // film Table filmsTreeTable.setRoot(filmRoot); filmsTreeTable.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY); filmsTreeTable.setShowRoot(false); // write content into cell columnStreamUrl.setCellValueFactory(cellData -> cellData.getValue().getValue().streamUrlProperty()); columnTitle.setCellValueFactory(cellData -> cellData.getValue().getValue().titleProperty()); columnSeason.setCellValueFactory(cellData -> cellData.getValue().getValue().seasonProperty()); columnEpisode.setCellValueFactory(cellData -> cellData.getValue().getValue().episodeProperty()); columnFavorite.setCellValueFactory(cellData -> cellData.getValue().getValue().imageProperty()); // context menu for treeTableViewfilm filmsTreeTable.setContextMenu(menu); // sourcesTreeTable sourceColumn.setCellValueFactory(cellData -> cellData.getValue().pathProperty()); modeColumn.setCellValueFactory(cellData -> cellData.getValue().modeProperty()); sourcesTable.setItems(sourcesList); } // Initializing the actions private void initActions() { // general actions HamburgerBackArrowBasicTransition burgerTask = new HamburgerBackArrowBasicTransition(menuHam); menuHam.addEventHandler(MouseEvent.MOUSE_PRESSED, (e) -> { if (menuTrue) { sideMenuSlideOut(); burgerTask.setRate(-1.0); burgerTask.play(); menuTrue = false; } else { sideMenuSlideIn(); burgerTask.setRate(1.0); burgerTask.play(); menuTrue = true; } if (settingsScrollPane.isVisible()) { settingsScrollPane.setVisible(false); } }); languageChoisBox.getSelectionModel().selectedIndexProperty().addListener((e, oldValue, newValue) -> { String local = languageChoisBox.getItems().get((int) newValue).toString(); local = local.substring(local.length() - 6, local.length() - 1); // reading only en_US from English (en_US) XMLController.setUsrLocal(local); setLocalUI(); xmlController.saveSettings(); }); branchChoisBox.getSelectionModel().selectedIndexProperty().addListener((e, oldValue, newValue) -> { if (branchChoisBox.getItems().get((int) newValue).toString() == "beta") { XMLController.setUseBeta(true); } else { XMLController.setUseBeta(false); } xmlController.saveSettings(); }); fontsizeSlider.valueProperty().addListener(e -> { XMLController.setFontSize(fontsizeSlider.getValue()); if (!getCurrentTitle().isEmpty()) { setSelectedFilmInfo(dbController.readCache(getCurrentStreamUrl())); } xmlController.saveSettings(); }); // Table-Mode actions searchTextField.textProperty().addListener((e, oldValue, newValue) -> { filmRoot.getChildren().clear(); filterData.clear(); filterData = filmsList.stream() .filter(x -> x.getTitle().toLowerCase().contains(searchTextField.getText().toLowerCase())) .collect(Collectors.toCollection(FXCollections::observableArrayList)); addFilmsToTable(filterData); if (searchTextField.getText().hashCode() == hashA) { XMLController.setColor("000000"); colorPicker.setValue(new Color(0, 0, 0, 1)); applyColor(); } }); like.setOnAction(e -> { dbController.like(getCurrentStreamUrl()); filmsList.set(indexList, dbController.getStream(getCurrentStreamUrl())); refreshTableElement(); }); dislike.setOnAction(e -> { dbController.dislike(getCurrentStreamUrl()); filmsList.set(indexList, dbController.getStream(getCurrentStreamUrl())); refreshTableElement(); }); // FIXME fix bug when sort by ASCENDING, wrong order columnFavorite.sortTypeProperty().addListener((e, paramT1, paramT2) -> { filmRoot.getChildren().clear(); filterData.clear(); if (paramT2.equals(SortType.DESCENDING)) { // add favorites at the top for (FilmTabelDataType film : filmsList) { if (film.getFavorite()) { filterData.add(0, film); } else { filterData.add(film); } } } else { // add favorites at the bottom for (FilmTabelDataType film : filmsList) { if (!film.getFavorite()) { filterData.add(0, film); } else { filterData.add(film); } } } addFilmsToTable(filterData); }); // Change-listener for treeTableViewfilm filmsTreeTable.getSelectionModel().selectedItemProperty().addListener((e, paramT1, paramT2) -> { if (filmsTreeTable.getSelectionModel().getSelectedItem() == null) { return; } currentTableFilm = filmsTreeTable.getSelectionModel().getSelectedItem().getValue(); // set the current film object indexTable = filmsTreeTable.getSelectionModel().getSelectedIndex(); // get selected items table index last = indexTable - 1; next = indexTable + 1; for (FilmTabelDataType film : filmsList) { if (film.equals(currentTableFilm)) { indexList = filmsList.indexOf(film); // get selected items list index } } if ((currentTableFilm.getCached().isAfter(lastValidCache)) && dbController.searchCacheByURL(getCurrentStreamUrl())) { LOGGER.info("loading from cache: " + getCurrentTitle()); setSelectedFilmInfo(dbController.readCache(getCurrentStreamUrl())); } else { // this is not perfect! new Thread(() -> { Thread omdbAPIThread = new Thread(new OMDbAPIController(dbController, currentTableFilm, XMLController.getOmdbAPIKey())); omdbAPIThread.setName("OMDbAPI"); omdbAPIThread.start(); synchronized (omdbAPIThread) { try { omdbAPIThread.wait(); } catch (InterruptedException e1) { LOGGER.error(e1); } // update the GUI for the selected film Platform.runLater(() -> { setSelectedFilmInfo(dbController.readCache(getCurrentStreamUrl())); }); } }).start(); } }); // Poster-Mode actions } // Table-Mode fxml actions @FXML private void playbtnclicked() { if (currentTableFilm.getStreamUrl().length() > 0) { if (currentTableFilm.getStreamUrl().contains("_rootNode")) { LOGGER.info("rootNode found, getting last watched episode"); currentTableFilm = dbController.getLastWatchedEpisode(currentTableFilm.getTitle()); } if (isSupportedFormat(currentTableFilm)) { new Player(getCurrentTableFilm()); } 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("which vlc: " + output); input.close(); } catch (IOException e1) { e1.printStackTrace(); } if (output.contains("which: no vlc") || output == "") { JFXInfoAlert vlcInfoAlert = new JFXInfoAlert("Info", XMLController.getLocalBundle().getString("vlcNotInstalled"), btnStyle, primaryStage); 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 { Desktop.getDesktop().open(new File(getCurrentStreamUrl())); } catch (IOException 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! "); } } } } @FXML private void openfolderbtnclicked() { File dest = new File(getCurrentStreamUrl()).getParentFile(); if (!System.getProperty("os.name").contains("Linux")) { try { Desktop.getDesktop().open(dest); } catch (IOException e) { e.printStackTrace(); } } } @FXML private void returnBtnclicked() { filmsTreeTable.getSelectionModel().select(last); } @FXML private void forwardBtnclicked() { filmsTreeTable.getSelectionModel().select(next); } // general fxml actions @FXML private void aboutBtnAction() { String bodyText = "Project HomeFlix \nVersion: " + version + " (Build: " + buildNumber + ") \"" + versionName + "\" \n" + XMLController.getLocalBundle().getString("infoText"); JFXInfoAlert infoAlert = new JFXInfoAlert("Project HomeFlix", bodyText, btnStyle, primaryStage); infoAlert.showAndWait(); } @FXML private void settingsBtnclicked() { settingsScrollPane.setVisible(!settingsScrollPane.isVisible()); } @FXML private void addDirectoryBtnAction() { DirectoryChooser directoryChooser = new DirectoryChooser(); directoryChooser.setTitle(XMLController.getLocalBundle().getString("addDirectory")); File selectedFolder = directoryChooser.showDialog(primaryStage); if (selectedFolder != null && selectedFolder.exists()) { addSource(selectedFolder.getPath(), "local"); } else { LOGGER.error("The selected folder dosen't exist!"); } } @FXML private void addStreamSourceBtnAction() { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle(XMLController.getLocalBundle().getString("addStreamSource")); File selectedFile = fileChooser.showOpenDialog(primaryStage); if (selectedFile != null && selectedFile.exists()) { addSource(selectedFile.getPath(), "stream"); } else { LOGGER.error("The selected file dosen't exist!"); } } @FXML private void colorPickerAction() { XMLController.setColor(colorPicker.getValue().toString().substring(2, 10)); xmlController.saveSettings(); applyColor(); } @FXML private void updateBtnAction() { updateController = new UpdateController(this, buildNumber, XMLController.isUseBeta()); Thread updateThread = new Thread(updateController); updateThread.setName("Updater"); updateThread.start(); } @FXML private void autoUpdateToggleBtnAction() { XMLController.setAutoUpdate(!XMLController.isAutoUpdate()); xmlController.saveSettings(); } @FXML private void autoplayToggleBtnAction() { XMLController.setAutoplay(!XMLController.isAutoplay()); xmlController.saveSettings(); } // refresh the selected child of the root node private void refreshTableElement() { filmRoot.getChildren().get(indexTable).setValue(filmsList.get(indexList)); } /** * refresh all films in filmsList and in filmsTable clear the FilmsList and * FilmRoot children, then update the database */ private void refreshAllFilms() { filmsList.clear(); dbController.refreshDataBase(); // refreshes the database after a source path was added filmsList = dbController.getStreamsList(); // returns a list of all films stored in the database // refresh filmRoot in filmsTreeTable filmRoot.getChildren().clear(); addFilmsToTable(filmsList); // } /** * TODO rework! add data from a ObservableList to the films-table * * @param elementsList a list of elements you want to add */ public void addFilmsToTable(ObservableList elementsList) { for (FilmTabelDataType element : elementsList) { // only if the entry contains a season and a episode it's a valid series if (!element.getSeason().isEmpty() && !element.getEpisode().isEmpty()) { // if there is any node check if it's the root node to the episode // else there is no node at all so we must create a new if (filmRoot.getChildren().size() > 0) { for (int i = 0; i < filmRoot.getChildren().size(); i++) { // if a root node exists, add element // else create a new root node and add the element (if rootNode is the last // node) (works since we edit the element!) if (filmRoot.getChildren().get(i).getValue().getTitle().equals(element.getTitle())) { TreeItem episodeNode = new TreeItem<>( new FilmTabelDataType(element.getStreamUrl(), element.getTitle(), element.getSeason(), element.getEpisode(), element.getFavorite(), element.getCached(), element.getImage())); filmRoot.getChildren().get(i).getChildren().add(episodeNode); } else if (filmRoot.getChildren().get(i).nextSibling() == null) { TreeItem seriesRootNode = new TreeItem<>( new FilmTabelDataType(element.getTitle() + "_rootNode", element.getTitle(), "", "", element.getFavorite(), element.getCached(), element.getImage())); filmRoot.getChildren().add(seriesRootNode); } } } else { // add new root node TreeItem seriesRootNode = new TreeItem<>( new FilmTabelDataType(element.getTitle() + "_rootNode", element.getTitle(), "", "", element.getFavorite(), element.getCached(), element.getImage())); filmRoot.getChildren().add(seriesRootNode); // add new element TreeItem episodeNode = new TreeItem<>(new FilmTabelDataType( element.getStreamUrl(), element.getTitle(), element.getSeason(), element.getEpisode(), element.getFavorite(), element.getCached(), element.getImage())); filmRoot.getChildren().get(0).getChildren().add(episodeNode); } } else { // if season and episode are empty, we can assume the object is a film filmRoot.getChildren().add(new TreeItem(element)); } } } // add a all elements of sourcesList to the sources table on the settings pane public void addSourceToTable() { for (SourceDataType source : sourcesList) { sourceRoot.getChildren().add(new TreeItem(source)); // add data to root-node } } /** * add a source to the newsources list * * @param path to the source * @param mode of the source (local or streaming) */ public void addSource(String path, String mode) { JsonArray newsources = null; try { // read old array File oldSources = new File(XMLController.getDirHomeFlix() + "/sources.json"); if (oldSources.exists()) { newsources = Json.parse(new FileReader(XMLController.getDirHomeFlix() + "/sources.json")).asArray(); } else { newsources = Json.array(); } // add new source JsonObject source = Json.object().add("path", path).add("mode", mode); newsources.add(source); Writer writer = new FileWriter(XMLController.getDirHomeFlix() + "/sources.json"); newsources.writeTo(writer); writer.close(); } catch (IOException e) { LOGGER.error(e); } // clear old sources list/table getSourcesList().clear(); sourceRoot.getChildren().clear(); refreshAllFilms(); // refresh the FilmsList checkAllPosters(); // check if there is anything to cache } /** * set the color of the GUI-Elements if usedColor is less than checkColor set * text fill white, else black */ private void applyColor() { String menuBtnStyle; BigInteger usedColor = new BigInteger(XMLController.getColor(), 16); BigInteger checkColor = new BigInteger("78909cff", 16); if (usedColor.compareTo(checkColor) == -1) { btnStyle = "-fx-button-type: RAISED; -fx-background-color: #" + XMLController.getColor() + "; -fx-text-fill: WHITE;"; menuBtnStyle = "-fx-text-fill: WHITE;"; playbtn.setGraphic(new ImageView(new Image("icons/ic_play_arrow_white_18dp_1x.png"))); returnBtn.setGraphic(new ImageView(new Image("icons/ic_skip_previous_white_18dp_1x.png"))); forwardBtn.setGraphic(new ImageView(new Image("icons/ic_skip_next_white_18dp_1x.png"))); menuHam.getStyleClass().clear(); menuHam.getStyleClass().add("jfx-hamburgerW"); } else { btnStyle = "-fx-button-type: RAISED; -fx-background-color: #" + XMLController.getColor() + "; -fx-text-fill: BLACK;"; menuBtnStyle = "-fx-text-fill: BLACK;"; playbtn.setGraphic(new ImageView(new Image("icons/ic_play_arrow_black_18dp_1x.png"))); returnBtn.setGraphic(new ImageView(new Image("icons/ic_skip_previous_black_18dp_1x.png"))); forwardBtn.setGraphic(new ImageView(new Image("icons/ic_skip_next_black_18dp_1x.png"))); menuHam.getStyleClass().clear(); menuHam.getStyleClass().add("jfx-hamburgerB"); } // boxes and TextFields sideMenuVBox.setStyle("-fx-background-color: #" + XMLController.getColor() + ";"); topHBox.setStyle("-fx-background-color: #" + XMLController.getColor() + ";"); searchTextField.setFocusColor(Color.valueOf(XMLController.getColor())); // normal buttons addDirectoryBtn.setStyle(btnStyle); addStreamSourceBtn.setStyle(btnStyle); updateBtn.setStyle(btnStyle); playbtn.setStyle(btnStyle); openfolderbtn.setStyle(btnStyle); returnBtn.setStyle(btnStyle); forwardBtn.setStyle(btnStyle); // menu buttons settingsBtn.setStyle(menuBtnStyle); aboutBtn.setStyle(menuBtnStyle); } // slide in in 400ms private void sideMenuSlideIn() { sideMenuVBox.setVisible(true); TranslateTransition translateTransition = new TranslateTransition(Duration.millis(400), sideMenuVBox); translateTransition.setFromX(-150); translateTransition.setToX(0); translateTransition.play(); } // slide out in 400ms private void sideMenuSlideOut() { TranslateTransition translateTransition = new TranslateTransition(Duration.millis(400), sideMenuVBox); translateTransition.setFromX(0); translateTransition.setToX(-150); translateTransition.play(); } /** * set the local based on the languageChoisBox selection */ private void setLocalUI() { switch (XMLController.getUsrLocal()) { case "en_US": XMLController.setLocalBundle(ResourceBundle.getBundle("locals.HomeFlix-Local", Locale.US)); // us_English languageChoisBox.getSelectionModel().select(0); break; case "de_DE": XMLController.setLocalBundle(ResourceBundle.getBundle("locals.HomeFlix-Local", Locale.GERMAN)); // German languageChoisBox.getSelectionModel().select(1); break; default: XMLController.setLocalBundle(ResourceBundle.getBundle("locals.HomeFlix-Local", Locale.US)); // default local languageChoisBox.getSelectionModel().select(0); break; } aboutBtn.setText(XMLController.getLocalBundle().getString("info")); settingsBtn.setText(XMLController.getLocalBundle().getString("settings")); searchTextField.setPromptText(XMLController.getLocalBundle().getString("tfSearch")); openfolderbtn.setText(XMLController.getLocalBundle().getString("openFolder")); updateBtn.setText(XMLController.getLocalBundle().getString("checkUpdates")); addDirectoryBtn.setText(XMLController.getLocalBundle().getString("addDirectory")); addStreamSourceBtn.setText(XMLController.getLocalBundle().getString("addStreamSource")); homeflixSettingsLbl.setText(XMLController.getLocalBundle().getString("homeflixSettingsLbl")); mainColorLbl.setText(XMLController.getLocalBundle().getString("mainColorLbl")); fontsizeLbl.setText(XMLController.getLocalBundle().getString("fontsizeLbl")); languageLbl.setText(XMLController.getLocalBundle().getString("languageLbl")); autoUpdateToggleBtn.setText(XMLController.getLocalBundle().getString("autoUpdate")); autoplayToggleBtn.setText(XMLController.getLocalBundle().getString("autoplay")); branchLbl.setText(XMLController.getLocalBundle().getString("branchLbl")); columnStreamUrl.setText(XMLController.getLocalBundle().getString("columnStreamUrl")); columnTitle.setText(XMLController.getLocalBundle().getString("columnName")); columnFavorite.setText(XMLController.getLocalBundle().getString("columnFavorite")); columnSeason.setText(XMLController.getLocalBundle().getString("columnSeason")); columnEpisode.setText(XMLController.getLocalBundle().getString("columnEpisode")); } private void setSelectedFilmInfo(String[] cacheData) { Font font = Font.font("System", FontWeight.BOLD, (int) Math.round(XMLController.getFontSize())); ObservableList textFlow = getTextFlow().getChildren(); // TODO this should move! *** Text[] nameText = new Text[20]; nameText[0] = new Text(XMLController.getLocalBundle().getString("title") + ": "); nameText[1] = new Text(XMLController.getLocalBundle().getString("year") + ": "); nameText[2] = new Text(XMLController.getLocalBundle().getString("rated") + ": "); nameText[3] = new Text(XMLController.getLocalBundle().getString("released") + ": "); nameText[4] = new Text(XMLController.getLocalBundle().getString("season") + ": "); nameText[5] = new Text(XMLController.getLocalBundle().getString("episode") + ": "); nameText[6] = new Text(XMLController.getLocalBundle().getString("runtime") + ": "); nameText[7] = new Text(XMLController.getLocalBundle().getString("genre") + ": "); nameText[8] = new Text(XMLController.getLocalBundle().getString("director") + ": "); nameText[9] = new Text(XMLController.getLocalBundle().getString("writer") + ": "); nameText[10] = new Text(XMLController.getLocalBundle().getString("actors") + ": "); nameText[11] = new Text(XMLController.getLocalBundle().getString("plot") + ": "); nameText[12] = new Text(XMLController.getLocalBundle().getString("language") + ": "); nameText[13] = new Text(XMLController.getLocalBundle().getString("country") + ": "); nameText[14] = new Text(XMLController.getLocalBundle().getString("awards") + ": "); nameText[15] = new Text(XMLController.getLocalBundle().getString("metascore") + ": "); nameText[16] = new Text(XMLController.getLocalBundle().getString("imdbRating") + ": "); nameText[17] = new Text(XMLController.getLocalBundle().getString("type") + ": "); nameText[18] = new Text(XMLController.getLocalBundle().getString("boxOffice") + ": "); nameText[19] = new Text(XMLController.getLocalBundle().getString("website") + ": "); // *** // set the correct font for the nameText for (Text text : nameText) { text.setFont(font); } // clear the textFlow and add the new text textFlow.clear(); for (int i = 0; i < 20; i++) { // if the cacheData exists and they are not empty add the text if(cacheData[i] != null && cacheData[i].length() > 0) { textFlow.addAll(nameText[i], new Text(cacheData[i] + "\n")); } } getTextFlow().setStyle("-fx-font-size : " + ((int) Math.round(XMLController.getFontSize()) + 1) + "px;"); // add the image if (new File(cacheData[20]).isFile()) { try { posterImageView.setImage(new Image(new File(cacheData[20]).toURI().toString())); } catch (Exception e) { posterImageView.setImage(new Image(cacheData[20])); LOGGER.error("No Poster found, useing default."); } } else { posterImageView.setImage(new Image(cacheData[20])); } } // if AutoUpdate, then check for updates private void checkAutoUpdate() { if (XMLController.isAutoUpdate()) { try { LOGGER.info("AutoUpdate: looking for updates on startup ..."); updateController = new UpdateController(this, buildNumber, XMLController.isUseBeta()); Thread updateThread = new Thread(updateController); updateThread.setName("Updater"); updateThread.start(); updateThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 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")); } /** * Poser Mode WIP */ private void posterModeStartup() { checkAllPosters(); addGUIElements(); } /** * check if all posters are cached, if not cache the missing ones */ private void checkAllPosters() { // get all not cached entries, none of them should have a cached poster ExecutorService executor = Executors.newFixedThreadPool(5); for (FilmTabelDataType entry : dbController.getAllNotCachedEntries()) { System.out.println(entry.getStreamUrl() + " is NOT cached!"); Runnable OMDbAPIWorker = new OMDbAPIController(dbController, entry, XMLController.getOmdbAPIKey()); executor.execute(OMDbAPIWorker); } executor.shutdown(); // TODO show loading screen // executor.awaitTermination(1, TimeUnit.MINUTES); // we might need this as otherwise it would load before all tasks are finished // update all elements from the database refreshAllFilms(); System.out.println("finished refresh"); } /** * add all cached films/series to the PosterMode GUI */ private void addGUIElements() { // refresh the posterModeElements list posterEmenents.clear(); posterEmenents = dbController.getPosterElementsList(); // returns a list of all PosterElements stored in the database posterModeAnchorPane.getChildren().clear(); // remove all GUIElements from the posterModeAnchorPane // reset the position xPos = -200; yPos = 17; xNextElement = 0; // add all films/series as new GUIElements to the posterModeAnchorPane for(PosterModeElement element : posterEmenents) { generatePosition(); element.setLayoutX(xPos); element.setLayoutY(yPos); posterModeAnchorPane.getChildren().add(element); } } /** * xMaxElements based on window width -36 * calculates how many games can be displayed in one row */ private void generatePosition() { int xMaxElements = (int) Math.floor((mainAnchorPane.getWidth() - 36) / 217); if(xNextElement >= xMaxElements){ // oldXPosHelper = xNextElement; // only needed if window resizing is allowed xPos = 17; yPos = yPos + 345; xNextElement = 1; }else{ xPos = xPos + 217; xNextElement++; } } // getter and setter public FilmTabelDataType getCurrentTableFilm() { return currentTableFilm; } public String getCurrentTitle() { return currentTableFilm.getTitle(); } public String getCurrentStreamUrl() { return currentTableFilm.getStreamUrl(); } public int getIndexTable() { return indexTable; } public int getIndexList() { return indexList; } public static ObservableList getSourcesList() { return sourcesList; } public TextFlow getTextFlow() { return textFlow; } public JFXButton getUpdateBtn() { return updateBtn; } }