master
Dmitry Isaenko 2019-01-05 17:34:46 +03:00
parent c743b903da
commit 4e0ba6f086
43 changed files with 324 additions and 96 deletions

31
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,31 @@
pipeline {
agent {
docker {
image 'maven:3-alpine'
args '-v /home/docker/jenkins/files/m2:/root/.m2'
}
}
stages {
stage('Build') {
steps {
sh 'mvn -B -DskipTests clean package'
}
}
stage('Test') {
steps {
echo 'Skip testing...'
}
}
stage('Deploy') {
steps {
echo 'Skip deployment...'
}
}
}
post {
always {
archiveArtifacts artifacts: 'target/*-jar-with-dependencies.jar', onlyIfSuccessful: true
}
}
}

View File

@ -1,60 +0,0 @@
package mplayer4anime;
/**
Name: mplayer4anime
@author Dmitry Isaenko
License: GNU GPL v.3
@version 0.11
@see https://developersu.blogspot.com/search/label/mplayer4anime
@see https://github.com/developersu/mplayer4anime
2018, Russia
*/
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import java.util.Locale;
import java.util.ResourceBundle;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("landingPage.fxml"));
if (Locale.getDefault().getISO3Language().equals("rus")) {
loader.setResources(ResourceBundle.getBundle("mplayer4anime.localization.locale", new Locale("ru")));
} else {
loader.setResources(ResourceBundle.getBundle("mplayer4anime.localization.locale", new Locale("en")));
}
Parent root = loader.load();
// tmp?
Controller controller = loader.getController();
controller.setHostServices(getHostServices());
// end
primaryStage.getIcons().addAll(
new Image(Main.class.getResourceAsStream("/mplayer4anime/res/app_icon32x32.png")),
new Image(Main.class.getResourceAsStream("/mplayer4anime/res/app_icon48x48.png")),
new Image(Main.class.getResourceAsStream("/mplayer4anime/res/app_icon64x64.png")),
new Image(Main.class.getResourceAsStream("/mplayer4anime/res/app_icon128x128.png"))
);
primaryStage.setTitle("mplayer4anime");
primaryStage.setMinWidth(500);
primaryStage.setMinHeight(375);
primaryStage.setScene(new Scene(root, 1200, 800));
// Make linkage to controller method to handle exit() event in there.
primaryStage.setOnHidden(e -> controller.shutdown());
primaryStage.show();
}
}

View File

@ -1,13 +1,13 @@
# mplayer4anime
mplayer4anime is mplayer launcher to play video file with audio layer and/or subtitles (.ass and .srt) at once.
mplayer4anime is mplayer launcher to play video file with audio layer and/or subtitles (.ass, .srt, etc,,,) at once.
## License
Source code spreads under the GNU General Public License v.3. You can find it in LICENSE file or just visit www.gnu.org (it should be there for sure).
Note: Since 0.10 application supports playlists management and implements own json-based format that (somehow) could be used in third-party application,
it would be nice to leave it as is. At least, I would prefer to have .alpr file extension used for this. As for the format of playlist format, please
it would be nice to leave it as is. At least, I would prefer to have .alpr file extension used for this. As for the format of playlist, please
refer to WFTPL license.
## Used libraries

Binary file not shown.

63
pom.xml Normal file
View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>loper</groupId>
<artifactId>mplayer4anime</artifactId>
<version>0.12-SNAPSHOT</version>
<packaging>jar</packaging>
<name>InnaIrcBot</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<archive>
<manifest>
<mainClass>
mplayer4anime.Main
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

3
src/META-INF/MANIFEST.MF Normal file
View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: mplayer4anime.Main

View File

