diff --git a/mpv_library/Makefile b/mpv_library/Makefile new file mode 100644 index 0000000..2dccfb8 --- /dev/null +++ b/mpv_library/Makefile @@ -0,0 +1,37 @@ +# Compiler +CC=gcc +# Flags +CFLAGS=-O2 +MKDIR_P = mkdir -p +APP_NAME = mpvjni + +all: x86 amd64 + +x86: + $(MKDIR_P) ./x86 + $(CC) ${CFLAGS} -m32 -c -fPIC -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" ${APP_NAME}.c -o ${APP_NAME}_x86.o + $(CC) ${CFLAGS} -m32 -shared -fPIC -o ./x86/${APP_NAME}.so ${APP_NAME}_x86.o -lc + +amd64: + $(MKDIR_P) ./amd64 + $(CC) ${CFLAGS} -m64 -c -fPIC -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" ${APP_NAME}.c -o ${APP_NAME}_amd64.o + $(CC) ${CFLAGS} -m64 -shared -fPIC -o ./amd64/${APP_NAME}.so ${APP_NAME}_amd64.o -lc + +clean: + rm -rf \ + ${APP_NAME}_amd64.o \ + ${APP_NAME}_x86.o \ + ./x86 \ + ./amd64 + +headers: + cd /src/main/java + javac mplayer4anime/mpv/MpvJni.java -h ../../../mpv_library/ + +install: x86 amd64 + install ./x86/${APP_NAME}.so ../src/main/resources/native/linux/x86/ + install ./amd64/${APP_NAME}.so ../src/main/resources/native/linux/amd64/ + +uninstall: + rm ../src/main/resources/native/linux/x86/${APP_NAME}.so + rm ../src/main/resources/native/linux/amd64/${APP_NAME}.so diff --git a/mpv_library/mplayer4anime_mpv_MpvSlave.h b/mpv_library/mplayer4anime_mpv_MpvSlave.h new file mode 100644 index 0000000..9c9fbbe --- /dev/null +++ b/mpv_library/mplayer4anime_mpv_MpvSlave.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class mplayer4anime_mpv_MpvSlave */ + +#ifndef _Included_mplayer4anime_mpv_MpvSlave +#define _Included_mplayer4anime_mpv_MpvSlave +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: mplayer4anime_mpv_MpvSlave + * Method: play + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_mplayer4anime_mpv_MpvSlave_play + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/mpv_library/mpvjni.c b/mpv_library/mpvjni.c new file mode 100644 index 0000000..f3e3b1c --- /dev/null +++ b/mpv_library/mpvjni.c @@ -0,0 +1,6 @@ +#include +#include "mplayer4anime_mpv_MpvSlave.h" + +JNIEXPORT void JNICALL Java_mplayer4anime_mpv_MpvSlave_play(JNIEnv * jnienv, jobject jobject){ + +}; \ No newline at end of file diff --git a/src/main/java/mplayer4anime/AppPreferences.java b/src/main/java/mplayer4anime/AppPreferences.java index 47d54db..8ab3e07 100644 --- a/src/main/java/mplayer4anime/AppPreferences.java +++ b/src/main/java/mplayer4anime/AppPreferences.java @@ -122,4 +122,7 @@ public class AppPreferences { public double getSceneHeight(){ return preferences.getDouble("window_height", 800.0); } public void setSceneHeight(double value){ preferences.putDouble("window_height", value); } + + public int getBackendEngineIndexId(){ return preferences.getInt("backend_player", 0); } + public void setBackendEngineIndexId(int value){ preferences.putInt("backend_player", value); } } diff --git a/src/main/java/mplayer4anime/Controller.java b/src/main/java/mplayer4anime/Controller.java index eaec6ba..bcc90af 100644 --- a/src/main/java/mplayer4anime/Controller.java +++ b/src/main/java/mplayer4anime/Controller.java @@ -32,6 +32,8 @@ import mplayer4anime.Playlists.Playlists; import mplayer4anime.Settings.SettingsWindow; import mplayer4anime.appPanes.ControllerPane; import mplayer4anime.appPanes.ControllerSUB; +import mplayer4anime.mplayer.MplayerSlave; +import mplayer4anime.mpv.MpvSlave; import java.io.*; import java.net.URL; @@ -56,12 +58,10 @@ public class Controller implements Initializable { private final AppPreferences appPreferences = AppPreferences.getINSTANCE(); private ResourceBundle resourceBundle; - // Get host services for opening URLs etc. private HostServices hostServices; - private String currentPlaylistLocation; - - private MplayerSlave mplayer; + private String backend; + private ISlaveModeAppOrchestration player; // If application started with playlist passed as an argument, then we'll try to load it (if it's valid). public void setPlaylistAsArgument(String playlist) { @@ -96,8 +96,14 @@ public class Controller implements Initializable { continue; addRecentlyOpened(recentPlaylists[i]); } - - mplayer = new MplayerSlave(resourceBundle); + if (appPreferences.getBackendEngineIndexId() == 0) { + backend = "mplayer"; + player = new MplayerSlave(resourceBundle); + } + else { + backend = "mpv"; + player = new MpvSlave(resourceBundle); + } } void setHostServices(HostServices hostServices) { @@ -126,11 +132,15 @@ public class Controller implements Initializable { } @FXML - private void infoBtn(){ new AboutWindow(this.hostServices); } // TODO: fix this shit with hostSerivces that doesn't work @ linux + private void infoBtn(){ + new AboutWindow(this.hostServices); + } // TODO: fix this shit with hostSerivces that doesn't work @ linux /** SETTINGS HANDLE */ @FXML - private void settingsBtn(){ new SettingsWindow(); } + private void settingsBtn(){ + new SettingsWindow(); + } // Get event that notify application in case some settings has been changed // This function called from MediatorControl after mediator receives request form SettingsController indicating that user updated some required fields. void updateAfterSettingsChanged(){ @@ -138,6 +148,18 @@ public class Controller implements Initializable { subPaneController.setEncoding(appPreferences.getSubsEncodingList(), null); // In case of application failure should be better to save this immediately appPreferences.setLastTimeUsedSubsEncoding(subPaneController.getSelectedEncoding()); + switchBackend(appPreferences.getBackendEngineIndexId()); + } + private void switchBackend(int newBackEndId){ + if (newBackEndId == 0 && backend.equals("mpv")){ + backend = "mplayer"; + player = new MplayerSlave(resourceBundle); + return; + } + if (newBackEndId == 1 && backend.equals("mplayer")){ + backend = "mpv"; + player = new MpvSlave(resourceBundle); + } } @FXML @@ -147,44 +169,51 @@ public class Controller implements Initializable { } private void setAllLists(JsonStorage jsonStorage){ if (jsonStorage != null) { - mkvPaneController.cleanList(); - mkaPaneController.cleanList(); - subPaneController.cleanList(); mkvPaneController.setFilesFromList(jsonStorage.getVideo()); mkaPaneController.setFilesFromList(jsonStorage.getAudio()); subPaneController.setFilesFromList(jsonStorage.getSubs()); subPaneController.selectEncodingValue(jsonStorage.getSubEncoding(), appPreferences); - currentPlaylistLocation = Playlists.getPlaylistLocation(); // TODO: Implement listener? mmm... - //System.out.println(currentPlaylistLocation); + currentPlaylistLocation = Playlists.getPlaylistLocation(); // TODO: Implement listener? mmm... statusLbl.setText(currentPlaylistLocation); addRecentlyOpened(currentPlaylistLocation); } } @FXML private void saveBtn() { - if (mkvPaneController.getElementsCount() == 0) - ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), resourceBundle.getString("ErrorUnableToSaveEmptyPlaylist")); - else { - JsonStorage jsonStorage = new JsonStorage(mkvPaneController.getElementsAll(), mkaPaneController.getElementsAll(), subPaneController.getElementsAll(), subPaneController.getSelectedEncoding()); - if (Playlists.SaveCurrent(resourceBundle, jsonStorage)) { - this.currentPlaylistLocation = Playlists.getPlaylistLocation(); - this.statusLbl.setText(currentPlaylistLocation); //TODO: update header of the application to include this? - addRecentlyOpened(currentPlaylistLocation); - } + if (mkvPaneController.getElementsCount() == 0) { + ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), + resourceBundle.getString("ErrorUnableToSaveEmptyPlaylist")); + return; + } + JsonStorage jsonStorage = new JsonStorage( + mkvPaneController.getElementsAll(), + mkaPaneController.getElementsAll(), + subPaneController.getElementsAll(), + subPaneController.getSelectedEncoding()); + if (Playlists.SaveCurrent(resourceBundle, jsonStorage)) { + this.currentPlaylistLocation = Playlists.getPlaylistLocation(); + this.statusLbl.setText(currentPlaylistLocation); //TODO: update header of the application to include this? + addRecentlyOpened(currentPlaylistLocation); } } @FXML private void saveAsBtn() { - if (mkvPaneController.getElementsCount() == 0) - ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), resourceBundle.getString("ErrorUnableToSaveEmptyPlaylist")); - else { - JsonStorage jsonStorage = new JsonStorage(mkvPaneController.getElementsAll(), mkaPaneController.getElementsAll(), subPaneController.getElementsAll(), subPaneController.getSelectedEncoding()); - if (Playlists.SaveAs(resourceBundle, jsonStorage)) { - this.currentPlaylistLocation = Playlists.getPlaylistLocation(); - this.statusLbl.setText(currentPlaylistLocation); //TODO: update header of the application to include this? - addRecentlyOpened(currentPlaylistLocation); - } + if (mkvPaneController.getElementsCount() == 0) { + ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), + resourceBundle.getString("ErrorUnableToSaveEmptyPlaylist")); + return; + } + + JsonStorage jsonStorage = new JsonStorage( + mkvPaneController.getElementsAll(), + mkaPaneController.getElementsAll(), + subPaneController.getElementsAll(), + subPaneController.getSelectedEncoding()); + if (Playlists.SaveAs(resourceBundle, jsonStorage)) { + this.currentPlaylistLocation = Playlists.getPlaylistLocation(); + this.statusLbl.setText(currentPlaylistLocation); //TODO: update header of the application to include this? + addRecentlyOpened(currentPlaylistLocation); } } @FXML @@ -223,15 +252,15 @@ public class Controller implements Initializable { /* PLAYER */ @FXML private void subsTriggerBtn(){ - mplayer.subtitlesSwitch(); + player.subtitlesSwitch(); } @FXML private void fullscreenBtn(){ - mplayer.fullscreenSwitch(); + player.fullscreenSwitch(); } @FXML private void muteBtn(){ - mplayer.mute(); + player.mute(); } @FXML private void playPrevTrackBtn(){ @@ -240,7 +269,7 @@ public class Controller implements Initializable { return; mkvPaneController.setElementSelectedByIndex(index-1); - mplayer.forcePlay(appPreferences.getPath(), + player.forcePlay(appPreferences.getPath(), mkvPaneController.getElementSelected(), mkaPaneController.getElementSelected(), subPaneController.getElementSelected(), @@ -265,7 +294,7 @@ public class Controller implements Initializable { subPaneController.setElementSelectedByIndex(index + 1); } - mplayer.forcePlay(appPreferences.getPath(), + player.forcePlay(appPreferences.getPath(), mkvPaneController.getElementSelected(), mkaPaneController.getElementSelected(), subPaneController.getElementSelected(), @@ -279,7 +308,7 @@ public class Controller implements Initializable { if (mkvPaneController.getElementSelected() == null) return; - mplayer.playPause(appPreferences.getPath(), + player.playPause(appPreferences.getPath(), mkvPaneController.getElementSelected(), mkaPaneController.getElementSelected(), subPaneController.getElementSelected(), @@ -290,15 +319,15 @@ public class Controller implements Initializable { } @FXML private void stopBtn(){ - mplayer.stop(); + player.stop(); } @FXML private void volumeUpBtn(){ - mplayer.volumeUp(); + player.volumeUp(); } @FXML private void volumeDownBtn(){ - mplayer.volumeDown(); + player.volumeDown(); } } diff --git a/src/main/java/mplayer4anime/IMediatorContol.java b/src/main/java/mplayer4anime/IMediatorContol.java deleted file mode 100644 index 584cf96..0000000 --- a/src/main/java/mplayer4anime/IMediatorContol.java +++ /dev/null @@ -1,6 +0,0 @@ -package mplayer4anime; - -public interface IMediatorContol { - void registerMainController(mplayer4anime.Controller mc); - void sentUpdates(); -} diff --git a/src/main/java/mplayer4anime/IPC/ServerSocketProvider.java b/src/main/java/mplayer4anime/IPC/ServerSocketProvider.java index 5ee1142..73a389b 100644 --- a/src/main/java/mplayer4anime/IPC/ServerSocketProvider.java +++ b/src/main/java/mplayer4anime/IPC/ServerSocketProvider.java @@ -1,3 +1,21 @@ +/* + Copyright 2018-2021 Dmitry Isaenko + + This file is part of mplayer4anime. + + mplayer4anime 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. + + mplayer4anime 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 mplayer4anime. If not, see . + */ package mplayer4anime.IPC; import javafx.application.Platform; @@ -11,8 +29,8 @@ import java.net.Socket; class ServerSocketProvider implements Runnable{ - private ServerSocket serverSocket; - private Controller controller; + private final ServerSocket serverSocket; + private final Controller controller; ServerSocketProvider(Controller mainCntrl, ServerSocket srvSock){ this.serverSocket = srvSock; @@ -42,6 +60,7 @@ class ServerSocketProvider implements Runnable{ } } catch (IOException ex){ + ex.printStackTrace(); System.out.println("Socket has been closed."); } } diff --git a/src/main/java/mplayer4anime/IPC/SingleInstanceHandler.java b/src/main/java/mplayer4anime/IPC/SingleInstanceHandler.java index 2ddecac..17bcd30 100644 --- a/src/main/java/mplayer4anime/IPC/SingleInstanceHandler.java +++ b/src/main/java/mplayer4anime/IPC/SingleInstanceHandler.java @@ -7,6 +7,7 @@ import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; +// TODO: Rewrite and remove. Or just remove. public class SingleInstanceHandler implements Runnable{ private ServerSocket servSock; @@ -41,15 +42,9 @@ public class SingleInstanceHandler implements Runnable{ @Override public void run() { - while (true) { - if ( Thread.currentThread().isInterrupted() ){ - try { - servSock.close(); - } catch (IOException e) { - System.out.println("Internal issue: unable to create client socket."); - } - break; - } - } + while (! Thread.currentThread().isInterrupted()); + try { + servSock.close(); + } catch (IOException ignore) {} } } \ No newline at end of file diff --git a/src/main/java/mplayer4anime/ISlaveModeAppOrchestration.java b/src/main/java/mplayer4anime/ISlaveModeAppOrchestration.java index 463e840..fe830a0 100644 --- a/src/main/java/mplayer4anime/ISlaveModeAppOrchestration.java +++ b/src/main/java/mplayer4anime/ISlaveModeAppOrchestration.java @@ -19,5 +19,25 @@ package mplayer4anime; public interface ISlaveModeAppOrchestration { - // TODO: implement unified interface for mplayer and mpv + void subtitlesSwitch(); + void fullscreenSwitch(); + void mute(); + void forcePlay(String mplayerPath, + String VideoFile, + String AudioFile, + String SubtitlesFile, + String subtitlesEncoding, + boolean subtitlesHidden, + boolean isFullscreen); + boolean pause(); + void playPause(String mplayerPath, + String VideoFile, + String AudioFile, + String SubtitlesFile, + String subtitlesEncoding, + boolean subtitlesHidden, + boolean isFullscreen); + void stop(); + void volumeUp(); + void volumeDown(); } diff --git a/src/main/java/mplayer4anime/MediatorControl.java b/src/main/java/mplayer4anime/MediatorControl.java index b9d9e51..783e397 100644 --- a/src/main/java/mplayer4anime/MediatorControl.java +++ b/src/main/java/mplayer4anime/MediatorControl.java @@ -1,14 +1,12 @@ package mplayer4anime; -public class MediatorControl implements IMediatorContol{ +public class MediatorControl{ private Controller mainController; - @Override public void registerMainController(Controller mc) { mainController = mc; } - @Override public void sentUpdates() { mainController.updateAfterSettingsChanged(); } diff --git a/src/main/java/mplayer4anime/Playlists/Playlists.java b/src/main/java/mplayer4anime/Playlists/Playlists.java index 32a4392..20f881b 100644 --- a/src/main/java/mplayer4anime/Playlists/Playlists.java +++ b/src/main/java/mplayer4anime/Playlists/Playlists.java @@ -1,3 +1,21 @@ +/* + Copyright 2018-2021 Dmitry Isaenko + + This file is part of mplayer4anime. + + mplayer4anime 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. + + mplayer4anime 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 mplayer4anime. If not, see . + */ package mplayer4anime.Playlists; import com.google.gson.*; @@ -9,12 +27,10 @@ import java.nio.charset.StandardCharsets; import java.util.ResourceBundle; public class Playlists { - private static String playlistLocation; + //TODO: Show popUp if unable to write! Or nothing to write! Or overwrite! - /** - * Interface for Save As functionality - * */ + //TODO: Disable 'Save' button if no files added public static boolean SaveAs(ResourceBundle resourceBundle, JsonStorage jStorage){ File playlistFile; FileChooser fileChooser = new FileChooser(); @@ -27,48 +43,50 @@ public class Playlists { return writeFile(resourceBundle, playlistFile, jStorage); } - /** - * Interface for Save functionality - * */ + public static boolean SaveCurrent(ResourceBundle resourceBundle, JsonStorage jStorage) { if (playlistLocation == null || playlistLocation.equals("")){ return Playlists.SaveAs(resourceBundle, jStorage); } - else { - return writeFile(resourceBundle, new File(playlistLocation), jStorage); - } + return writeFile(resourceBundle, new File(playlistLocation), jStorage); } - // Working with file itself + /** + * @return true for success, false for failure + * */ private static boolean writeFile(ResourceBundle resourceBundle, File playlistFile, JsonStorage jStorage){ - // TODO: Add 'Override pop-up notification!' - if (playlistFile != null) { - if (!playlistFile.getAbsolutePath().endsWith(".alpr")) { - playlistFile = new File(playlistFile.getAbsolutePath() + ".alpr"); - } - try (Writer writer = new OutputStreamWriter(new FileOutputStream(playlistFile.getAbsolutePath()), StandardCharsets.UTF_8)) - { - Gson jsonObject = new GsonBuilder().setPrettyPrinting().create(); - jsonObject.toJson(jStorage, writer); - writer.close(); - - playlistLocation = playlistFile.getAbsolutePath(); - // Return success notification - return true; - - } catch (java.io.FileNotFoundException e){ - ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), resourceBundle.getString("ErrorFileNotFound")); - } catch (java.io.UnsupportedEncodingException e){ - ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), resourceBundle.getString("ErrorOnSaveIncorrectEncoding")); - } catch (java.io.IOException e){ - ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), resourceBundle.getString("ErrorOnSaveIOProblem")); - } + if (playlistFile == null) { + ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), + "Unable to save: File not selected");// TODO: translate return false; } - else { - System.out.println("Unable to save: File not selected"); - return false; + + if (!playlistFile.getAbsolutePath().endsWith(".alpr")) { + playlistFile = new File(playlistFile.getAbsolutePath() + ".alpr"); } + + try (Writer writer = new OutputStreamWriter( + new FileOutputStream(playlistFile.getAbsolutePath()), StandardCharsets.UTF_8)) + { + Gson jsonObject = new GsonBuilder().setPrettyPrinting().create(); + jsonObject.toJson(jStorage, writer); + writer.close(); + + playlistLocation = playlistFile.getAbsolutePath(); + + return true; + + } catch (java.io.FileNotFoundException e){ + ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), + resourceBundle.getString("ErrorFileNotFound")); + } catch (java.io.UnsupportedEncodingException e){ + ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), + resourceBundle.getString("ErrorOnSaveIncorrectEncoding")); + } catch (java.io.IOException e){ + ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), + resourceBundle.getString("ErrorOnSaveIOProblem")); + } + return false; } /** * Interface for Opening playlists via FileChooser @@ -89,29 +107,29 @@ public class Playlists { * Interface for Opening playlists using file itself * */ public static JsonStorage ReadByPath(ResourceBundle resourceBundle, File playlistFile){ - if (playlistFile != null) { - try (Reader reader = new InputStreamReader(new FileInputStream(playlistFile))) { - JsonStorage jStorage = new Gson().fromJson(reader, JsonStorage.class); - if (jStorage != null){ - playlistLocation = playlistFile.getAbsolutePath(); - //System.out.println("FILE:|"+playlistLocation+"|"); - return jStorage; - } - else - return null; - } catch (java.io.FileNotFoundException e){ - ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), resourceBundle.getString("ErrorFileNotFound")); - } catch (com.google.gson.JsonSyntaxException e){ - ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), resourceBundle.getString("ErrorOnOpenIncorrectFormatOfFile")); - } catch (java.io.IOException e){ - ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), resourceBundle.getString("ErrorOnOpenIOProblem")); + if (playlistFile == null) { + ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), + "Playlist file not selected");// TODO: translate + return null; + } + + try (Reader reader = new InputStreamReader(new FileInputStream(playlistFile))) { + JsonStorage jStorage = new Gson().fromJson(reader, JsonStorage.class); + if (jStorage != null){ + playlistLocation = playlistFile.getAbsolutePath(); + return jStorage; } - return null; - } - else { - System.out.println("Playlist file not selected"); - return null; + } catch (java.io.FileNotFoundException e){ + ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), + resourceBundle.getString("ErrorFileNotFound")); + } catch (com.google.gson.JsonSyntaxException e){ + ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), + resourceBundle.getString("ErrorOnOpenIncorrectFormatOfFile")); + } catch (java.io.IOException e){ + ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), + resourceBundle.getString("ErrorOnOpenIOProblem")); } + return null; } /** Return path to file opened */ diff --git a/src/main/java/mplayer4anime/ServiceWindow.java b/src/main/java/mplayer4anime/ServiceWindow.java index 7e42bbe..644f537 100644 --- a/src/main/java/mplayer4anime/ServiceWindow.java +++ b/src/main/java/mplayer4anime/ServiceWindow.java @@ -20,6 +20,7 @@ package mplayer4anime; import javafx.scene.control.Alert; import javafx.scene.layout.Region; +import javafx.stage.Stage; /** * Creates window with notification @@ -30,7 +31,13 @@ public class ServiceWindow { alertBox.setTitle(title); alertBox.setHeaderText(null); alertBox.setContentText(body); - alertBox.getDialogPane().setMinHeight(Region.USE_PREF_SIZE); // Java bug workaround for linux + alertBox.getDialogPane().setMinWidth(Region.USE_PREF_SIZE); + alertBox.getDialogPane().setMinHeight(Region.USE_PREF_SIZE); + alertBox.setResizable(true); alertBox.show(); + + Stage dialogStage = (Stage) alertBox.getDialogPane().getScene().getWindow(); + dialogStage.setAlwaysOnTop(true); + dialogStage.toFront(); } } diff --git a/src/main/java/mplayer4anime/Settings/SettingsController.java b/src/main/java/mplayer4anime/Settings/SettingsController.java index 5600412..404dca4 100644 --- a/src/main/java/mplayer4anime/Settings/SettingsController.java +++ b/src/main/java/mplayer4anime/Settings/SettingsController.java @@ -42,6 +42,8 @@ public class SettingsController implements Initializable { private Label pathToMplayerLbl; @FXML private CheckBox subtitlesFirstCheckBox; + @FXML + private ChoiceBox backEndEngineChoiceBox; @Override public void initialize(URL url, ResourceBundle resBundle) { @@ -55,6 +57,8 @@ public class SettingsController implements Initializable { subEncodingListController.setList(appPreferences.getSubsEncodingList(), false); videoExtensionListController.setList(appPreferences.getVideoExtensionsList(), true); audioExtensionListController.setList(appPreferences.getAudioExtensionsList(), true); + backEndEngineChoiceBox.getItems().addAll("mplayer", "mpv"); + backEndEngineChoiceBox.getSelectionModel().select(appPreferences.getBackendEngineIndexId()); } @FXML @@ -103,6 +107,7 @@ public class SettingsController implements Initializable { appPreferences.setSubsEncodingList(subEncodingListController.getList()); appPreferences.setVideoExtensionsList(videoExtensionListController.getList()); appPreferences.setAudioExtensionsList(audioExtensionListController.getList()); + appPreferences.setBackendEngineIndexId(backEndEngineChoiceBox.getSelectionModel().getSelectedIndex()); MediatorControl.getInstance().sentUpdates(); // TODO: implement list to track what should be updated } diff --git a/src/main/java/mplayer4anime/appPanes/ControllerPane.java b/src/main/java/mplayer4anime/appPanes/ControllerPane.java index 0416fe3..2e1cc29 100644 --- a/src/main/java/mplayer4anime/appPanes/ControllerPane.java +++ b/src/main/java/mplayer4anime/appPanes/ControllerPane.java @@ -238,6 +238,7 @@ public class ControllerPane implements Initializable { * Set files using lists. Used if playlist loaded * */ public void setFilesFromList(String[] fileLocations){ + cleanList(); if (fileLocations != null && fileLocations.length != 0) { File[] files = new File[fileLocations.length]; for (int i=0; i < fileLocations.length; i++) diff --git a/src/main/java/mplayer4anime/LineRedirecter.java b/src/main/java/mplayer4anime/mplayer/LineRedirecter.java similarity index 97% rename from src/main/java/mplayer4anime/LineRedirecter.java rename to src/main/java/mplayer4anime/mplayer/LineRedirecter.java index 4867d69..e5c9467 100644 --- a/src/main/java/mplayer4anime/LineRedirecter.java +++ b/src/main/java/mplayer4anime/mplayer/LineRedirecter.java @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with mplayer4anime. If not, see . */ -package mplayer4anime; +package mplayer4anime.mplayer; import java.io.*; diff --git a/src/main/java/mplayer4anime/MplayerSlave.java b/src/main/java/mplayer4anime/mplayer/MplayerSlave.java similarity index 96% rename from src/main/java/mplayer4anime/MplayerSlave.java rename to src/main/java/mplayer4anime/mplayer/MplayerSlave.java index c552baa..5a7c653 100644 --- a/src/main/java/mplayer4anime/MplayerSlave.java +++ b/src/main/java/mplayer4anime/mplayer/MplayerSlave.java @@ -16,7 +16,10 @@ You should have received a copy of the GNU General Public License along with mplayer4anime. If not, see . */ -package mplayer4anime; +package mplayer4anime.mplayer; + +import mplayer4anime.ISlaveModeAppOrchestration; +import mplayer4anime.ServiceWindow; import java.io.*; import java.util.ResourceBundle; @@ -42,7 +45,7 @@ public class MplayerSlave implements ISlaveModeAppOrchestration { } return false; } - + @Override public void subtitlesSwitch(){ if (! playerSingleCommand("get_sub_visibility")) return; @@ -66,15 +69,15 @@ public class MplayerSlave implements ISlaveModeAppOrchestration { System.out.println("Can't determine whether subtitles enabled or disabled"); } } - + @Override public void fullscreenSwitch(){ playerSingleCommand("vo_fullscreen"); } - + @Override public void mute(){ playerSingleCommand("mute"); } - + @Override public void forcePlay(String mplayerPath, String VideoFile, String AudioFile, @@ -94,7 +97,7 @@ public class MplayerSlave implements ISlaveModeAppOrchestration { e.printStackTrace(); } } - + @Override public boolean pause(){ if (player == null || !player.isAlive()) return false; @@ -103,7 +106,7 @@ public class MplayerSlave implements ISlaveModeAppOrchestration { playerIn.flush(); return true; } - + @Override public void playPause(String mplayerPath, String VideoFile, String AudioFile, @@ -155,15 +158,15 @@ public class MplayerSlave implements ISlaveModeAppOrchestration { ServiceWindow.getErrorNotification(resourceBundle.getString("Error"), resourceBundle.getString("ErrorUnableToStartMplayer")); } } - + @Override public void stop(){ playerSingleCommand("stop"); } - + @Override public void volumeUp(){ playerSingleCommand("volume +1 0"); } - + @Override public void volumeDown(){ playerSingleCommand("volume -1 0"); } diff --git a/src/main/java/mplayer4anime/mpv/MpvJniLibraryLoader.java b/src/main/java/mplayer4anime/mpv/MpvJniLibraryLoader.java new file mode 100644 index 0000000..48bd958 --- /dev/null +++ b/src/main/java/mplayer4anime/mpv/MpvJniLibraryLoader.java @@ -0,0 +1,108 @@ +/* + Copyright 2018-2021 Dmitry Isaenko + + This file is part of mplayer4anime. + + mplayer4anime 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. + + mplayer4anime 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 mplayer4anime. If not, see . + */ +package mplayer4anime.mpv; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.net.URL; + +public final class MpvJniLibraryLoader { + private MpvJniLibraryLoader(){} + public static boolean load(){ + String osName = System.getProperty("os.name").toLowerCase().replace(" ", ""); + String osArch = System.getProperty("os.arch").toLowerCase().replace(" ", ""); + String libPostfix = "so"; + + if (osName.equals("linux")){ + switch (osArch){ + case "i386": + case "i586": + case "i686": + osArch = "x86"; + break; + case "x86_64": + case "amd64": + osArch = "amd64"; + break; +// case "arm": +// osArch = "arm"; +// break; + default: + return false; + } + } + else + return false; + + final URL url_ = MpvJniLibraryLoader.class.getResource("/native/"+osName+"/"+osArch+"/mpvjni."+libPostfix); + if (url_ == null) + return false; + + String proto = url_.getProtocol(); + + File libraryFile; + if (proto.equals("file")){ + // We can pick file from disk as is. + try { + libraryFile = new File(url_.toURI()); + } + catch (URISyntaxException e){ + e.printStackTrace(); + return false; + } + } + else if (proto.equals("jar")){ + // We have to export file to temp dir. + InputStream inStream = MpvJniLibraryLoader.class.getResourceAsStream("/native/"+osName+"/"+osArch+"/mpvjni."+libPostfix); + if (inStream == null) + return false; + // Create temp folder + try{ + File tmpDirFile = File.createTempFile("jni", null); + if (! tmpDirFile.delete()) + return false; + if (! tmpDirFile.mkdirs()) + return false; + libraryFile = new File(tmpDirFile, "mpvjni."+libPostfix); + byte[] ioBuffer = new byte[8192]; + FileOutputStream foStream = new FileOutputStream(libraryFile); + while (inStream.read(ioBuffer) != -1) + foStream.write(ioBuffer); + foStream.close(); + inStream.close(); + libraryFile.deleteOnExit(); + tmpDirFile.deleteOnExit(); + } + catch (IOException ioe){ + ioe.printStackTrace(); + return false; + } + } + else + return false; + + //System.out.println("LIB LOCATION: "+libraryFile); + System.load(libraryFile.getAbsolutePath()); + //System.out.println("LIB LOADED"); + return true; + } +} diff --git a/src/main/java/mplayer4anime/mpv/MpvSlave.java b/src/main/java/mplayer4anime/mpv/MpvSlave.java new file mode 100644 index 0000000..3a5a068 --- /dev/null +++ b/src/main/java/mplayer4anime/mpv/MpvSlave.java @@ -0,0 +1,96 @@ +/* + Copyright 2018-2021 Dmitry Isaenko + + This file is part of mplayer4anime. + + mplayer4anime 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. + + mplayer4anime 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 mplayer4anime. If not, see . + */ +package mplayer4anime.mpv; + +import mplayer4anime.ISlaveModeAppOrchestration; +import mplayer4anime.ServiceWindow; + +import java.util.ResourceBundle; + +public class MpvSlave implements ISlaveModeAppOrchestration { + static { + if (! MpvJniLibraryLoader.load()){ + ServiceWindow.getErrorNotification("Error", + "Unable to load mpv back end library. Please use mplayer instead"); // TODO: use bundle & translate + } + } + + native void play(); + + public MpvSlave(ResourceBundle resourceBundle){ + + } + + @Override + public void subtitlesSwitch() { + + } + + @Override + public void fullscreenSwitch() { + + } + + @Override + public void mute() { + + } + + @Override + public void forcePlay(String mplayerPath, + String VideoFile, + String AudioFile, + String SubtitlesFile, + String subtitlesEncoding, + boolean subtitlesHidden, + boolean isFullscreen) { + + } + + @Override + public boolean pause() { + return false; + } + + @Override + public void playPause(String mplayerPath, + String VideoFile, + String AudioFile, + String SubtitlesFile, + String subtitlesEncoding, + boolean subtitlesHidden, + boolean isFullscreen) { + + } + + @Override + public void stop() { + + } + + @Override + public void volumeUp() { + + } + + @Override + public void volumeDown() { + + } +} diff --git a/src/main/resources/Settings/SettingsLayout.fxml b/src/main/resources/Settings/SettingsLayout.fxml index 7bec19c..ab58379 100644 --- a/src/main/resources/Settings/SettingsLayout.fxml +++ b/src/main/resources/Settings/SettingsLayout.fxml @@ -3,6 +3,7 @@ + @@ -42,6 +43,12 @@ + + + + diff --git a/src/main/resources/locale.properties b/src/main/resources/locale.properties index b245891..7537564 100644 --- a/src/main/resources/locale.properties +++ b/src/main/resources/locale.properties @@ -53,6 +53,7 @@ settings_Tab_Subtitles=Subtitles settings_videoExtensionList=Avaliable video files extensions: settings_audioExtensionList=Avaliable audio layer extensions: ApplyBtn=Apply +settings_backendSelect=Backend engine: diff --git a/src/main/resources/locale_rus.properties b/src/main/resources/locale_rus.properties index aa4b42e..e7df953 100644 --- a/src/main/resources/locale_rus.properties +++ b/src/main/resources/locale_rus.properties @@ -53,4 +53,5 @@ settings_Tab_Video=\u0412\u0438\u0434\u0435\u043E settings_videoExtensionList=\u0414\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F \u0434\u043B\u044F \u0444\u0430\u0439\u043B\u043E\u0432 \u0432\u0438\u0434\u0435\u043E: settings_audioExtensionList=\u0414\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F \u0434\u043B\u044F \u0430\u0443\u0434\u0438\u043E\u0434\u043E\u0440\u043E\u0436\u0435\u043A: ApplyBtn=\u041F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C +settings_backendSelect=\u0414\u0432\u0438\u0436\u043E\u043A \u0432\u043E\u0441\u043F\u0440\u043E\u0438\u0437\u0432\u0435\u0434\u0435\u043D\u0438\u044F: diff --git a/src/main/resources/native/linux/amd64/mpvjni.so b/src/main/resources/native/linux/amd64/mpvjni.so new file mode 100755 index 0000000..5ec25db Binary files /dev/null and b/src/main/resources/native/linux/amd64/mpvjni.so differ diff --git a/src/main/resources/native/linux/x86/mpvjni.so b/src/main/resources/native/linux/x86/mpvjni.so new file mode 100755 index 0000000..46cdf99 Binary files /dev/null and b/src/main/resources/native/linux/x86/mpvjni.so differ