├── LICENCE.txt
├── Languages
├── Languages
│ ├── ar.properties
│ ├── cs.properties
│ ├── de.properties
│ ├── en.properties
│ ├── es.properties
│ ├── fr.properties
│ ├── hu.properties
│ ├── it.properties
│ ├── ja.properties
│ ├── la.properties
│ ├── nl.properties
│ ├── pl.properties
│ ├── pt_BR.properties
│ ├── ru.properties
│ ├── sl.properties
│ ├── sv.properties
│ ├── tr.properties
│ ├── uk.properties
│ ├── vi.properties
│ ├── zh_CN.properties
│ └── zh_TW.properties
├── ar.properties
├── cs.properties
├── de.properties
├── en.properties
├── es.properties
├── fr.properties
├── hu.properties
├── it.properties
├── ja.properties
├── la.properties
├── nl.properties
├── pl.properties
├── pt_BR.properties
├── ru.properties
├── sl.properties
├── sv.properties
├── tr.properties
├── uk.properties
├── vi.properties
├── zh_CN.properties
└── zh_TW.properties
├── Library
└── sources.txt
├── README.md
├── Shutter Encoder.jar
├── SocialBanner.png
├── fonts
├── FreeSans.ttf
├── Magneto.ttf
├── Montserrat.ttf
└── NotoSansSC.otf
├── lib
├── activation.jar
├── commons-io-2.5.jar
├── commons-net-3.5.jar
├── flatlaf-3.5.2.jar
├── flatlaf-extras-3.5.2.jar
├── javax.mail.jar
├── jgoodies-common-1.8.0.jar
├── jgoodies-forms-1.8.0.jar
├── jnativehook-2.2.1.jar
├── jsoup-1.9.1.jar
├── jsvg-1.0.0.jar
├── pdfbox-app-2.0.28.jar
├── slf4j-api-1.7.9.jar
├── slf4j-simple-1.7.9.jar
├── swt-x86.jar
└── swt.jar
├── logo.png
└── src
├── application
├── Console.java
├── Donate.java
├── Ftp.java
├── Functions.java
├── GOP.java
├── GlobalKeyListener.java
├── HashGenerator.java
├── Informations.java
├── RecordInputDevice.java
├── ReducedWindow.java
├── Renamer.java
├── RenderQueue.java
├── SceneDetection.java
├── Settings.java
├── Shutter.java
├── Splash.java
├── SubtitlesEdit.java
├── SubtitlesEmbed.java
├── SubtitlesHelp.java
├── SubtitlesTimeline.java
├── Update.java
├── Utils.java
├── VideoPlayer.java
├── VideoWeb.java
└── fileOverwriteWindow.java
├── contents
├── 2013-2016.jpg
├── arrow.svg
├── avid.png
├── check.svg
├── complete.wav
├── davinci.png
├── drop.svg
├── error.wav
├── generate.svg
├── help.svg
├── help_hover.svg
├── help_pressed.svg
├── icon.png
├── item.svg
├── list.svg
├── list_hover.svg
├── list_pressed.svg
├── lock.svg
├── mail.svg
├── max.svg
├── max_hover.svg
├── max_pressed.svg
├── new.svg
├── new_hover.svg
├── new_pressed.svg
├── pause.svg
├── play.svg
├── premiere.png
├── presets.svg
├── presets_hover.svg
├── presets_pressed.svg
├── preview.svg
├── preview_hover.svg
├── qrcode.png
├── quit.svg
├── quit_hover.svg
├── quit_pressed.svg
├── reduce.svg
├── reduce_hover.svg
├── reduce_pressed.svg
├── screenshot.svg
├── settings.svg
├── settings_hover.svg
├── settings_pressed.svg
├── stop.svg
├── stream.svg
├── unlock.svg
└── volume.svg
├── functions
├── AudioEncoders.java
├── AudioNormalization.java
├── BlackDetection.java
├── Command.java
├── Conform.java
├── DVDRIP.java
├── Extract.java
├── FrameMD5.java
├── LoudnessTruePeak.java
├── Merge.java
├── OfflineDetection.java
├── Picture.java
├── ReplaceAudio.java
├── Rewrap.java
├── VMAF.java
├── VideoEncoders.java
└── VideoInserts.java
├── library
├── BMXTRANSWRAP.java
├── DCRAW.java
├── DVDAUTHOR.java
├── EXIFTOOL.java
├── FFMPEG.java
├── FFPROBE.java
├── MEDIAINFO.java
├── NCNN.java
├── PDF.java
├── SEVENZIP.java
├── TSMUXER.java
└── YOUTUBEDL.java
└── settings
├── AdvancedFeatures.java
├── AudioSettings.java
├── BitratesAdjustement.java
├── Colorimetry.java
├── Corrections.java
├── Filter.java
├── FunctionUtils.java
├── Image.java
├── ImageSequence.java
├── InputAndOutput.java
├── Overlay.java
├── Timecode.java
└── Transitions.java
/Languages/Languages/cs.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/cs.properties
--------------------------------------------------------------------------------
/Languages/Languages/de.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/de.properties
--------------------------------------------------------------------------------
/Languages/Languages/en.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/en.properties
--------------------------------------------------------------------------------
/Languages/Languages/es.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/es.properties
--------------------------------------------------------------------------------
/Languages/Languages/fr.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/fr.properties
--------------------------------------------------------------------------------
/Languages/Languages/hu.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/hu.properties
--------------------------------------------------------------------------------
/Languages/Languages/it.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/it.properties
--------------------------------------------------------------------------------
/Languages/Languages/la.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/la.properties
--------------------------------------------------------------------------------
/Languages/Languages/nl.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/nl.properties
--------------------------------------------------------------------------------
/Languages/Languages/pl.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/pl.properties
--------------------------------------------------------------------------------
/Languages/Languages/pt_BR.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/pt_BR.properties
--------------------------------------------------------------------------------
/Languages/Languages/sv.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/sv.properties
--------------------------------------------------------------------------------
/Languages/Languages/tr.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/tr.properties
--------------------------------------------------------------------------------
/Languages/Languages/vi.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/vi.properties
--------------------------------------------------------------------------------
/Languages/cs.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/cs.properties
--------------------------------------------------------------------------------
/Languages/de.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/de.properties
--------------------------------------------------------------------------------
/Languages/en.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/en.properties
--------------------------------------------------------------------------------
/Languages/es.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/es.properties
--------------------------------------------------------------------------------
/Languages/fr.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/fr.properties
--------------------------------------------------------------------------------
/Languages/hu.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/hu.properties
--------------------------------------------------------------------------------
/Languages/it.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/it.properties
--------------------------------------------------------------------------------
/Languages/la.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/la.properties
--------------------------------------------------------------------------------
/Languages/nl.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/nl.properties
--------------------------------------------------------------------------------
/Languages/pl.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/pl.properties
--------------------------------------------------------------------------------
/Languages/pt_BR.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/pt_BR.properties
--------------------------------------------------------------------------------
/Languages/sv.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/sv.properties
--------------------------------------------------------------------------------
/Languages/tr.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/tr.properties
--------------------------------------------------------------------------------
/Languages/vi.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/vi.properties
--------------------------------------------------------------------------------
/Library/sources.txt:
--------------------------------------------------------------------------------
1 | ffmpeg: ffmpeg.org
2 | 7za: www.7-zip.org
3 | exiftool: exiftool.org
4 | dcraw: www.dechifro.org/dcraw
5 | yt-dlp: github.com/yt-dlp/yt-dlp
6 | dvdauthor: dvdauthor.sourceforge.net
7 | tsMuxeR: github.com/justdan96/tsMuxer
8 | mediainfo: mediaarea.net/fr/MediaInfo
9 | bmxtranswrap: sourceforge.net/p/bmxlib/home/Home
10 | ncnn: https://github.com/xinntao/Real-ESRGAN-ncnn-vulkan
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
Shutter Encoder v19.1
3 |
4 | 
5 |
6 | Download required [dependencies](../master/Library/sources.txt) into "Library" folder.
7 |
8 | Include [fonts](../master/fonts) with JRE.
9 |
10 | I'm using [Java version 20](https://jdk.java.net/20/) built using jlink:
11 | --compress 0 --strip-debug --no-header-files --no-man-pages --add-modules java.base,java.datatransfer,java.desktop,java.logging,java.security.sasl,java.xml,jdk.crypto.ec --output JRE
12 |
13 | ## Official website
14 |
15 | https://www.shutterencoder.com
16 |
17 | ### Builds
18 |
19 | https://www.shutterencoder.com/en/#downloads
20 |
21 | #### Changelog
22 |
23 | https://www.shutterencoder.com/changelog/
24 |
--------------------------------------------------------------------------------
/Shutter Encoder.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Shutter Encoder.jar
--------------------------------------------------------------------------------
/SocialBanner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/SocialBanner.png
--------------------------------------------------------------------------------
/fonts/FreeSans.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/fonts/FreeSans.ttf
--------------------------------------------------------------------------------
/fonts/Magneto.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/fonts/Magneto.ttf
--------------------------------------------------------------------------------
/fonts/Montserrat.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/fonts/Montserrat.ttf
--------------------------------------------------------------------------------
/fonts/NotoSansSC.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/fonts/NotoSansSC.otf
--------------------------------------------------------------------------------
/lib/activation.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/activation.jar
--------------------------------------------------------------------------------
/lib/commons-io-2.5.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/commons-io-2.5.jar
--------------------------------------------------------------------------------
/lib/commons-net-3.5.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/commons-net-3.5.jar
--------------------------------------------------------------------------------
/lib/flatlaf-3.5.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/flatlaf-3.5.2.jar
--------------------------------------------------------------------------------
/lib/flatlaf-extras-3.5.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/flatlaf-extras-3.5.2.jar
--------------------------------------------------------------------------------
/lib/javax.mail.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/javax.mail.jar
--------------------------------------------------------------------------------
/lib/jgoodies-common-1.8.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/jgoodies-common-1.8.0.jar
--------------------------------------------------------------------------------
/lib/jgoodies-forms-1.8.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/jgoodies-forms-1.8.0.jar
--------------------------------------------------------------------------------
/lib/jnativehook-2.2.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/jnativehook-2.2.1.jar
--------------------------------------------------------------------------------
/lib/jsoup-1.9.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/jsoup-1.9.1.jar
--------------------------------------------------------------------------------
/lib/jsvg-1.0.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/jsvg-1.0.0.jar
--------------------------------------------------------------------------------
/lib/pdfbox-app-2.0.28.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/pdfbox-app-2.0.28.jar
--------------------------------------------------------------------------------
/lib/slf4j-api-1.7.9.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/slf4j-api-1.7.9.jar
--------------------------------------------------------------------------------
/lib/slf4j-simple-1.7.9.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/slf4j-simple-1.7.9.jar
--------------------------------------------------------------------------------
/lib/swt-x86.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/swt-x86.jar
--------------------------------------------------------------------------------
/lib/swt.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/swt.jar
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/logo.png
--------------------------------------------------------------------------------
/src/application/Donate.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package application;
21 |
22 | import java.awt.Color;
23 | import java.awt.Cursor;
24 | import java.awt.Desktop;
25 | import java.awt.Font;
26 | import java.awt.MouseInfo;
27 | import java.awt.Rectangle;
28 | import java.awt.event.MouseEvent;
29 | import java.awt.event.MouseListener;
30 | import java.awt.event.MouseMotionListener;
31 | import java.awt.geom.Area;
32 | import java.io.IOException;
33 | import java.net.URI;
34 | import java.net.URISyntaxException;
35 |
36 | import javax.swing.BorderFactory;
37 | import javax.swing.ImageIcon;
38 | import javax.swing.JFrame;
39 | import javax.swing.JLabel;
40 | import javax.swing.JPanel;
41 | import javax.swing.SwingConstants;
42 | import javax.swing.border.MatteBorder;
43 |
44 | import com.formdev.flatlaf.extras.FlatSVGIcon;
45 |
46 | public class Donate {
47 |
48 | private static int MousePositionX;
49 | private static int MousePositionY;
50 |
51 | public Donate() {
52 |
53 | JFrame frame = new JFrame();
54 | frame.getContentPane().setBackground(Utils.bg32);
55 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
56 | frame.setTitle("Thanks!");
57 | frame.setBackground(Utils.bg32);
58 | frame.setForeground(Color.WHITE);
59 | frame.getContentPane().setLayout(null);
60 | frame.setSize(280, 335);
61 |
62 | frame.setResizable(false);
63 | frame.setUndecorated(true);
64 | frame.getRootPane().setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, new Color(45,45,45)));
65 | Area shape1 = new Area(new AntiAliasedRoundRectangle(0, 0, frame.getWidth(), frame.getHeight(), 15, 15));
66 | Area shape2 = new Area(new Rectangle(0, frame.getHeight()-15, frame.getWidth(), 15));
67 | shape1.add(shape2);
68 | frame.setShape(shape1);
69 | frame.setAlwaysOnTop(true);
70 |
71 | frame.setIconImage(new ImageIcon(getClass().getClassLoader().getResource("contents/icon.png")).getImage());
72 | frame.setLocation(Shutter.frame.getX() + (Shutter.frame.getWidth() - frame.getWidth()) / 2, Shutter.frame.getY() + (Shutter.frame.getHeight() / 2 - frame.getHeight()));
73 |
74 | JPanel topPanel = new JPanel();
75 | topPanel.setLayout(null);
76 | topPanel.setBackground(Utils.bg32);
77 | topPanel.setBounds(0, 0, frame.getWidth(), 28);
78 |
79 | JLabel quit = new JLabel(new FlatSVGIcon("contents/quit.svg", 15, 15));
80 | quit.setHorizontalAlignment(SwingConstants.CENTER);
81 | quit.setBounds(frame.getSize().width - 20, 4, 15, 15);
82 | topPanel.add(quit);
83 |
84 | quit.addMouseListener(new MouseListener() {
85 |
86 | private boolean accept = false;
87 |
88 | @Override
89 | public void mouseClicked(MouseEvent e) {
90 | }
91 |
92 | @Override
93 | public void mousePressed(MouseEvent e) {
94 |
95 | quit.setIcon(new FlatSVGIcon("contents/quit_pressed.svg", 15, 15));
96 | accept = true;
97 | }
98 |
99 | @Override
100 | public void mouseReleased(MouseEvent e) {
101 |
102 | if (accept)
103 | {
104 | System.exit(0);
105 | }
106 | }
107 |
108 | @Override
109 | public void mouseEntered(MouseEvent e) {
110 | quit.setIcon(new FlatSVGIcon("contents/quit_hover.svg", 15, 15));
111 | }
112 |
113 | @Override
114 | public void mouseExited(MouseEvent e) {
115 | quit.setIcon(new FlatSVGIcon("contents/quit.svg", 15, 15));
116 | accept = false;
117 | }
118 |
119 | });
120 |
121 | JLabel title = new JLabel(frame.getTitle());
122 | title.setHorizontalAlignment(JLabel.CENTER);
123 | title.setBounds(0, 1, frame.getWidth(), 24);
124 | title.setFont(new Font(Shutter.mainFont, Font.PLAIN, 17));
125 | topPanel.add(title);
126 |
127 | JLabel topImage = new JLabel();
128 | topImage.setBackground(new Color(35,35,40));
129 | topImage.setOpaque(true);
130 | topImage.setBorder(new MatteBorder(1, 0, 1, 0, new Color(45,45,45)));
131 | topImage.setBounds(0, 0, topPanel.getWidth(), 24);
132 | topPanel.add(topImage);
133 |
134 | topImage.addMouseListener(new MouseListener() {
135 |
136 | @Override
137 | public void mouseClicked(MouseEvent down) {
138 | }
139 |
140 | @Override
141 | public void mousePressed(MouseEvent down) {
142 | MousePositionX = down.getPoint().x;
143 | MousePositionY = down.getPoint().y;
144 | }
145 |
146 | @Override
147 | public void mouseReleased(MouseEvent e) {
148 | }
149 |
150 | @Override
151 | public void mouseEntered(MouseEvent e) {
152 | }
153 |
154 | @Override
155 | public void mouseExited(MouseEvent e) {
156 | }
157 |
158 | });
159 |
160 | topImage.addMouseMotionListener(new MouseMotionListener(){
161 |
162 | @Override
163 | public void mouseDragged(MouseEvent e) {
164 | frame.setLocation(MouseInfo.getPointerInfo().getLocation().x - MousePositionX, MouseInfo.getPointerInfo().getLocation().y - MousePositionY);
165 | }
166 |
167 | @Override
168 | public void mouseMoved(MouseEvent e) {
169 | }
170 |
171 | });
172 |
173 | frame.getContentPane().add(topPanel);
174 |
175 | JLabel qrcode = new JLabel();
176 | qrcode.setIcon(new ImageIcon(getClass().getClassLoader().getResource("contents/qrcode.png")));
177 | qrcode.setHorizontalAlignment(SwingConstants.CENTER);
178 | qrcode.setBounds((frame.getWidth() - 250) / 2, topPanel.getHeight() + 10, 250, 250);
179 | frame.getContentPane().add(qrcode);
180 |
181 | qrcode.addMouseListener(new MouseListener() {
182 |
183 | @Override
184 | public void mouseClicked(MouseEvent arg0) {
185 | try {
186 | Desktop.getDesktop().browse(new URI("https://donate.stripe.com/28o29m0QwfRZ4U0cMM"));
187 | } catch (IOException | URISyntaxException e) {}
188 |
189 | System.exit(0);
190 | }
191 |
192 | @Override
193 | public void mouseEntered(MouseEvent arg0) {
194 | frame.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
195 | }
196 |
197 | @Override
198 | public void mouseExited(MouseEvent arg0) {
199 | frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
200 | }
201 |
202 | @Override
203 | public void mousePressed(MouseEvent arg0) {
204 | }
205 |
206 | @Override
207 | public void mouseReleased(MouseEvent arg0) {
208 | }
209 |
210 | });
211 |
212 | JLabel line1 = new JLabel("Hope you enjoyed the software!");
213 | line1.setHorizontalAlignment(SwingConstants.CENTER);
214 | line1.setSize(frame.getWidth(), 16);
215 | line1.setFont(new Font(Shutter.mainFont, Font.PLAIN, 12));
216 | line1.setLocation((frame.getWidth() - line1.getWidth()) / 2, qrcode.getY() + qrcode.getHeight() + 7);
217 | frame.getContentPane().add(line1);
218 |
219 | JLabel line2 = new JLabel("Support me to make it even better!");
220 | line2.setHorizontalAlignment(SwingConstants.CENTER);
221 | line2.setSize(frame.getWidth(), 16);
222 | line2.setFont(new Font(Shutter.mainFont, Font.PLAIN, 12));
223 | line2.setLocation((frame.getWidth() - line2.getWidth()) / 2, line1.getY() + line1.getHeight());
224 | frame.getContentPane().add(line2);
225 |
226 | frame.setVisible(true);
227 | }
228 | }
229 |
--------------------------------------------------------------------------------
/src/application/GOP.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package application;
21 |
22 | import java.awt.Color;
23 | import java.awt.Component;
24 | import java.awt.Font;
25 | import java.awt.event.AdjustmentEvent;
26 | import java.awt.event.AdjustmentListener;
27 | import java.awt.event.WindowEvent;
28 | import java.awt.event.WindowListener;
29 | import java.io.File;
30 |
31 | import javax.swing.ImageIcon;
32 | import javax.swing.JDialog;
33 | import javax.swing.JFrame;
34 | import javax.swing.JLabel;
35 | import javax.swing.JScrollBar;
36 | import javax.swing.SwingConstants;
37 |
38 | import library.FFPROBE;
39 |
40 | public class GOP {
41 |
42 | public static JDialog frame;
43 | private JScrollBar scrollBar;
44 |
45 | public GOP() {
46 |
47 | frame = new JDialog();
48 | frame.setResizable(false);
49 | frame.setModal(false);
50 | frame.setForeground(Color.WHITE);
51 | frame.getContentPane().setLayout(null);
52 | frame.getContentPane().setBackground(Utils.bg32);
53 | frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
54 | frame.setIconImage(new ImageIcon(getClass().getClassLoader().getResource("contents/icon.png")).getImage());
55 |
56 | scrollBar = new JScrollBar();
57 | scrollBar.setOrientation(JScrollBar.HORIZONTAL);
58 | scrollBar.setVisible(true);
59 | scrollBar.setBackground(Utils.c30);
60 | frame.getContentPane().add(scrollBar);
61 |
62 | scrollBar.addAdjustmentListener(new AdjustmentListener(){
63 |
64 | public void adjustmentValueChanged(AdjustmentEvent ae) {
65 | if (scrollBar.getValueIsAdjusting())
66 | {
67 | int i = 12;
68 | for (Component c : frame.getContentPane().getComponents())
69 | {
70 | if (c instanceof JLabel)
71 | {
72 | c.setLocation(i - scrollBar.getValue(), 12);
73 | i += 112;
74 | }
75 | }
76 | }
77 | }
78 |
79 | });
80 |
81 | JLabel image1 = new JLabel("I");
82 | image1.setFont(new Font(Shutter.mainFont, Font.PLAIN, 40));
83 | image1.setHorizontalAlignment(SwingConstants.CENTER);
84 | image1.setBackground(new Color(232,67,67));
85 | image1.setOpaque(true);
86 | image1.setForeground(Color.BLACK);
87 | image1.setBounds(12, 12, 100, 100);
88 | frame.getContentPane().add(image1);
89 |
90 | File fichier = new File(Shutter.fileList.getSelectedValue());
91 |
92 | FFPROBE.AnalyzeGOP(fichier.toString(), true);
93 |
94 | do {
95 | try {
96 | Thread.sleep(100);
97 | } catch (InterruptedException e) {}
98 | } while (FFPROBE.isRunning);
99 |
100 | frame.setTitle(Shutter.language.getProperty("analyzeOf") + " " + fichier.getName() + " | GOP " + Shutter.language.getProperty("of") + " " + FFPROBE.gopCount);
101 |
102 | if (FFPROBE.gopCount <= 12)
103 | {
104 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux"))
105 | frame.setSize(FFPROBE.gopSpace + 8, 154);
106 | else
107 | frame.setSize(FFPROBE.gopSpace + 8 + 10, 164);
108 |
109 | scrollBar.setVisible(false);
110 | }
111 | else if (FFPROBE.gopSpace + 8 > 1476)
112 | {
113 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux"))
114 | frame.setSize(1476, 171);
115 | else
116 | frame.setSize(1486, 181);
117 |
118 | scrollBar.setVisible(true);
119 | }
120 | else
121 | {
122 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux"))
123 | frame.setSize(FFPROBE.gopSpace + 8, 171);
124 | else
125 | frame.setSize(FFPROBE.gopSpace + 8 + 10, 181);
126 | scrollBar.setVisible(true);
127 | }
128 |
129 | frame.setLocation(Shutter.frame.getLocation().x + (Shutter.frame.getSize().width / 2) - (frame.getSize().width / 2), Shutter.frame.getLocation().y + 150);
130 |
131 | scrollBar.setBounds(0, 125, frame.getSize().width - 6, 17);
132 | scrollBar.setMaximum((112 * (FFPROBE.gopCount - 12) + 8));
133 |
134 | frame.addWindowListener(new WindowListener(){
135 |
136 | @Override
137 | public void windowActivated(WindowEvent arg0) {
138 | }
139 |
140 | @Override
141 | public void windowClosed(WindowEvent arg0) {
142 | frame.getContentPane().removeAll();
143 | }
144 |
145 | @Override
146 | public void windowClosing(WindowEvent arg0) {
147 |
148 | }
149 |
150 | @Override
151 | public void windowDeactivated(WindowEvent arg0) {
152 | }
153 |
154 | @Override
155 | public void windowDeiconified(WindowEvent arg0) {
156 | }
157 |
158 | @Override
159 | public void windowIconified(WindowEvent arg0) {
160 | }
161 |
162 | @Override
163 | public void windowOpened(WindowEvent arg0) {
164 | }
165 |
166 | });
167 |
168 | frame.setVisible(true);
169 | }
170 |
171 | public static void newImage(char type, int gopSpace)
172 | {
173 | JLabel image;
174 | if (type == 'I')
175 | {
176 | image = new JLabel("I");
177 | image.setFont(new Font(Shutter.mainFont, Font.PLAIN, 40));
178 | image.setHorizontalAlignment(SwingConstants.CENTER);
179 | image.setForeground(Color.BLACK);
180 | image.setBackground(new Color(232,67,67));
181 | image.setOpaque(true);
182 | }
183 | else if (type == 'P')
184 | {
185 | image = new JLabel("P");
186 | image.setFont(new Font(Shutter.mainFont, Font.PLAIN, 40));
187 | image.setHorizontalAlignment(SwingConstants.CENTER);
188 | image.setForeground(Color.BLACK);
189 | image.setBackground(new Color(68,139,233));
190 | image.setOpaque(true);
191 | }
192 | else
193 | {
194 | image = new JLabel("B");
195 | image.setFont(new Font(Shutter.mainFont, Font.PLAIN, 40));
196 | image.setHorizontalAlignment(SwingConstants.CENTER);
197 | image.setForeground(Color.BLACK);
198 | image.setBackground(new Color(100,232,67));
199 | image.setOpaque(true);
200 | }
201 | image.setSize(100, 100);
202 | image.setLocation(gopSpace, 12);
203 | frame.getContentPane().add(image);
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/src/application/GlobalKeyListener.java:
--------------------------------------------------------------------------------
1 | /* JNativeHook: Global keyboard and mouse hooking for Java.
2 | * Copyright (C) 2006-2015 Alexander Barker. All Rights Received.
3 | * https://github.com/kwhat/jnativehook/
4 | *
5 | * JNativeHook is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * JNativeHook is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package application;
20 |
21 | import com.github.kwhat.jnativehook.GlobalScreen;
22 | import com.github.kwhat.jnativehook.NativeHookException;
23 | import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent;
24 | import com.github.kwhat.jnativehook.keyboard.NativeKeyListener;
25 |
26 | public class GlobalKeyListener implements NativeKeyListener {
27 | public static boolean keyIsPressed = false;
28 |
29 | public void nativeKeyPressed(NativeKeyEvent e) {
30 | keyIsPressed = true;
31 | }
32 |
33 | public void nativeKeyReleased(NativeKeyEvent e) {
34 | keyIsPressed = false;
35 | }
36 |
37 | public void nativeKeyTyped(NativeKeyEvent e) {
38 | }
39 |
40 | public static void main(String[] args) {
41 | try {
42 | GlobalScreen.registerNativeHook();
43 | }
44 | catch (NativeHookException ex) {}
45 |
46 | GlobalScreen.addNativeKeyListener(new GlobalKeyListener());
47 | }
48 | }
--------------------------------------------------------------------------------
/src/application/Splash.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package application;
21 |
22 | import java.awt.Color;
23 | import java.awt.Graphics;
24 | import java.awt.Graphics2D;
25 | import java.awt.Image;
26 | import java.awt.RenderingHints;
27 |
28 | import javax.swing.ImageIcon;
29 | import javax.swing.JWindow;
30 |
31 | @SuppressWarnings("serial")
32 | public class Splash extends JWindow {
33 |
34 | public static Graphics g;
35 | private static int loading = 0;
36 | Image splashScreen;
37 |
38 | public Splash() {
39 |
40 | splashScreen = new ImageIcon(getClass().getClassLoader().getResource("contents/icon.png")).getImage();
41 |
42 | setBackground(new Color(0,0,0,0));
43 |
44 | setSize(256, 256);
45 |
46 | setLocationRelativeTo(null);
47 |
48 | setVisible(true);
49 |
50 | if (System.getProperty("os.name").contains("Windows"))
51 | updateProgressBar();
52 | }
53 |
54 | public void paint(Graphics g) {
55 | super.paint(g);
56 |
57 | RenderingHints qualityHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
58 | qualityHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY );
59 | ((Graphics2D) g).setRenderingHints(qualityHints);
60 |
61 | g.drawImage(splashScreen, 0, 0, this);
62 | g.setColor(Color.WHITE);
63 | g.drawRoundRect(26, 128, 200, 10, 10, 10);
64 | g.fillRoundRect(26, 128, loading, 10, 10, 10);
65 |
66 | if (System.getProperty("os.name").contains("Windows") == false)
67 | {
68 | do {
69 | g.fillRoundRect(26, 128, loading, 10, 10, 10);
70 | } while (Shutter.frame.isVisible() == false);
71 |
72 | dispose();
73 | }
74 | }
75 |
76 | public static void increment() {
77 | loading += 7;
78 | if (loading > 200)
79 | loading = 200;
80 | }
81 |
82 | public void updateProgressBar() {
83 |
84 | Thread refresh = new Thread(new Runnable() {
85 |
86 | @Override
87 | public void run() {
88 | do {
89 | repaint();
90 | try {
91 | Thread.sleep(10);
92 | } catch (InterruptedException e) {}
93 | } while (loading < 200);
94 |
95 | dispose();
96 | }
97 |
98 | });
99 | refresh.start();
100 | }
101 | }
--------------------------------------------------------------------------------
/src/application/SubtitlesHelp.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package application;
21 |
22 | import javax.swing.ImageIcon;
23 | import javax.swing.JFrame;
24 | import javax.swing.JTextPane;
25 |
26 | import java.awt.*;
27 |
28 | public class SubtitlesHelp {
29 |
30 | public static JFrame frame;
31 |
32 | public SubtitlesHelp() {
33 |
34 | frame = new JFrame();
35 | frame.getContentPane().setLayout(null);
36 | frame.setResizable(false);
37 | frame.setTitle(Shutter.language.getProperty("frameSubtitles"));
38 | frame.getContentPane().setBackground(Utils.bg32);
39 | frame.setIconImage(new ImageIcon(getClass().getClassLoader().getResource("contents/icon.png")).getImage());
40 | frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
41 |
42 | frame.setLocation(Shutter.frame.getLocation().x + Shutter.frame.getSize().width/2 - 200, Shutter.frame.getLocation().y + Shutter.frame.getHeight() /2 - 150);
43 |
44 | JTextPane lblHelp = new JTextPane();
45 | lblHelp.setBackground(Utils.c30);
46 | lblHelp.setText(Shutter.language.getProperty("txtShortcuts"));
47 | lblHelp.setForeground(Color.WHITE);
48 | lblHelp.setHighlighter(null);
49 | lblHelp.setFocusable(false);
50 | lblHelp.setEditable(false);
51 | lblHelp.setFont(new Font(Shutter.boldFont, Font.PLAIN, 12));
52 | lblHelp.setBounds(10, 12, 420, 320);
53 | frame.getContentPane().add(lblHelp);
54 |
55 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux"))
56 | frame.setSize(lblHelp.getWidth() + 10, lblHelp.getY() + lblHelp.getHeight());
57 | else
58 | frame.setSize(lblHelp.getWidth() + 10, lblHelp.getY() + lblHelp.getHeight() + 10);
59 |
60 | frame.setVisible(true);
61 |
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/application/fileOverwriteWindow.java:
--------------------------------------------------------------------------------
1 | package application;
2 |
3 | import java.awt.Font;
4 | import java.awt.event.ActionEvent;
5 | import java.awt.event.ActionListener;
6 |
7 | import javax.swing.ImageIcon;
8 | import javax.swing.JButton;
9 | import javax.swing.JCheckBox;
10 | import javax.swing.JDialog;
11 |
12 | public class fileOverwriteWindow {
13 |
14 | public static JCheckBox caseApplyToAll = new JCheckBox(Shutter.language.getProperty("caseApplyToAll"));
15 | public static String value;
16 |
17 | public fileOverwriteWindow(String file) {
18 |
19 | value = "cancel";
20 |
21 | JDialog frame = new JDialog();
22 | frame.setTitle(file + " " + Shutter.language.getProperty("alreadyExist").toLowerCase());
23 | frame.setLayout(null);
24 | frame.setIconImage(new ImageIcon(getClass().getClassLoader().getResource("contents/icon.png")).getImage());
25 | frame.setResizable(false);
26 | frame.setModal(true);
27 | frame.getContentPane().setLayout(null);
28 |
29 | System.setProperty("apple.laf.useScreenMenuBar", "false");
30 |
31 | JButton btnKeep = new JButton(Shutter.language.getProperty("btnKeep"));
32 | btnKeep.setFont(new Font(Shutter.boldFont, Font.PLAIN, 12));
33 | btnKeep.setBounds(7, 7, btnKeep.getPreferredSize().width, 21);
34 | frame.getContentPane().add(btnKeep);
35 |
36 | btnKeep.addActionListener(new ActionListener() {
37 |
38 | @Override
39 | public void actionPerformed(ActionEvent arg0) {
40 |
41 | value = "keep";
42 | frame.dispose();
43 |
44 | }
45 |
46 | });
47 |
48 | JButton btnOverwrite = new JButton(Shutter.language.getProperty("btnOverwrite"));
49 | btnOverwrite.setFont(new Font(Shutter.boldFont, Font.PLAIN, 12));
50 | btnOverwrite.setBounds(btnKeep.getX() + btnKeep.getWidth() + 4, 7, btnOverwrite.getPreferredSize().width, 21);
51 | frame.getContentPane().add(btnOverwrite);
52 |
53 | btnOverwrite.addActionListener(new ActionListener() {
54 |
55 | @Override
56 | public void actionPerformed(ActionEvent arg0) {
57 |
58 | value = "overwrite";
59 | frame.dispose();
60 |
61 | }
62 |
63 | });
64 |
65 | JButton btnSkip = new JButton(Shutter.language.getProperty("btnSkip"));
66 | btnSkip.setFont(new Font(Shutter.boldFont, Font.PLAIN, 12));
67 | btnSkip.setBounds(btnOverwrite.getX() + btnOverwrite.getWidth() + 4, 7, btnSkip.getPreferredSize().width, 21);
68 | frame.getContentPane().add(btnSkip);
69 |
70 | btnSkip.addActionListener(new ActionListener() {
71 |
72 | @Override
73 | public void actionPerformed(ActionEvent arg0) {
74 |
75 | value = "skip";
76 | frame.dispose();
77 |
78 | }
79 |
80 | });
81 |
82 | JButton btnCancel = new JButton(Shutter.language.getProperty("btnCancel"));
83 | btnCancel.setFont(new Font(Shutter.boldFont, Font.PLAIN, 12));
84 | btnCancel.setBounds(btnSkip.getX() + btnSkip.getWidth() + 4, 7, btnCancel.getPreferredSize().width, 21);
85 | frame.getContentPane().add(btnCancel);
86 |
87 | btnCancel.addActionListener(new ActionListener() {
88 |
89 | @Override
90 | public void actionPerformed(ActionEvent arg0) {
91 |
92 | frame.dispose();
93 |
94 | }
95 |
96 | });
97 |
98 | caseApplyToAll.setSelected(false);
99 | caseApplyToAll.setEnabled(true);
100 | caseApplyToAll.setFont(new Font(Shutter.mainFont, Font.PLAIN, 12));
101 | caseApplyToAll.setBounds((btnCancel.getX() + btnCancel.getWidth() + 7 - caseApplyToAll.getPreferredSize().width) / 2, btnCancel.getY() + btnCancel.getHeight() + 4, caseApplyToAll.getPreferredSize().width, 23);
102 | frame.getContentPane().add(caseApplyToAll);
103 |
104 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux"))
105 | {
106 | frame.setSize(btnCancel.getX() + btnCancel.getWidth() + 7, 90);
107 | }
108 | else
109 | frame.setSize(btnCancel.getX() + btnCancel.getWidth() + 17, 100);
110 |
111 | frame.setLocation(Shutter.frame.getX() + (Shutter.frame.getWidth() - frame.getWidth()) / 2, Shutter.frame.getY() + (Shutter.frame.getHeight()- frame.getHeight()) / 2);
112 | frame.setVisible(true);
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/contents/2013-2016.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/2013-2016.jpg
--------------------------------------------------------------------------------
/src/contents/arrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/src/contents/avid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/avid.png
--------------------------------------------------------------------------------
/src/contents/check.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/contents/complete.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/complete.wav
--------------------------------------------------------------------------------
/src/contents/davinci.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/davinci.png
--------------------------------------------------------------------------------
/src/contents/drop.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/contents/error.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/error.wav
--------------------------------------------------------------------------------
/src/contents/generate.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/contents/help.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/help_hover.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/help_pressed.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/icon.png
--------------------------------------------------------------------------------
/src/contents/item.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/list.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/list_hover.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/list_pressed.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/lock.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/mail.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/contents/max.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/max_hover.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/max_pressed.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/new.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/new_hover.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/new_pressed.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/pause.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/contents/play.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/contents/premiere.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/premiere.png
--------------------------------------------------------------------------------
/src/contents/presets.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/contents/presets_hover.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/contents/presets_pressed.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/contents/preview.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/preview_hover.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/qrcode.png
--------------------------------------------------------------------------------
/src/contents/quit.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/src/contents/quit_hover.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/src/contents/quit_pressed.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/src/contents/reduce.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/reduce_hover.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/reduce_pressed.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/screenshot.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/contents/settings.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/contents/settings_hover.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/contents/settings_pressed.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/contents/stop.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/contents/stream.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/unlock.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/contents/volume.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/functions/BlackDetection.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package functions;
21 |
22 | import java.awt.FileDialog;
23 | import java.io.File;
24 | import java.io.FileNotFoundException;
25 | import java.io.PrintWriter;
26 | import java.io.UnsupportedEncodingException;
27 |
28 | import javax.swing.JOptionPane;
29 |
30 | import application.Shutter;
31 | import application.VideoPlayer;
32 | import library.FFMPEG;
33 | import settings.FunctionUtils;
34 | import settings.InputAndOutput;
35 |
36 | public class BlackDetection extends Shutter {
37 |
38 | public static void main() {
39 |
40 | Thread thread = new Thread(new Runnable(){
41 | @Override
42 | public void run() {
43 |
44 | if (scanIsRunning == false)
45 | FunctionUtils.completed = 0;
46 |
47 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed));
48 |
49 | for (int i = 0 ; i < liste.getSize() ; i++)
50 | {
51 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i)));
52 |
53 | if (file == null)
54 | break;
55 |
56 | try {
57 |
58 | String fileName = file.getName();
59 |
60 | lblCurrentEncoding.setText(fileName);
61 |
62 | //Data analyze
63 | if (FunctionUtils.analyze(file, false) == false)
64 | continue;
65 |
66 | //InOut
67 | InputAndOutput.getInputAndOutput(VideoPlayer.getFileList(file.toString()));
68 |
69 | String levels = "0.1";
70 | if (comboFilter.getSelectedIndex() == 1)
71 | levels = "0.0";
72 |
73 | //Command
74 | String cmd;
75 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux"))
76 | cmd = " -an -vf blackdetect=d=0.0:pix_th=" + levels + " -f null -";
77 | else
78 | cmd = " -an -vf blackdetect=d=0.0:pix_th=" + levels + " -f null -" + '"';
79 |
80 | FFMPEG.run(InputAndOutput.inPoint + " -i " + '"' + file.toString() + '"' + InputAndOutput.outPoint + cmd);
81 |
82 | do
83 | {
84 | Thread.sleep(100);
85 | }
86 | while(FFMPEG.runProcess.isAlive());
87 |
88 | //Show detection
89 | if (cancelled == false)
90 | showDetection(fileName);
91 |
92 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
93 | {
94 | if (lastActions(file, fileName))
95 | break;
96 | }
97 |
98 | } catch (InterruptedException e) {
99 | FFMPEG.error = true;
100 | }
101 | }
102 |
103 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
104 | enfOfFunction();
105 | }
106 |
107 | });
108 | thread.start();
109 |
110 | }
111 |
112 | private static void showDetection(String fileName) {
113 |
114 | if (FFMPEG.blackFrame.length() > 0 && Shutter.cancelled == false && FFMPEG.error == false)
115 | {
116 | JOptionPane.showMessageDialog(frame, FFMPEG.blackFrame, Shutter.language.getProperty("functionBlackDetection"), JOptionPane.ERROR_MESSAGE);
117 | int q = JOptionPane.showConfirmDialog(Shutter.frame, Shutter.language.getProperty("saveResult"), Shutter.language.getProperty("analyzeEnded"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE);
118 |
119 | if (q == JOptionPane.YES_OPTION)
120 | {
121 | FileDialog dialog = new FileDialog(frame, Shutter.language.getProperty("saveResult"), FileDialog.SAVE);
122 | dialog.setDirectory(System.getProperty("user.home") + "/Desktop");
123 | dialog.setVisible(true);
124 |
125 | if (dialog.getFile() != null)
126 | {
127 | try {
128 | PrintWriter writer = new PrintWriter(dialog.getDirectory() + dialog.getFile().replace(".txt", "") + ".txt", "UTF-8");
129 | writer.println(Shutter.language.getProperty("analyzeOf") + " " + fileName);
130 | writer.println("");
131 | writer.println(FFMPEG.blackFrame);
132 | writer.close();
133 | } catch (FileNotFoundException | UnsupportedEncodingException e) {}
134 |
135 | }
136 |
137 | }
138 | else
139 | {
140 | cancelled = false;
141 | }
142 | }
143 | else
144 | JOptionPane.showMessageDialog(frame, Shutter.language.getProperty("noErrorDetected"), Shutter.language.getProperty("functionBlackDetection"), JOptionPane.INFORMATION_MESSAGE);
145 | }
146 |
147 | private static boolean lastActions(File file, String fileName) {
148 |
149 | //Errors
150 | if (FFMPEG.error)
151 | {
152 | FFMPEG.errorList.append(fileName);
153 | FFMPEG.errorList.append(System.lineSeparator());
154 | }
155 |
156 | //Process cancelled
157 | if (cancelled)
158 | {
159 | return true;
160 | }
161 | else
162 | {
163 | if(FFMPEG.error == false)
164 | FunctionUtils.completed++;
165 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed));
166 | }
167 |
168 | //Sending process
169 | FunctionUtils.addFileForMail(fileName);
170 |
171 | //Watch folder
172 | if (Shutter.scanIsRunning)
173 | {
174 | FunctionUtils.moveScannedFiles(file);
175 | BlackDetection.main();
176 | return true;
177 | }
178 | return false;
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/src/functions/Command.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package functions;
21 |
22 | import java.io.File;
23 |
24 | import application.Ftp;
25 | import application.Shutter;
26 | import library.EXIFTOOL;
27 | import library.FFMPEG;
28 | import settings.FunctionUtils;
29 |
30 | public class Command extends Shutter {
31 |
32 | public static void main() {
33 |
34 | Thread thread = new Thread(new Runnable(){
35 | @Override
36 | public void run() {
37 |
38 | if (scanIsRunning == false)
39 | FunctionUtils.completed = 0;
40 |
41 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed));
42 |
43 | for (int i = 0 ; i < liste.getSize() ; i++)
44 | {
45 | //Render queue only accept selected files
46 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")))
47 | {
48 | boolean isSelected = false;
49 |
50 | for (String input : Shutter.fileList.getSelectedValuesList())
51 | {
52 | if (liste.getElementAt(i).equals(input))
53 | {
54 | isSelected = true;
55 | }
56 | }
57 |
58 | if (isSelected == false)
59 | {
60 | continue;
61 | }
62 | }
63 |
64 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i)));
65 |
66 | if (file == null)
67 | break;
68 |
69 | try {
70 |
71 | String fileName = file.getName();
72 | final String extension = fileName.substring(fileName.lastIndexOf("."));
73 |
74 | lblCurrentEncoding.setText(fileName);
75 |
76 | //Output folder
77 | String labelOutput = FunctionUtils.setOutputDestination("", file);
78 |
79 | //File output name
80 | String prefix = "";
81 | if (casePrefix.isSelected())
82 | {
83 | prefix = FunctionUtils.setPrefixSuffix(txtPrefix.getText(), false);
84 | }
85 |
86 | String extensionName = "";
87 | if (btnExtension.isSelected())
88 | {
89 | extensionName = FunctionUtils.setPrefixSuffix(txtExtension.getText(), false);
90 | }
91 |
92 | //Output name
93 | String fileOutputName = labelOutput + "/" + prefix + fileName.replace(extension, extensionName + comboFilter.getEditor().getItem().toString()) ;
94 |
95 | //File output
96 | File fileOut = new File(fileOutputName);
97 | if(fileOut.exists())
98 | {
99 | fileOut = FunctionUtils.fileReplacement(labelOutput, prefix + fileName, extension, "_", comboFilter.getEditor().getItem().toString());
100 |
101 | if (fileOut == null)
102 | {
103 | cancelled = true;
104 | break;
105 | }
106 | else if (fileOut.toString().equals("skip"))
107 | {
108 | continue;
109 | }
110 | }
111 |
112 | //Command
113 | String cmd;
114 | if (comboFonctions.getEditor().getItem().toString().contains("-passlogfile")) //Passlogfile
115 | {
116 | String[] passlogfile = comboFonctions.getEditor().getItem().toString().substring(comboFonctions.getEditor().getItem().toString().indexOf("-passlogfile") + 13).split("\"");
117 | cmd = " " + comboFonctions.getEditor().getItem().toString().replace("ffmpeg", "").replace("-passlogfile " + '"' + passlogfile[1] + '"', "-passlogfile " + '"' + fileOut + '"') + " -y " ;
118 | }
119 | else
120 | cmd = " " + comboFonctions.getEditor().getItem().toString().replace("exiftool", "").replace("ffmpeg", "");
121 |
122 | if (comboFonctions.getEditor().getItem().toString().contains("ffmpeg"))
123 | {
124 | cmd += " -y ";
125 |
126 | FFMPEG.run(" -i " + '"' + file.toString() + '"' + cmd + '"' + fileOut + '"');
127 |
128 | do
129 | {
130 | Thread.sleep(100);
131 | } while(FFMPEG.runProcess.isAlive());
132 |
133 | if (cmd.contains("-pass"))
134 | {
135 | FFMPEG.run(" -i " + '"' + file.toString() + '"' + cmd.replace("-pass 1", "-pass 2") + '"' + fileOut + '"');
136 | }
137 |
138 | do
139 | {
140 | Thread.sleep(100);
141 | } while(FFMPEG.runProcess.isAlive());
142 | }
143 | else if (comboFonctions.getEditor().getItem().toString().contains("exiftool"))
144 | {
145 | btnStart.setEnabled(false);
146 |
147 | EXIFTOOL.run(" -tagsfromfile " + '"' + file.toString() + '"' + cmd + " " + '"' + file.toString() + '"');
148 |
149 | do
150 | {
151 | Thread.sleep(100);
152 | } while (EXIFTOOL.isRunning);
153 |
154 | btnStart.setEnabled(true);
155 | }
156 |
157 | //Removing temporary files
158 | final File folder = new File(fileOut.getParent());
159 | FunctionUtils.listFilesForFolder(fileName.replace(extension, ""), folder);
160 |
161 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
162 | {
163 | if (lastActions(file, fileName, fileOut, labelOutput))
164 | break;
165 | }
166 |
167 | } catch (InterruptedException e) {
168 | FFMPEG.error = true;
169 | }
170 | }
171 |
172 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
173 | enfOfFunction();
174 | }
175 |
176 | });
177 | thread.start();
178 |
179 | }
180 |
181 | private static boolean lastActions(File file, String fileName, File fileOut, String output) {
182 |
183 | if (FunctionUtils.cleanFunction(file, fileName, fileOut, output))
184 | return true;
185 |
186 | //Sending processes
187 | FunctionUtils.addFileForMail(fileName);
188 | Ftp.sendToFtp(fileOut);
189 | FunctionUtils.copyFile(fileOut);
190 |
191 |
192 | //Watch folder
193 | if (Shutter.scanIsRunning)
194 | {
195 | FunctionUtils.moveScannedFiles(file);
196 | Command.main();
197 | return true;
198 | }
199 | return false;
200 | }
201 |
202 | }
203 |
--------------------------------------------------------------------------------
/src/functions/Conform.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package functions;
21 |
22 | import java.io.File;
23 |
24 | import application.Ftp;
25 | import application.Shutter;
26 | import application.Utils;
27 | import application.VideoPlayer;
28 | import library.FFMPEG;
29 | import library.FFPROBE;
30 | import settings.FunctionUtils;
31 | import settings.InputAndOutput;
32 |
33 | public class Conform extends Shutter {
34 |
35 | public static void main() {
36 |
37 | Thread thread = new Thread(new Runnable(){
38 | @Override
39 | public void run() {
40 |
41 | if (scanIsRunning == false)
42 | FunctionUtils.completed = 0;
43 |
44 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed));
45 |
46 | for (int i = 0 ; i < liste.getSize() ; i++)
47 | {
48 | //Render queue only accept selected files
49 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")))
50 | {
51 | boolean isSelected = false;
52 |
53 | for (String input : Shutter.fileList.getSelectedValuesList())
54 | {
55 | if (liste.getElementAt(i).equals(input))
56 | {
57 | isSelected = true;
58 | }
59 | }
60 |
61 | if (isSelected == false)
62 | {
63 | continue;
64 | }
65 | }
66 |
67 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i)));
68 |
69 | if (file == null)
70 | break;
71 |
72 | try {
73 |
74 | String fileName = file.getName();
75 | String extension = fileName.substring(fileName.lastIndexOf("."));
76 |
77 | lblCurrentEncoding.setText(fileName);
78 |
79 | //Data analyze
80 | if (FunctionUtils.analyze(file, false) == false)
81 | continue;
82 |
83 | //Output folder
84 | String labelOutput = FunctionUtils.setOutputDestination("", file);
85 |
86 | //File output name
87 | String prefix = "";
88 | if (casePrefix.isSelected())
89 | {
90 | prefix = FunctionUtils.setPrefixSuffix(txtPrefix.getText(), false);
91 | }
92 |
93 | String extensionName = "";
94 | if (btnExtension.isSelected())
95 | {
96 | extensionName = FunctionUtils.setPrefixSuffix(txtExtension.getText(), false);
97 | }
98 |
99 | //Output name
100 | String fileOutputName = labelOutput.replace("\\", "/") + "/" + prefix + fileName.replace(extension, extensionName + extension);
101 |
102 | //Audio
103 | String audio = setAudio();
104 |
105 | //InOut
106 | InputAndOutput.getInputAndOutput(VideoPlayer.getFileList(file.toString()));
107 |
108 | //File output
109 | File fileOut = new File(fileOutputName);
110 | if (fileOut.exists())
111 | {
112 | fileOut = FunctionUtils.fileReplacement(labelOutput, prefix + fileName, extension, extensionName + "_", extension);
113 |
114 | if (fileOut == null)
115 | {
116 | cancelled = true;
117 | break;
118 | }
119 | else if (fileOut.toString().equals("skip"))
120 | {
121 | continue;
122 | }
123 | }
124 |
125 | //Command
126 | float FPSOut = Float.parseFloat((comboFilter.getSelectedItem().toString().replace(" " + Shutter.language.getProperty("fps"), "").replace(",", ".")));
127 | float value = (float) (FFPROBE.currentFPS / FPSOut);
128 |
129 | String cmd = " -c:v copy -c:s copy" + audio + " -map v:0 -map a? -map s? -y ";
130 | FFMPEG.run(" -itsscale " + value + InputAndOutput.inPoint + " -i " + '"' + file + '"' + InputAndOutput.outPoint + cmd + '"' + fileOut + '"');
131 |
132 | do
133 | {
134 | Thread.sleep(100);
135 | }
136 | while(FFMPEG.runProcess.isAlive());
137 |
138 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
139 | {
140 | if (lastActions(file, fileName, fileOut, labelOutput))
141 | break;
142 | }
143 |
144 | } catch (InterruptedException e) {
145 | FFMPEG.error = true;
146 | }
147 | }
148 |
149 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
150 | enfOfFunction();
151 | }
152 |
153 | });
154 | thread.start();
155 |
156 | }
157 |
158 | private static String setAudio() {
159 |
160 | float AudioFPSIn = FFPROBE.currentFPS;
161 | float AudioFPSOut = Float.parseFloat((comboFilter.getSelectedItem().toString().replace(" " + Shutter.language.getProperty("fps"), "").replace(",", ".")));
162 | float value = (float) (AudioFPSOut / AudioFPSIn);
163 | if (value < 0.5f || value > 2.0f)
164 | return " -an";
165 | else
166 | {
167 | if (FFPROBE.audioCodec != null && FFPROBE.audioCodec != "")
168 | return " -c:a " + FFPROBE.audioCodec + " -b:a " + FFPROBE.audioBitrate + "k -af atempo=" + value;
169 | else
170 | return " -an";
171 | }
172 |
173 | }
174 |
175 | private static boolean lastActions(File file, String fileName, File fileOut, String output) {
176 |
177 | if (FunctionUtils.cleanFunction(file, fileName, fileOut, output))
178 | return true;
179 |
180 | //Sending processes
181 | FunctionUtils.addFileForMail(fileName);
182 | Ftp.sendToFtp(fileOut);
183 | Utils.copyFile(fileOut);
184 |
185 | //Watch folder
186 | if (Shutter.scanIsRunning)
187 | {
188 | FunctionUtils.moveScannedFiles(file);
189 | Conform.main();
190 | return true;
191 | }
192 | return false;
193 | }
194 |
195 | }
--------------------------------------------------------------------------------
/src/functions/DVDRIP.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package functions;
21 |
22 | import java.io.File;
23 | import java.io.PrintWriter;
24 |
25 | import javax.swing.JOptionPane;
26 |
27 | import application.Console;
28 | import application.Ftp;
29 | import application.Shutter;
30 | import application.Utils;
31 | import library.FFMPEG;
32 | import library.FFPROBE;
33 | import settings.FunctionUtils;
34 |
35 | public class DVDRIP extends Shutter {
36 |
37 | public static void main() {
38 |
39 | Thread thread = new Thread(new Runnable(){
40 | @Override
41 | public void run() {
42 |
43 | FunctionUtils.completed = 0;
44 |
45 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed));
46 |
47 | //Scan VIDEO_TS folder
48 | File [] volumes;
49 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux"))
50 | volumes = new File("/Volumes").listFiles();
51 | else
52 | volumes = File.listRoots();
53 |
54 | //DVD folder
55 | File dvdFolder = setDVDFolder(volumes);
56 |
57 | if (dvdFolder == null)
58 | {
59 | JOptionPane.showMessageDialog(frame, Shutter.language.getProperty("noDVD"), Shutter.language.getProperty("DVDMissing"), JOptionPane.ERROR_MESSAGE);
60 | cancelled = true;
61 | }
62 | else
63 | {
64 | Console.consoleFFMPEG.append(System.lineSeparator() + dvdFolder + System.lineSeparator() );
65 |
66 | //Récupération des fichiers vidéo .VOB
67 | String[] vobArray = new String[dvdFolder.listFiles().length];
68 | int i = 0;
69 | for (File VOB : dvdFolder.listFiles())
70 | {
71 | if (VOB.isHidden() == false)
72 | {
73 | String ext = VOB.toString().substring(VOB.toString().lastIndexOf("."));
74 |
75 | if (VOB.getName().contains("VTS") && ext.equals(".VOB")) //Filtre des .VOB par VTS et extension
76 | {
77 | String [] s = VOB.getName().split("_");
78 | if (s[2].replace(ext, "").equals("0") == false)
79 | {
80 | vobArray[i] = VOB.toString();
81 | i ++;
82 | }
83 | }
84 | }
85 | }
86 |
87 | //Découpe des différentes vidéos
88 | File concatFile = new File(lblDestination1.getText() + "/DVD_RIP.txt");
89 |
90 | if (concatFile.exists())
91 | concatFile.delete();
92 |
93 | //Création du fichier texte pour la liste
94 | PrintWriter writer = null;
95 |
96 | int vtsNumber = 1;
97 | String VOB = null;
98 | int dureeTotale = 0;
99 | for (i = 0; i < vobArray.length ; i++)
100 | {
101 | VOB = vobArray[i];
102 |
103 | if (VOB != null)
104 | {
105 | String[] s = new File(VOB).getName().split("_");
106 | int actualVOB = Integer.valueOf(s[1]);
107 |
108 | if (actualVOB == vtsNumber)//Par exemple si le VTS_01 contient VTS_01_00, VTS_01_02, VTS_01_03... on ajoute le fichier à la liste
109 | {
110 | if (concatFile.exists() == false)
111 | {
112 | try {
113 | writer = new PrintWriter(concatFile, "UTF-8");
114 | } catch (Exception e1) {}
115 | }
116 | writer.println("file '" + VOB + "'");
117 |
118 | FFPROBE.Data(VOB);
119 | do {
120 | try {
121 | Thread.sleep(100);
122 | } catch (InterruptedException e1) {}
123 | } while (FFPROBE.isRunning == true);
124 | dureeTotale += FFPROBE.totalLength;
125 |
126 | Console.consoleFFMPEG.append(VOB + System.lineSeparator());
127 | }
128 | else //Si le fichier VTS passe de VTS_01 à VTS_02 on execute le bout à bout existant avant de le recréer ou si il n'y a pas de VTS_02
129 | {
130 | progressBar1.setMaximum((int) (dureeTotale / 1000));
131 |
132 | //On enregistre le fichier de la liste des VOB
133 | writer.close();
134 |
135 | if (runRIP(vtsNumber, concatFile, VOB))
136 | break;
137 |
138 | //Après exécution on passe on VTS suivant et on scan le nombre de fichiers existant sous le même nom dans la condition if suivante
139 | vtsNumber = actualVOB;
140 | i--;
141 | dureeTotale = 0;
142 | }
143 |
144 | }
145 | }
146 |
147 | //On execute la dernière liste de VTS
148 | if (cancelled == false)
149 | {
150 | writer.close();
151 | progressBar1.setMaximum((int) (dureeTotale / 1000));
152 | runRIP(vtsNumber, concatFile, VOB);
153 | }
154 |
155 | }
156 |
157 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
158 | enfOfFunction();
159 | }
160 |
161 | });
162 | thread.start();
163 |
164 | }
165 |
166 | protected static File setDVDFolder(File[] volumes) {
167 |
168 | for (File folder : volumes)
169 | {
170 | Console.consoleFFMPEG.append(String.valueOf(folder) + System.lineSeparator());
171 | try{
172 | for (File video_ts_folder : folder.listFiles())
173 | {
174 | if (video_ts_folder.getName().equals("VIDEO_TS"))
175 | return video_ts_folder;
176 | }
177 | } catch (Exception e) {}
178 | }
179 | return null;
180 | }
181 |
182 | private static boolean runRIP(int vtsNumber, File concatFile, String VOB) {
183 |
184 | try {
185 | String videoName = "VIDEO_" + vtsNumber + ".VOB";
186 | lblCurrentEncoding.setText(videoName);
187 |
188 | String labelOutput = lblDestination1.getText();
189 | lblDestination1.setText(labelOutput);
190 |
191 | //File output
192 | File fileOut = new File(labelOutput + "/" + videoName);
193 | if(fileOut.exists())
194 | {
195 | int q = JOptionPane.showConfirmDialog(Shutter.frame, Shutter.language.getProperty("eraseFile"), Shutter.language.getProperty("theFile") + " " + videoName + " " + Shutter.language.getProperty("alreadyExist"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE);
196 | if (q == JOptionPane.NO_OPTION)
197 | cancelled = true;
198 | }
199 |
200 | if (cancelled == false)
201 | {
202 | //Command
203 | String cmd = " -c:v copy -c:a copy -c:s copy -err_detect ignore_err -map v:0? -map a? -map s? -y ";
204 | FFMPEG.run(" -safe 0 -f concat -i " + '"' + concatFile.toString() + '"' + cmd + '"' + fileOut + '"');
205 |
206 | do
207 | {
208 | Thread.sleep(100);
209 | }
210 | while(FFMPEG.runProcess.isAlive());
211 | }
212 | else
213 | return true;
214 |
215 | if (cancelled == true)
216 | {
217 | lastActions(VOB, fileOut, labelOutput);
218 | concatFile.delete();
219 | return true;
220 | }
221 |
222 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
223 | {
224 | lastActions(VOB, fileOut, labelOutput);
225 | }
226 |
227 | } catch (InterruptedException e) {
228 | FFMPEG.error = true;
229 | }
230 | finally { //Dans tous les cas on vide la liste de fichiers VOB
231 | concatFile.delete();
232 | }
233 | return false;
234 | }
235 |
236 | private static void lastActions(String fileName, File fileOut, String output) {
237 |
238 | FunctionUtils.cleanFunction(null, fileName, fileOut, output);
239 |
240 | //Sending processes
241 | FunctionUtils.addFileForMail(fileName);
242 | Ftp.sendToFtp(fileOut);
243 | Utils.copyFile(fileOut);
244 |
245 | }
246 | }
--------------------------------------------------------------------------------
/src/functions/FrameMD5.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package functions;
21 |
22 | import java.io.File;
23 |
24 | import application.Ftp;
25 | import application.Shutter;
26 | import application.Utils;
27 | import application.VideoPlayer;
28 | import library.FFMPEG;
29 | import settings.FunctionUtils;
30 | import settings.InputAndOutput;
31 |
32 | public class FrameMD5 extends Shutter {
33 |
34 | public static Thread thread;
35 |
36 | public static void main() {
37 |
38 | thread = new Thread(new Runnable() {
39 |
40 | @Override
41 | public void run() {
42 |
43 | if (scanIsRunning == false)
44 | FunctionUtils.completed = 0;
45 |
46 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed));
47 |
48 | for (int i = 0 ; i < liste.getSize() ; i++)
49 | {
50 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i)));
51 |
52 | if (file == null)
53 | break;
54 |
55 | try {
56 |
57 | String fileName = file.getName();
58 | String extension = fileName.substring(fileName.lastIndexOf("."));
59 | String container = ".framemd5";
60 |
61 | lblCurrentEncoding.setText(fileName);
62 |
63 | //Data analyze
64 | if (FunctionUtils.analyze(file, false) == false)
65 | continue;
66 |
67 | //InOut
68 | InputAndOutput.getInputAndOutput(VideoPlayer.getFileList(file.toString()));
69 |
70 | //Output folder
71 | String labelOutput = FunctionUtils.setOutputDestination("", file);
72 |
73 | //File output name
74 | String prefix = "";
75 | if (casePrefix.isSelected())
76 | {
77 | prefix = FunctionUtils.setPrefixSuffix(txtPrefix.getText(), false);
78 | }
79 |
80 | String extensionName = "";
81 | if (btnExtension.isSelected())
82 | {
83 | extensionName = FunctionUtils.setPrefixSuffix(txtExtension.getText(), false);
84 | }
85 |
86 | //Output name
87 | String fileOutputName = labelOutput.replace("\\", "/") + "/" + prefix + fileName.replace(extension, extensionName + container);
88 |
89 | //File output
90 | File fileOut = new File(fileOutputName);
91 | if (fileOut.exists())
92 | {
93 | fileOut = FunctionUtils.fileReplacement(labelOutput, prefix + fileName, extension, extensionName + "_", container);
94 |
95 | if (fileOut == null)
96 | {
97 | cancelled = true;
98 | break;
99 | }
100 | else if (fileOut.toString().equals("skip"))
101 | {
102 | continue;
103 | }
104 | }
105 |
106 | //Concat mode or Image sequence
107 | String concat = FunctionUtils.setConcat(file, labelOutput);
108 | if ((grpImageSequence.isVisible() && caseEnableSequence.isSelected()))
109 | {
110 | file = new File(labelOutput.replace("\\", "/") + "/" + fileName.replace(extension, ".txt"));
111 | }
112 |
113 | //Command
114 | FFMPEG.run(InputAndOutput.inPoint + concat + " -i " + '"' + file.toString() + '"' + InputAndOutput.outPoint + " -f framemd5 -y " + '"' + fileOut + '"');
115 |
116 | do {
117 | Thread.sleep(100);
118 | } while(FFMPEG.runProcess.isAlive());
119 |
120 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false
121 | || FFMPEG.saveCode == false && caseEnableSequence.isSelected())
122 | {
123 | if (lastActions(file, fileName, fileOut, labelOutput))
124 | break;
125 | }
126 |
127 | } catch (InterruptedException e) {
128 | FFMPEG.error = true;
129 | }
130 | }
131 |
132 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
133 | enfOfFunction();
134 | }
135 |
136 | });
137 | thread.start();
138 |
139 | }
140 |
141 | private static boolean lastActions(File file, String fileName, File fileOut, String output) {
142 |
143 | if (FunctionUtils.cleanFunction(file, fileName, fileOut, output))
144 | return true;
145 |
146 | //Sending processes
147 | FunctionUtils.addFileForMail(fileName);
148 | Ftp.sendToFtp(fileOut);
149 | Utils.copyFile(fileOut);
150 |
151 | //Image sequence and merge
152 | if (caseEnableSequence.isSelected())
153 | return true;
154 |
155 | //Watch folder
156 | if (Shutter.scanIsRunning)
157 | {
158 | FunctionUtils.moveScannedFiles(file);
159 | FrameMD5.main();
160 | return true;
161 | }
162 |
163 | return false;
164 | }
165 |
166 | }
--------------------------------------------------------------------------------
/src/functions/LoudnessTruePeak.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package functions;
21 |
22 | import java.io.File;
23 | import java.io.FileNotFoundException;
24 | import java.io.PrintWriter;
25 | import java.io.UnsupportedEncodingException;
26 |
27 | import javax.swing.JOptionPane;
28 |
29 | import application.Shutter;
30 | import application.VideoPlayer;
31 | import library.FFMPEG;
32 | import library.FFPROBE;
33 | import settings.FunctionUtils;
34 | import settings.InputAndOutput;
35 |
36 | public class LoudnessTruePeak extends Shutter {
37 |
38 | public static void main() {
39 |
40 | Thread thread = new Thread(new Runnable(){
41 | @Override
42 | public void run() {
43 |
44 | if (scanIsRunning == false)
45 | FunctionUtils.completed = 0;
46 |
47 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed));
48 |
49 | for (int i = 0 ; i < liste.getSize() ; i++)
50 | {
51 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i)));
52 |
53 | if (file == null)
54 | break;
55 |
56 | try {
57 |
58 | String fileName = file.getName();
59 | lblCurrentEncoding.setText(fileName);
60 |
61 | //Data analyze
62 | if (FunctionUtils.analyze(file, false) == false)
63 | continue;
64 |
65 | //InOut
66 | InputAndOutput.getInputAndOutput(VideoPlayer.getFileList(file.toString()));
67 |
68 | //Audio
69 | String audio = setAudio();
70 |
71 | //Sending command
72 | String cmd;
73 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux"))
74 | cmd = " -vn" + audio + " -f null -";
75 | else
76 | cmd = " -vn" + audio + " -f null -" + '"';
77 |
78 | FFMPEG.run(InputAndOutput.inPoint + " -i " + '"' + file.toString() + '"' + InputAndOutput.outPoint + cmd);
79 |
80 | do
81 | {
82 | Thread.sleep(100);
83 | }
84 | while(FFMPEG.runProcess.isAlive());
85 |
86 | //Show detection
87 | if (cancelled == false)
88 | showDetection(file);
89 |
90 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
91 | {
92 | if (lastActions(file, fileName))
93 | break;
94 | }
95 |
96 | } catch (InterruptedException e) {
97 | FFMPEG.error = true;
98 | }
99 | }
100 |
101 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
102 | enfOfFunction();
103 | }
104 |
105 | });
106 | thread.start();
107 |
108 | }
109 |
110 | private static String setAudio() {
111 |
112 | if (FFPROBE.stereo)
113 | {
114 | return " -af ebur128=peak=true";
115 | }
116 | else if (FFPROBE.channels > 1)
117 | {
118 | if (FFPROBE.channels >= 4)
119 | {
120 | String[] options = {"A1 & A2", "A3 & A4"};
121 | int q = JOptionPane.showOptionDialog(frame, language.getProperty("ChooseMultitrack"), language.getProperty("multitrack"), JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[0]);
122 | if (q == 0)
123 | return " -filter_complex " + '"' + "[0:a:0][0:a:1]amerge=inputs=2[a];[a]ebur128=peak=true" + '"';
124 | else
125 | return " -filter_complex " + '"' + "[0:a:2][0:a:3]amerge=inputs=2[a];[a]ebur128=peak=true" + '"';
126 | }
127 | else
128 | return " -filter_complex " + '"' + "[0:a:0][0:a:1]amerge=inputs=2[a];[a]ebur128=peak=true" + '"';
129 | }
130 | else
131 | return " -af ebur128=peak=true";
132 | }
133 |
134 | private static void showDetection(File file) {
135 |
136 | if (FFMPEG.analyseLufs != null && Shutter.cancelled == false && FFMPEG.error == false)
137 | {
138 | if (comboFilter.getSelectedIndex() == 0) // Display
139 | {
140 | JOptionPane.showMessageDialog(frame, FFMPEG.analyseLufs, file.getName(), JOptionPane.INFORMATION_MESSAGE);
141 | }
142 | else // Save
143 | {
144 | //File output name
145 | String prefix = "";
146 | if (casePrefix.isSelected())
147 | {
148 | prefix = FunctionUtils.setPrefixSuffix(txtPrefix.getText(), false);
149 | }
150 |
151 | String extensionName = "";
152 | if (btnExtension.isSelected())
153 | {
154 | extensionName = FunctionUtils.setPrefixSuffix(txtExtension.getText(), false);
155 | }
156 |
157 | //Output name
158 | String fileOutputName = FunctionUtils.setOutputDestination("", file).replace("\\", "/") + "/" + prefix + file.getName() + extensionName;
159 |
160 | try {
161 | PrintWriter writer = new PrintWriter(fileOutputName + ".txt", "UTF-8");
162 | writer.println(Shutter.language.getProperty("analyzeOf") + " " + file.getName());
163 | writer.println("");
164 | writer.println(FFMPEG.analyseLufs + System.lineSeparator() + System.lineSeparator() + FFMPEG.shortTermValues);
165 | writer.close();
166 | } catch (FileNotFoundException | UnsupportedEncodingException e) {}
167 | }
168 | }
169 | }
170 |
171 | private static boolean lastActions(File file, String fileName) {
172 |
173 | //Errors
174 | if (FFMPEG.error)
175 | {
176 | FFMPEG.errorList.append(fileName);
177 | FFMPEG.errorList.append(System.lineSeparator());
178 | }
179 |
180 | //Process cancelled
181 | if (cancelled)
182 | {
183 | return true;
184 | }
185 | else
186 | {
187 | if(FFMPEG.error == false)
188 | FunctionUtils.completed++;
189 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed));
190 | }
191 |
192 | //Sending process
193 | FunctionUtils.addFileForMail(fileName);
194 |
195 | //Watch folder
196 | if (Shutter.scanIsRunning)
197 | {
198 | FunctionUtils.moveScannedFiles(file);
199 | LoudnessTruePeak.main();
200 | return true;
201 | }
202 | return false;
203 | }
204 |
205 | }
--------------------------------------------------------------------------------
/src/functions/OfflineDetection.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package functions;
21 |
22 | import java.awt.FileDialog;
23 | import java.io.File;
24 | import java.io.FileNotFoundException;
25 | import java.io.PrintWriter;
26 | import java.io.UnsupportedEncodingException;
27 |
28 | import javax.swing.JOptionPane;
29 |
30 | import application.Shutter;
31 | import application.VideoPlayer;
32 | import library.FFMPEG;
33 | import settings.FunctionUtils;
34 | import settings.InputAndOutput;
35 |
36 | public class OfflineDetection extends Shutter {
37 |
38 | public static void main() {
39 |
40 | Thread thread = new Thread(new Runnable(){
41 | @Override
42 | public void run() {
43 |
44 | if (scanIsRunning == false)
45 | FunctionUtils.completed = 0;
46 |
47 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed));
48 |
49 | for (int i = 0 ; i < liste.getSize() ; i++)
50 | {
51 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i)));
52 |
53 | if (file == null)
54 | break;
55 |
56 | try {
57 |
58 | String fileName = file.getName();
59 | lblCurrentEncoding.setText(fileName);
60 |
61 | //Data analyze
62 | if (FunctionUtils.analyze(file, false) == false)
63 | continue;
64 |
65 | //InOut
66 | InputAndOutput.getInputAndOutput(VideoPlayer.getFileList(file.toString()));
67 |
68 | //Stats_file
69 | String stats_file;
70 | if (System.getProperty("os.name").contains("Windows"))
71 | stats_file = "stats_file";
72 | else
73 | stats_file = Shutter.dirTemp + "stats_file";
74 |
75 | //Command
76 | String cmd = " -i " + '"' + Shutter.dirTemp + "offline.png" + '"' + " -lavfi " + '"' + "[0:v]scale=1920x1080[source];[1:v]scale=1920x1080[reference];[source][reference]psnr=" + stats_file + '"' + " -an -f null -";
77 |
78 | if (System.getProperty("os.name").contains("Windows"))
79 | cmd += '"';
80 |
81 | FFMPEG.run(InputAndOutput.inPoint + " -i " + '"' + file.toString() + '"' + InputAndOutput.outPoint + cmd);
82 |
83 | do
84 | {
85 | Thread.sleep(100);
86 | }
87 | while(FFMPEG.runProcess.isAlive());
88 |
89 | //Show detection
90 | if (cancelled == false)
91 | showDetection(fileName);
92 |
93 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
94 | {
95 | if (lastActions(file, fileName))
96 | break;
97 | }
98 |
99 | } catch (InterruptedException e) {
100 | FFMPEG.error = true;
101 | }
102 | }
103 |
104 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
105 | enfOfFunction();
106 | }
107 |
108 | });
109 | thread.start();
110 |
111 | }
112 |
113 | private static void showDetection(String fileName) {
114 |
115 | if (FFMPEG.mediaOfflineFrame.length() > 0 && Shutter.cancelled == false && FFMPEG.error == false)
116 | {
117 | JOptionPane.showMessageDialog(frame, FFMPEG.mediaOfflineFrame, Shutter.language.getProperty("functionOfflineDetection"), JOptionPane.ERROR_MESSAGE);
118 | int q = JOptionPane.showConfirmDialog(Shutter.frame, Shutter.language.getProperty("saveResult"), Shutter.language.getProperty("analyzeEnded"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE);
119 |
120 | if (q == JOptionPane.YES_OPTION)
121 | {
122 | FileDialog dialog = new FileDialog(frame, Shutter.language.getProperty("saveResult"), FileDialog.SAVE);
123 | dialog.setDirectory(System.getProperty("user.home") + "/Desktop");
124 | dialog.setVisible(true);
125 |
126 | if (dialog.getFile() != null)
127 | {
128 | try {
129 | PrintWriter writer = new PrintWriter(dialog.getDirectory() + dialog.getFile().replace(".txt", "") + ".txt", "UTF-8");
130 | writer.println(Shutter.language.getProperty("analyzeOf") + " " + fileName);
131 | writer.println("");
132 | writer.println(FFMPEG.mediaOfflineFrame);
133 | writer.close();
134 | } catch (FileNotFoundException | UnsupportedEncodingException e) {}
135 |
136 | }
137 |
138 | }//End Question
139 | else
140 | {
141 | cancelled = false;
142 | }
143 | }
144 | else
145 | JOptionPane.showMessageDialog(frame, Shutter.language.getProperty("noErrorDetected"), Shutter.language.getProperty("functionOfflineDetection"), JOptionPane.INFORMATION_MESSAGE);
146 | }
147 |
148 | private static boolean lastActions(File file, String fileName) {
149 |
150 | //Errors
151 | if (FFMPEG.error)
152 | {
153 | FFMPEG.errorList.append(fileName);
154 | FFMPEG.errorList.append(System.lineSeparator());
155 | }
156 |
157 | //Process cancelled
158 | if (cancelled)
159 | {
160 | return true;
161 | }
162 | else
163 | {
164 | if(FFMPEG.error == false)
165 | FunctionUtils.completed++;
166 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed));
167 | }
168 |
169 | //Sending process
170 | FunctionUtils.addFileForMail(fileName);
171 |
172 | //Watch folder
173 | if (Shutter.scanIsRunning)
174 | {
175 | FunctionUtils.moveScannedFiles(file);
176 | OfflineDetection.main();
177 | return true;
178 | }
179 | return false;
180 | }
181 | }
--------------------------------------------------------------------------------
/src/functions/VMAF.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package functions;
21 |
22 | import java.awt.FileDialog;
23 | import java.io.File;
24 | import java.io.FileNotFoundException;
25 | import java.io.PrintWriter;
26 | import java.io.UnsupportedEncodingException;
27 | import javax.swing.JOptionPane;
28 |
29 | import application.Shutter;
30 | import application.VideoPlayer;
31 | import library.FFMPEG;
32 | import settings.FunctionUtils;
33 | import settings.InputAndOutput;
34 |
35 | public class VMAF extends Shutter {
36 |
37 | boolean warningSourceFile = true;
38 |
39 | public static void main() {
40 |
41 | Thread thread = new Thread(new Runnable(){
42 | @Override
43 | public void run() {
44 |
45 | if (scanIsRunning == false)
46 | FunctionUtils.completed = 0;
47 |
48 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed));
49 |
50 | for (int i = 0 ; i < liste.getSize() ; i++)
51 | {
52 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i)));
53 |
54 | if (file == null)
55 | break;
56 |
57 | JOptionPane.showMessageDialog(frame, language.getProperty("sourceFile") + language.getProperty("colon") + System.lineSeparator() + file.getName(), "VMAF", JOptionPane.INFORMATION_MESSAGE);
58 |
59 | FileDialog dialog = new FileDialog(frame, language.getProperty("source"), FileDialog.LOAD);
60 | dialog.setDirectory(new File(file.toString()).getParent());
61 | dialog.setLocation(frame.getLocation().x - 50, frame.getLocation().y + 50);
62 | dialog.setAlwaysOnTop(true);
63 | dialog.setMultipleMode(false);
64 | dialog.setVisible(true);
65 |
66 | if (dialog.getFile() == null)
67 | {
68 | continue;
69 | }
70 |
71 | try {
72 |
73 | String fileName = file.getName();
74 | lblCurrentEncoding.setText(fileName);
75 |
76 | //Data analyze
77 | if (FunctionUtils.analyze(file, false) == false)
78 | continue;
79 |
80 | //InOut
81 | InputAndOutput.getInputAndOutput(VideoPlayer.getFileList(file.toString()));
82 |
83 | //Sending command
84 | String cmd;
85 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux"))
86 | cmd = " -filter_complex libvmaf -an -f null -";
87 | else
88 | cmd = " -filter_complex libvmaf -an -f null -" + '"';
89 |
90 | FFMPEG.run(InputAndOutput.inPoint + " -i " + '"' + file.toString() + '"' + InputAndOutput.inPoint + " -i " + '"' + dialog.getDirectory() + dialog.getFile().toString() + '"' + InputAndOutput.outPoint + cmd);
91 |
92 | do
93 | {
94 | Thread.sleep(100);
95 | }
96 | while(FFMPEG.runProcess.isAlive());
97 |
98 | //Show detection
99 | if (cancelled == false)
100 | showDetection(file);
101 |
102 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
103 | {
104 | if (lastActions(file, fileName))
105 | break;
106 | }
107 |
108 | } catch (InterruptedException e) {
109 | FFMPEG.error = true;
110 | }
111 | }
112 |
113 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false)
114 | enfOfFunction();
115 | }
116 |
117 | });
118 | thread.start();
119 |
120 | }
121 |
122 | private static void showDetection(File file) {
123 |
124 | if (FFMPEG.VMAFScore != null && Shutter.cancelled == false && FFMPEG.error == false)
125 | {
126 | if (comboFilter.getSelectedIndex() == 0) // Display
127 | {
128 | JOptionPane.showMessageDialog(frame, file.getName() + System.lineSeparator() + FFMPEG.VMAFScore, "VMAF", JOptionPane.INFORMATION_MESSAGE);
129 | }
130 | else // Save
131 | {
132 | //File output name
133 | String prefix = "";
134 | if (casePrefix.isSelected())
135 | {
136 | prefix = FunctionUtils.setPrefixSuffix(txtPrefix.getText(), false);
137 | }
138 |
139 | String extensionName = "";
140 | if (btnExtension.isSelected())
141 | {
142 | extensionName = FunctionUtils.setPrefixSuffix(txtExtension.getText(), false);
143 | }
144 |
145 | //Output name
146 | String fileOutputName = FunctionUtils.setOutputDestination("", file).replace("\\", "/") + "/" + prefix + file.getName() + extensionName;
147 |
148 | try {
149 | PrintWriter writer = new PrintWriter(fileOutputName + ".txt", "UTF-8");
150 | writer.println(Shutter.language.getProperty("analyzeOf") + " " + file.getName());
151 | writer.println("");
152 | writer.println(FFMPEG.VMAFScore);
153 | writer.close();
154 | } catch (FileNotFoundException | UnsupportedEncodingException e) {}
155 | }
156 | }
157 | }
158 |
159 | private static boolean lastActions(File file, String fileName) {
160 |
161 | //Errors
162 | if (FFMPEG.error)
163 | {
164 | FFMPEG.errorList.append(fileName);
165 | FFMPEG.errorList.append(System.lineSeparator());
166 | }
167 |
168 | //Process cancelled
169 | if (cancelled)
170 | {
171 | return true;
172 | }
173 | else
174 | {
175 | if(FFMPEG.error == false)
176 | FunctionUtils.completed++;
177 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed));
178 | }
179 |
180 | //Sending process
181 | FunctionUtils.addFileForMail(fileName);
182 |
183 | //Watch folder
184 | if (Shutter.scanIsRunning)
185 | {
186 | FunctionUtils.moveScannedFiles(file);
187 | VMAF.main();
188 | return true;
189 | }
190 | return false;
191 | }
192 |
193 | }
--------------------------------------------------------------------------------
/src/library/BMXTRANSWRAP.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package library;
21 |
22 | import java.io.BufferedReader;
23 | import java.io.IOException;
24 | import java.io.InputStreamReader;
25 | import java.io.OutputStream;
26 |
27 | import application.Console;
28 | import application.RenderQueue;
29 | import application.Shutter;
30 |
31 | public class BMXTRANSWRAP extends Shutter {
32 |
33 | public static boolean error = false;
34 | public static boolean isRunning = false;
35 | public static Thread runProcess;
36 | public static Process process;
37 |
38 | public static void run(final String cmd) {
39 |
40 | Console.consoleBMXTRANSWRAP.append(Shutter.language.getProperty("command") + " " + cmd);
41 |
42 | error = false;
43 |
44 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) && RenderQueue.btnStartRender.isEnabled())
45 | {
46 | RenderQueue.tableRow.addRow(new Object[] {lblCurrentEncoding.getText(), "bmxtranswrap " + cmd, lblDestination1.getText()});
47 | RenderQueue.caseRunParallel.setSelected(false);
48 | RenderQueue.caseRunParallel.setEnabled(false);
49 | RenderQueue.parallelValue.setEnabled(false);
50 |
51 | lblCurrentEncoding.setText(Shutter.language.getProperty("lblEncodageEnCours"));
52 |
53 | if (caseChangeFolder1.isSelected() == false)
54 | lblDestination1.setText(Shutter.language.getProperty("sameAsSource"));
55 | }
56 | else
57 | {
58 | disableAll();
59 |
60 | progressBar1.setValue(0);
61 | progressBar1.setMaximum(100);
62 |
63 | runProcess = new Thread(new Runnable() {
64 | @Override
65 | public void run() {
66 | try {
67 | String PathToBMX;
68 | ProcessBuilder processBMX;
69 | if (System.getProperty("os.name").contains("Windows"))
70 | {
71 | PathToBMX = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
72 | PathToBMX = PathToBMX.substring(1,PathToBMX.length()-1);
73 | PathToBMX = '"' + PathToBMX.substring(0,(int) (PathToBMX.lastIndexOf("/"))).replace("%20", " ") + "/Library/bmxtranswrap.exe" + '"';
74 | processBMX = new ProcessBuilder(PathToBMX + " " + cmd);
75 | }
76 | else
77 | {
78 | PathToBMX = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
79 | PathToBMX = PathToBMX.substring(0,PathToBMX.length()-1);
80 | PathToBMX = PathToBMX.substring(0,(int) (PathToBMX.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/bmxtranswrap";
81 | processBMX = new ProcessBuilder("/bin/bash", "-c" , PathToBMX + " " + cmd);
82 | }
83 |
84 | isRunning = true;
85 | process = processBMX.start();
86 |
87 | OutputStream out = process.getOutputStream();
88 | out.write("os get /value".getBytes());
89 | out.flush();
90 |
91 | InputStreamReader isr = new InputStreamReader(process.getInputStream());
92 | BufferedReader br = new BufferedReader(isr);
93 | String line;
94 |
95 | //Analyse des données
96 | do {
97 | line = br.readLine();
98 |
99 | if (line != null)
100 | {
101 | if (line.contains("%"))
102 | {
103 | String s[] = line.split("\\.");
104 | int value = Integer.valueOf(s[0].replace(" ", ""));
105 | progressBar1.setValue(value);
106 | }
107 | }
108 |
109 | } while(line !=null);
110 | process.waitFor();
111 |
112 | } catch (IOException | InterruptedException e) {
113 | error = true;
114 | } finally {
115 | isRunning = false;
116 | }
117 |
118 | }
119 | });
120 | runProcess.start();
121 | }
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/src/library/DVDAUTHOR.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package library;
21 |
22 | import java.io.BufferedReader;
23 | import java.io.IOException;
24 | import java.io.InputStreamReader;
25 |
26 | import application.Console;
27 | import application.RenderQueue;
28 | import application.Shutter;
29 |
30 | public class DVDAUTHOR extends Shutter {
31 |
32 | public static boolean error = false;
33 | public static boolean isRunning = false;
34 | public static Thread runProcess;
35 | public static Process process;
36 |
37 | public static void run(final String cmd) {
38 |
39 | Console.consoleDVDAUTHOR.append(Shutter.language.getProperty("command") + " " + cmd);
40 |
41 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) && RenderQueue.btnStartRender.isEnabled())
42 | {
43 | RenderQueue.tableRow.addRow(new Object[] {lblCurrentEncoding.getText(), "dvdauthor " + cmd, lblDestination1.getText()});
44 | RenderQueue.caseRunParallel.setSelected(false);
45 | RenderQueue.caseRunParallel.setEnabled(false);
46 | RenderQueue.parallelValue.setEnabled(false);
47 |
48 | lblCurrentEncoding.setText(Shutter.language.getProperty("lblEncodageEnCours"));
49 |
50 | if (caseChangeFolder1.isSelected() == false)
51 | lblDestination1.setText(Shutter.language.getProperty("sameAsSource"));
52 | }
53 | else
54 | {
55 | progressBar1.setValue(0);
56 | progressBar1.setMaximum(100);
57 |
58 | runProcess = new Thread(new Runnable() {
59 | @Override
60 | public void run() {
61 | try {
62 | String PathToDVDAUTHOR;
63 | ProcessBuilder processDVDAUTHOR;
64 | if (System.getProperty("os.name").contains("Windows"))
65 | {
66 | PathToDVDAUTHOR = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
67 | PathToDVDAUTHOR = PathToDVDAUTHOR.substring(1,PathToDVDAUTHOR.length()-1);
68 | PathToDVDAUTHOR = '"' + PathToDVDAUTHOR.substring(0,(int) (PathToDVDAUTHOR.lastIndexOf("/"))).replace("%20", " ") + "/Library/dvdauthor.exe" + '"';
69 | processDVDAUTHOR = new ProcessBuilder(PathToDVDAUTHOR + " " + cmd);
70 | }
71 | else
72 | {
73 | PathToDVDAUTHOR = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
74 | PathToDVDAUTHOR = PathToDVDAUTHOR.substring(0,PathToDVDAUTHOR.length()-1);
75 | PathToDVDAUTHOR = PathToDVDAUTHOR.substring(0,(int) (PathToDVDAUTHOR.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/dvdauthor";
76 | processDVDAUTHOR = new ProcessBuilder("/bin/bash", "-c" , PathToDVDAUTHOR + " " + cmd);
77 | }
78 |
79 | isRunning = true;
80 | process = processDVDAUTHOR.start();
81 |
82 | String line;
83 | BufferedReader input = new BufferedReader(new InputStreamReader(process.getErrorStream()));
84 |
85 | Console.consoleDVDAUTHOR.append(System.lineSeparator());
86 |
87 | while ((line = input.readLine()) != null) {
88 |
89 | Console.consoleDVDAUTHOR.append(line + System.lineSeparator());
90 |
91 | if (line.contains("%"))
92 | {
93 | String s[] = line.split(" ");
94 | int value = Integer.valueOf(s[s.length-1].replace("%)", ""));
95 | progressBar1.setValue(value);
96 | }
97 |
98 | }//While
99 | process.waitFor();
100 |
101 | Console.consoleDVDAUTHOR.append(System.lineSeparator());
102 |
103 | } catch (IOException | InterruptedException e) {
104 | error = true;
105 | } finally {
106 | isRunning = false;
107 | }
108 |
109 | }
110 | });
111 | runProcess.start();
112 | }
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/src/library/EXIFTOOL.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package library;
21 |
22 | import java.io.BufferedReader;
23 | import java.io.InputStreamReader;
24 |
25 | import application.Console;
26 | import application.Shutter;
27 |
28 | public class EXIFTOOL extends Shutter {
29 |
30 | public static boolean error = false;
31 | public static boolean isRunning = false;
32 | public static Thread runProcess;
33 | public static String exifDate;
34 | public static String exifHours;
35 | public static String creationDate;
36 | public static String creationHours;
37 | public static String exifWidth;
38 | public static String exifHeight;
39 | private static boolean scanOrientation = true;
40 | private static Boolean horizontal = true;
41 |
42 | public static void run(final String cmd) {
43 |
44 | error = false;
45 | scanOrientation = true;
46 | horizontal = true;
47 | exifDate = "0000:00:00";
48 | exifHours = "00:00:00";
49 | creationDate = "0000:00:00";
50 | creationHours = "00:00:00";
51 | exifWidth = "";
52 | exifHeight = "";
53 |
54 | if (cmd != '"' + "" + '"')
55 | {
56 | Console.consoleEXIFTOOL.append(System.lineSeparator());
57 | Console.consoleEXIFTOOL.append(Shutter.language.getProperty("command") + " " + cmd);
58 | }
59 |
60 | //Watermark scaling
61 | FFPROBE.previousImageWidth = FFPROBE.imageWidth;
62 |
63 | runProcess = new Thread(new Runnable() {
64 | @Override
65 | public void run() {
66 |
67 | try {
68 |
69 | String PathToEXIFTOOL;
70 | ProcessBuilder processEXIFTOOL;
71 | if (System.getProperty("os.name").contains("Windows"))
72 | {
73 | PathToEXIFTOOL = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
74 | PathToEXIFTOOL = PathToEXIFTOOL.substring(1,PathToEXIFTOOL.length()-1);
75 | PathToEXIFTOOL = '"' + PathToEXIFTOOL.substring(0,(int) (PathToEXIFTOOL.lastIndexOf("/"))).replace("%20", " ") + "/Library/exiftool.exe" + '"';
76 | processEXIFTOOL = new ProcessBuilder(PathToEXIFTOOL + " " + cmd);
77 | }
78 | else
79 | {
80 | PathToEXIFTOOL = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
81 | PathToEXIFTOOL = PathToEXIFTOOL.substring(0,PathToEXIFTOOL.length()-1);
82 | PathToEXIFTOOL = PathToEXIFTOOL.substring(0,(int) (PathToEXIFTOOL.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/exiftool";
83 | processEXIFTOOL = new ProcessBuilder("/bin/bash", "-c" , PathToEXIFTOOL + " " + cmd);
84 | }
85 |
86 | isRunning = true;
87 | Process process = processEXIFTOOL.start();
88 |
89 | InputStreamReader isr = new InputStreamReader(process.getInputStream());
90 | BufferedReader br = new BufferedReader(isr);
91 |
92 | String line;
93 |
94 | if (cmd != '"' + "" + '"')
95 | {
96 | Console.consoleEXIFTOOL.append(System.lineSeparator());
97 | }
98 |
99 | //Analyse des données
100 | while ((line = br.readLine()) != null)
101 | {
102 | Console.consoleEXIFTOOL.append(line + System.lineSeparator());
103 |
104 | if (line.contains("Error"))
105 | {
106 | error = true;
107 | }
108 |
109 | if (line.contains("Date/Time Original"))
110 | {
111 | String l = line.substring(line.indexOf(":") + 2);
112 | String f[] = l.split(" ");
113 | exifDate = f[0]; //2018:04:06
114 | exifHours = f[1]; //12:30:00
115 | }
116 |
117 | if (line.contains("Create Date") && line.contains("+") == false)
118 | {
119 | String l = line.substring(line.indexOf(":") + 2);
120 | String f[] = l.split(" ");
121 | creationDate = f[0].toString(); //2018:04:06
122 |
123 | String time[] = f[1].split(":"); //12:30:00
124 | creationHours = time[0] + ":" + time[1] + ":" + time[2];
125 | }
126 |
127 | if (line.contains("Image Width"))
128 | exifWidth = line.substring(line.indexOf(":") + 2);
129 |
130 | if (line.contains("Image Height"))
131 | exifHeight = line.substring(line.indexOf(":") + 2);
132 |
133 | if (line.contains("Orientation") && scanOrientation)
134 | {
135 | if (line.substring(line.indexOf(":") + 2).contains("Horizontal") == false && line.substring(line.indexOf(":") + 2).contains("Rotate 180") == false)
136 | {
137 | horizontal = false;
138 | }
139 |
140 | scanOrientation = false;
141 | }
142 | }
143 | process.waitFor();
144 |
145 | //Si il n'y a pas d'exif on lit la date de création système
146 | if (exifDate == "" && exifHours == "")
147 | {
148 | exifDate = creationDate;
149 | exifHours = creationHours;
150 | }
151 |
152 | //On inject la résolution dans FFPROBE
153 | if (exifWidth != "" && exifHeight != "")
154 | {
155 | if (horizontal)
156 | {
157 | FFPROBE.imageResolution = exifWidth + "x" + exifHeight;
158 | FFPROBE.imageWidth = Integer.parseInt(exifWidth);
159 | FFPROBE.imageHeight = Integer.parseInt(exifHeight);
160 | }
161 | else
162 | {
163 | FFPROBE.imageResolution = exifHeight + "x" + exifWidth;
164 | FFPROBE.imageWidth = Integer.parseInt(exifHeight);
165 | FFPROBE.imageHeight = Integer.parseInt(exifWidth);
166 | }
167 |
168 | FFPROBE.imageRatio = (float) FFPROBE.imageWidth / FFPROBE.imageHeight;
169 | }
170 |
171 | } catch (Exception e) {
172 | error = true;
173 | } finally {
174 | isRunning = false;
175 | }
176 |
177 | }
178 | });
179 | runProcess.start();
180 | }
181 | }
--------------------------------------------------------------------------------
/src/library/MEDIAINFO.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package library;
21 |
22 | import java.awt.Color;
23 | import java.awt.Cursor;
24 | import java.io.BufferedReader;
25 | import java.io.File;
26 | import java.io.IOException;
27 | import java.io.InputStreamReader;
28 |
29 | import javax.swing.JLabel;
30 | import javax.swing.JScrollPane;
31 |
32 | import application.Console;
33 | import application.Informations;
34 | import application.Shutter;
35 | import application.Utils;
36 |
37 | public class MEDIAINFO extends Shutter {
38 |
39 | static int dureeTotale = 0;
40 | public static boolean error = false;
41 | public static boolean isRunning = false;
42 | public static Thread runProcess;
43 |
44 | public static void run(final String file, boolean showInformationsFrame) {
45 |
46 | error = false;
47 |
48 | Console.consoleMEDIAINFO.append(Shutter.language.getProperty("command") + " --Output=HTML " + '"' + file.toString() + '"');
49 |
50 | runProcess = new Thread(new Runnable() {
51 | @Override
52 | public void run() {
53 |
54 | if (showInformationsFrame)
55 | Informations.frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
56 |
57 | try {
58 |
59 | String PathToMEDIAINFO;
60 | ProcessBuilder processMEDIAINFO;
61 | if (System.getProperty("os.name").contains("Windows"))
62 | {
63 | PathToMEDIAINFO = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
64 | PathToMEDIAINFO = PathToMEDIAINFO.substring(1,PathToMEDIAINFO.length()-1);
65 | PathToMEDIAINFO = '"' + PathToMEDIAINFO.substring(0,(int) (PathToMEDIAINFO.lastIndexOf("/"))).replace("%20", " ") + "/Library/MediaInfo.exe" + '"';
66 | processMEDIAINFO = new ProcessBuilder(PathToMEDIAINFO + " --Output=HTML " + '"' + file.toString() + '"');
67 | }
68 | else
69 | {
70 | PathToMEDIAINFO = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
71 | PathToMEDIAINFO = PathToMEDIAINFO.substring(0,PathToMEDIAINFO.length()-1);
72 | PathToMEDIAINFO = PathToMEDIAINFO.substring(0,(int) (PathToMEDIAINFO.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/mediainfo";
73 | processMEDIAINFO = new ProcessBuilder("/bin/bash", "-c" , PathToMEDIAINFO + " --Output=HTML " + '"' + file.toString() + '"');
74 | }
75 |
76 | isRunning = true;
77 | Process process = processMEDIAINFO.start();
78 |
79 | InputStreamReader isr = new InputStreamReader(process.getInputStream());
80 | BufferedReader br = new BufferedReader(isr);
81 | StringBuilder infoData = new StringBuilder();
82 |
83 | Console.consoleMEDIAINFO.append(System.lineSeparator());
84 |
85 | String line;
86 | while ((line = br.readLine()) != null)
87 | {
88 | infoData.append(line);
89 | /*
90 | //Variable Frame Rate
91 | if (line.contains("Frame rate mode :"))
92 | {
93 | infoData.append(System.lineSeparator());
94 |
95 | line = br.readLine();
96 | infoData.append(line);
97 |
98 | String s[] = line.split(">");
99 | String s2[] = s[1].split("<");
100 |
101 | if (s2[0].equals("Variable"))
102 | {
103 | FFPROBE.currentFPS = FFPROBE.timebaseFPS;
104 | }
105 | }*/
106 |
107 | //Timecode
108 | if (line.contains("Time code of first frame") && FFPROBE.timecode1 == "")
109 | {
110 | infoData.append(System.lineSeparator());
111 |
112 | line = br.readLine();
113 | infoData.append(line);
114 |
115 | String s[] = line.split(">");
116 | String s2[] = s[1].split("<");
117 | String str[]= s2[0].replace(";" , ":").split(":");
118 |
119 | FFPROBE.timecode1 = str[0];
120 | FFPROBE.timecode2 = str[1];
121 | FFPROBE.timecode3 = str[2];
122 | FFPROBE.timecode4 = str[3];
123 | }
124 |
125 | //Interlaced
126 | if (line.contains("Scan type :") && FFPROBE.interlaced == null)
127 | {
128 | infoData.append(System.lineSeparator());
129 |
130 | line = br.readLine();
131 | infoData.append(line);
132 |
133 | String s[] = line.split(">");
134 | String s2[] = s[1].split("<");
135 |
136 | if (s2[0].equals("Interlaced"))
137 | {
138 | FFPROBE.interlaced = "1";
139 | }
140 | else
141 | FFPROBE.interlaced = "0";
142 | }
143 |
144 | //Field order
145 | if (line.contains("Scan order :") && FFPROBE.interlaced.equals("1") && FFPROBE.fieldOrder == null)
146 | {
147 | infoData.append(System.lineSeparator());
148 |
149 | line = br.readLine();
150 | infoData.append(line);
151 |
152 | String s[] = line.split(">");
153 | String s2[] = s[1].split("<");
154 |
155 | if (s2[0].equals("Bottom Field First"))
156 | {
157 | FFPROBE.fieldOrder = "1";
158 | }
159 | else
160 | FFPROBE.fieldOrder = "0";
161 | }
162 |
163 | infoData.append(System.lineSeparator());
164 | }
165 |
166 | process.waitFor();
167 |
168 | Console.consoleMEDIAINFO.append(System.lineSeparator());
169 |
170 | String StrTotal = "";
171 |
172 | int x = infoData.indexOf("");
173 | x = infoData.indexOf("", x + 1);
174 | x = infoData.indexOf("", x + 1);
175 |
176 | StrTotal = infoData.substring(infoData.indexOf("") + (x + 3));
177 |
178 | Console.consoleMEDIAINFO.append("" + System.lineSeparator() + "" + System.lineSeparator() + StrTotal.toString());
179 |
180 | if (showInformationsFrame)
181 | {
182 | //Adding tab
183 | Informations.addTabControl();
184 |
185 | String informationsFrameSize = String.valueOf((int) Informations.frame.getSize().width - 320);
186 | String htmlSize = "";
187 | for (String l : StrTotal.toString().split(System.lineSeparator()))
188 | {
189 | if (l.contains("td width"))
190 | {
191 | String s[] = l.split("\"");
192 | htmlSize = s[1];
193 | }
194 |
195 | }
196 |
197 | JLabel content = new JLabel("" + System.lineSeparator() + "" + System.lineSeparator()
198 | + StrTotal.toString().replace(htmlSize, informationsFrameSize).replace("", "").replace("border:1px solid Navy", "border-bottom:1px solid rgb(55,55,55); border-top:1px solid rgb(55,55,55)"));
199 |
200 | content.setBackground(Utils.c30);
201 | content.setForeground(new Color(235,235,240));
202 | content.setOpaque(true);
203 |
204 | JScrollPane scrollPane = new JScrollPane();
205 | scrollPane.setViewportView(content);
206 | scrollPane.setBounds(Informations.tabPanel.getBounds());
207 | scrollPane.getVerticalScrollBar().setUnitIncrement(16);
208 |
209 | Informations.lblWait.setVisible(false);
210 | Informations.lblArrows.setVisible(true);
211 |
212 | Informations.infoTabbedPane.addTab(new File(file).getName(), scrollPane);
213 | }
214 |
215 | } catch (IOException | InterruptedException e) {
216 | error = true;
217 | } finally {
218 | isRunning = false;
219 | }
220 |
221 | if (showInformationsFrame)
222 | Informations.frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
223 | }
224 | });
225 | runProcess.start();
226 | }
227 |
228 | }
229 |
--------------------------------------------------------------------------------
/src/library/NCNN.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package library;
21 |
22 | import java.io.BufferedReader;
23 | import java.io.File;
24 | import java.io.IOException;
25 | import java.io.InputStreamReader;
26 |
27 | import javax.imageio.ImageIO;
28 |
29 | import application.Console;
30 | import application.RenderQueue;
31 | import application.Shutter;
32 | import application.VideoPlayer;
33 |
34 | public class NCNN extends Shutter {
35 |
36 | static int dureeTotale = 0;
37 | public static boolean error = false;
38 | public static boolean isRunning = false;
39 | public static Thread runProcess;
40 | public static Process process;
41 | public static String modelsPath;
42 |
43 | public static void run(final String cmd, boolean isVideoPlayer) {
44 |
45 | error = false;
46 | progressBar1.setValue(0);
47 | tempsEcoule.setVisible(false);
48 |
49 | Console.consoleNCNN.append(language.getProperty("command") + " " + cmd);
50 |
51 | if (btnStart.getText().equals(language.getProperty("btnAddToRender")) && RenderQueue.btnStartRender.isEnabled() && cmd.contains("-f rawvideo") == false && cmd.contains("preview.bmp") == false && cmd.contains("preview.png") == false)
52 | {
53 | RenderQueue.tableRow.addRow(new Object[] { lblCurrentEncoding.getText(), "ncnn" + cmd, lblDestination1.getText()});
54 | RenderQueue.caseRunParallel.setSelected(false);
55 | RenderQueue.caseRunParallel.setEnabled(false);
56 | RenderQueue.parallelValue.setEnabled(false);
57 |
58 | lblCurrentEncoding.setText(language.getProperty("lblEncodageEnCours"));
59 |
60 | if (caseChangeFolder1.isSelected() == false)
61 | lblDestination1.setText(language.getProperty("sameAsSource"));
62 | }
63 | else
64 | {
65 | isRunning = true;
66 |
67 | runProcess = new Thread(new Runnable() {
68 |
69 | @Override
70 | public void run() {
71 |
72 | try {
73 |
74 | String PathToNCNN;
75 | ProcessBuilder processNCNN;
76 |
77 | if (System.getProperty("os.name").contains("Windows"))
78 | {
79 | PathToNCNN = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
80 | PathToNCNN = PathToNCNN.substring(1,PathToNCNN.length()-1);
81 | PathToNCNN = '"' + PathToNCNN.substring(0,(int) (PathToNCNN.lastIndexOf("/"))).replace("%20", " ") + "/Library/realesrgan-ncnn-vulkan.exe" + '"';
82 | processNCNN = new ProcessBuilder(PathToNCNN + cmd);
83 | }
84 | else
85 | {
86 | PathToNCNN = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
87 | PathToNCNN = PathToNCNN.substring(0,PathToNCNN.length()-1);
88 | PathToNCNN = PathToNCNN.substring(0,(int) (PathToNCNN.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/realesrgan-ncnn-vulkan";
89 | processNCNN = new ProcessBuilder("/bin/bash", "-c" , PathToNCNN + cmd);
90 | }
91 |
92 | process = processNCNN.start();
93 |
94 | String line;
95 | BufferedReader input = new BufferedReader(new InputStreamReader(process.getErrorStream()));
96 |
97 | if (caseCreateSequence.isSelected() == false
98 | && (comboFonctions.getSelectedItem().toString().contains("JPEG") || comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionPicture"))))
99 | {
100 | progressBar1.setValue(0);
101 | progressBar1.setMaximum(100);
102 | }
103 |
104 | Console.consoleNCNN.append(System.lineSeparator());
105 |
106 | int progressValue = 0;
107 |
108 | if (isVideoPlayer == false)
109 | btnStart.setText(language.getProperty("btnPauseFunction"));
110 |
111 | while ((line = input.readLine()) != null)
112 | {
113 | if (line.contains("%") == false)
114 | {
115 | Console.consoleNCNN.append(line + System.lineSeparator());
116 | }
117 |
118 | if ((line.contains("%") && caseCreateSequence.isSelected() == false
119 | && (comboFonctions.getSelectedItem().toString().contains("JPEG") || comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionPicture"))))
120 | || line.contains("%") && isVideoPlayer)
121 | {
122 | String s[] = line.split("\\.");
123 | if (System.getProperty("os.name").contains("Windows"))
124 | {
125 | s = line.split(",");
126 | }
127 |
128 | progressBar1.setValue(Integer.parseInt(s[0]));
129 | }
130 | else if (line.contains("done"))
131 | {
132 | progressValue ++;
133 | progressBar1.setValue(progressValue);
134 |
135 | if (comboFonctions.getSelectedItem().toString().contains("JPEG") == false
136 | && comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionPicture")) == false
137 | && caseDisplay.isSelected())
138 | {
139 | try {
140 | String s[] = line.split(" ");
141 | VideoPlayer.frameVideo = ImageIO.read(new File(s[2].toString()));
142 | VideoPlayer.player.repaint();
143 | } catch (Exception e) {}
144 | }
145 | }
146 | }
147 | process.waitFor();
148 |
149 | Console.consoleNCNN.append(System.lineSeparator());
150 |
151 | } catch (IOException | InterruptedException e) {
152 | error = true;
153 | } finally {
154 |
155 | isRunning = false;
156 |
157 | if (caseCreateSequence.isSelected() == false
158 | && (comboFonctions.getSelectedItem().toString().contains("JPEG") || comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionPicture"))))
159 | {
160 | if (cancelled == false)
161 | {
162 | progressBar1.setValue(100);
163 | }
164 | else
165 | progressBar1.setValue(0);
166 | }
167 | }
168 |
169 | }
170 | });
171 | runProcess.start();
172 | }
173 | }
174 |
175 | }
176 |
--------------------------------------------------------------------------------
/src/library/PDF.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package library;
21 |
22 | import java.awt.Cursor;
23 | import java.awt.image.BufferedImage;
24 | import java.io.File;
25 |
26 | import org.apache.pdfbox.pdmodel.PDDocument;
27 | import org.apache.pdfbox.rendering.ImageType;
28 | import org.apache.pdfbox.rendering.PDFRenderer;
29 |
30 | import application.Shutter;
31 | import application.VideoPlayer;
32 |
33 | public class PDF extends Shutter {
34 |
35 | public static boolean error = false;
36 | public static boolean isRunning = false;
37 | public static Thread runProcess;
38 | public static int pagesCount = 1;
39 |
40 | public static void run(File file, int pageNumber) {
41 |
42 | error = false;
43 | progressBar1.setValue(0);
44 | btnStart.setEnabled(false);
45 |
46 | runProcess = new Thread(new Runnable() {
47 |
48 | @Override
49 | public void run() {
50 |
51 | try {
52 |
53 | isRunning = true;
54 | frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
55 |
56 | PDDocument document = PDDocument.load(file);
57 | PDFRenderer pdfRenderer = new PDFRenderer(document);
58 |
59 | pagesCount = document.getNumberOfPages();
60 |
61 | VideoPlayer.preview = pdfRenderer.renderImageWithDPI(pageNumber, 300, ImageType.RGB);
62 |
63 | document.close();
64 |
65 | FFPROBE.interlaced = null;
66 | FFPROBE.analyzedMedia = VideoPlayer.videoPath;
67 |
68 | VideoPlayer.setInfo();
69 |
70 | } catch (Exception e) {
71 | error = true;
72 | } finally {
73 | btnStart.setEnabled(true);
74 | isRunning = false;
75 | frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
76 | }
77 |
78 | }
79 | });
80 | runProcess.start();
81 |
82 | }
83 |
84 | public static void info(String file) {
85 |
86 | error = false;
87 |
88 | FFPROBE.hasAudio = false;
89 | FFPROBE.totalLength = 0;
90 |
91 | //Watermark scaling
92 | FFPROBE.previousImageWidth = FFPROBE.imageWidth;
93 |
94 | runProcess = new Thread(new Runnable() {
95 |
96 | @Override
97 | public void run() {
98 |
99 | try {
100 |
101 | isRunning = true;
102 | frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
103 |
104 | PDDocument document = PDDocument.load(new File(file));
105 | PDFRenderer pdfRenderer = new PDFRenderer(document);
106 |
107 | pagesCount = document.getNumberOfPages();
108 |
109 | BufferedImage image = pdfRenderer.renderImageWithDPI(0, 300, ImageType.RGB);
110 |
111 | FFPROBE.imageResolution = image.getWidth() + "x" + image.getHeight();
112 | FFPROBE.imageWidth = image.getWidth();
113 | FFPROBE.imageHeight = image.getHeight();
114 | FFPROBE.imageRatio = (float) image.getWidth() / image.getHeight();
115 |
116 | document.close();
117 |
118 | } catch (Exception e) {
119 | error = true;
120 | } finally {
121 | isRunning = false;
122 | frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
123 | }
124 |
125 | }
126 | });
127 | runProcess.start();
128 |
129 | }
130 |
131 | }
--------------------------------------------------------------------------------
/src/library/SEVENZIP.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package library;
21 |
22 | import java.awt.Desktop;
23 | import java.io.BufferedReader;
24 | import java.io.File;
25 | import java.io.IOException;
26 | import java.io.InputStreamReader;
27 | import java.io.OutputStream;
28 |
29 | import javax.swing.SwingUtilities;
30 |
31 | import application.Console;
32 | import application.Shutter;
33 |
34 | public class SEVENZIP extends Shutter {
35 |
36 | public static boolean isRunning = false;
37 | public static Thread runProcess;
38 | public static boolean error = false;
39 |
40 | public static void run(final String cmd, final boolean notUpdate){
41 |
42 | runProcess = new Thread(new Runnable() {
43 | @Override
44 | public void run() {
45 |
46 | Console.consoleFFMPEG.append(Shutter.language.getProperty("command") + " " + cmd);
47 |
48 | try {
49 | String PathTo7za;
50 | ProcessBuilder process7za;
51 | if (System.getProperty("os.name").contains("Windows"))
52 | {
53 | PathTo7za = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
54 | PathTo7za = PathTo7za.substring(1,PathTo7za.length()-1);
55 | PathTo7za = '"' + PathTo7za.substring(0,(int) (PathTo7za.lastIndexOf("/"))).replace("%20", " ") + "/Library/7za.exe" + '"';
56 | process7za = new ProcessBuilder(PathTo7za + " " + cmd);
57 | }
58 | else
59 | {
60 | PathTo7za = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
61 | PathTo7za = PathTo7za.substring(0,PathTo7za.length()-1);
62 | PathTo7za = PathTo7za.substring(0,(int) (PathTo7za.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/7za";
63 | process7za = new ProcessBuilder("/bin/bash", "-c" , PathTo7za + " " + cmd);
64 | }
65 |
66 | isRunning = true;
67 | Process process = process7za.start();
68 |
69 | OutputStream out = process.getOutputStream();
70 | out.write("os get /value".getBytes());
71 | out.flush();
72 |
73 | InputStreamReader isr = new InputStreamReader(process.getInputStream());
74 | BufferedReader br = new BufferedReader(isr);
75 | String line;
76 |
77 | Console.consoleFFMPEG.append(System.lineSeparator());
78 |
79 | //Analyse des données
80 | do {
81 | line = br.readLine();
82 | Console.consoleFFMPEG.append(line + System.lineSeparator());
83 | } while (line != null);
84 |
85 | process.waitFor();
86 |
87 | Console.consoleFFMPEG.append(System.lineSeparator());
88 |
89 | isRunning = false;
90 |
91 | } catch (IOException | InterruptedException e) {
92 | System.out.println(cmd);
93 | error = true;
94 | }
95 |
96 | if (notUpdate)
97 | {
98 | if (error == false)
99 | {
100 | try {
101 | Desktop.getDesktop().open(new File(lblDestination1.getText()));
102 | } catch (IOException e1) {}
103 | }
104 | else
105 | FFMPEG.cancelled = true;
106 |
107 | SwingUtilities.invokeLater(new Runnable()
108 | {
109 | @Override
110 | public void run() {
111 | progressBar1.setIndeterminate(false);
112 | }
113 | });
114 |
115 | FFMPEG.enfOfFunction();
116 | FFMPEG.enableAll();
117 | }
118 |
119 | }
120 | });
121 | runProcess.start();
122 | }
123 |
124 | }
125 |
126 |
127 |
--------------------------------------------------------------------------------
/src/library/TSMUXER.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package library;
21 |
22 | import java.io.BufferedReader;
23 | import java.io.IOException;
24 | import java.io.InputStreamReader;
25 |
26 | import application.Console;
27 | import application.RenderQueue;
28 | import application.Shutter;
29 |
30 | public class TSMUXER extends Shutter {
31 |
32 | static int dureeTotale = 0;
33 | public static boolean error = false;
34 | public static boolean isRunning = false;
35 | public static Thread runProcess;
36 | public static Process process;
37 |
38 | public static void run(final String cmd) {
39 |
40 | Console.consoleFFMPEG.append(System.lineSeparator());
41 | Console.consoleTSMUXER.append(Shutter.language.getProperty("command") + " " + cmd);
42 |
43 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) && RenderQueue.btnStartRender.isEnabled())
44 | {
45 | RenderQueue.tableRow.addRow(new Object[] {lblCurrentEncoding.getText(), "tsMuxeR " + cmd, lblDestination1.getText()});
46 | RenderQueue.caseRunParallel.setSelected(false);
47 | RenderQueue.caseRunParallel.setEnabled(false);
48 | RenderQueue.parallelValue.setEnabled(false);
49 |
50 | lblCurrentEncoding.setText(Shutter.language.getProperty("lblEncodageEnCours"));
51 |
52 | if (caseChangeFolder1.isSelected() == false)
53 | lblDestination1.setText(Shutter.language.getProperty("sameAsSource"));
54 | }
55 | else
56 | {
57 | progressBar1.setValue(0);
58 | progressBar1.setMaximum(100);
59 |
60 | runProcess = new Thread(new Runnable() {
61 | @Override
62 | public void run() {
63 | try {
64 | String PathToDVDAUTHOR;
65 | ProcessBuilder processDVDAUTHOR;
66 | if (System.getProperty("os.name").contains("Windows"))
67 | {
68 | PathToDVDAUTHOR = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
69 | PathToDVDAUTHOR = PathToDVDAUTHOR.substring(1,PathToDVDAUTHOR.length()-1);
70 | PathToDVDAUTHOR = '"' + PathToDVDAUTHOR.substring(0,(int) (PathToDVDAUTHOR.lastIndexOf("/"))).replace("%20", " ") + "/Library/tsMuxeR.exe" + '"';
71 | processDVDAUTHOR = new ProcessBuilder(PathToDVDAUTHOR + " " + cmd);
72 | }
73 | else
74 | {
75 | PathToDVDAUTHOR = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath();
76 | PathToDVDAUTHOR = PathToDVDAUTHOR.substring(0,PathToDVDAUTHOR.length()-1);
77 | PathToDVDAUTHOR = PathToDVDAUTHOR.substring(0,(int) (PathToDVDAUTHOR.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/tsMuxeR";
78 | processDVDAUTHOR = new ProcessBuilder("/bin/bash", "-c" , PathToDVDAUTHOR + " " + cmd);
79 | }
80 |
81 | isRunning = true;
82 | process = processDVDAUTHOR.start();
83 |
84 | InputStreamReader isr = new InputStreamReader(process.getInputStream());
85 | BufferedReader br = new BufferedReader(isr);
86 |
87 | Console.consoleTSMUXER.append(System.lineSeparator());
88 |
89 | String line;
90 | do {
91 | line = br.readLine();
92 |
93 | Console.consoleTSMUXER.append(line + System.lineSeparator());
94 |
95 | if (line != null)
96 | {
97 | if (line.contains("%"))
98 | {
99 | String s[] = line.split("\\.");
100 | int value = Integer.parseInt(s[0]);
101 | progressBar1.setValue(value);
102 | }
103 | }
104 |
105 | } while (line != null);
106 | process.waitFor();
107 |
108 | Console.consoleTSMUXER.append(System.lineSeparator());
109 |
110 | } catch (IOException | InterruptedException e) {
111 | error = true;
112 | } finally {
113 | isRunning = false;
114 | }
115 |
116 | }
117 | });
118 | runProcess.start();
119 | }
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/src/settings/BitratesAdjustement.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package settings;
21 |
22 | import application.Shutter;
23 | import library.FFPROBE;
24 |
25 | public class BitratesAdjustement extends Shutter {
26 |
27 | public static boolean DVD2Pass;
28 | public static int DVDBitrate;
29 |
30 | public static String setPass(String outputFile) {
31 |
32 | if (case2pass.isSelected() || comboFonctions.getSelectedItem().toString().equals("DVD") && DVDBitrate <= 6000)
33 | {
34 | DVD2Pass = true;
35 | return " -pass 1 -passlogfile " + '"' + outputFile + '"';
36 | }
37 | else
38 | DVD2Pass = false;
39 |
40 | return "";
41 | }
42 |
43 | public static String setCrop(String filterComplex) {
44 |
45 | if (Shutter.caseEnableCrop.isSelected())
46 | {
47 | if (filterComplex != "")
48 | filterComplex += "[w];[w]";
49 |
50 | //IMPORTANT
51 | float imageRatio = 1.0f;
52 |
53 | int ow = FFPROBE.imageWidth;
54 |
55 | if (Shutter.comboFonctions.getSelectedItem().toString().equals("DVD") == false && Shutter.comboResolution.getSelectedItem().toString().equals(Shutter.language.getProperty("source")) == false)
56 | {
57 | if (comboResolution.getSelectedItem().toString().contains("AI"))
58 | {
59 | if (Shutter.comboResolution.getSelectedItem().toString().contains("2x"))
60 | {
61 | ow = (int) Math.round(ow * 2);
62 | }
63 | else
64 | {
65 | ow = (int) Math.round(ow * 4);
66 | }
67 | }
68 | else
69 | {
70 | String s[] = comboResolution.getSelectedItem().toString().split("x");
71 | ow = Integer.parseInt(s[0]);
72 | }
73 |
74 | imageRatio = (float) FFPROBE.imageWidth / ow;
75 | }
76 |
77 | int cropWidth = Math.round((float) Integer.parseInt(Shutter.textCropWidth.getText()) / imageRatio);
78 | int cropHeight = Math.round((float) Integer.parseInt(Shutter.textCropHeight.getText()) / imageRatio);
79 | int cropX = Math.round((float)Integer.parseInt(Shutter.textCropPosX.getText()) / imageRatio);
80 | int cropY = Math.round((float)Integer.parseInt(Shutter.textCropPosY.getText()) / imageRatio);
81 |
82 | filterComplex += "crop=" + cropWidth + ":" + cropHeight + ":" + cropX + ":" + cropY;
83 | }
84 |
85 | return filterComplex;
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/src/settings/Corrections.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package settings;
21 |
22 | import java.io.File;
23 |
24 | import application.Shutter;
25 | import library.FFMPEG;
26 | import library.FFPROBE;
27 |
28 | public class Corrections extends Shutter {
29 |
30 | public static File vidstab = null;
31 |
32 | public static String setStabilisation(String filterComplex, File file, String fichier, String concat) throws InterruptedException {
33 |
34 | if (Shutter.caseStabilisation.isSelected())
35 | {
36 | if (System.getProperty("os.name").contains("Windows"))
37 | vidstab = new File("vidstab.trf");
38 | else
39 | {
40 |
41 | vidstab = new File(Shutter.dirTemp + "vidstab.trf");
42 | }
43 |
44 | lblCurrentEncoding.setText(Shutter.language.getProperty("analyzeOf") + " " + fichier);
45 |
46 | //Analyse du fichier
47 | String cmd;
48 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux"))
49 | cmd = " -an -pix_fmt yuv420p -f yuv4mpegpipe - | PathToFFMPEG -i pipe:0 -vf vidstabdetect=result=" + vidstab.toString() + " -y -f null -";
50 | else
51 | cmd = " -an -pix_fmt yuv420p -f yuv4mpegpipe - | PathToFFMPEG -i pipe:0 -vf vidstabdetect=result=" + vidstab.toString() + " -y -f null -" + '"';
52 |
53 | FFMPEG.run(InputAndOutput.inPoint + concat + " -i " + '"' + file.toString() + '"' + InputAndOutput.outPoint + cmd);
54 |
55 | do
56 | {
57 | Thread.sleep(100);
58 | }
59 | while(FFMPEG.runProcess.isAlive());
60 |
61 | if (filterComplex != "") filterComplex += ",";
62 |
63 | filterComplex += "vidstabtransform=input=" + vidstab.toString();
64 |
65 | lblCurrentEncoding.setText(fichier);
66 | }
67 |
68 | return filterComplex;
69 | }
70 |
71 | public static String setDeflicker(String filterComplex) {
72 |
73 | if (Shutter.caseDeflicker.isSelected())
74 | {
75 | if (filterComplex != "") filterComplex += ",";
76 |
77 | filterComplex += "split[a][b];[b]setpts=PTS-STARTPTS+" + (1 / FFPROBE.currentFPS) + "/TB,format=rgba,colorchannelmixer=aa=0.5[deflicker];[a][deflicker]overlay=shortest=1";
78 | }
79 |
80 | return filterComplex;
81 | }
82 |
83 | public static String setDeband(String filterComplex) {
84 |
85 | if (Shutter.caseBanding.isSelected())
86 | {
87 | if (filterComplex != "") filterComplex += ",";
88 |
89 | filterComplex += "deband=r=32";
90 | }
91 |
92 | return filterComplex;
93 | }
94 |
95 | public static String setLimiter(String filterComplex) {
96 |
97 | if (Shutter.caseLimiter.isSelected())
98 | {
99 | if (filterComplex != "") filterComplex += ",";
100 |
101 | if (FFPROBE.imageDepth == 8)
102 | filterComplex += "limiter=16:235";
103 | else if (FFPROBE.imageDepth == 10)
104 | filterComplex += "limiter=64:940";
105 | else if (FFPROBE.imageDepth == 12)
106 | filterComplex += "limiter=256:3760";
107 | else if (FFPROBE.imageDepth == 16)
108 | filterComplex += "limiter=4096:60160";
109 | }
110 |
111 | return filterComplex;
112 | }
113 |
114 | public static String setDetails(String filterComplex) {
115 |
116 | if (Shutter.caseDetails.isSelected())
117 | {
118 | float value = (0 - (float) Shutter.sliderDetails.getValue() / 10);
119 |
120 | if (filterComplex != "") filterComplex += ",";
121 |
122 | filterComplex += "smartblur=1.0:" + value;
123 | }
124 |
125 | return filterComplex;
126 | }
127 |
128 | public static String setDenoiser(String filterComplex) {
129 |
130 | if (Shutter.caseDenoise.isSelected())
131 | {
132 | int value = Shutter.sliderDenoise.getValue();
133 |
134 | if (filterComplex != "") filterComplex += ",";
135 |
136 | filterComplex += "hqdn3d=" + value + ":" + value + ":" + value + ":" + value;
137 | }
138 |
139 | return filterComplex;
140 | }
141 |
142 | public static String setSmoothExposure(String filterComplex) {
143 |
144 | if (Shutter.caseSmoothExposure.isSelected())
145 | {
146 | int value = Shutter.sliderSmoothExposure.getValue();
147 |
148 | if (filterComplex != "") filterComplex += ",";
149 |
150 | filterComplex += "deflicker=s=" + Math.ceil((128 * value) / 100 + 1);
151 | }
152 |
153 | return filterComplex;
154 | }
155 |
156 | }
157 |
--------------------------------------------------------------------------------
/src/settings/Filter.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package settings;
21 |
22 | import java.io.File;
23 |
24 | import application.Shutter;
25 | import library.EXIFTOOL;
26 |
27 | public class Filter extends Shutter {
28 |
29 | public static boolean dateFilter(File file) throws InterruptedException {
30 |
31 | if (caseYear.isSelected() || caseMonth.isSelected() || caseDay.isSelected() || caseFrom.isSelected())
32 | {
33 | String date[] = EXIFTOOL.exifDate.split(":");
34 |
35 | if (caseYear.isSelected())
36 | {
37 | if (comboYear.getSelectedItem().toString().equals(date[0]) == false)
38 | return false;
39 | }
40 | if (caseMonth.isSelected())
41 | {
42 | if (comboMonth.getSelectedItem().toString().equals(date[1]) == false)
43 | return false;
44 | }
45 | if (caseDay.isSelected())
46 | {
47 | if (comboDay.getSelectedItem().toString().equals(date[2]) == false)
48 | return false;
49 | }
50 | if (caseFrom.isSelected())
51 | {
52 | String exif[] = EXIFTOOL.exifHours.split(":");
53 | String from[] = comboFrom.getSelectedItem().toString().split(":");
54 | String to[] = comboTo.getSelectedItem().toString().split(":");
55 |
56 | int eH = Integer.parseInt(exif[0]) * 60;
57 | int eM = Integer.parseInt(exif[1]);
58 | int exifTime = eH + eM;
59 |
60 | int fH = Integer.parseInt(from[0]) * 60;
61 | int fM = Integer.parseInt(from[1]);
62 | int fromTime = fH + fM;
63 |
64 | int tH = Integer.parseInt(to[0]) * 60;
65 | int tM = Integer.parseInt(to[1]);
66 | int toTime = tH + tM;
67 |
68 | if ((exifTime >= fromTime && exifTime <= toTime) == false)
69 | return false;
70 | }
71 | }
72 | return true;
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/settings/ImageSequence.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package settings;
21 |
22 | import application.Shutter;
23 | import application.VideoPlayer;
24 |
25 | public class ImageSequence extends Shutter {
26 |
27 | public static String setBlend(String filterComplex) {
28 |
29 | if ((grpImageSequence.isVisible() || VideoPlayer.fullscreenPlayer) && caseBlend.isSelected())
30 | {
31 | int value = sliderBlend.getValue();
32 | StringBuilder blend = new StringBuilder();
33 | for (int i = 0 ; i < value ; i++)
34 | {
35 | blend.append("tblend=all_mode=average,");
36 | }
37 |
38 | blend.append("setpts=" + (float) 25 / Float.parseFloat(caseSequenceFPS.getSelectedItem().toString().replace(",", ".")) + "*PTS");
39 |
40 | if (filterComplex != "") filterComplex += ",";
41 |
42 | filterComplex += blend;
43 | }
44 |
45 | return filterComplex;
46 | }
47 |
48 | public static String setMotionBlur(String filterComplex) {
49 |
50 | if ((grpImageSequence.isVisible() || VideoPlayer.fullscreenPlayer) && caseMotionBlur.isSelected())
51 | {
52 | float fps = Float.parseFloat(caseSequenceFPS.getSelectedItem().toString().replace(",", ".")) * 2;
53 |
54 | if (filterComplex != "") filterComplex += ",";
55 |
56 | filterComplex += "minterpolate=fps=" + fps + ",tblend=all_mode=average,framestep=2";
57 | }
58 |
59 | return filterComplex;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/settings/InputAndOutput.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package settings;
21 |
22 | import application.Shutter;
23 | import application.VideoPlayer;
24 | import library.FFPROBE;
25 |
26 | public class InputAndOutput extends Shutter {
27 |
28 | public static String inPoint = "";
29 | public static String outPoint = "";
30 |
31 | public static void getInputAndOutput(boolean setInputAndOutput) {
32 |
33 | if (setInputAndOutput)
34 | {
35 | float timeIn = (Integer.parseInt(VideoPlayer.caseInH.getText()) * 3600 + Integer.parseInt(VideoPlayer.caseInM.getText()) * 60 + Integer.parseInt(VideoPlayer.caseInS.getText())) * FFPROBE.currentFPS + Integer.parseInt(VideoPlayer.caseInF.getText());
36 |
37 | //NTSC timecode
38 | timeIn = Timecode.getNonDropFrameTC(timeIn);
39 |
40 | if (timeIn > 0.0f)
41 | {
42 | inPoint = " -ss " + (long) (timeIn * VideoPlayer.inputFramerateMS) + "ms";
43 | }
44 | else
45 | inPoint = "";
46 |
47 | if (VideoPlayer.playerOutMark < VideoPlayer.waveformContainer.getWidth() - 2 && caseEnableSequence.isSelected() == false)
48 | {
49 | String frames[] = VideoPlayer.lblDuration.getText().split(" ");
50 |
51 | if ((comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionPicture")) || comboFonctions.getSelectedItem().toString().contains("JPEG")) && caseCreateSequence.isSelected())
52 | {
53 | float outputFPS = FFPROBE.currentFPS / Float.parseFloat(comboInterpret.getSelectedItem().toString().replace(",", "."));
54 |
55 | outPoint = " -frames:v " + (int) Math.ceil(Integer.parseInt(frames[frames.length - 2]) / outputFPS);
56 | }
57 | else if (FFPROBE.audioOnly || (caseConform.isSelected() && comboConform.getSelectedItem().toString().equals(language.getProperty("conformBySpeed")) == false)
58 | || comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionCut"))
59 | || comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionRewrap"))
60 | || comboFonctions.getSelectedItem().toString().equals("VP8")
61 | || comboFonctions.getSelectedItem().toString().equals("VP9")
62 | || comboFonctions.getSelectedItem().toString().contains("XDCAM")
63 | || comboFonctions.getSelectedItem().toString().equals("AVC-Intra 100")
64 | || comboFonctions.getSelectedItem().toString().equals("XAVC")) //Issue for audio, libvpx & added mute track
65 | {
66 | outPoint = " -t " + (int) Math.floor(Integer.parseInt(frames[frames.length - 2]) * ((float) 1000 / FFPROBE.currentFPS)) + "ms";
67 | }
68 | else
69 | {
70 | outPoint = " -frames:v " + Integer.parseInt(frames[frames.length - 2]);
71 | }
72 | }
73 | else
74 | outPoint = "";
75 |
76 | if (VideoPlayer.comboMode.getSelectedItem().toString().equals(language.getProperty("splitMode")))
77 | {
78 | outPoint += " -f segment -reset_timestamps 1 -segment_time " + VideoPlayer.splitValue.getText();
79 | }
80 | }
81 | else
82 | {
83 | inPoint = "";
84 | outPoint = "";
85 | }
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/src/settings/Timecode.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package settings;
21 |
22 | import java.io.File;
23 | import java.io.IOException;
24 | import java.nio.file.Files;
25 | import java.nio.file.Paths;
26 | import java.nio.file.attribute.BasicFileAttributes;
27 | import java.time.Instant;
28 | import java.time.ZoneId;
29 | import java.time.format.DateTimeFormatter;
30 |
31 | import application.Shutter;
32 | import application.VideoPlayer;
33 | import library.FFPROBE;
34 |
35 | public class Timecode extends Shutter {
36 |
37 | public static String setTimecode(File file) {
38 |
39 | String dropFrame = ":";
40 | if (isDropFrame())
41 | {
42 | dropFrame = ";";
43 | }
44 |
45 | if (Shutter.caseConform.isSelected())
46 | {
47 | if (Shutter.comboFPS.getSelectedItem().toString().equals("29,97") || Shutter.comboFPS.getSelectedItem().toString().equals("59,94"))
48 | {
49 | dropFrame = ";";
50 | }
51 | else
52 | dropFrame = ":";
53 | }
54 |
55 | if (caseGenerateFromDate.isSelected())
56 | {
57 | try {
58 |
59 | BasicFileAttributes attrs = Files.readAttributes(Paths.get(file.toString()), BasicFileAttributes.class);
60 | Instant creationTime = attrs.creationTime().toInstant();
61 | String date = DateTimeFormatter.ofPattern("HH:mm:ss").withZone(ZoneId.systemDefault()).format(creationTime);
62 |
63 | String s[] = date.split(":");
64 |
65 | return " -timecode " + '"' + s[0] + ":" + s[1] + ":" + s[2] + dropFrame + "00" + '"';
66 |
67 | } catch (IOException e) {}
68 | }
69 | else if (caseSetTimecode.isSelected())
70 | {
71 | return " -timecode " + '"' + TCset1.getText() + ":" + TCset2.getText() + ":" + TCset3.getText() + dropFrame + TCset4.getText() + '"';
72 | }
73 | else if (FFPROBE.timecode1 != "")
74 | {
75 | return " -timecode " + '"' + FFPROBE.timecode1 + ":" + FFPROBE.timecode2 + ":" + FFPROBE.timecode3 + dropFrame + FFPROBE.timecode4 + '"';
76 | }
77 |
78 | return "";
79 | }
80 |
81 | public static boolean isDropFrame() {
82 |
83 | if (FFPROBE.dropFrameTC.equals(":") == false && (FFPROBE.currentFPS == 29.97f || FFPROBE.currentFPS == 59.94f))
84 | {
85 | return true;
86 | }
87 | else
88 | return false;
89 | }
90 |
91 | public static boolean isNonDropFrame() {
92 |
93 | if (FFPROBE.dropFrameTC.equals(":") && (FFPROBE.currentFPS == 29.97f || FFPROBE.currentFPS == 59.94f) || FFPROBE.currentFPS == 23.98f)
94 | {
95 | return true;
96 | }
97 | else
98 | return false;
99 | }
100 |
101 | public static float setNonDropFrameTC(float currentFrame) {
102 |
103 | //NTSC framerates && non drop frame timecode => remove a frame to reach round framerate
104 | if (isNonDropFrame() && currentFrame > 0)
105 | {
106 | float currentTime = VideoPlayer.playerCurrentFrame * VideoPlayer.inputFramerateMS;
107 |
108 | if (FFPROBE.currentFPS == 23.98f)
109 | {
110 | currentFrame -= (currentTime * 0.024 / 1000) - 1;
111 | }
112 | if (FFPROBE.currentFPS == 29.97f)
113 | {
114 | currentFrame -= (currentTime * 0.03 / 1000) - 1;
115 | }
116 | else if (FFPROBE.currentFPS == 59.94f)
117 | {
118 | currentFrame -= (currentTime * 0.06 / 1000) - 1;
119 | }
120 | }
121 |
122 | return currentFrame;
123 | }
124 |
125 | public static float getNonDropFrameTC(float currentFrame) {
126 |
127 | //Allows to set the current seeking values
128 | if (isNonDropFrame())
129 | {
130 | float currentTime = currentFrame * VideoPlayer.inputFramerateMS;
131 |
132 | if (FFPROBE.currentFPS == 23.98f)
133 | {
134 | currentFrame += (currentTime * 0.024 / 1000);
135 | }
136 | else if (FFPROBE.currentFPS == 29.97f)
137 | {
138 | currentFrame += (currentTime * 0.03 / 1000);
139 | }
140 | else if (FFPROBE.currentFPS == 59.94f)
141 | {
142 | currentFrame += (currentTime * 0.06 / 1000);
143 | }
144 |
145 | return (float) Math.floor(currentFrame);
146 | }
147 |
148 | return currentFrame;
149 | }
150 |
151 | }
152 |
--------------------------------------------------------------------------------
/src/settings/Transitions.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************************
2 | * Copyright (C) 2025 PACIFICO PAUL
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation; either version 2 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License along
15 | * with this program; if not, write to the Free Software Foundation, Inc.,
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | *
18 | ********************************************************************************************/
19 |
20 | package settings;
21 |
22 | import application.Shutter;
23 | import application.Settings;
24 | import application.VideoPlayer;
25 | import library.FFPROBE;
26 |
27 | public class Transitions extends Shutter {
28 |
29 | public static String setVideoFade(String filterComplex, boolean isVideoPlayer) {
30 |
31 | if (grpTransitions.isEnabled() || VideoPlayer.fullscreenPlayer)
32 | {
33 | //Fade-in
34 | if (Shutter.caseVideoFadeIn.isSelected())
35 | {
36 | if (filterComplex != "") filterComplex += ",";
37 |
38 | long videoInValue = (long) (Integer.parseInt(Shutter.spinnerVideoFadeIn.getText()) * ((float) 1000 / FFPROBE.currentFPS));
39 |
40 | String color = "black";
41 | if (Shutter.lblFadeInColor.getText().equals(language.getProperty("white")))
42 | color = "white";
43 |
44 | String videoFade = "fade=in:st=0ms:d=" + videoInValue + "ms:color=" + color;
45 |
46 | if (isVideoPlayer)
47 | {
48 | if (VideoPlayer.cursorWaveform.getX() == VideoPlayer.playerInMark || VideoPlayer.playTransition)
49 | {
50 | filterComplex += videoFade;
51 | }
52 | else
53 | filterComplex += "null";
54 | }
55 | else
56 | filterComplex += videoFade;
57 | }
58 |
59 | //Fade-out
60 | if (Shutter.caseVideoFadeOut.isSelected())
61 | {
62 | if (filterComplex != "") filterComplex += ",";
63 |
64 | long videoOutValue = (long) (Integer.parseInt(Shutter.spinnerVideoFadeOut.getText()) * ((float) 1000 / FFPROBE.currentFPS));
65 | long videoStart = (long) FFPROBE.totalLength - videoOutValue;
66 |
67 | if (caseEnableSequence.isSelected())
68 | {
69 | videoOutValue = (long) (Integer.parseInt(Shutter.spinnerVideoFadeOut.getText()) * ((float) 1000 / Integer.parseInt(caseSequenceFPS.getSelectedItem().toString().replace(",", "."))));
70 | videoStart = (long) ((float) ((float) 1000 / Integer.parseInt(caseSequenceFPS.getSelectedItem().toString().replace(",", "."))) * liste.getSize()) - videoOutValue;
71 | }
72 | else if (Settings.btnSetBab.isSelected())
73 | {
74 | videoOutValue = (long) (Integer.parseInt(Shutter.spinnerVideoFadeOut.getText()) * ((float) 1000 / FFPROBE.currentFPS));
75 | videoStart = (long) FunctionUtils.mergeDuration - videoOutValue;
76 | }
77 | else
78 | {
79 | long totalIn = (long) (Integer.parseInt(VideoPlayer.caseInH.getText()) * 3600000 + Integer.parseInt(VideoPlayer.caseInM.getText()) * 60000 + Integer.parseInt(VideoPlayer.caseInS.getText()) * 1000 + Integer.parseInt(VideoPlayer.caseInF.getText()) * (1000 / FFPROBE.currentFPS));
80 | long totalOut = FFPROBE.totalLength;
81 |
82 | if (VideoPlayer.playerOutMark < VideoPlayer.waveformContainer.getWidth() - 2)
83 | {
84 | totalOut = (long) (Integer.parseInt(VideoPlayer.caseOutH.getText()) * 3600000 + Integer.parseInt(VideoPlayer.caseOutM.getText()) * 60000 + Integer.parseInt(VideoPlayer.caseOutS.getText()) * 1000 + Integer.parseInt(VideoPlayer.caseOutF.getText()) * (1000 / FFPROBE.currentFPS));
85 | }
86 |
87 | if (isVideoPlayer)
88 | {
89 | totalIn = (long) Math.floor(VideoPlayer.playerCurrentFrame * ((float) 1000 / FFPROBE.currentFPS));
90 | }
91 |
92 | if (VideoPlayer.comboMode.getSelectedItem().toString().contentEquals(Shutter.language.getProperty("cutUpper")))
93 | {
94 | videoStart = (totalOut - totalIn) - videoOutValue;
95 | }
96 | else //Remove mode
97 | videoStart = FFPROBE.totalLength - (totalOut - totalIn) - videoOutValue;
98 | }
99 |
100 | String color = "black";
101 | if (Shutter.lblFadeOutColor.getText().equals(language.getProperty("white")))
102 | color = "white";
103 |
104 | String videoFade = "fade=out:st=" + videoStart + "ms:d=" + videoOutValue + "ms:color=" + color;
105 |
106 | if (videoStart > 0)
107 | {
108 | filterComplex += videoFade;
109 | }
110 | else
111 | filterComplex += "null";
112 | }
113 | }
114 |
115 | return filterComplex;
116 | }
117 |
118 | public static String setAudioFadeIn(boolean isVideoPlayer) {
119 |
120 | String audioFilter = "";
121 |
122 | //Fade-in
123 | if ((grpTransitions.isEnabled() || VideoPlayer.fullscreenPlayer) && Shutter.caseAudioFadeIn.isSelected())
124 | {
125 | long audioInValue = (long) (Integer.parseInt(Shutter.spinnerAudioFadeIn.getText()) * ((float) 1000 / FFPROBE.currentFPS));
126 |
127 | if (isVideoPlayer)
128 | {
129 | if (VideoPlayer.cursorWaveform.getX() == VideoPlayer.playerInMark || VideoPlayer.playTransition)
130 | {
131 | audioFilter += "afade=in:st=0ms:d=" + audioInValue + "ms";
132 | }
133 | else
134 | audioFilter += "anull";
135 | }
136 | else
137 | audioFilter += "afade=in:st=0ms:d=" + audioInValue + "ms";
138 | }
139 |
140 | return audioFilter;
141 | }
142 |
143 | public static String setAudioFadeOut(boolean isVideoPlayer) {
144 |
145 | String audioFilter = "";
146 |
147 | //Fade-out
148 | if ((grpTransitions.isEnabled() || VideoPlayer.fullscreenPlayer) && Shutter.caseAudioFadeOut.isSelected())
149 | {
150 | long audioOutValue = (long) (Integer.parseInt(Shutter.spinnerAudioFadeOut.getText()) * ((float) 1000 / FFPROBE.currentFPS));
151 | long audioStart = (long) FFPROBE.totalLength - audioOutValue;
152 |
153 | if (Settings.btnSetBab.isSelected())
154 | {
155 | audioOutValue = (long) (Integer.parseInt(Shutter.spinnerVideoFadeOut.getText()) * ((float) 1000 / FFPROBE.currentFPS));
156 | audioStart = (long) FunctionUtils.mergeDuration - audioOutValue;
157 | }
158 | else
159 | {
160 | long totalIn = (long) (Integer.parseInt(VideoPlayer.caseInH.getText()) * 3600000 + Integer.parseInt(VideoPlayer.caseInM.getText()) * 60000 + Integer.parseInt(VideoPlayer.caseInS.getText()) * 1000 + Integer.parseInt(VideoPlayer.caseInF.getText()) * (1000 / FFPROBE.currentFPS));
161 | long totalOut = FFPROBE.totalLength;
162 |
163 | if (VideoPlayer.playerOutMark < VideoPlayer.waveformContainer.getWidth() - 2)
164 | {
165 | totalOut = (long) (Integer.parseInt(VideoPlayer.caseOutH.getText()) * 3600000 + Integer.parseInt(VideoPlayer.caseOutM.getText()) * 60000 + Integer.parseInt(VideoPlayer.caseOutS.getText()) * 1000 + Integer.parseInt(VideoPlayer.caseOutF.getText()) * (1000 / FFPROBE.currentFPS));
166 | }
167 |
168 | if (isVideoPlayer)
169 | {
170 | totalIn = (long) Math.floor(VideoPlayer.playerCurrentFrame * ((float) 1000 / FFPROBE.currentFPS));
171 | }
172 |
173 | if (VideoPlayer.comboMode.getSelectedItem().toString().contentEquals(Shutter.language.getProperty("cutUpper")))
174 | {
175 | audioStart = (totalOut - totalIn) - audioOutValue;
176 | }
177 | else //Remove mode
178 | audioStart = FFPROBE.totalLength - (totalOut - totalIn) - audioOutValue;
179 | }
180 |
181 | if (audioStart > 0)
182 | {
183 | audioFilter += "afade=out:st=" + audioStart + "ms:d=" + audioOutValue + "ms";
184 | }
185 | else
186 | audioFilter += "anull";
187 | }
188 |
189 | return audioFilter;
190 | }
191 |
192 | public static String setAudioSpeed() {
193 |
194 | String audioFilter = "";
195 |
196 | if (grpTransitions.isEnabled() || VideoPlayer.fullscreenPlayer || grpAudio.isVisible() || grpSetAudio.isVisible())
197 | {
198 | //Audio Speed
199 | if (caseConform.isSelected() && (comboConform.getSelectedItem().toString().equals(language.getProperty("conformBySpeed"))
200 | || comboConform.getSelectedItem().toString().equals(language.getProperty("conformByReverse")))
201 | || grpImageSequence.isVisible() && caseEnableSequence.isSelected())
202 | {
203 | float newFPS = Float.parseFloat((comboFPS.getSelectedItem().toString()).replace(",", "."));
204 |
205 | if (caseEnableSequence.isSelected())
206 | {
207 | newFPS = Float.parseFloat((caseSequenceFPS.getSelectedItem().toString()).replace(",", "."));
208 | }
209 |
210 | float value = (float) (newFPS / FFPROBE.currentFPS);
211 |
212 | if (value >= 0.5f && value <= 2.0f)
213 | {
214 | audioFilter = "atempo=" + value;
215 | }
216 | else if (value <= 0.5f && value >= 0.25f)
217 | {
218 | audioFilter = "atempo=" + ((float) value * 2);
219 | audioFilter += ",";
220 | audioFilter += "atempo=" + ((float) value * 2);
221 | }
222 | else if (value >= 2.0f && value <= 4.0f)
223 | {
224 | audioFilter = "atempo=" + ((float) value / 2);
225 | audioFilter += ",";
226 | audioFilter += "atempo=" + ((float) value / 2);
227 | }
228 | else
229 | {
230 | return " -an";
231 | }
232 | }
233 | else if (caseConform.isSelected() && comboConform.getSelectedItem().toString().equals(language.getProperty("conformBySlowMotion")))
234 | {
235 | return " -an";
236 | }
237 | else if (caseConvertAudioFramerate.isSelected())
238 | {
239 | float AudioFPSIn = Float.parseFloat((comboAudioIn.getSelectedItem().toString()).replace(",", "."));
240 | float AudioFPSOut = Float.parseFloat((comboAudioOut.getSelectedItem().toString()).replace(",", "."));
241 | float value = (float) (AudioFPSOut / AudioFPSIn);
242 |
243 | audioFilter += "atempo=" + value;
244 | }
245 | }
246 |
247 | return audioFilter;
248 | }
249 |
250 | }
251 |
--------------------------------------------------------------------------------