@ -20,13 +20,13 @@ public class AboutWindow {
stageAbout.setMinWidth(500);
stageAbout.setMinHeight(500);
FXMLLoader loaderAbout = new FXMLLoader(getClass().getResource("AboutLayout.fxml"));
FXMLLoader loaderAbout = new FXMLLoader(getClass().getResource("/About/AboutLayout.fxml"));
ResourceBundle resourceBundle;
if (Locale.getDefault().getISO3Language().equals("rus")) {
resourceBundle = ResourceBundle.getBundle("mplayer4anime.localization.locale", new Locale("ru"));
resourceBundle = ResourceBundle.getBundle("locale", new Locale("ru"));
} else {
resourceBundle = ResourceBundle.getBundle("mplayer4anime.localization.locale", new Locale("en"));
resourceBundle = ResourceBundle.getBundle("locale", new Locale("en"));
}
loaderAbout.setResources(resourceBundle);
@ -37,10 +37,10 @@ public class AboutWindow {
stageAbout.setTitle(resourceBundle.getString("about_AboutName"));
stageAbout.getIcons().addAll(
new Image(Main.class.getResourceAsStream("/mplayer4anime/res/app_icon32x32.png")),
new Image(Main.class.getResourceAsStream("/mplayer4anime/res/app_icon48x48.png")),
new Image(Main.class.getResourceAsStream("/mplayer4anime/res/app_icon64x64.png")),
new Image(Main.class.getResourceAsStream("/mplayer4anime/res/app_icon128x128.png"))
new Image(Main.class.getResourceAsStream("/res/app_icon32x32.png")),
new Image(Main.class.getResourceAsStream("/res/app_icon48x48.png")),
new Image(Main.class.getResourceAsStream("/res/app_icon64x64.png")),
new Image(Main.class.getResourceAsStream("/res/app_icon128x128.png"))
); // TODO: change to something reliable
stageAbout.setScene(new Scene(parentAbout, 500, 500));

View File

@ -50,6 +50,13 @@ public class Controller implements Initializable {
private CheckMenuItem subsHide;
private String currentPlaylistLocation = null; //TODO: move to the constructor?
// 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) {
JsonStorage jsonStorage = Playlists.ReadByPath(resourceBundle, new File(playlist));
setAllLists(jsonStorage);
}
@Override
public void initialize(URL url, ResourceBundle rb) {
mkvPaneController.setPaneType("Video");
@ -77,7 +84,7 @@ public class Controller implements Initializable {
addRecentlyOpened(recentPlaylists[i]);
}
public void setHostServices(HostServices hostServices) {
void setHostServices(HostServices hostServices) {
this.hostServices = hostServices;
}
@ -139,10 +146,19 @@ public class Controller implements Initializable {
}
int index;
index = mkvPaneController.getElementSelectedIndex();
// TODO: add 'link' button
if (index+1 < mkvPaneController.getElementsCount() ) {
mkvPaneController.setElementSelectedByIndex(index+1);
playBtn();
}
index = mkaPaneController.getElementSelectedIndex();
if (index+1 < mkaPaneController.getElementsCount() ) {
mkaPaneController.setElementSelectedByIndex(index+1);
}
index = subPaneController.getElementSelectedIndex();
if (index+1 < subPaneController.getElementsCount() ) {
subPaneController.setElementSelectedByIndex(index+1);
}
playBtn();
}
private Process player;
@ -225,7 +241,6 @@ public class Controller implements Initializable {
storeRecentArr[i] = (String) recentlyOpenedMenu.getItems().get(i).getUserData();
}
appPreferences.setRecentPlaylists(storeRecentArr);
Platform.exit();
}
@ -260,6 +275,7 @@ public class Controller implements Initializable {
subPaneController.selectEncodingValue(jsonStorage.getSubEncoding(), appPreferences);
currentPlaylistLocation = Playlists.getPlaylistLocation(); // TODO: Implement listener? mmm...
//System.out.println(currentPlaylistLocation);
statusLbl.setText(currentPlaylistLocation);
addRecentlyOpened(currentPlaylistLocation);
}
@ -308,17 +324,10 @@ public class Controller implements Initializable {
MenuItem menuItem = new MenuItem();
String fileNameOnly;
if (playlistPath.contains("/")) { // Unix
fileNameOnly = playlistPath.substring(playlistPath.lastIndexOf("/") + 1, playlistPath.length());
menuItem.setText(fileNameOnly);
}
else if (playlistPath.contains("\\")) { // Windows
fileNameOnly = playlistPath.substring(playlistPath.lastIndexOf("\\") + 1, playlistPath.length());
menuItem.setText(fileNameOnly);
}
else { // Other o_0
menuItem.setText(playlistPath);
}
fileNameOnly = playlistPath.substring(playlistPath.lastIndexOf(File.separator) + 1);
menuItem.setText(fileNameOnly);
menuItem.setUserData(playlistPath);
menuItem.setOnAction(new EventHandler<ActionEvent>() {
@Override

View File

@ -0,0 +1,48 @@
package mplayer4anime.IPC;
import javafx.application.Platform;
import mplayer4anime.Controller;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
class ServerSocketProvider implements Runnable{
private ServerSocket serverSocket;
private Controller controller;
ServerSocketProvider(Controller mainCntrl, ServerSocket srvSock){
this.serverSocket = srvSock;
this.controller = mainCntrl;
}
@Override
public void run() {
Socket servSockClient;
try{
while (!serverSocket.isClosed()){
servSockClient = serverSocket.accept();
BufferedReader servInpRdr = new BufferedReader(
new InputStreamReader(servSockClient.getInputStream())
);
String line = servInpRdr.readLine();
// Avoid 'Not on FX application thread' error.
Platform.runLater(new Runnable() {
@Override
public void run() {
controller.setPlaylistAsArgument(line);
}
});
servSockClient.close();
}
}
catch (IOException ex){
System.out.println("Socket has been closed.");
}
}
}

View File

@ -0,0 +1,55 @@
package mplayer4anime.IPC;
import mplayer4anime.Controller;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class SingleInstanceHandler implements Runnable{
private ServerSocket servSock;
public SingleInstanceHandler(Controller mainCntrl, String argument){
int PORT = 65042;
// Creating client server socket;
try {
servSock = new ServerSocket(PORT, 10, InetAddress.getLocalHost());
Thread ssp = new Thread(new ServerSocketProvider(mainCntrl, servSock));
ssp.start();
} catch (IOException e) {
if (argument != null){
// Creating client socket;
try {
Socket clientSocket = new Socket(InetAddress.getLocalHost(), PORT);
OutputStream outStream = clientSocket.getOutputStream();
OutputStreamWriter outStreamWriter = new OutputStreamWriter(outStream);
outStreamWriter.write(argument + "\n");
outStreamWriter.flush();
outStream.close();
clientSocket.close();
} catch (IOException ex){
System.out.println("Internal issue: unable to create client socket.");
}
}
else
System.out.println("Application is already running.");
System.exit(0);
}
}
@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;
}
}
}
}

View File

@ -0,0 +1,77 @@
package mplayer4anime;
/**
Name: mplayer4anime
@author Dmitry Isaenko
License: GNU GPL v.3
@version 0.12
@see https://developersu.blogspot.com/search/label/mplayer4anime
@see https://github.com/developersu/mplayer4anime
2018-2019, Russia
*/
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import mplayer4anime.IPC.SingleInstanceHandler;
import java.util.Locale;
import java.util.ResourceBundle;
//TODO: Use one copy of AppPreferences object widely
//TODO: Drag-n-drop playlist/files/audio
//TODO: remember selected
//TODO: remember position
public class Main extends Application {
public static void main(String[] args) { launch(args); }
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("/landingPage.fxml"));
if (Locale.getDefault().getISO3Language().equals("rus")) {
loader.setResources(ResourceBundle.getBundle("locale", new Locale("ru")));
} else {
loader.setResources(ResourceBundle.getBundle("locale", new Locale("en")));
}
Parent root = loader.load();
// tmp?
Controller controller = loader.getController();
controller.setHostServices(getHostServices());
SingleInstanceHandler sih;
if (!getParameters().getUnnamed().isEmpty())
sih = new SingleInstanceHandler(controller, getParameters().getUnnamed().get(0));
else
sih = new SingleInstanceHandler(controller, null);
// end
Thread tsih = new Thread(sih);
tsih.start();
// TODO: refactor needed?
Runtime.getRuntime().addShutdownHook(new Thread(() -> tsih.interrupt()));
primaryStage.getIcons().addAll(
new Image(Main.class.getResourceAsStream("/res/app_icon32x32.png")),
new Image(Main.class.getResourceAsStream("/res/app_icon48x48.png")),
new Image(Main.class.getResourceAsStream("/res/app_icon64x64.png")),
new Image(Main.class.getResourceAsStream("/res/app_icon128x128.png"))
);
primaryStage.setTitle("mplayer4anime");
primaryStage.setMinWidth(500);
primaryStage.setMinHeight(375);
primaryStage.setScene(new Scene(root, 1200, 800));
// Make linkage to controller method to handle exit() event in there.
primaryStage.setOnHidden(e -> {
tsih.interrupt();
controller.shutdown();
});
primaryStage.show();
}
}

