Compare commits

..

1 Commits
dev ... master

Author SHA1 Message Date
Jannik 3805e6563d Merge branch 'dev' of Seil0/Project-HomeFlix into master 2019-07-04 12:41:05 +02:00
46 changed files with 890 additions and 1656 deletions

View File

@ -1,5 +0,0 @@
pipeline:
package:
image: maven
commands:
- mvn clean package

View File

@ -1,6 +1,5 @@
[![Build Status](https://ci.mosad.xyz/api/badges/Seil0/Project-HomeFlix/status.svg)](https://ci.mosad.xyz/Seil0/Project-HomeFlix) [![Latest](https://img.shields.io/badge/Download-latest-brightgreen.svg)](https://git.mosad.xyz/Seil0/Project-HomeFlix/releases)
[![Release](https://img.shields.io/badge/dynamic/json.svg?label=release&url=https://git.mosad.xyz/api/v1/repos/Seil0/Project-HomeFlix/releases&query=$[0].tag_name)](https://git.mosad.xyz/Seil0/Project-HomeFlix/releases)
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Latest](https://img.shields.io/badge/Download-latest-brightgreen.svg?style=flat-square)](https://git.mosad.xyz/Seil0/Project-HomeFlix/releases)
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg?style=flat-square)](https://www.gnu.org/licenses/gpl-3.0)
# Project-HomeFlix
Project-HomeFlix is a Kellerkinder Project, that alowes you to sort all your local saved movies in clean UI. Project-HomeFlix is free and open-source software and uses other open-source projects to provied a nice user experience.
@ -14,6 +13,6 @@ The dev branch is **only merged** into master when a **new release** is released
[Libraries used in this Project](https://git.mosad.xyz/Seil0/Project-HomeFlix/wiki/Documentation#used-libraries-and-apis)
## Screenshots
![Screenshot](https://raw.githubusercontent.com/Seil0/Seil0.github.io/master/images/Project-HomeFlix_MainWindow.webp)
![Screenshot](https://raw.githubusercontent.com/Seil0/Seil0.github.io/master/images/Project-HomeFlix_MainWindow.png)
Project-HomeFlix © 2016-2019 mosad www.mosad.xyz, Project by [@Seil0](https://git.mosad.xyz/Seil0) and [@localhorst](https://git.mosad.xyz/localhorst)

41
pom.xml
View File

@ -3,17 +3,16 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.mosad</groupId>
<groupId>org.kellerkinder</groupId>
<artifactId>Project-HomeFlix</artifactId>
<version>0.8.0</version>
<version>0.7.0</version>
<packaging>jar</packaging>
<name>Project-HomeFlix</name>
<url>https://www.mosad.xyz</url>
<url>http://www.mosad.xyz</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<javafx.version>16</javafx.version>
</properties>
<dependencies>
@ -21,44 +20,38 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
<version>12.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
<version>12.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>uk.co.caprica</groupId>
<artifactId>vlcj</artifactId>
<version>4.5.2</version>
<version>12.0.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
<version>2.6</version>
</dependency>
<dependency>
<groupId>com.jfoenix</groupId>
<artifactId>jfoenix</artifactId>
<version>9.0.10</version>
<version>9.0.9</version>
</dependency>
<dependency>
@ -70,19 +63,19 @@
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.36.0.3</version>
<version>3.27.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.1</version>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
<version>2.11.2</version>
</dependency>
</dependencies>
@ -92,7 +85,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<version>3.8.0</version>
<configuration>
<source>11</source>
<target>11</target>
@ -105,7 +98,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<version>1.6.0</version>
<executions>
<execution>
<goals>
@ -114,21 +107,21 @@
</execution>
</executions>
<configuration>
<mainClass>org.mosad.homeflix.application.Main</mainClass>
<mainClass>kellerkinder.HomeFlix.application.Main</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<version>3.2.1</version>
<configuration>
<finalName>Project-HomeFlix</finalName>
<shadedArtifactAttached>true</shadedArtifactAttached>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.mosad.homeflix.application.JavaFX11Main</mainClass>
<mainClass>kellerkinder.HomeFlix.application.JavaFX11Main</mainClass>
</transformer>
</transformers>
</configuration>

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <@Seil0>
* 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
@ -20,7 +20,7 @@
*
*/
package org.mosad.homeflix.application.view;
package kellerkinder.HomeFlix.application;
import java.awt.Desktop;
import java.io.File;
@ -28,20 +28,24 @@ import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mosad.homeflix.controller.DBController;
import org.mosad.homeflix.controller.XMLController;
import org.mosad.homeflix.datatypes.OMDbAPIResponseDataType;
import org.mosad.homeflix.player.Player;
import com.jfoenix.controls.JFXButton;
import javafx.animation.FadeTransition;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.text.Text;
import javafx.util.Duration;
import kellerkinder.HomeFlix.controller.DBController;
import kellerkinder.HomeFlix.controller.XMLController;
import kellerkinder.HomeFlix.player.Player;
public class FilmDetailView extends DetailView {
public class FilmDetailView {
@FXML private AnchorPane filmDVPane;
@FXML private Label lblTitle;
@FXML private Label lblYear;
@ -83,7 +87,7 @@ public class FilmDetailView extends DetailView {
public void initialize() {
dbController = DBController.getInstance();
rootPane.setStyle("-fx-background-color: rgba(89,89,89,0.9);");
filmDVPane.setStyle("-fx-background-color: rgba(89,89,89,0.9);");
}
@FXML
@ -110,7 +114,7 @@ public class FilmDetailView extends DetailView {
@FXML
private void btnPlayAction() {
new Player(currentStreamURL);
playFilm();
}
@FXML
@ -132,29 +136,29 @@ public class FilmDetailView extends DetailView {
*/
public void setFilm(String streamURL) {
currentStreamURL = streamURL;
OMDbAPIResponseDataType cacheInfo = dbController.readCache(streamURL); // get the cache data from the database
String[] cacheInfo = dbController.readCache(streamURL); // get the cache data from the database
// add the cache data to the GUI
lblTitle.setText(cacheInfo.getTitle());
lblYear.setText("(" + cacheInfo.getYear() + ")");
lblScore.setText(XMLController.getLocalBundle().getString("score") + ": " + cacheInfo.getMetascore() + "%");
lblTitle.setText(cacheInfo[0]);
lblYear.setText("(" + cacheInfo[1] + ")");
lblScore.setText(XMLController.getLocalBundle().getString("score") + ": " + cacheInfo[15] + "%");
textPlot.setText(cacheInfo.getPlot());
textPlot.setText(cacheInfo[11]);
lblDirectors.setText(cacheInfo.getDirector());
lblWriters.setText(cacheInfo.getWriter());
lblActors.setText(cacheInfo.getActors());
lblDirectors.setText(cacheInfo[8]);
lblWriters.setText(cacheInfo[9]);
lblActors.setText(cacheInfo[10]);
lblRuntime.setText(cacheInfo.getRuntime());
lblLanguage.setText(cacheInfo.getLanguage());
lblRevenue.setText(cacheInfo.getBoxOffice());
lblRating.setText(cacheInfo.getRated());
lblRuntime.setText(cacheInfo[6]);
lblLanguage.setText(cacheInfo[12]);
lblRevenue.setText(cacheInfo[18]);
lblRating.setText(cacheInfo[2]);
try {
if (new File(cacheInfo.getPoster()).isFile()) {
imgPoster.setImage(new Image(new File(cacheInfo.getPoster()).toURI().toString()));
if (new File(cacheInfo[20]).isFile()) {
imgPoster.setImage(new Image(new File(cacheInfo[20]).toURI().toString()));
} else {
imgPoster.setImage(new Image(cacheInfo.getPoster()));
imgPoster.setImage(new Image(cacheInfo[20]));
}
} catch (Exception e) {
imgPoster.setImage(new Image("icons/Homeflix_Poster.png"));
@ -173,7 +177,6 @@ public class FilmDetailView extends DetailView {
/**
* update the text of all static GUI elements of FilmDeatilView
*/
@Override
public void updateGUILocal() {
lblCrew.setText(XMLController.getLocalBundle().getString("crew"));
lblDirectorsInfo.setText(XMLController.getLocalBundle().getString("directors"));
@ -186,5 +189,38 @@ public class FilmDetailView extends DetailView {
lblRevenueInfo.setText(XMLController.getLocalBundle().getString("boxOffice"));
lblRatingInfo.setText(XMLController.getLocalBundle().getString("rated"));
}
/**
* show the FilmDVpane
*/
public void showPane() {
filmDVPane.setVisible(true);
FadeTransition fadeIn = new FadeTransition(Duration.millis(300), filmDVPane);
fadeIn.setFromValue(0.3);
fadeIn.setToValue(1.0);
fadeIn.play();
}
/**
* hide the FilmDVpane
*/
private void hidePane() {
FadeTransition fadeOut = new FadeTransition(Duration.millis(200), filmDVPane);
fadeOut.setFromValue(1.0);
fadeOut.setToValue(0.3);
fadeOut.play();
filmDVPane.setVisible(false);
MainWindowController.getInstance().disableBlur(); // disable blur
}
private void playFilm() {
if(new File(currentStreamURL).isDirectory()) {
return;
}
new Player(currentStreamURL);
}
}

View File

@ -1,4 +1,4 @@
package org.mosad.homeflix.application;
package kellerkinder.HomeFlix.application;
public class JavaFX11Main {

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <@Seil0>
* 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
@ -20,15 +20,13 @@
*
*/
package org.mosad.homeflix.application;
package kellerkinder.HomeFlix.application;
import java.io.File;
import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mosad.homeflix.controller.DBController;
import org.mosad.homeflix.controller.XMLController;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
@ -36,6 +34,7 @@ import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import kellerkinder.HomeFlix.controller.XMLController;
public class Main extends Application {
@ -44,14 +43,12 @@ public class Main extends Application {
private MainWindowController mainWindowController;
private static XMLController xmlController;
private static Logger LOGGER;
public static final String version = "0.8.91";
public static final String buildNumber = "177";
public static final String versionName = "nimbly xlr8";
// TODO rename streamURL to mediaURL
public static final String version = "0.8.0";
public static final String buildNumber = "173";
public static final String versionName = "toothless dragon";
@Override
public void start(Stage primaryStage) {
public void start(Stage primaryStage) throws IOException {
//initialize the mainWindowController and the primaryStage
try {
@ -63,10 +60,7 @@ 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(event -> {
DBController.getInstance().closeDBConnection();
System.exit(0);
});
primaryStage.setOnCloseRequest(event -> System.exit(0));
// generate window
scene = new Scene(pane); // create new scene, append pane to scene
@ -104,9 +98,7 @@ public class Main extends Application {
LOGGER.info("Java: " + XMLController.getJavaVend() + " " + XMLController.getJavaVers());
LOGGER.info("User: " + XMLController.getUserName() + " " + XMLController.getUserHome());
xmlController = new XMLController(); // Initialize the XMLController
// TODO run Migrations
xmlController = new XMLController();
if (!XMLController.getConfigFile().exists()) {
xmlController.saveSettings(); // save the settings file with default values if it doesn't exist
@ -118,7 +110,7 @@ public class Main extends Application {
XMLController.getPosterCache().mkdir();
}
launch();
launch(args);
}
}

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <@Seil0>
* 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
@ -20,7 +20,7 @@
*
*/
package org.mosad.homeflix.application;
package kellerkinder.HomeFlix.application;
import java.io.File;
import java.io.FileReader;
@ -39,14 +39,6 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.kellerkinder.Alerts.JFX2BtnCancelAlert;
import org.kellerkinder.Alerts.JFXInfoAlert;
import org.mosad.homeflix.application.view.FilmDetailView;
import org.mosad.homeflix.application.view.SeriesDetailView;
import org.mosad.homeflix.controller.DBController;
import org.mosad.homeflix.controller.OMDbAPIController;
import org.mosad.homeflix.controller.UpdateController;
import org.mosad.homeflix.controller.XMLController;
import org.mosad.homeflix.datatypes.FilmTabelDataType;
import org.mosad.homeflix.datatypes.PosterModeElement;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
@ -71,6 +63,12 @@ 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;
public class MainWindowController {
@ -106,7 +104,7 @@ public class MainWindowController {
private String btnStyle;
private ObservableList<PosterModeElement> posterEmenents = FXCollections.observableArrayList();
private final LocalDate lastValidCache = LocalDate.now().minusDays(30); // current date - 30 days is the last valid cache date
private LocalDate lastValidCache = LocalDate.now().minusDays(30); // current date - 30 days is the last valid cache date
public MainWindowController() {
// the constructor
@ -149,7 +147,7 @@ public class MainWindowController {
// load data list in gui
posterModeStartup();
checkAutoUpdate(); // TODO async
}
@ -158,7 +156,7 @@ public class MainWindowController {
// general actions
HamburgerBackArrowBasicTransition burgerTask = new HamburgerBackArrowBasicTransition(menuHam);
menuHam.addEventHandler(MouseEvent.MOUSE_PRESSED, e -> {
menuHam.addEventHandler(MouseEvent.MOUSE_PRESSED, (e) -> {
if (menuTrue) {
sideMenuSlideOut();
@ -360,27 +358,29 @@ public class MainWindowController {
* check if all posters are cached, if not cache the missing ones
*/
void checkAllPosters() {
dbController.refreshDataBase(); // refreshes the database after a source path was added
// get all not cached entries, none of them should have a cached poster
ExecutorService executor = Executors.newFixedThreadPool(5);
dbController.refreshDataBase(); // refreshes the database after a source path was added
// get all not cached entries
for (FilmTabelDataType entry : dbController.getAllNotCachedEntries()) {
// System.out.println(entry.getStreamUrl() + " is NOT cached!");
Runnable OMDbAPIWorker = new OMDbAPIController(entry);
executor.execute(OMDbAPIWorker);
}
executor.shutdown();
// TODO show loading screen
// wait for all OMDbAPI requests to finish
// we might need this as otherwise it would load before all tasks are finished
try {
executor.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
LOGGER.error(e);
}
LOGGER.info("finished refresh");
System.out.println("finished refresh");
}
/**
@ -393,7 +393,7 @@ public class MainWindowController {
// add button onAction
for (PosterModeElement element : posterEmenents) {
element.getButton().addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
element.getButton().addEventHandler(MouseEvent.MOUSE_CLICKED, (event) -> {
enableBlur(); // blur the FlowPane
// if the selected element is a file it's a film, else a series
@ -409,6 +409,8 @@ public class MainWindowController {
posterModeFlowPane.getChildren().clear(); // remove all GUIElements from the posterModeFlowPane
posterModeFlowPane.getChildren().addAll(posterEmenents); // add all films/series as new GUIElements to the posterModeFlowPane
System.out.println("added gui elements");
}
// TODO can this be done in dbController? with dbController.refreshDataBase();

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <@Seil0>
* 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
@ -20,7 +20,7 @@
*
*/
package org.mosad.homeflix.application.view;
package kellerkinder.HomeFlix.application;
import java.awt.Desktop;
import java.io.File;
@ -28,14 +28,10 @@ import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mosad.homeflix.controller.DBController;
import org.mosad.homeflix.controller.XMLController;
import org.mosad.homeflix.datatypes.OMDbAPIResponseDataType;
import org.mosad.homeflix.datatypes.SeriesDVEpisode;
import org.mosad.homeflix.player.Player;
import com.jfoenix.controls.JFXButton;
import javafx.animation.FadeTransition;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
@ -45,11 +41,18 @@ import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.util.Duration;
import kellerkinder.HomeFlix.controller.DBController;
import kellerkinder.HomeFlix.controller.XMLController;
import kellerkinder.HomeFlix.datatypes.SeriresDVEpisode;
import kellerkinder.HomeFlix.player.Player;
public class SeriesDetailView extends DetailView {
public class SeriesDetailView {
@FXML private AnchorPane seriesDVPane;
@FXML private ScrollPane scrollPaneEpisodes;
@FXML private HBox hBoxEpisodes;
@ -86,7 +89,7 @@ public class SeriesDetailView extends DetailView {
public void initialize() {
dbController = DBController.getInstance();
rootPane.setStyle("-fx-background-color: rgba(89,89,89,0.9);");
seriesDVPane.setStyle("-fx-background-color: rgba(89,89,89,0.9);");
scrollPaneEpisodes.setStyle("-fx-background-color: transparent;");
scrollPaneEpisodes.setHbarPolicy(ScrollBarPolicy.ALWAYS);
@ -141,21 +144,21 @@ public class SeriesDetailView extends DetailView {
*/
public void setSeries(String streamURL) {
currentStreamURL = streamURL;
OMDbAPIResponseDataType cacheInfo = dbController.readCache(streamURL); // get the cache data from the database
String[] cacheInfo = dbController.readCache(streamURL); // get the cache data from the database
// add the cache data to the GUI
lblTitle.setText(cacheInfo.getTitle());
lblYear.setText("(" + cacheInfo.getYear() + ")");
lblScore.setText(XMLController.getLocalBundle().getString("score") + ": " + cacheInfo.getMetascore() + "%");
lblTitle.setText(cacheInfo[0]);
lblYear.setText("(" + cacheInfo[1] + ")");
lblScore.setText(XMLController.getLocalBundle().getString("score") + ": " + cacheInfo[15] + "%");
textPlot.setText(cacheInfo.getPlot());
textPlot.setText(cacheInfo[11]);
lblDirectors.setText(cacheInfo.getDirector());
lblWriters.setText(cacheInfo.getWriter());
lblActors.setText(cacheInfo.getActors());
lblDirectors.setText(cacheInfo[8]);
lblWriters.setText(cacheInfo[9]);
lblActors.setText(cacheInfo[10]);
try {
imgPoster.setImage(new Image(new File(cacheInfo.getPoster()).toURI().toString()));
imgPoster.setImage(new Image(new File(cacheInfo[20]).toURI().toString()));
} catch (Exception e) {
imgPoster.setImage(new Image("icons/Homeflix_Poster.png"));
LOGGER.error("No Poster found, useing default.");
@ -184,7 +187,6 @@ public class SeriesDetailView extends DetailView {
/**
* update the text of all static GUI elements of FilmDeatilView
*/
@Override
public void updateGUILocal() {
lblCrew.setText(XMLController.getLocalBundle().getString("crew"));
lblDirectorsInfo.setText(XMLController.getLocalBundle().getString("directors"));
@ -192,6 +194,31 @@ public class SeriesDetailView extends DetailView {
lblActorsInfo.setText(XMLController.getLocalBundle().getString("actors"));
}
/**
* show the FilmDVpane
*/
public void showPane() {
seriesDVPane.setVisible(true);
FadeTransition fadeIn = new FadeTransition(Duration.millis(300), seriesDVPane);
fadeIn.setFromValue(0.3);
fadeIn.setToValue(1.0);
fadeIn.play();
}
/**
* hide the FilmDVpane
*/
private void hidePane() {
FadeTransition fadeOut = new FadeTransition(Duration.millis(200), seriesDVPane);
fadeOut.setFromValue(1.0);
fadeOut.setToValue(0.3);
fadeOut.play();
seriesDVPane.setVisible(false);
MainWindowController.getInstance().disableBlur(); // disable blur
}
/**
* add all episodes of one season to the ScrollPane
* @param season the season to add
@ -205,7 +232,7 @@ public class SeriesDetailView extends DetailView {
} catch (Exception e) {
poster = new Image("icons/Homeflix_Poster.png");
}
hBoxEpisodes.getChildren().add(new SeriesDVEpisode(episodePoster[0], episodePoster[1], poster));
hBoxEpisodes.getChildren().add(new SeriresDVEpisode(episodePoster[0], episodePoster[1], poster));
}
}

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <@Seil0>
* 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
@ -20,7 +20,7 @@
*
*/
package org.mosad.homeflix.application;
package kellerkinder.HomeFlix.application;
import java.io.File;
import java.io.FileReader;
@ -30,11 +30,6 @@ import java.io.Writer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mosad.homeflix.application.view.FilmDetailView;
import org.mosad.homeflix.controller.DBController;
import org.mosad.homeflix.controller.UpdateController;
import org.mosad.homeflix.controller.XMLController;
import org.mosad.homeflix.datatypes.SourceDataType;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
@ -59,6 +54,10 @@ import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import kellerkinder.HomeFlix.controller.DBController;
import kellerkinder.HomeFlix.controller.UpdateController;
import kellerkinder.HomeFlix.controller.XMLController;
import kellerkinder.HomeFlix.datatypes.SourceDataType;
public class SettingsView {
@ -87,7 +86,6 @@ public class SettingsView {
@FXML private JFXToggleButton autoUpdateToggleBtn;
@FXML private JFXToggleButton autoplayToggleBtn;
@FXML private JFXToggleButton fullscreenToggleBtn;
@FXML private TableView<SourceDataType> sourcesTable;
@FXML private TableColumn<SourceDataType, String> sourceColumn;
@ -110,7 +108,6 @@ public class SettingsView {
autoUpdateToggleBtn.setSelected(XMLController.isAutoUpdate());
autoplayToggleBtn.setSelected(XMLController.isAutoplay());
fullscreenToggleBtn.setSelected(XMLController.isFullscreen());
languageChoisBox.setItems(languages);
branchChoisBox.setItems(branches);
@ -199,12 +196,6 @@ public class SettingsView {
XMLController.setAutoplay(!XMLController.isAutoplay());
xmlController.saveSettings();
}
@FXML
private void fullscreenToggleBtnAction(ActionEvent event) {
XMLController.setFullscreen(!XMLController.isFullscreen());
xmlController.saveSettings();
}
@FXML
private void colorPickerAction(ActionEvent event) {
@ -215,12 +206,16 @@ public class SettingsView {
@FXML
private void updateBtnAction(ActionEvent event) {
new UpdateController();
if (UpdateController.isUpdateAvailable()) {
updateBtn.setText(XMLController.getLocalBundle().getString("updateBtnUpdateAvailable"));
UpdateController.update();
} else {
updateBtn.setText(XMLController.getLocalBundle().getString("updateBtnNoUpdateAvailable"));
}
}
/** TODO can this be done async?
@ -280,8 +275,6 @@ public class SettingsView {
autoUpdateToggleBtn.setToggleLineColor(Color.valueOf(XMLController.getColor()));
autoplayToggleBtn.setToggleColor(Color.valueOf(XMLController.getColor()));
autoplayToggleBtn.setToggleLineColor(Color.valueOf(XMLController.getColor()));
fullscreenToggleBtn.setToggleColor(Color.valueOf(XMLController.getColor()));
fullscreenToggleBtn.setToggleLineColor(Color.valueOf(XMLController.getColor()));
}
public void updateGUILocal() {
@ -298,7 +291,6 @@ public class SettingsView {
autoUpdateToggleBtn.setText(XMLController.getLocalBundle().getString("autoUpdate"));
autoplayToggleBtn.setText(XMLController.getLocalBundle().getString("autoplay"));
fullscreenToggleBtn.setText(XMLController.getLocalBundle().getString("fullscreen"));
}
public void setVisible(boolean visible) {

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <@Seil0>
* 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
@ -19,7 +19,7 @@
* MA 02110-1301, USA.
*/
package org.mosad.homeflix.controller;
package kellerkinder.HomeFlix.controller;
import java.io.File;
import java.io.FileNotFoundException;
@ -38,14 +38,14 @@ import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mosad.homeflix.datatypes.DatabaseDataType;
import org.mosad.homeflix.datatypes.FilmTabelDataType;
import org.mosad.homeflix.datatypes.OMDbAPIResponseDataType;
import org.mosad.homeflix.datatypes.PosterModeElement;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.image.Image;
import kellerkinder.HomeFlix.datatypes.DatabaseDataType;
import kellerkinder.HomeFlix.datatypes.FilmTabelDataType;
import kellerkinder.HomeFlix.datatypes.OMDbAPIResponseDataType;
import kellerkinder.HomeFlix.datatypes.PosterModeElement;
public class DBController {
@ -103,13 +103,15 @@ public class DBController {
* cache table: streamUrl is primary key
*/
private void createDatabase() {
try (Statement stmt = connection.createStatement();) {
try {
Statement stmt = connection.createStatement();
stmt.executeUpdate("create table if not exists films (streamUrl, title, season, episode, favorite, cached, currentTime)");
stmt.executeUpdate("create table if not exists cache ("
+ "streamUrl, Title, Year, Rated, Released, Season, Episode ,Runtime, Genre, Director, Writer,"
+ " Actors, Plot, Language, Country, Awards, Poster, Metascore, imdbRating, imdbVotes,"
+ " imdbID, Type, dvd, BoxOffice, Website, Response)");
connection.commit();
stmt.close();
} catch (SQLException e) {
LOGGER.error(e);
}
@ -120,16 +122,16 @@ public class DBController {
*/
private void loadDatabase() {
// get all entries from the table
try (Statement stmt = connection.createStatement();) {
try (ResultSet rs = stmt.executeQuery("SELECT * FROM films");) {
while (rs.next()) {
databaseStreams.add(new DatabaseDataType(rs.getString("streamUrl"),
rs.getString("title"), rs.getString("season"), rs.getString("episode"),
rs.getInt("favorite"), rs.getDouble("currentTime")));
}
try {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM films");
while (rs.next()) {
databaseStreams.add(new DatabaseDataType(rs.getString("streamUrl"),
rs.getString("title"), rs.getString("season"), rs.getString("episode"),
rs.getInt("favorite"), rs.getDouble("currentTime")));
}
stmt.close();
rs.close();
} catch (SQLException e) {
LOGGER.error("Ups! an error occured!", e);
}
@ -143,18 +145,6 @@ public class DBController {
sourceStreams = sourcesController.loadSources();
}
/**
* try to close the databse connection
*/
public void closeDBConnection( ) {
try {
connection.commit();
connection.close();
} catch (SQLException e) {
LOGGER.error("Error while trying to close the databse connection", e);
}
}
/**
* load all streams from the database to a ObservableList, order entries by title
* @return a ObservableList that contains all streams from the database
@ -162,17 +152,17 @@ public class DBController {
public ObservableList<FilmTabelDataType> getStreamsList() {
ObservableList<FilmTabelDataType> filmsList = FXCollections.observableArrayList();
LOGGER.info("loading data from database ...");
//load local Data
try (Statement stmt = connection.createStatement(); ) {
try {
//load local Data
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM films ORDER BY title");
try (ResultSet rs = stmt.executeQuery("SELECT * FROM films ORDER BY title");) {
while (rs.next()) {
filmsList.add(new FilmTabelDataType(rs.getString("streamUrl"),
rs.getString("title"), rs.getString("season"), rs.getString("episode")));
}
while (rs.next()) {
filmsList.add(new FilmTabelDataType(rs.getString("streamUrl"),
rs.getString("title"), rs.getString("season"), rs.getString("episode")));
}
stmt.close();
rs.close();
} catch (SQLException e) {
LOGGER.error("Ups! an error occured!", e);
}
@ -188,16 +178,17 @@ public class DBController {
public FilmTabelDataType getStream(String streamUrl) {
FilmTabelDataType film = null;
LOGGER.info("refresh data for " + streamUrl);
try (PreparedStatement ps = connection.prepareStatement("SELECT * FROM films WHERE streamUrl = ?");) {
try {
PreparedStatement ps = connection.prepareStatement("SELECT * FROM films WHERE streamUrl = ?");
ps.setString(1, streamUrl);
ResultSet rs = ps.executeQuery();
try (ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
film = new FilmTabelDataType(rs.getString("streamUrl"),
rs.getString("title"), rs.getString("season"), rs.getString("episode"));
}
while (rs.next()) {
film = new FilmTabelDataType(rs.getString("streamUrl"),
rs.getString("title"), rs.getString("season"), rs.getString("episode"));
}
rs.close();
ps.close();
} catch (Exception e) {
LOGGER.error("Ups! error while refreshing mwc!", e);
}
@ -210,24 +201,25 @@ public class DBController {
* @return a ObservableList of PosterModeElements
*/
public ObservableList<PosterModeElement> getPosterElementsList() {
ObservableList<PosterModeElement> posterElementsList = FXCollections.observableArrayList();
LOGGER.info("loading data from database ...");
//load local Data
try (Statement stmt = connection.createStatement();) {
try {
//load local Data
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM films WHERE season = '' OR season = '0' ORDER BY title");
try (ResultSet rs = stmt.executeQuery("SELECT * FROM films WHERE season = '' OR season = '0' ORDER BY title");) {
while (rs.next()) {
String[] cacheData = readCacheLegacy(rs.getString("streamUrl")); // get from the cache table
if(cacheData[20] != null && cacheData[20].length() > 0) {
posterElementsList.add(new PosterModeElement(rs.getString("streamUrl"), cacheData[0], new Image(new File(cacheData[20]).toURI().toString())));
} else {
posterElementsList.add(new PosterModeElement(rs.getString("streamUrl"), cacheData[0], new Image("icons/Homeflix_Poster.png")));
}
while (rs.next()) {
String[] cacheData = readCache(rs.getString("streamUrl")); // get from the cache table
if(cacheData[20] != null && cacheData[20].length() > 0) {
posterElementsList.add(new PosterModeElement(rs.getString("streamUrl"), cacheData[0], new Image(new File(cacheData[20]).toURI().toString())));
} else {
posterElementsList.add(new PosterModeElement(rs.getString("streamUrl"), cacheData[0], new Image("icons/Homeflix_Poster.png")));
}
}
stmt.close();
rs.close();
} catch (SQLException e) {
LOGGER.error("An error occured while getting all PosterElements!", e);
}
@ -264,71 +256,69 @@ public class DBController {
* check if there are any entries that have been removed from the film-directory
* @throws SQLException
*/
private void checkRemoveEntry() {
private void checkRemoveEntry() throws SQLException {
PreparedStatement ps = connection.prepareStatement("DELETE FROM films WHERE streamUrl = ?");
LOGGER.info("checking for entrys to remove to DB ...");
try (PreparedStatement ps = connection.prepareStatement("DELETE FROM films WHERE streamUrl = ?");) {
for (DatabaseDataType dbStreamEntry : databaseStreams) {
// if the directory doen't contain the entry form the database, remove it
// if sourceStreams has a item where StreamUrl equals dbStreamEntry.getStreamUrl() return it, else null
DatabaseDataType result = sourceStreams.stream()
.filter(x -> dbStreamEntry.getStreamUrl().equals(x.getStreamUrl()))
.findAny()
.orElse(null);
// if the result is null, the file is missing, remove it from the database
if (result == null) {
ps.setString(1, dbStreamEntry.getStreamUrl());
ps.addBatch();
LOGGER.info("removed \"" + dbStreamEntry.getTitle() + "\" from database");
}
}
for (DatabaseDataType dbStreamEntry : databaseStreams) {
// if the directory doen't contain the entry form the database, remove it
ps.executeBatch();
connection.commit();
} catch (SQLException e) {
LOGGER.error("An error occured, while cheking for media to remove", e);
// if sourceStreams has a item where StreamUrl equals dbStreamEntry.getStreamUrl() return it, else null
DatabaseDataType result = sourceStreams.stream()
.filter(x -> dbStreamEntry.getStreamUrl().equals(x.getStreamUrl()))
.findAny()
.orElse(null);
// if the result is null, the file is missing, remove it from the database
if (result == null) {
ps.setString(1, dbStreamEntry.getStreamUrl());
ps.addBatch();
LOGGER.info("removed \"" + dbStreamEntry.getTitle() + "\" from database");
}
}
ps.executeBatch();
connection.commit();
ps.close();
}
/**
* check for new media in the source directories
* check if there are new films in the film-directory
* @throws SQLException
* @throws FileNotFoundException
* @throws IOException
*/
private void checkAddEntry() throws FileNotFoundException, IOException {
private void checkAddEntry() throws SQLException, FileNotFoundException, IOException {
PreparedStatement ps = connection.prepareStatement("insert into films values (?, ?, ?, ?, ?, ?, ?)");
LOGGER.info("checking for entrys to add to DB ...");
try (PreparedStatement ps = connection.prepareStatement("insert into films values (?, ?, ?, ?, ?, ?, ?)");) {
for (DatabaseDataType sourceStreamEntry : sourceStreams) {
// if databaseStream has a item where StreamUrl equals sourceStreamEntry.getStreamUrl() return it, else null
DatabaseDataType result = databaseStreams.stream()
.filter(x -> sourceStreamEntry.getStreamUrl().equals(x.getStreamUrl()))
.findAny()
.orElse(null);
// if the result is null, the entry is missing, add it to the database
if (result == null) {
ps.setString(1, sourceStreamEntry.getStreamUrl());
ps.setString(2, sourceStreamEntry.getTitle());
ps.setString(3, sourceStreamEntry.getSeason());
ps.setString(4, sourceStreamEntry.getEpisode());
ps.setInt(5, sourceStreamEntry.getFavorite());
ps.setDate(6, new Date(0));
ps.setDouble(7, sourceStreamEntry.getCurrentTime());
ps.addBatch(); // adds the entry
LOGGER.info("Added \"" + sourceStreamEntry.getTitle() + "\" to database");
databaseStreams.add(sourceStreamEntry);
}
}
// new
for (DatabaseDataType sourceStreamEntry : sourceStreams) {
ps.executeBatch();
connection.commit();
} catch (SQLException e) {
LOGGER.error("An error occured, while cheking for new media", e);
// if databaseStream has a item where StreamUrl equals sourceStreamEntry.getStreamUrl() return it, else null
DatabaseDataType result = databaseStreams.stream()
.filter(x -> sourceStreamEntry.getStreamUrl().equals(x.getStreamUrl()))
.findAny()
.orElse(null);
// if the result is null, the entry is missing, add it to the database
if (result == null) {
ps.setString(1, sourceStreamEntry.getStreamUrl());
ps.setString(2, sourceStreamEntry.getTitle());
ps.setString(3, sourceStreamEntry.getSeason());
ps.setString(4, sourceStreamEntry.getEpisode());
ps.setInt(5, sourceStreamEntry.getFavorite());
ps.setDate(6, new Date(0));
ps.setDouble(7, sourceStreamEntry.getCurrentTime());
ps.addBatch(); // adds the entry
LOGGER.info("Added \"" + sourceStreamEntry.getTitle() + "\" to database");
databaseStreams.add(sourceStreamEntry);
}
}
ps.executeBatch();
connection.commit();
ps.close();
}
/**
@ -337,42 +327,44 @@ public class DBController {
*/
public void printAllDBEntriesDEBUG() {
System.out.println("Outputting all entries ... \n");
try (Statement stmt = connection.createStatement();) {
try (ResultSet rs = stmt.executeQuery("SELECT * FROM films");) {
while (rs.next()) {
System.out.println(rs.getString("streamUrl"));
System.out.println(rs.getString("title"));
System.out.println(rs.getString("season"));
System.out.println(rs.getString("episode"));
System.out.println(rs.getString("rating"));
System.out.println(rs.getString("cached"));
System.out.println(rs.getString("currentTime") + "\n");
}
try {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM films");
while (rs.next()) {
System.out.println(rs.getString("streamUrl"));
System.out.println(rs.getString("title"));
System.out.println(rs.getString("season"));
System.out.println(rs.getString("episode"));
System.out.println(rs.getString("rating"));
System.out.println(rs.getString("cached"));
System.out.println(rs.getString("currentTime") + "\n");
}
rs.close();
stmt.close();
} catch (SQLException e) {
LOGGER.error("An error occured, while printing all entries", e);
}
}
/**
* return the favorite status of a media entry
* @param mediaURL URL of the media
* return the favorite state for a stream
* @param streamURL URL of the stream
* @return 0 if it's not a favorite, else 1
*/
public int getFavoriteState(String mediaURL) {
public int getFavoriteState(String streamURL) {
int favoriteState = 0;
try (PreparedStatement ps = connection.prepareStatement("SELECT favorite FROM films WHERE streamUrl = ?");) {
ps.setString(1, mediaURL);
PreparedStatement ps;
try {
ps = connection.prepareStatement("SELECT favorite FROM films WHERE streamUrl = ?");
ps.setString(1, streamURL);
ResultSet rs = ps.executeQuery();
try (ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
favoriteState = rs.getInt("favorite");
}
while (rs.next()) {
favoriteState = rs.getInt("favorite");
}
rs.close();
ps.close();
} catch (SQLException e) {
LOGGER.error("Ups! an error occured!", e);
}
@ -381,13 +373,18 @@ public class DBController {
}
public void toggleFavoriteState(String streamURL) {
int fav = getFavoriteState(streamURL) == 0 ? 1 : 0;
try (PreparedStatement ps = connection.prepareStatement("UPDATE films SET favorite = ? WHERE streamUrl = ?");) {
ps.setInt(1, fav);
ps.setString(2, streamURL);
PreparedStatement ps;
try {
if (getFavoriteState(streamURL) == 0) {
ps = connection.prepareStatement("UPDATE films SET favorite = 1 WHERE streamUrl = ?");
} else {
ps = connection.prepareStatement("UPDATE films SET favorite = 0 WHERE streamUrl = ?");
}
ps.setString(1, streamURL);
ps.executeUpdate();
connection.commit();
ps.close();
} catch (SQLException e) {
LOGGER.error("Ups! an error occured!", e);
}
@ -399,11 +396,12 @@ public class DBController {
*/
public void dislike(String streamUrl) {
LOGGER.info("dislike " + streamUrl);
try (PreparedStatement ps = connection.prepareStatement("UPDATE films SET favorite = 0 WHERE streamUrl = ?");){
try {
PreparedStatement ps = connection.prepareStatement("UPDATE films SET favorite = 0 WHERE streamUrl = ?");
ps.setString(1, streamUrl);
ps.executeUpdate();
connection.commit();
ps.close();
} catch (SQLException e) {
LOGGER.error("Ups! an error occured!", e);
}
@ -415,13 +413,14 @@ public class DBController {
*/
public void like(String streamUrl) {
LOGGER.info("like " + streamUrl);
try (PreparedStatement ps = connection.prepareStatement("UPDATE films SET favorite = 1 WHERE streamUrl = ?");) {
try {
PreparedStatement ps = connection.prepareStatement("UPDATE films SET favorite = 1 WHERE streamUrl = ?");
ps.setString(1, streamUrl);
ps.executeUpdate();
connection.commit();
ps.close();
} catch (SQLException e) {
LOGGER.error("Ups! An error occured!", e);
LOGGER.error("Ups! an error occured!", e);
}
}
@ -430,13 +429,15 @@ public class DBController {
* @param streamUrl URL of the film
*/
public void setCached(String streamUrl) {
try (PreparedStatement ps = connection.prepareStatement("UPDATE films SET cached = ? WHERE streamUrl = ?");) {
try {
PreparedStatement ps = connection.prepareStatement("UPDATE films SET cached = ? WHERE streamUrl = ?");
ps.setDate(1, new Date(System.currentTimeMillis()));
ps.setString(2, streamUrl);
ps.executeUpdate();
connection.commit();
ps.close();
} catch (SQLException e) {
LOGGER.error("Ups! An error occured, while setting cached = DATE for {}.", streamUrl, e);
LOGGER.error("Ups! an error occured!", e);
}
}
@ -446,18 +447,19 @@ public class DBController {
*/
public LocalDate getCacheDate(String streamUrl) {
LocalDate cacheDate = LocalDate.now().minusDays(31);
try (PreparedStatement ps = connection.prepareStatement("SELECT cached FROM films WHERE streamUrl = ?");){
try {
PreparedStatement ps = connection.prepareStatement("SELECT cached FROM films WHERE streamUrl = ?");
ps.setString(1, streamUrl);
ResultSet rs = ps.executeQuery();
try (ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
cacheDate = rs.getDate("cached").toLocalDate();
}
while (rs.next()) {
cacheDate = rs.getDate("cached").toLocalDate();
}
rs.close();
ps.close();
} catch (SQLException e) {
LOGGER.error("Ups! An error occured, while rerading the cached date for {}.", streamUrl, e);
LOGGER.error("Ups! an error occured!", e);
}
return cacheDate;
@ -469,9 +471,10 @@ public class DBController {
* @param omdbResponse the response data from omdbAPI
*/
public void addCache(String streamUrl, OMDbAPIResponseDataType omdbResponse) {
LOGGER.info("adding cache for: " + streamUrl);
try (PreparedStatement ps = connection.prepareStatement("insert into cache values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");){
try {
PreparedStatement ps = connection.prepareStatement("insert into cache values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
LOGGER.info("adding cache for: " + streamUrl);
ps.setString(1,streamUrl);
ps.setString(2,omdbResponse.getTitle());
ps.setString(3,omdbResponse.getYear());
@ -502,8 +505,9 @@ public class DBController {
ps.addBatch();
ps.executeBatch();
connection.commit();
ps.close();
} catch (Exception e) {
LOGGER.error("Ups! An error while adding cache data for {}.", streamUrl, e);
LOGGER.error(e);
}
}
@ -514,15 +518,15 @@ public class DBController {
*/
public boolean searchCacheByURL(String streamUrl) {
boolean retValue = false;
try (PreparedStatement ps = connection.prepareStatement("SELECT * FROM cache WHERE streamUrl = ?");) {
try {
PreparedStatement ps = connection.prepareStatement("SELECT * FROM cache WHERE streamUrl = ?");
ps.setString(1, streamUrl);
try (ResultSet rs = ps.executeQuery();) {
retValue = rs.next();
}
ResultSet rs = ps.executeQuery();
retValue = rs.next();
rs.close();
ps.close();
} catch (Exception e) {
LOGGER.error("Ups! An error while searching for {} in the cache.", streamUrl, e);
LOGGER.error("Ups! error while getting the current time!", e);
}
return retValue;
@ -533,89 +537,47 @@ public class DBController {
* @param streamUrl URL of the film
* @return a String array (length = 21) with all cached data
*/
public String[] readCacheLegacy(String streamUrl) {
public String[] readCache(String streamUrl) {
String[] cacheData = new String[21];
try (PreparedStatement ps = connection.prepareStatement("SELECT * FROM cache WHERE streamUrl = ?");) {
try {
PreparedStatement ps = connection.prepareStatement("SELECT * FROM cache WHERE streamUrl = ?");
ps.setString(1, streamUrl);
ResultSet rs = ps.executeQuery();
try (ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
cacheData[0] = rs.getString("Title");
cacheData[1] = rs.getString("Year");
cacheData[2] = rs.getString("Rated");
cacheData[3] = rs.getString("Released");
cacheData[4] = rs.getString("Season");
cacheData[5] = rs.getString("Episode");
cacheData[6] = rs.getString("Runtime");
cacheData[7] = rs.getString("Genre");
cacheData[8] = rs.getString("Director");
cacheData[9] = rs.getString("Writer");
cacheData[10] = rs.getString("Actors");
cacheData[11] = rs.getString("Plot");
cacheData[12] = rs.getString("Language");
cacheData[13] = rs.getString("Country");
cacheData[14] = rs.getString("Awards");
cacheData[15] = rs.getString("metascore");
cacheData[16] = rs.getString("imdbRating");
cacheData[17] = rs.getString("Type");
cacheData[18] = rs.getString("BoxOffice");
cacheData[19] = rs.getString("Website");
cacheData[20] = rs.getString("Poster");
}
while (rs.next()) {
cacheData[0] = rs.getString("Title");
cacheData[1] = rs.getString("Year");
cacheData[2] = rs.getString("Rated");
cacheData[3] = rs.getString("Released");
cacheData[4] = rs.getString("Season");
cacheData[5] = rs.getString("Episode");
cacheData[6] = rs.getString("Runtime");
cacheData[7] = rs.getString("Genre");
cacheData[8] = rs.getString("Director");
cacheData[9] = rs.getString("Writer");
cacheData[10] = rs.getString("Actors");
cacheData[11] = rs.getString("Plot");
cacheData[12] = rs.getString("Language");
cacheData[13] = rs.getString("Country");
cacheData[14] = rs.getString("Awards");
cacheData[15] = rs.getString("metascore");
cacheData[16] = rs.getString("imdbRating");
cacheData[17] = rs.getString("Type");
cacheData[18] = rs.getString("BoxOffice");
cacheData[19] = rs.getString("Website");
cacheData[20] = rs.getString("Poster");
}
rs.close();
ps.close();
} catch (SQLException e) {
LOGGER.error("Ups! error while getting the current time for {}.", streamUrl, e);
LOGGER.error("Ups! an error occured!", e);
}
return cacheData;
}
public OMDbAPIResponseDataType readCache(String streamUrl) {
OMDbAPIResponseDataType omdbResponse = new OMDbAPIResponseDataType();
try (PreparedStatement ps = connection.prepareStatement("SELECT * FROM cache WHERE streamUrl = ?");) {
ps.setString(1, streamUrl);
try (ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
omdbResponse.setTitle(rs.getString("Title"));
omdbResponse.setYear(rs.getString("Year"));
omdbResponse.setRated(rs.getString("Rated"));
omdbResponse.setReleased(rs.getString("Released"));
omdbResponse.setSeason(rs.getString("Season"));
omdbResponse.setEpisode(rs.getString("Episode"));
omdbResponse.setRuntime(rs.getString("Runtime"));
omdbResponse.setGenre(rs.getString("Genre"));
omdbResponse.setDirector(rs.getString("Director"));
omdbResponse.setWriter(rs.getString("Writer"));
omdbResponse.setActors(rs.getString("Actors"));
omdbResponse.setPlot(rs.getString("Plot"));
omdbResponse.setLanguage(rs.getString("Language"));
omdbResponse.setCountry(rs.getString("Country"));
omdbResponse.setAwards(rs.getString("Awards"));
omdbResponse.setMetascore(rs.getString("metascore"));
omdbResponse.setImdbRating(rs.getString("imdbRating"));
omdbResponse.setImdbVotes(rs.getString("imdbVotes"));
omdbResponse.setImdbID(rs.getString("imdbID"));
omdbResponse.setType(rs.getString("Type"));
omdbResponse.setDvd(rs.getString("dvd"));
omdbResponse.setBoxOffice(rs.getString("BoxOffice"));
//omdbResponse.setProduction(object.getString("Production", ""));
omdbResponse.setWebsite(rs.getString("Website"));
omdbResponse.setResponse(rs.getString("Response"));
omdbResponse.setPoster(rs.getString("Poster"));
}
}
} catch (SQLException e) {
LOGGER.error("Ups! error while getting the current time for {}.", streamUrl, e);
}
return omdbResponse;
}
/**
* get all NOT cached entries
* @return a {@link ArrayList} of all NOT cached entries
@ -623,15 +585,15 @@ public class DBController {
public ArrayList<FilmTabelDataType> getAllNotCachedEntries() {
ArrayList<FilmTabelDataType> notCachedEntries = new ArrayList<>();
try (Statement stmt = connection.createStatement();) {
try (ResultSet rs = stmt.executeQuery("SELECT * FROM films WHERE cached = 0");) {
while (rs.next()) {
notCachedEntries.add(new FilmTabelDataType(rs.getString("streamUrl"),
rs.getString("title"), rs.getString("season"), rs.getString("episode")));
}
try {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM films WHERE cached = 0");
while (rs.next()) {
notCachedEntries.add(new FilmTabelDataType(rs.getString("streamUrl"),
rs.getString("title"), rs.getString("season"), rs.getString("episode")));
}
stmt.close();
rs.close();
} catch (SQLException e) {
LOGGER.error("An error occured, while getting all NOT cached entries", e);
}
@ -648,14 +610,13 @@ public class DBController {
public double getCurrentTime(String streamUrl) {
LOGGER.info("get currentTime for " + streamUrl);
double currentTime = 0;
try (PreparedStatement ps = connection.prepareStatement("SELECT * FROM films WHERE streamUrl = ?");) {
try {
PreparedStatement ps = connection.prepareStatement("SELECT * FROM films WHERE streamUrl = ?");
ps.setString(1, streamUrl);
try (ResultSet rs = ps.executeQuery();) {
currentTime = rs.getDouble("currentTime");
}
ResultSet rs = ps.executeQuery();
currentTime = rs.getDouble("currentTime");
rs.close();
ps.close();
} catch (Exception e) {
LOGGER.error("Ups! error while getting the current time!", e);
}
@ -670,12 +631,13 @@ public class DBController {
*/
public void setCurrentTime(String streamUrl, double currentTime) {
LOGGER.info("set currentTime = " + currentTime + " for " + streamUrl);
try (PreparedStatement ps = connection.prepareStatement("UPDATE films SET currentTime = ? WHERE streamUrl = ?");) {
try {
PreparedStatement ps = connection.prepareStatement("UPDATE films SET currentTime = ? WHERE streamUrl = ?");
ps.setDouble(1, currentTime);
ps.setString(2, streamUrl);
ps.executeUpdate();
connection.commit();
ps.close();
} catch (SQLException e) {
LOGGER.error("Ups! error while updateing the current time!", e);
}
@ -689,19 +651,18 @@ public class DBController {
*/
public ArrayList<String[]> getEpisodes(String title, int season) {
ArrayList<String[]> episodePosters =new ArrayList<>();
// try to get a all episode of one season
try (PreparedStatement ps = connection.prepareStatement("SELECT streamUrl, episode FROM films WHERE title = ? AND season = ?");) {
try {
// try to get a all episode of one season
PreparedStatement ps = connection.prepareStatement("SELECT streamUrl, episode FROM films WHERE title = ? AND season = ?");
ps.setString(1, title);
ps.setString(2, Integer.toString(season));
ResultSet rs = ps.executeQuery();
try (ResultSet rs = ps.executeQuery();) {
// for each episode load cache data
while (rs.next()) {
String[] cacheData = readCacheLegacy(rs.getString("streamUrl"));
String[] ret = {rs.getString("streamUrl"), rs.getString("episode"), cacheData[20]};
episodePosters.add(ret);
}
// for each episode load cache data
while (rs.next()) {
String[] cacheData = readCache(rs.getString("streamUrl"));
String[] ret = {rs.getString("streamUrl"), rs.getString("episode"), cacheData[20]};
episodePosters.add(ret);
}
} catch(Exception e) {
LOGGER.error("Ups! error while getting episodes of a season!", e);

View File

@ -20,7 +20,7 @@
*
*/
package org.mosad.homeflix.controller;
package kellerkinder.HomeFlix.controller;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
@ -32,13 +32,14 @@ import javax.imageio.ImageIO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mosad.homeflix.datatypes.FilmTabelDataType;
import org.mosad.homeflix.datatypes.OMDbAPIResponseDataType;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;
import kellerkinder.HomeFlix.datatypes.FilmTabelDataType;
import kellerkinder.HomeFlix.datatypes.OMDbAPIResponseDataType;
public class OMDbAPIController implements Runnable {
private DBController dbController;

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <@Seil0>
* 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
@ -20,7 +20,7 @@
*
*/
package org.mosad.homeflix.controller;
package kellerkinder.HomeFlix.controller;
import java.io.File;
import java.io.FileReader;
@ -31,13 +31,14 @@ import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mosad.homeflix.datatypes.DatabaseDataType;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;
import kellerkinder.HomeFlix.datatypes.DatabaseDataType;
public class SourcesController {
private List<DatabaseDataType> sourceStreams = new ArrayList<DatabaseDataType>();
@ -84,10 +85,10 @@ public class SourcesController {
for (File file : new File(path).listFiles()) {
// if it's valid file add it to the sourceStreams
if (isValidFile(file)) {
sourceStreams.add(new DatabaseDataType(file.getPath(), cutOffEnd(file.getName().replace("_", " ")), "", "", 0, 0.0));
sourceStreams.add(new DatabaseDataType(file.getPath(), cutOffEnd(file.getName()), "", "", 0, 0.0));
} else if(isValidSeriesRoot(file)) {
// get all directories (series), root and season must be directories
sourceStreams.add(new DatabaseDataType(file.getPath(), file.getName().replace("_", " "), "0", "0", 0, 0.0)); // add the series root node
sourceStreams.add(new DatabaseDataType(file.getPath(), file.getName(), "0", "0", 0, 0.0)); // add the series root node
int sn = 1;
for (File season : file.listFiles()) {
if (season.isDirectory()) {

View File

@ -19,7 +19,7 @@
* MA 02110-1301, USA.
*/
package org.mosad.homeflix.controller;
package kellerkinder.HomeFlix.controller;
import java.io.BufferedReader;
import java.io.File;
@ -34,13 +34,14 @@ import javax.swing.ProgressMonitorInputStream;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mosad.homeflix.application.Main;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;
import kellerkinder.HomeFlix.application.Main;
public class UpdateController {
private static int updateBuildNumber; // tag_name from gitea
@ -56,6 +57,9 @@ public class UpdateController {
/**
* updater for Project HomeFlix based on cemu_UIs, checks for Updates and download it
*/
public UpdateController() {
}
public static void update() {
if (browserDownloadUrl != null) {

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <@Seil0>
* 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
@ -20,7 +20,7 @@
*
*/
package org.mosad.homeflix.controller;
package kellerkinder.HomeFlix.controller;
import java.io.BufferedReader;
import java.io.File;
@ -61,7 +61,6 @@ public class XMLController {
private static boolean autoUpdate = false;
private static boolean useBeta = false;
private static boolean autoplay = false;
private static boolean fullscreen = true;
private static double fontSize = 17;
private static ResourceBundle localBundle = ResourceBundle.getBundle("locals.HomeFlix-Local", Locale.US);
@ -277,14 +276,6 @@ public class XMLController {
public static void setAutoplay(boolean autoplay) {
XMLController.autoplay = autoplay;
}
public static boolean isFullscreen() {
return fullscreen;
}
public static void setFullscreen(boolean fullscreen) {
XMLController.fullscreen = fullscreen;
}
public static double getFontSize() {
return fontSize;

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <@Seil0>
* 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
@ -20,7 +20,7 @@
*
*/
package org.mosad.homeflix.datatypes;
package kellerkinder.HomeFlix.datatypes;
public class DatabaseDataType {

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <@Seil0>
* 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
@ -18,7 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.mosad.homeflix.datatypes;
package kellerkinder.HomeFlix.datatypes;
public class FilmTabelDataType {
private String streamUrl;

View File

@ -20,36 +20,36 @@
*
*/
package org.mosad.homeflix.datatypes;
package kellerkinder.HomeFlix.datatypes;
public class OMDbAPIResponseDataType {
private String title = "";
private String year = "";
private String rated = "";
private String released = "";
private String season = "";
private String episode = "";
private String runtime = "";
private String genre = "";
private String director = "";
private String writer = "";
private String actors = "";
private String plot = "";
private String language = "";
private String country = "";
private String awards = "";
private String poster = "";
private String metascore = "";
private String imdbRating = "";
private String imdbVotes = "";
private String imdbID = "";
private String type = "";
private String dvd = "";
private String boxOffice = "";
private String production = "";
private String website = "";
private String response = "";
private String title;
private String year;
private String rated;
private String released;
private String season;
private String episode;
private String runtime;
private String genre;
private String director;
private String writer;
private String actors;
private String plot;
private String language;
private String country;
private String awards;
private String poster;
private String metascore;
private String imdbRating;
private String imdbVotes;
private String imdbID;
private String type;
private String dvd;
private String boxOffice;
private String production;
private String website;
private String response;
/**
* OMDbAPIResponseDataType is the data-type for the omdbAPI response
@ -71,7 +71,7 @@ public class OMDbAPIResponseDataType {
}
public void setYear(String year) {
this.year = year == null ? "N/A" : year;
this.year = year;
}
public String getRated() {
@ -79,7 +79,7 @@ public class OMDbAPIResponseDataType {
}
public void setRated(String rated) {
this.rated = rated == null ? "N/A" : rated;
this.rated = rated;
}
public String getReleased() {
@ -87,7 +87,7 @@ public class OMDbAPIResponseDataType {
}
public void setReleased(String released) {
this.released = released == null ? "N/A" : released;
this.released = released;
}
public String getSeason() {
@ -127,7 +127,7 @@ public class OMDbAPIResponseDataType {
}
public void setDirector(String director) {
this.director = director == null ? "N/A" : director;
this.director = director;
}
public String getWriter() {
@ -135,7 +135,7 @@ public class OMDbAPIResponseDataType {
}
public void setWriter(String writer) {
this.writer = writer == null ? "N/A" : writer;
this.writer = writer;
}
public String getActors() {
@ -143,7 +143,7 @@ public class OMDbAPIResponseDataType {
}
public void setActors(String actors) {
this.actors = actors == null ? "N/A" : actors;
this.actors = actors;
}
public String getPlot() {
@ -151,7 +151,7 @@ public class OMDbAPIResponseDataType {
}
public void setPlot(String plot) {
this.plot = plot == null ? "N/A" : plot;
this.plot = plot;
}
public String getLanguage() {
@ -159,7 +159,7 @@ public class OMDbAPIResponseDataType {
}
public void setLanguage(String language) {
this.language = language == null ? "N/A" : language;
this.language = language;
}
public String getCountry() {
@ -167,7 +167,7 @@ public class OMDbAPIResponseDataType {
}
public void setCountry(String country) {
this.country = country == null ? "N/A" : country;
this.country = country;
}
public String getAwards() {
@ -175,7 +175,7 @@ public class OMDbAPIResponseDataType {
}
public void setAwards(String awards) {
this.awards = awards == null ? "N/A" : awards;
this.awards = awards;
}
public String getPoster() {
@ -191,7 +191,7 @@ public class OMDbAPIResponseDataType {
}
public void setMetascore(String metascore) {
this.metascore = metascore == null ? "N/A" : metascore;
this.metascore = metascore;
}
public String getImdbRating() {
@ -199,7 +199,7 @@ public class OMDbAPIResponseDataType {
}
public void setImdbRating(String imdbRating) {
this.imdbRating = imdbRating == null ? "N/A" : imdbRating;
this.imdbRating = imdbRating;
}
public String getImdbVotes() {
@ -207,7 +207,7 @@ public class OMDbAPIResponseDataType {
}
public void setImdbVotes(String imdbVotes) {
this.imdbVotes = imdbVotes == null ? "N/A" : imdbVotes;
this.imdbVotes = imdbVotes;
}
public String getImdbID() {
@ -231,7 +231,7 @@ public class OMDbAPIResponseDataType {
}
public void setDvd(String dvd) {
this.dvd = dvd == null ? "N/A" : dvd;
this.dvd = dvd;
}
public String getBoxOffice() {
@ -239,7 +239,7 @@ public class OMDbAPIResponseDataType {
}
public void setBoxOffice(String boxOffice) {
this.boxOffice = boxOffice == null ? "N/A" : boxOffice;
this.boxOffice = boxOffice;
}
public String getProduction() {
@ -247,7 +247,7 @@ public class OMDbAPIResponseDataType {
}
public void setProduction(String production) {
this.production = production == null ? "N/A" : production;
this.production = production;
}
public String getWebsite() {
@ -255,7 +255,7 @@ public class OMDbAPIResponseDataType {
}
public void setWebsite(String website) {
this.website = website == null ? "N/A" : website;
this.website = website;
}
public String getResponse() {

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <@Seil0>
* 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
@ -20,7 +20,7 @@
*
*/
package org.mosad.homeflix.datatypes;
package kellerkinder.HomeFlix.datatypes;
import com.jfoenix.controls.JFXButton;

View File

@ -1,20 +1,19 @@
package org.mosad.homeflix.datatypes;
import org.mosad.homeflix.player.Player;
package kellerkinder.HomeFlix.datatypes;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import kellerkinder.HomeFlix.player.Player;
public class SeriesDVEpisode extends AnchorPane {
public class SeriresDVEpisode extends AnchorPane {
private String streamURL;
private Label label = new Label();
private ImageView imageView = new ImageView();
public SeriesDVEpisode() {
public SeriresDVEpisode() {
super.getChildren().addAll(imageView, label);
super.prefWidth(200);
super.prefHeight(112);
@ -28,7 +27,7 @@ public class SeriesDVEpisode extends AnchorPane {
super.setLeftAnchor(label, 7.0);
}
public SeriesDVEpisode(String streamURL, String episode, Image poster) {
public SeriresDVEpisode(String streamURL, String episode, Image poster) {
this();
this.streamURL = streamURL;

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <@Seil0>
* 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
@ -18,7 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.mosad.homeflix.datatypes;
package kellerkinder.HomeFlix.datatypes;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

View File

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <seil0@mosad.xyz>
* 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
@ -20,7 +20,7 @@
*
*/
package org.mosad.homeflix.player;
package kellerkinder.HomeFlix.player;
import java.awt.Desktop;
import java.io.BufferedReader;
@ -31,15 +31,14 @@ import java.net.URLConnection;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mosad.homeflix.application.Main;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import kellerkinder.HomeFlix.application.Main;
import kellerkinder.HomeFlix.controller.DBController;
public class Player {
private PlayerController playerController;
@ -55,20 +54,21 @@ public class Player {
* @param currentTableFilm the currently selected film
*/
public Player(String streamURL) {
try {
defaultPlayer(streamURL);
} catch (Exception e) {
LOGGER.error("Error while playing media", e);
if (isSupportedFormat(streamURL)) {
hfPlayer(streamURL);
} else {
legacyPlayer(streamURL);
}
}
/**
* start the integrated player
* @param streamURL
*/
private void defaultPlayer(String mediaURL) {
playerController = new PlayerController(this, mediaURL);
private void hfPlayer(String streamURL) {
playerController = new PlayerController(this, streamURL);
try {
FXMLLoader fxmlLoader = new FXMLLoader();
@ -77,19 +77,19 @@ public class Player {
pane = (AnchorPane) fxmlLoader.load();
stage = new Stage();
scene = new Scene(pane);
scene.getStylesheets().add(getClass().getResource("/css/Player.css").toExternalForm());
stage.setScene(scene);
stage.setTitle("HomeFlix");
stage.getIcons().add(new Image(Main.class.getResourceAsStream("/icons/Homeflix_Icon_64x64.png")));
stage.setOnCloseRequest(event -> {
playerController.stop();
DBController.getInstance().setCurrentTime(streamURL, playerController.getCurrentTime());
playerController.getMediaPlayer().stop();
stage.close();
});
//stage.setFullScreen(true);
stage.show();
playerController.init();
playerController.start();
stage.setFullScreen(true);
stage.show();
} catch (Exception e) {
e.printStackTrace();
}
@ -158,8 +158,4 @@ public class Player {
return scene;
}
public Pane getPane() {
return pane;
}
}

View File

@ -0,0 +1,310 @@
/**
* 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.player;
import java.io.File;
import java.util.Timer;
import java.util.TimerTask;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXSlider;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.Cursor;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import javafx.scene.media.MediaView;
import javafx.util.Duration;
import kellerkinder.HomeFlix.controller.DBController;
import kellerkinder.HomeFlix.controller.XMLController;
import kellerkinder.HomeFlix.datatypes.FilmTabelDataType;
public class PlayerController {
@FXML private MediaView mediaView;
@FXML private VBox bottomVBox;
@FXML private HBox controlsHBox;
@FXML private JFXSlider timeSlider;
@FXML private JFXButton stopBtn;
@FXML private JFXButton playBtn;
@FXML private JFXButton fullscreenBtn;
@FXML private JFXButton nextEpBtn;
@FXML private ImageView stopIcon;
@FXML private ImageView playIcon;
@FXML private ImageView fullscreenIcon;
private Player player;
private Media media;
private MediaPlayer mediaPlayer;
private FilmTabelDataType film;
private double currentTime = 0;
private double seekTime = 0;
private double startTime = 0;
private double duration = 0;
private int season = 0;
private int episode = 0;
private int countdown = 0;
private boolean mousePressed = false;
private boolean showControls = true;
private boolean autoplay;
private Image playArrow = new Image("icons/baseline_play_arrow_black_48dp.png");
private Image pause = new Image("icons/baseline_pause_black_48dp.png");
private Image fullscreen = new Image("icons/baseline_fullscreen_black_48dp.png");
private Image fullscreenExit = new Image("icons/baseline_fullscreen_exit_black_48dp.png");
/**
* create a new PlayerWindow object
* @param mainWCon the MainWindowController TODO do we need this?
* @param player the player object (needed for closing action)
* @param film the film object
*/
public PlayerController(Player player, String streamURL) {
this.player = player;
this.film = DBController.getInstance().getStream(streamURL);
}
/**
* initialize the PlayerWindow
*/
public void init() {
initActions();
if (film.getStreamUrl().startsWith("http")) {
media = new Media(film.getStreamUrl());
} else {
media = new Media(new File(film.getStreamUrl()).toURI().toString());
}
// create the MediaPlayer object
mediaPlayer = new MediaPlayer(media);
mediaView.setPreserveRatio(true);
mediaView.setMediaPlayer(mediaPlayer);
final DoubleProperty width = mediaView.fitWidthProperty();
final DoubleProperty height = mediaView.fitHeightProperty();
width.bind(Bindings.selectDouble(mediaView.sceneProperty(), "width"));
height.bind(Bindings.selectDouble(mediaView.sceneProperty(), "height"));
startTime = DBController.getInstance().getCurrentTime(film.getStreamUrl());
autoplay = XMLController.isAutoplay();
season = !film.getSeason().isEmpty() ? Integer.parseInt(film.getSeason()) : 0;
episode = !film.getEpisode().isEmpty() ? Integer.parseInt(film.getEpisode()) : 0;
initMediaPlayer();
// set the control elements to the correct value
playIcon.setImage(pause);
fullscreenIcon.setImage(fullscreenExit);
timeSlider.setValue(0);
}
private void initMediaPlayer() {
// start the media if the player is ready
mediaPlayer.setOnReady(new Runnable() {
@Override
public void run() {
duration = media.getDuration().toMillis();
timeSlider.setMax((duration / 1000) / 60);
mediaPlayer.play();
mediaPlayer.seek(Duration.millis(startTime));
}
});
// every time the play time changes execute this
mediaPlayer.currentTimeProperty().addListener(new ChangeListener<Duration>() {
@Override
public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
currentTime = newValue.toMillis(); // set the current time
double timeToEnd = (duration - currentTime);
if (timeToEnd < 20000 && episode != 0 && autoplay) {
// show 20 seconds before the end a button (next episode in 10 seconds)
if (!nextEpBtn.isVisible())
nextEpBtn.setVisible(true);
if (countdown != (int) ((timeToEnd - 10000) / 1000)) {
countdown = (int) ((timeToEnd - 10000) / 1000);
nextEpBtn.setText("next episode in " + countdown + " seconds"); // TODO translate
bottomVBox.setVisible(true);
}
// if we are end time -10 seconds, do autoplay, if activated
if (timeToEnd < 10000) {
nextEpBtn.setVisible(false);
autoPlayNewFilm();
}
} else if (timeToEnd < 120) {
// if we are 120ms to the end stop the media
mediaPlayer.stop();
DBController.getInstance().setCurrentTime(film.getStreamUrl(), 0); // reset old video start time
playIcon.setImage(playArrow);
} else {
if (nextEpBtn.isVisible())
nextEpBtn.setVisible(false);
}
if (!mousePressed) {
timeSlider.setValue((currentTime / 1000) / 60);
}
}
});
}
/**
* initialize some PlayerWindow GUI-Elements actions
*/
private void initActions() {
player.getScene().addEventFilter(MouseEvent.MOUSE_MOVED, new EventHandler<MouseEvent>() {
// hide controls timer initialization
final Timer timer = new Timer();
TimerTask controlAnimationTask = null; // task to execute save operation
final long delayTime = 3000; // hide the controls after 2 seconds
@Override
public void handle(MouseEvent mouseEvent) {
// show controls
if (!showControls) {
player.getScene().setCursor(Cursor.DEFAULT);
bottomVBox.setVisible(true);
}
// hide controls
if (controlAnimationTask != null)
controlAnimationTask.cancel();
controlAnimationTask = new TimerTask() {
@Override
public void run() {
bottomVBox.setVisible(false);
player.getScene().setCursor(Cursor.NONE);
showControls = false;
}
};
timer.schedule(controlAnimationTask, delayTime);
}
});
// if the mouse on the timeSlider is released seek to the new position
timeSlider.setOnMouseReleased(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
mediaPlayer.seek(new Duration(seekTime));
mousePressed = false;
}
});
timeSlider.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
mousePressed = true;
}
});
// get the new seek time
timeSlider.valueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) {
seekTime = (double) new_val * 1000 * 60;
}
});
}
@FXML
void stopBtnAction(ActionEvent event) {
DBController.getInstance().setCurrentTime(film.getStreamUrl(), currentTime);
mediaPlayer.stop();
player.getStage().close();
}
@FXML
void fullscreenBtnAction(ActionEvent event) {
if (player.getStage().isFullScreen()) {
player.getStage().setFullScreen(false);
fullscreenIcon.setImage(fullscreen);
} else {
player.getStage().setFullScreen(true);
fullscreenIcon.setImage(fullscreenExit);
}
}
@FXML
void playBtnAction(ActionEvent event) {
if (mediaPlayer.getStatus().equals(Status.PLAYING)) {
mediaPlayer.pause();
playIcon.setImage(playArrow);
} else {
mediaPlayer.play();
playIcon.setImage(pause);
}
}
@FXML
void nextEpBtnAction(ActionEvent event) {
autoPlayNewFilm();
}
private void autoPlayNewFilm() {
autoplay = false;
DBController.getInstance().setCurrentTime(film.getStreamUrl(), 0); // reset old video start time
FilmTabelDataType nextFilm = DBController.getInstance().getNextEpisode(film.getTitle(), episode, season);
if (nextFilm != null) {
mediaPlayer.stop();
film = nextFilm;
init();
autoplay = true;
}
}
public MediaPlayer getMediaPlayer() {
return mediaPlayer;
}
public double getCurrentTime() {
return currentTime;
}
}

View File

@ -1,42 +0,0 @@
package org.mosad.homeflix.application.view;
import org.mosad.homeflix.application.MainWindowController;
import javafx.animation.FadeTransition;
import javafx.fxml.FXML;
import javafx.scene.layout.AnchorPane;
import javafx.util.Duration;
public class DetailView {
@FXML protected AnchorPane rootPane;
public void updateGUILocal() {
throw new UnsupportedOperationException();
}
/**
* show the root pane
*/
public void showPane() {
rootPane.setVisible(true);
FadeTransition fadeIn = new FadeTransition(Duration.millis(300), rootPane);
fadeIn.setFromValue(0.3);
fadeIn.setToValue(1.0);
fadeIn.play();
}
/**
* hide the root pane and disable the blur in MainWindowController
*/
protected void hidePane() {
FadeTransition fadeOut = new FadeTransition(Duration.millis(200), rootPane);
fadeOut.setFromValue(1.0);
fadeOut.setToValue(0.3);
fadeOut.play();
rootPane.setVisible(false);
MainWindowController.getInstance().disableBlur(); // disable blur
}
}

View File

@ -1,172 +0,0 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <seil0@mosad.xyz>
*
* 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 org.mosad.homeflix.player;
import uk.co.caprica.vlcj.media.MediaRef;
import uk.co.caprica.vlcj.media.TrackType;
import uk.co.caprica.vlcj.player.base.MediaPlayer;
import uk.co.caprica.vlcj.player.base.MediaPlayerEventListener;
public class HFMediaPlayerEventListener implements MediaPlayerEventListener {
@Override
public void mediaChanged(MediaPlayer mediaPlayer, MediaRef media) {
// Auto-generated method stub
}
@Override
public void opening(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void buffering(MediaPlayer mediaPlayer, float newCache) {
// Auto-generated method stub
}
@Override
public void playing(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void paused(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void stopped(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void forward(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void backward(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void finished(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void timeChanged(MediaPlayer mediaPlayer, long newTime) {
// Auto-generated method stub
}
@Override
public void positionChanged(MediaPlayer mediaPlayer, float newPosition) {
// Auto-generated method stub
}
@Override
public void seekableChanged(MediaPlayer mediaPlayer, int newSeekable) {
// Auto-generated method stub
}
@Override
public void pausableChanged(MediaPlayer mediaPlayer, int newPausable) {
// Auto-generated method stub
}
@Override
public void titleChanged(MediaPlayer mediaPlayer, int newTitle) {
// Auto-generated method stub
}
@Override
public void snapshotTaken(MediaPlayer mediaPlayer, String filename) {
// Auto-generated method stub
}
@Override
public void lengthChanged(MediaPlayer mediaPlayer, long newLength) {
// Auto-generated method stub
}
@Override
public void videoOutput(MediaPlayer mediaPlayer, int newCount) {
// Auto-generated method stub
}
@Override
public void scrambledChanged(MediaPlayer mediaPlayer, int newScrambled) {
// Auto-generated method stub
}
@Override
public void elementaryStreamAdded(MediaPlayer mediaPlayer, TrackType type, int id) {
// Auto-generated method stub
}
@Override
public void elementaryStreamDeleted(MediaPlayer mediaPlayer, TrackType type, int id) {
// Auto-generated method stub
}
@Override
public void elementaryStreamSelected(MediaPlayer mediaPlayer, TrackType type, int id) {
// Auto-generated method stub
}
@Override
public void corked(MediaPlayer mediaPlayer, boolean corked) {
// Auto-generated method stub
}
@Override
public void muted(MediaPlayer mediaPlayer, boolean muted) {
// Auto-generated method stub
}
@Override
public void volumeChanged(MediaPlayer mediaPlayer, float volume) {
// Auto-generated method stub
}
@Override
public void audioDeviceChanged(MediaPlayer mediaPlayer, String audioDevice) {
// Auto-generated method stub
}
@Override
public void chapterChanged(MediaPlayer mediaPlayer, int newChapter) {
// Auto-generated method stub
}
@Override
public void error(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void mediaPlayerReady(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
}

View File

@ -1,635 +0,0 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2022 <seil0@mosad.xyz>
*
* 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 org.mosad.homeflix.player;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import org.mosad.homeflix.controller.DBController;
import org.mosad.homeflix.controller.XMLController;
import org.mosad.homeflix.datatypes.FilmTabelDataType;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialogLayout;
import com.jfoenix.controls.JFXListCell;
import com.jfoenix.controls.JFXListView;
import com.jfoenix.controls.JFXPopup;
import com.jfoenix.controls.JFXPopup.PopupHPosition;
import com.jfoenix.controls.JFXPopup.PopupVPosition;
import com.jfoenix.controls.JFXSlider;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.Cursor;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelBuffer;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.WritableImage;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
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.util.StringConverter;
import uk.co.caprica.vlcj.factory.MediaPlayerFactory;
import uk.co.caprica.vlcj.media.Media;
import uk.co.caprica.vlcj.media.MediaEventAdapter;
import uk.co.caprica.vlcj.media.MediaParsedStatus;
import uk.co.caprica.vlcj.player.base.MediaPlayer;
import uk.co.caprica.vlcj.player.base.TrackDescription;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
import uk.co.caprica.vlcj.player.embedded.videosurface.CallbackVideoSurface;
import uk.co.caprica.vlcj.player.embedded.videosurface.VideoSurfaceAdapters;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormat;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormatCallback;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.RenderCallback;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.format.RV32BufferFormat;
/**
* The PlayerController class is the main component of the HomeFlix Player.
* It uses vlcj to play videos and some modified jfoenix GUI components to
* create a Netflix like GUI.
*
* @author seil0
*
* TODO this class needs heavy cleaning
*/
public class PlayerController {
@FXML private AnchorPane panePlayer;
@FXML private ImageView videoImageView;
@FXML private HBox hBoxTop;
@FXML private HBox controlsHBox;
@FXML private VBox bottomVBox;
@FXML private JFXSlider timeSlider;
@FXML private JFXButton btnBack;
@FXML private JFXButton btnPlay;
@FXML private JFXButton btnReplay;
@FXML private JFXButton btnForward;
@FXML private JFXButton btnAudio;
@FXML private JFXButton btnFullscreen;
@FXML private JFXButton btnNextEpisode;
@FXML private ImageView stopIcon;
@FXML private ImageView playIcon;
@FXML private ImageView fullscreenIcon;
@FXML private Label lblTitle;
@FXML private Label lblEndTime;
private Player player;
private MediaPlayerFactory mediaPlayerFactory;
private EmbeddedMediaPlayer embeddedMediaPlayer;
private WritableImage videoImage;
private PixelBuffer<ByteBuffer> videoPixelBuffer;
private FilmTabelDataType media;
private long startTime = 0;
private long currentTime = 0;
private long endTime = 0;
private long skipTime = 0;
private long duration = 0;
private List<TrackDescription> audioTracks = new ArrayList<>();
private List<TrackDescription> subtitleTracks = new ArrayList<>();
private int currentAudioTrack = 0;
private int currentSubtitleTrack = 0;
private int season = 0;
private int episode = 0;
private boolean mousePressed = false;
private boolean showControls = true;
private boolean autoplay;
private Image playArrow = new Image("icons/baseline_play_arrow_white_48dp.png");
private Image pause = new Image("icons/baseline_pause_white_48dp.png");
private Image fullscreen = new Image("icons/baseline_fullscreen_white_48dp.png");
private Image fullscreenExit = new Image("icons/baseline_fullscreen_exit_white_48dp.png");
private JFXPopup audioPopup;
// fix wrong buffer resolution
private int videoWidth = 0;
private int videoHeigth = 0;
/**
* create a new PlayerWindow object
* @param player the player object (needed for closing action)
* @param film the film object
*/
public PlayerController(Player player, String mediaURL) {
this.player = player;
this.media = DBController.getInstance().getStream(mediaURL);
mediaPlayerFactory = new MediaPlayerFactory();
embeddedMediaPlayer = mediaPlayerFactory.mediaPlayers().newEmbeddedMediaPlayer();
embeddedMediaPlayer.videoSurface().set(new FXCallbackVideoSurface());
}
public void init() {
// initialize the image view
videoImageView.setPreserveRatio(true);
videoImageView.fitWidthProperty().bind(player.getStage().widthProperty());
videoImageView.fitHeightProperty().bind(player.getStage().heightProperty());
// set needed variables
startTime = (long) DBController.getInstance().getCurrentTime(media.getStreamUrl());
autoplay = XMLController.isAutoplay();
season = !media.getSeason().isEmpty() ? Integer.parseInt(media.getSeason()) : 0;
episode = !media.getEpisode().isEmpty() ? Integer.parseInt(media.getEpisode()) : 0;
if (episode > 0) {
// if the media is a TV show, add season + episode to the title
lblTitle.setText(media.getTitle() + " S" + season + ":E" + episode);
} else {
lblTitle.setText(media.getTitle());
}
initPlayerWindow();
initMediaPlayer();
initTimeSlider();
}
/**
* initialize some PlayerWindow GUI-Elements actions
*/
private void initPlayerWindow() {
player.getScene().addEventFilter(MouseEvent.MOUSE_MOVED, new EventHandler<MouseEvent>() {
// hide controls timer initialization
final Timer timer = new Timer();
TimerTask controlAnimationTask = null; // task to execute save operation
final long delayTime = 3000; // hide the controls after 2 seconds
@Override
public void handle(MouseEvent mouseEvent) {
// show controls
if (!showControls) {
showControls = true;
updateControls(); // update controls before showing them
player.getScene().setCursor(Cursor.DEFAULT);
hBoxTop.setVisible(true);
bottomVBox.setVisible(true);
showControls = true;
}
// hide controls
if (controlAnimationTask != null)
controlAnimationTask.cancel();
controlAnimationTask = new TimerTask() {
@Override
public void run() {
// TODO a animation would be nice
hBoxTop.setVisible(false);
bottomVBox.setVisible(false);
player.getScene().setCursor(Cursor.NONE);
showControls = false;
}
};
timer.schedule(controlAnimationTask, delayTime);
}
});
if (XMLController.isFullscreen()) {
player.getStage().setFullScreen(!player.getStage().isFullScreen());
fullscreenIcon.setImage(player.getStage().isFullScreen() ? fullscreenExit : fullscreen);
}
// fix focused button has rippler fill https://github.com/jfoenixadmin/JFoenix/issues/1051
btnBack.setStyle("-jfx-rippler-fill: black;");
}
/**
* initialize the embedded media player
*/
private void initMediaPlayer() {
embeddedMediaPlayer.events().addMediaPlayerEventListener( new HFMediaPlayerEventListener() {
@Override
public void mediaPlayerReady(MediaPlayer mediaPlayer) {
audioTracks = mediaPlayer.audio().trackDescriptions();
subtitleTracks = mediaPlayer.subpictures().trackDescriptions();
currentAudioTrack = mediaPlayer.audio().track();
currentSubtitleTrack = mediaPlayer.subpictures().track();
}
@Override
public void timeChanged(MediaPlayer mediaPlayer, long newTime) {
currentTime = newTime;
endTime = duration - newTime;
Platform.runLater(() -> {
updateControls();
});
}
@Override
public void error(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void lengthChanged(MediaPlayer mediaPlayer, long newLength) {
duration = newLength;
timeSlider.setMax(duration / 1000);
}
});
embeddedMediaPlayer.events().addMediaEventListener(new MediaEventAdapter() {
@Override
public void mediaParsedChanged(Media media, MediaParsedStatus newStatus) {
super.mediaParsedChanged(media, newStatus);
videoWidth = embeddedMediaPlayer.video().videoDimension().width;
videoHeigth= embeddedMediaPlayer.video().videoDimension().height;
// start the video
embeddedMediaPlayer.media().play(media.newMediaRef());
embeddedMediaPlayer.controls().skipTime(startTime); // skip to the start time
}
});
}
/**
* initialize the time slider
*/
private void initTimeSlider() {
// if the mouse on the timeSlider is released, skip to the new position
timeSlider.setOnMouseReleased(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
embeddedMediaPlayer.controls().skipTime(skipTime);
// update time-stamps if video is paused
if (!embeddedMediaPlayer.status().isPlaying()) {
Platform.runLater(() -> {
lblEndTime.setText(String.format("%d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(endTime - skipTime) % 24,
TimeUnit.MILLISECONDS.toMinutes(endTime - skipTime) % 60,
TimeUnit.MILLISECONDS.toSeconds(endTime - skipTime) % 60));
});
}
mousePressed = false;
}
});
timeSlider.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
mousePressed = true;
}
});
// on value change, get the new skip time
timeSlider.valueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) {
skipTime = ((new_val.longValue() * 1000) - currentTime);
//System.out.println(timeSlider.getChildrenUnmodifiable());
}
});
timeSlider.setOnMouseMoved(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
//System.out.println("TEST");
}
});
// show h:mm:ss in the animated thumb
StringConverter<Double> convert = new StringConverter<Double>() {
@Override
public String toString(Double object) {
long time = object.longValue();
return String.format("%d:%02d:%02d", TimeUnit.SECONDS.toHours(time) % 24,
TimeUnit.SECONDS.toMinutes(time) % 60, TimeUnit.SECONDS.toSeconds(time) % 60);
}
@Override
public Double fromString(String string) {
return null;
}
};
timeSlider.setLabelFormatter(convert);
// get the animated thumb as StackPane
StackPane animatedThumb = (StackPane) timeSlider.lookup(".animated-thumb");
// System.out.println(animatedThumb);
// System.out.println(animatedThumb.getChildren());
// modify the animated thumb
Text thumbText = (Text) animatedThumb.getChildren().get(0);
thumbText.setStyle("-fx-font-size: 15px; -fx-fill: white;");
// TODO add a preview to the animated thumb, if that's possible
// ImageView iv = new ImageView(fullscreenExit);
// animatedThumb.getChildren().add(iv);
}
// Start the parsing the media meta data
public void start() {
// parse meta data
embeddedMediaPlayer.media().prepare(media.getStreamUrl());
embeddedMediaPlayer.media().parsing().parse();
}
/**
* Stop and release the media player.
* Always call this method to stop the media player.
*/
public void stop() {
DBController.getInstance().setCurrentTime(media.getStreamUrl(), embeddedMediaPlayer.status().time());
embeddedMediaPlayer.controls().stop();
embeddedMediaPlayer.release();
mediaPlayerFactory.release();
}
/**
* call this every second to update all timers
*/
private void updateControls() {
// update control if they are visible
if (showControls) {
// update slider position, if the mouse does not press on the time
if (!mousePressed) {
timeSlider.setValue(currentTime / 1000);
}
// update endTime label
lblEndTime.setText(String.format("%d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(endTime) % 24,
TimeUnit.MILLISECONDS.toMinutes(endTime) % 60,
TimeUnit.MILLISECONDS.toSeconds(endTime) % 60));
}
// show the next episode button 30 seconds before the end of a episode
if (endTime < 31000 && episode != 0 && autoplay) {
int countdown = (int) ((endTime / 1000) - 20); // a 10 seconds countdown
if (!btnNextEpisode.isVisible()) {
btnNextEpisode.setVisible(true);
}
if (endTime > 20000) {
btnNextEpisode.setText(XMLController.getLocalBundle().getString("nextEpisode")
+ countdown + XMLController.getLocalBundle().getString("seconds"));
bottomVBox.setVisible(true);
} else {
btnNextEpisode.setVisible(false);
playNextMedia();
}
}
}
@FXML
void btnBackAction(ActionEvent event) {
stop();
player.getStage().close();
}
@FXML
void btnPlayAction(ActionEvent event) {
if (embeddedMediaPlayer.status().isPlaying()) {
embeddedMediaPlayer.controls().pause();
playIcon.setImage(playArrow);
} else {
embeddedMediaPlayer.controls().play();
playIcon.setImage(pause);
}
}
@FXML
void btnReplayAction(ActionEvent event) {
embeddedMediaPlayer.controls().skipTime(-10000);
// update currentTime, endTime and controls if play back is paused
if (!embeddedMediaPlayer.status().isPlaying()) {
currentTime = currentTime - 10000;
endTime = endTime + 10000;
Platform.runLater(() -> {
updateControls();
});
}
}
@FXML
void btnForwardAction(ActionEvent event) {
embeddedMediaPlayer.controls().skipTime(10000);
// update currentTime, endTime and controls if play back is paused
if (!embeddedMediaPlayer.status().isPlaying()) {
currentTime = currentTime + 10000;
endTime = endTime - 10000;
Platform.runLater(() -> {
updateControls();
});
}
}
@FXML
void btnAudioAction(ActionEvent event) {
if (audioPopup == null) {
audioPopup = new JFXPopup();
// audio track
JFXListView<TrackDescription> audioList = new JFXListView<>();
audioList.setCellFactory(param -> new TrackDescriptionCellFactory());
audioList.setOnMouseClicked(ev -> {
setAudioTrack(audioList.getSelectionModel().getSelectedItem().id());
audioPopup.hide();
});
audioTracks.forEach(track -> {
audioList.getItems().add(track);
if (track.id() == currentAudioTrack) {
audioList.getSelectionModel().select(track);
}
});
Text audioHeading = new Text("Audio");
audioHeading.setFill(Color.WHITE);
audioHeading.setFont(Font.font(null, FontWeight.BOLD, 16));
// subtitle track
JFXListView<TrackDescription> subtitleList = new JFXListView<>();
subtitleList.setCellFactory(param -> new TrackDescriptionCellFactory());
subtitleList.setOnMouseClicked(ev -> {
setSubtitleTrack(subtitleList.getSelectionModel().getSelectedItem().id());
audioPopup.hide();
});
subtitleTracks.forEach(track -> {
subtitleList.getItems().add(track);
if (track.id() == currentSubtitleTrack) {
subtitleList.getSelectionModel().select(track);
}
});
Text subtitleHeading = new Text("Subtitles");
subtitleHeading.setFill(Color.WHITE);
subtitleHeading.setFont(Font.font(null, FontWeight.BOLD, 16));
// build dialog layout
VBox audioBox = new VBox(audioHeading, audioList);
VBox subtileBox = new VBox(subtitleHeading, subtitleList);
HBox hbox = new HBox(audioBox, subtileBox);
JFXDialogLayout content = new JFXDialogLayout();
content.setBody(hbox);
content.setPadding(new Insets(-20, -20, -20, -20)); // fix JFXDialogLayout padding
content.setSpacing(-10); // fix JFXDialogLayout spacing
audioPopup.setPopupContent(content);
}
if (!audioPopup.isShowing()) {
// TODO this does not work properly
audioPopup.show(btnAudio, PopupVPosition.BOTTOM, PopupHPosition.RIGHT,
0, -1 * bottomVBox.getHeight());
} else {
audioPopup.hide();
}
}
@FXML
private void btnFullscreenAction(ActionEvent event) {
player.getStage().setFullScreen(!player.getStage().isFullScreen());
fullscreenIcon.setImage(player.getStage().isFullScreen() ? fullscreenExit : fullscreen);
}
@FXML
private void btnNextEpisodeAction(ActionEvent event) {
btnNextEpisode.setVisible(false);
playNextMedia();
}
/**
* play the next media
*/
private void playNextMedia() {
autoplay = false;
DBController.getInstance().setCurrentTime(media.getStreamUrl(), 0); // reset old video start time
FilmTabelDataType nextMedia = DBController.getInstance().getNextEpisode(media.getTitle(), episode, season);
if (nextMedia != null) {
embeddedMediaPlayer.media().play(nextMedia.getStreamUrl());
media = nextMedia;
autoplay = true;
}
}
/**
* change the audio track
* @param track the index of the audio track
*/
private void setAudioTrack(int track) {
embeddedMediaPlayer.audio().setTrack(track);
currentAudioTrack = track;
}
private void setSubtitleTrack(int track) {
embeddedMediaPlayer.subpictures().setTrack(track);
currentSubtitleTrack = track;
}
public double getCurrentTime() {
return currentTime;
}
private class FXCallbackVideoSurface extends CallbackVideoSurface {
FXCallbackVideoSurface() {
super(new FXBufferFormatCallback(), new FXRenderCallback(), true,
VideoSurfaceAdapters.getVideoSurfaceAdapter());
}
}
private class FXBufferFormatCallback implements BufferFormatCallback {
@Override
public BufferFormat getBufferFormat(int sourceWidth, int sourceHeight) {
return new RV32BufferFormat(sourceWidth, sourceHeight);
}
@Override
public void allocatedBuffers(ByteBuffer[] buffers) {
PixelFormat<ByteBuffer> pixelFormat = PixelFormat.getByteBgraPreInstance();
// fixes buffer resolution, video resolution mismatch
videoPixelBuffer = new PixelBuffer<>(videoWidth, videoHeigth, buffers[0], pixelFormat);
//videoPixelBuffer = new PixelBuffer<>(sourceWidth, sourceHeight, buffers[0], pixelFormat);
videoImage = new WritableImage(videoPixelBuffer);
videoImageView.setImage(videoImage);
}
}
private class FXRenderCallback implements RenderCallback {
@Override
public void display(MediaPlayer mediaPlayer, ByteBuffer[] nativeBuffers, BufferFormat bufferFormat) {
Platform.runLater(() -> videoPixelBuffer.updateBuffer(pb -> null));
}
}
private class TrackDescriptionCellFactory extends JFXListCell<TrackDescription> {
@Override
protected void updateItem(TrackDescription item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null || item.description() == null) {
setText(null);
} else {
setText(item.description());
}
}
}
}

View File

@ -209,3 +209,4 @@
.scroll-pane > .viewport {
-fx-background-color: transparent;
}

View File

@ -1,92 +0,0 @@
* {
-theme-secondary-dark: #303030;
}
/*******************************************************************************
* *
* Slider *
* *
******************************************************************************/
.jfx-slider .slider-value {
-fx-rotate: 0.0;
}
/*
.jfx-slider > .track {
-fx-background-color: yellow;
}
*/
.jfx-slider > .colored-track {
-fx-background-color: #ee3523;
}
.jfx-slider > .thumb {
-fx-background-color: #ee3523;
}
.jfx-slider .animated-thumb {
-fx-rotate: 0.0;
-fx-pref-height: 30.0px;
-fx-pref-width: 80.0px;
-fx-background-color: -theme-secondary-dark;
-fx-background-radius: 5.0px 5.0px 5.0px 5.0px;
}
/*******************************************************************************
* *
* ListView *
* *
******************************************************************************/
.list-view {
-fx-background-color: -theme-secondary-dark;
-fx-padding: 1.0px;
}
.list-view .list-cell:hover {
-fx-background-color: #434343;
}
.list-view .list-cell:selected {
-fx-background-color: #434343;
}
.list-view .list-cell {
-fx-background-color: -theme-secondary-dark;
-fx-text-fill: white;
}
.list-view .label {
-fx-text-fill: white;
}
.jfx-rippler {
-jfx-rippler-fill: #ee3523;
}
/*******************************************************************************
* *
* Popup *
* *
******************************************************************************/
.jfx-popup-container {
-fx-background-color: -theme-secondary-dark;
}
/*******************************************************************************
* *
* Button *
* *
******************************************************************************/
/* FIXME disabled since buggy */
/*
.jfx-button:hover {
-fx-scale-x: 1.1;
-fx-scale-y: 1.1;
-fx-scale-z: 1.1;
}
*/

View File

@ -12,7 +12,7 @@
<?import javafx.scene.text.Text?>
<?import javafx.scene.text.TextFlow?>
<AnchorPane fx:id="rootPane" prefHeight="568.0" prefWidth="1130.0" style="-fx-background-color: #595959;" visible="false" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.mosad.homeflix.application.view.FilmDetailView">
<AnchorPane fx:id="filmDVPane" prefHeight="568.0" prefWidth="1130.0" style="-fx-background-color: #595959;" visible="false" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="kellerkinder.HomeFlix.application.FilmDetailView">
<children>
<HBox layoutX="22.0" layoutY="21.0" prefWidth="808.0" spacing="10.0" AnchorPane.leftAnchor="22.0" AnchorPane.rightAnchor="300.0" AnchorPane.topAnchor="22.0">
<children>

View File

@ -10,7 +10,7 @@
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="mainAnchorPane" prefHeight="600.0" prefWidth="1130.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.mosad.homeflix.application.MainWindowController">
<AnchorPane fx:id="mainAnchorPane" prefHeight="600.0" prefWidth="1130.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="kellerkinder.HomeFlix.application.MainWindowController">
<children>
<ScrollPane fx:id="posterModeScrollPane" fitToWidth="true" layoutX="10.0" layoutY="48.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="32.0">
<content>

View File

@ -3,145 +3,73 @@
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXSlider?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.media.MediaView?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="panePlayer" prefHeight="720.0" prefWidth="1280.0" style="-fx-background-color: black;" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox alignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<ImageView fx:id="videoImageView" pickOnBounds="true" preserveRatio="true" />
</children>
</HBox>
<HBox fx:id="hBoxTop" alignment="CENTER_LEFT" spacing="10.0" style="-fx-background-color: linear-gradient(to bottom, #000000aa, #00000000);" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<JFXButton fx:id="btnBack" contentDisplay="GRAPHIC_ONLY" onAction="#btnBackAction">
<graphic>
<ImageView fitHeight="32.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../icons/baseline_keyboard_backspace_white_48dp.png" />
</image>
</ImageView>
</graphic>
</JFXButton>
<Label fx:id="lblTitle" text="Title" textFill="WHITE">
<font>
<Font size="22.0" />
</font>
</Label>
</children>
<padding>
<Insets left="5.0" right="5.0" top="5.0" />
</padding>
</HBox>
<VBox fx:id="bottomVBox" alignment="CENTER" style="-fx-background-color: linear-gradient(to top, #000000dd, #00000000);" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<children>
<HBox spacing="10.0">
<children>
<JFXSlider fx:id="timeSlider" HBox.hgrow="ALWAYS">
<padding>
<Insets left="5.0" right="5.0" />
</padding>
</JFXSlider>
<Label fx:id="lblEndTime" text="0:00:00" textFill="WHITE">
<font>
<Font size="17.0" />
</font>
</Label>
</children>
<VBox.margin>
<Insets />
</VBox.margin>
<padding>
<Insets left="10.0" right="10.0" />
</padding>
</HBox>
<HBox fx:id="controlsHBox" spacing="10.0">
<children>
<HBox spacing="10.0">
<children>
<JFXButton fx:id="btnPlay" contentDisplay="GRAPHIC_ONLY" onAction="#btnPlayAction">
<graphic>
<ImageView fx:id="playIcon" fitHeight="42.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../icons/baseline_pause_white_48dp.png" />
</image>
</ImageView>
</graphic>
</JFXButton>
<JFXButton fx:id="btnReplay" contentDisplay="GRAPHIC_ONLY" onAction="#btnReplayAction">
<graphic>
<ImageView fitHeight="42.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../icons/baseline_replay_10_white_48dp.png" />
</image>
</ImageView>
</graphic>
</JFXButton>
<JFXButton fx:id="btnForward" contentDisplay="GRAPHIC_ONLY" onAction="#btnForwardAction">
<graphic>
<ImageView fitHeight="42.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../icons/baseline_forward_10_white_48dp.png" />
</image>
</ImageView>
</graphic>
</JFXButton>
</children>
<padding>
<Insets left="5.0" right="5.0" />
</padding>
</HBox>
<HBox alignment="TOP_RIGHT" spacing="10.0" HBox.hgrow="ALWAYS">
<children>
<JFXButton fx:id="btnAudio" contentDisplay="GRAPHIC_ONLY" onAction="#btnAudioAction">
<graphic>
<ImageView fitHeight="42.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../icons/baseline_subtitles_white_48dp.png" />
</image>
</ImageView>
</graphic>
</JFXButton>
<JFXButton fx:id="btnFullscreen" contentDisplay="GRAPHIC_ONLY" onAction="#btnFullscreenAction" prefHeight="39.0">
<graphic>
<ImageView fx:id="fullscreenIcon" fitHeight="42.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../icons/baseline_fullscreen_white_48dp.png" />
</image>
</ImageView>
</graphic>
</JFXButton>
</children>
<padding>
<Insets left="5.0" right="5.0" />
</padding>
</HBox>
</children>
<padding>
<Insets bottom="5.0" left="10.0" right="10.0" top="5.0" />
</padding>
</HBox>
</children>
<padding>
<Insets bottom="5.0" />
</padding>
</VBox>
<JFXButton fx:id="btnNextEpisode" onAction="#btnNextEpisodeAction" style="-fx-background-color: ee3523;" text="next episode in 10 seconds" textFill="WHITE" visible="false" AnchorPane.bottomAnchor="100.0" AnchorPane.rightAnchor="20.0">
<font>
<Font name="System Bold" size="14.0" />
</font>
<opaqueInsets>
<Insets />
</opaqueInsets>
<padding>
<Insets bottom="7.0" left="7.0" right="7.0" top="7.0" />
</padding>
</JFXButton>
</children>
<AnchorPane prefHeight="720.0" prefWidth="1280.0" style="-fx-background-color: black;" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox alignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<MediaView fx:id="mediaView" />
</children>
</HBox>
<VBox fx:id="bottomVBox" alignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<children>
<JFXSlider fx:id="timeSlider">
<padding>
<Insets left="5.0" right="5.0" />
</padding>
</JFXSlider>
<HBox fx:id="controlsHBox" alignment="CENTER" spacing="10.0">
<children>
<JFXButton fx:id="stopBtn" buttonType="RAISED" contentDisplay="GRAPHIC_ONLY" onAction="#stopBtnAction" prefHeight="39.0" style="-fx-background-color: white;">
<graphic>
<ImageView fx:id="stopIcon" fitHeight="29.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../icons/baseline_stop_black_48dp.png" />
</image>
</ImageView>
</graphic></JFXButton>
<JFXButton fx:id="playBtn" buttonType="RAISED" contentDisplay="GRAPHIC_ONLY" onAction="#playBtnAction" prefHeight="39.0" style="-fx-background-color: white;">
<graphic>
<ImageView fx:id="playIcon" fitHeight="29.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../icons/baseline_play_arrow_black_48dp.png" />
</image>
</ImageView>
</graphic></JFXButton>
<JFXButton fx:id="fullscreenBtn" buttonType="RAISED" contentDisplay="GRAPHIC_ONLY" onAction="#fullscreenBtnAction" prefHeight="39.0" style="-fx-background-color: white;">
<graphic>
<ImageView fx:id="fullscreenIcon" fitHeight="29.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../icons/baseline_fullscreen_black_48dp.png" />
</image>
</ImageView>
</graphic></JFXButton>
</children>
<padding>
<Insets bottom="5.0" top="5.0" />
</padding>
</HBox>
</children>
<padding>
<Insets bottom="5.0" />
</padding>
</VBox>
<JFXButton fx:id="nextEpBtn" onAction="#nextEpBtnAction" style="-fx-background-color: ee3523;" text="next episode in 10 seconds" textFill="WHITE" visible="false" AnchorPane.bottomAnchor="80.0" AnchorPane.rightAnchor="20.0">
<font>
<Font name="System Bold" size="14.0" />
</font>
<opaqueInsets>
<Insets />
</opaqueInsets>
<padding>
<Insets bottom="7.0" left="7.0" right="7.0" top="7.0" />
</padding></JFXButton>
</children>
</AnchorPane>

View File

@ -14,7 +14,7 @@
<?import javafx.scene.text.Text?>
<?import javafx.scene.text.TextFlow?>
<AnchorPane fx:id="rootPane" prefHeight="568.0" prefWidth="1130.0" style="-fx-background-color: #595959;" visible="false" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.mosad.homeflix.application.view.SeriesDetailView">
<AnchorPane fx:id="seriesDVPane" prefHeight="568.0" prefWidth="1130.0" style="-fx-background-color: #595959;" visible="false" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="kellerkinder.HomeFlix.application.SeriesDetailView">
<children>
<HBox layoutX="22.0" layoutY="21.0" prefWidth="808.0" spacing="10.0" AnchorPane.leftAnchor="22.0" AnchorPane.rightAnchor="310.0" AnchorPane.topAnchor="22.0">
<children>
@ -61,7 +61,7 @@
</graphic></JFXButton>
</children>
</HBox>
<TextFlow layoutX="22.0" layoutY="150.0" lineSpacing="1.0" maxHeight="-Infinity" prefHeight="130.0" prefWidth="808.0" AnchorPane.bottomAnchor="308.0" AnchorPane.leftAnchor="22.0" AnchorPane.rightAnchor="310.0" AnchorPane.topAnchor="130.0">
<TextFlow layoutX="22.0" layoutY="150.0" lineSpacing="1.0" maxHeight="-Infinity" prefHeight="130.0" prefWidth="808.0" AnchorPane.leftAnchor="22.0" AnchorPane.rightAnchor="310.0" AnchorPane.topAnchor="130.0">
<children>
<Text fx:id="textPlot" fill="#ecebed" strokeType="OUTSIDE" strokeWidth="0.0" text="Avatar: Der Herr der Elemente ist eine amerikanische Zeichentrickserie. Die Serie wurde erstellt und produziert von Michael Dante DiMartion und Bryan Konietzko. Avatar spielt in einer, stark asiatisch beeinflussten Welt, in der einige in der Lage sind die Elemente zu beeinflussen. Die Fähigkeit die Elemente zu &quot;bändigen&quot;, erfolgt in einer Mischung aus mentaler Beeinflussung und einer Variation von fernöstlicher Kampfkunst.Die Serie erzählt die Geschichte des zwölfjährigen Aangs und seinen Freunden, die versuchen das Gleichgewicht der Elemente wieder herzustellen, indem sie die Herrschaft des Feuerlords über die drei anderen Elemente beenden. Aang ist der letzte verbliebene Luftbändiger und gleichzeitig der Avatar, welcher 100 Jahre verschollen war.">
<font>
@ -70,11 +70,11 @@
</Text>
</children>
</TextFlow>
<Label fx:id="lblCrew" layoutX="31.0" layoutY="346.0" text="Haupt-Crew" textFill="#ecebed" AnchorPane.bottomAnchor="264.0" AnchorPane.leftAnchor="22.0">
<Label fx:id="lblCrew" layoutX="31.0" layoutY="346.0" text="Haupt-Crew" textFill="#ecebed" AnchorPane.leftAnchor="22.0" AnchorPane.topAnchor="280.0">
<font>
<Font size="20.0" />
</font></Label>
<HBox layoutX="22.0" layoutY="372.0" spacing="30.0" AnchorPane.bottomAnchor="218.0" AnchorPane.leftAnchor="22.0" AnchorPane.rightAnchor="310.0">
<HBox layoutX="22.0" layoutY="372.0" spacing="30.0" AnchorPane.leftAnchor="22.0" AnchorPane.rightAnchor="310.0" AnchorPane.topAnchor="310.0">
<children>
<VBox spacing="3.0">
<children>
@ -118,7 +118,7 @@
</VBox>
</children>
</HBox>
<ScrollPane fx:id="scrollPaneEpisodes" layoutX="22.0" layoutY="398.0" prefHeight="135.0" style="-fx-background-color: #595959;" AnchorPane.bottomAnchor="63.0" AnchorPane.leftAnchor="22.0" AnchorPane.rightAnchor="310.0">
<ScrollPane fx:id="scrollPaneEpisodes" layoutX="22.0" layoutY="398.0" prefHeight="135.0" style="-fx-background-color: #595959;" AnchorPane.leftAnchor="22.0" AnchorPane.rightAnchor="310.0" AnchorPane.topAnchor="370.0">
<content>
<HBox fx:id="hBoxEpisodes" maxHeight="-Infinity" minHeight="-Infinity" prefHeight="117.0" spacing="10.0">
<padding>
@ -127,7 +127,7 @@
</HBox>
</content>
</ScrollPane>
<HBox style="-fx-background-color: #ffffff;" AnchorPane.bottomAnchor="28.0" AnchorPane.leftAnchor="22.0">
<HBox style="-fx-background-color: #ffffff;" AnchorPane.leftAnchor="22.0" AnchorPane.topAnchor="515.0">
<children>
<ChoiceBox fx:id="cbSeason" prefHeight="25.0" prefWidth="168.0" />
</children>

View File

@ -16,7 +16,7 @@
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<ScrollPane fx:id="settingsScrollPane" fitToHeight="true" fitToWidth="true" prefHeight="568.0" prefWidth="980.0" style="-fx-background-color: #ffffff;" visible="false" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.mosad.homeflix.application.SettingsView">
<ScrollPane fx:id="settingsScrollPane" fitToHeight="true" fitToWidth="true" prefHeight="568.0" prefWidth="980.0" style="-fx-background-color: #ffffff;" visible="false" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="kellerkinder.HomeFlix.application.SettingsView">
<content>
<AnchorPane fx:id="settingsAnchorPane" style="-fx-background-color: #ffffff;">
<children>
@ -113,11 +113,6 @@
<Insets bottom="-5.0" top="-5.0" />
</padding>
</JFXToggleButton>
<JFXToggleButton fx:id="fullscreenToggleBtn" onAction="#fullscreenToggleBtnAction" text="start in fullscreen">
<padding>
<Insets bottom="-5.0" top="-5.0" />
</padding>
</JFXToggleButton>
</children>
</VBox>
<VBox spacing="10.0">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 616 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 B

View File

@ -1,32 +1,13 @@
# Project-HomeFlix
#
# Copyright 2016-2020 <seil0@mosad.xyz>
#
# 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.
#
# HomeFlix-Local_de_DE.properties German Local
#HomeFlix-Local_de_DE.properties German Local
# main window translations
#main window translations
info = Info
settings = Einstellungen
streamingSettings = Stream Einst.
tfSearch = Suche...
openFolder = Ordner \u00F6ffnen
# settings translations
#settings translations
homeflixSettingsLbl = HomeFlix Einstellungen
filmDirTextField = Pfad...
addDirectory = Ordner hinzuf\u00FCgen
@ -39,23 +20,22 @@ updateBtnChecking = Es wird nach Updates gesucht...
updateBtnUpdateAvailable = Update verf\u00FCgbar
updateBtnNoUpdateAvailable = Kein Update verf\u00FCgbar
autoUpdate = beim Start nach Updates suchen:
autoplay = Autoplay
fullscreen = starte im Vollbildmodus
autoplay = autoplay
branchLbl = Updatezweig
sourcesLbl = Quellen
# column translations
#column translations
columnStreamUrl = Datei Name
columnName = Name
columnSeason = Staffel
columnEpisode = Episode
columnFavorite = Favorit
# error translations
#error translations
vlcNotInstalled = Um einen Film abspielen wird der VLC Media Player ben\u00F6tigt!
infoText = \nAutoren: \n \u2022 seil0@mosad.xyz \n \u2022 localhorst@mosad.xyz \n(c) 2016-2020 mosad www.mosad.xyz
infoText = \nAutoren: \n \u2022 seil0@mosad.xyz \n \u2022 localhorst@mosad.xyz \n(c) 2016-2019 mosad www.mosad.xyz
# textFlow translations
#textFlow translations
title = Titel
year = Jahr
rated = Einstufung
@ -63,7 +43,7 @@ released = Ver\u00F6ffentlicht am
season = Staffel
episode = Episode
runtime = Laufzeit
genre = Genre
genre = Gener
directors = Regisseur
writers = Autoren
actors = Schauspieler
@ -77,15 +57,11 @@ type = Type
boxOffice = BoxOffice
website = Webseite
# first start
#first start
addSourceHeader = Neue Quelle hinzuf\u00FCgen
addSourceBody = HomeFlix konnte keine Quelle finden. \nF\u00FCge eine loakels Verzeichniss oder eine Sreaming Datei als neue Quelle hinzu.
addSourceBody = HomeFlix konnte keine Quelle finden. \nFüge eine loakels Verzeichniss oder eine Sreaming Datei als neue Quelle hinzu.
cancelBtnText = Abbrechen
# DetailView
#DetailView
crew = Haupt-Crew
score = Benutzerbewertung
# player
nextEpisode = Nächste Folge in\u0020
seconds = \u0020Sekunden

View File

@ -1,32 +1,13 @@
# Project-HomeFlix
#
# Copyright 2016-2020 <seil0@mosad.xyz>
#
# 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.
#
# HomeFlix-Local_en_US.properties US-English Local and default
#HomeFlix-Local_en_US.properties US-English Local and default
# main window translations
#main window translations
info = Info
settings = Settings
streamingSettings = Stream Settings
tfSearch = Search...
openFolder = open Folder
# settings translations
#settings translations
homeflixSettingsLbl = HomeFlix Settings
filmDirTextField = Path...
addDirectory = add directory
@ -39,23 +20,22 @@ updateBtnChecking = checking for updates...
updateBtnUpdateAvailable = update available
updateBtnNoUpdateAvailable = no update available
autoUpdate = check at startup for updates:
autoplay = Autoplay
fullscreen = start in fullscreen
autoplay = autoplay
branchLbl = Branch
sourcesLbl = Sources
sourcesLbl = Quellen
# column translations
#column translations
columnStreamUrl = File Name
columnName = Name
columnSeason = Season
columnEpisode = Episode
columnFavorite = Favorite
# error translations
#error translations
vlcNotInstalled = VLC Media Player is required to play a movie!
infoText = \nMaintainers: \n \u2022 seil0@mosad.xyz \n \u2022 localhorst@mosad.xyz \n(c) 2016-2020 mosad www.mosad.xyz
infoText = \nMaintainers: \n \u2022 seil0@mosad.xyz \n \u2022 localhorst@mosad.xyz \n(c) 2016-2019 mosad www.mosad.xyz
# textFlow translations
#textFlow translations
title = Title
year = Year
rated = Rating
@ -63,7 +43,7 @@ released = published on
season = Season
episode = Episode
runtime = Runtime
genre = Genre
genre = Gener
directors = Directors
writers = Writers
actors = Actors
@ -77,15 +57,11 @@ type = Type
boxOffice = BoxOffice
website = Website
# first startnext episode in
#first start
addSourceHeader = add a new source
addSourceBody = HomeFlix was not able to load a source. \nAdd a new local directory or a streaming file as new source.
addSourceBody = HomeFlix was not able to load a source. \nAdd a new local directory oa a streaming file as new source.
cancelBtnText = cancel
# DetailView
#DetailView
crew = Featured Crew
score = User Score
# player
nextEpisode = next episode in\u0020
seconds = \u0020seconds