View File

@ -5,6 +5,7 @@ import javafx.stage.FileChooser;
import mplayer4anime.ServiceWindow;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ResourceBundle;
public class Playlists {
@ -45,7 +46,7 @@ public class Playlists {
if (!playlistFile.getAbsolutePath().endsWith(".alpr")) {
playlistFile = new File(playlistFile.getAbsolutePath() + ".alpr");
}
try (Writer writer = new OutputStreamWriter(new FileOutputStream(playlistFile.getAbsolutePath()), "UTF-8"))
try (Writer writer = new OutputStreamWriter(new FileOutputStream(playlistFile.getAbsolutePath()), StandardCharsets.UTF_8))
{
Gson jsonObject = new GsonBuilder().setPrettyPrinting().create();
jsonObject.toJson(jStorage, writer);
@ -93,6 +94,7 @@ public class Playlists {
JsonStorage jStorage = new Gson().fromJson(reader, JsonStorage.class);
if (jStorage != null){
playlistLocation = playlistFile.getAbsolutePath();
//System.out.println("FILE:|"+playlistLocation+"|");
return jStorage;
}
else
@ -116,4 +118,4 @@ public class Playlists {
public static String getPlaylistLocation(){
return playlistLocation;
}
}
}

View File

@ -19,13 +19,13 @@ public class SettingsWindow {
stageAbout.setMinWidth(570);
stageAbout.setMinHeight(500);
FXMLLoader loaderSettings = new FXMLLoader(getClass().getResource("SettingsLayout.fxml"));
FXMLLoader loaderSettings = new FXMLLoader(getClass().getResource("/Settings/SettingsLayout.fxml"));
ResourceBundle resourceBundle;
if (Locale.getDefault().getISO3Language().equals("rus")) {
resourceBundle = ResourceBundle.getBundle("mplayer4anime.localization.locale", new Locale("ru"));
resourceBundle = ResourceBundle.getBundle("locale", new Locale("ru"));
} else {
resourceBundle = ResourceBundle.getBundle("mplayer4anime.localization.locale", new Locale("en"));
resourceBundle = ResourceBundle.getBundle("locale", new Locale("en"));
}
loaderSettings.setResources(resourceBundle);
@ -36,10 +36,10 @@ public class SettingsWindow {
stageAbout.setTitle(resourceBundle.getString("settings_SettingsName"));
stageAbout.getIcons().addAll(
new Image(Main.class.getResourceAsStream("/mplayer4anime/res/settings_icon32x32.png")),
new Image(Main.class.getResourceAsStream("/mplayer4anime/res/settings_icon48x48.png")),
new Image(Main.class.getResourceAsStream("/mplayer4anime/res/settings_icon64x64.png")),
new Image(Main.class.getResourceAsStream("/mplayer4anime/res/settings_icon128x128.png"))
new Image(Main.class.getResourceAsStream("/res/settings_icon32x32.png")),
new Image(Main.class.getResourceAsStream("/res/settings_icon48x48.png")),
new Image(Main.class.getResourceAsStream("/res/settings_icon64x64.png")),
new Image(Main.class.getResourceAsStream("/res/settings_icon128x128.png"))
); // TODO: change to something reliable
stageAbout.setScene(new Scene(parentAbout, 570, 500));
stageAbout.show();

View File

@ -1,5 +1,5 @@
about_line1=mplayer4amine distributes under GNU GPLv3 license.
about_line2=Release: v0.11
about_line2=Release: v0.12
about_line3=Development & maintenance by Dmitry Isaenko.
about_AboutName=About
main_tab_audio=Audio
@ -30,7 +30,7 @@ menu_File=File
menu_Tools=Tools
menu_Help=Help
menu_Help_AboutApp=About
menu_File_Close=Close
menu_File_Close=Exit
menu_Tools_Settings=Settings
menu_File_Open=Open playlist...
menu_File_Save=Save playlist

View File

@ -1,6 +1,6 @@
menu_File_Recent=\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0435 \u0444\u0430\u0439\u043B\u044B...
about_line1=mplayer4amine \u0440\u0430\u0441\u043F\u0440\u043E\u0441\u0442\u0440\u0430\u043D\u044F\u0435\u0442\u0441\u044F \u043F\u043E \u043B\u0438\u0446\u0435\u043D\u0437\u0438\u0438 GNU GPLv3.
about_line2=\u0420\u0435\u043B\u0438\u0437: v0.11
about_line2=\u0420\u0435\u043B\u0438\u0437: v0.12
about_line3=\u0420\u0430\u0437\u0440\u0430\u0431\u043E\u0442\u0430\u043D\u043E \u0438 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F \u0414\u043C\u0438\u0442\u0440\u0438\u0435\u043C \u0418\u0441\u0430\u0435\u043D\u043A\u043E.
about_AboutName=\u041E \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0438
main_tab_audio=\u0410\u0443\u0434\u0438\u043E
@ -31,7 +31,7 @@ menu_File=\u0424\u0430\u0439\u043B
menu_Tools=\u0418\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u044B
menu_Help=\u0421\u043F\u0440\u0430\u0432\u043A\u0430
menu_Help_AboutApp=\u041E \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0438
menu_File_Close=\u0417\u0430\u043A\u0440\u044B\u0442\u044C
menu_File_Close=\u0412\u044B\u0445\u043E\u0434
menu_Tools_Settings=\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438
menu_File_Open=\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u043F\u043B\u0435\u0439\u043B\u0438\u0441\u0442...
menu_File_Save=\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u043F\u043B\u0435\u0439\u043B\u0438\u0441\u0442

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB