diff --git a/pom.xml b/pom.xml
index a5d136bca..f0795de2b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,8 +3,22 @@
4.0.0
com.tonikelope
MegaBasterd
- 7.61
+ 7.62
jar
+
+
+ olivier-ayache-xuggler
+ https://dl.cloudsmith.io/public/olivier-ayache/xuggler/maven/
+
+ true
+ always
+
+
+ true
+ always
+
+
+
org.xerial
@@ -39,6 +53,11 @@
jackson-databind
2.12.6.1
+
+ xuggle
+ xuggle-xuggler-server-all
+ 5.7.0-SNAPSHOT
+
UTF-8
diff --git a/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.form b/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.form
index b3c8000ff..ffc10c15c 100644
--- a/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.form
+++ b/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.form
@@ -285,7 +285,6 @@
-
diff --git a/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.java b/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.java
index fd3451b3b..9e6eb71d0 100644
--- a/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.java
+++ b/src/main/java/com/tonikelope/megabasterd/FileGrabberDialog.java
@@ -330,7 +330,6 @@ public class FileGrabberDialog extends javax.swing.JDialog {
});
upload_log_checkbox.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N
- upload_log_checkbox.setSelected(true);
upload_log_checkbox.setText("Enable log file");
upload_log_checkbox.setDoubleBuffered(true);
upload_log_checkbox.setEnabled(false);
diff --git a/src/main/java/com/tonikelope/megabasterd/LabelTranslatorSingleton.java b/src/main/java/com/tonikelope/megabasterd/LabelTranslatorSingleton.java
index 924c756e6..cb3407d89 100644
--- a/src/main/java/com/tonikelope/megabasterd/LabelTranslatorSingleton.java
+++ b/src/main/java/com/tonikelope/megabasterd/LabelTranslatorSingleton.java
@@ -891,6 +891,7 @@ public class LabelTranslatorSingleton {
_addTranslation("Execute this command when MEGA download limit is reached:", "Ejecutar este comando cuando se alcance el límite de descarga de MEGA:");
_addTranslation("Use this proxy list (instead of the one included in MegaBasterd) Format is [*]IP:PORT[@user_b64:password_b64]", "Usar esta lista de proxys (en vez de la incluida en MegaBasterd) El formato es [*]IP:PUERTO[@usuario_b64:password_b64]");
_addTranslation("Waiting for completion handler ... ***DO NOT EXIT MEGABASTERD NOW***", "Esperando manejador de finalización ... ***NO CIERRES MEGABASTERD EN ESTE MOMENTO***");
+ _addTranslation("Creating and uploading thumbnails ... ***DO NOT EXIT MEGABASTERD NOW***", "Creando y subiendo thumbnails ... ***NO CIERRES MEGABASTERD EN ESTE MOMENTO***");
_addTranslation("Finishing calculating CBC-MAC code (this could take a while) ... ***DO NOT EXIT MEGABASTERD NOW***", "Terminando de calcular código CBC-MAC (esto podría llevar tiempo) ... ***NO CIERRES MEGABASTERD EN ESTE MOMENTO***");
_addTranslation("Split content in different uploads", "Separar contenido en diferentes subidas");
_addTranslation("Merge content in the same upload", "Juntar todo en la misma subida");
diff --git a/src/main/java/com/tonikelope/megabasterd/MainPanel.java b/src/main/java/com/tonikelope/megabasterd/MainPanel.java
index b6bd97e6a..d288c2de0 100644
--- a/src/main/java/com/tonikelope/megabasterd/MainPanel.java
+++ b/src/main/java/com/tonikelope/megabasterd/MainPanel.java
@@ -67,7 +67,7 @@ import javax.swing.UIManager;
*/
public final class MainPanel {
- public static final String VERSION = "7.61";
+ public static final String VERSION = "7.62";
public static final boolean FORCE_SMART_PROXY = false; //TRUE FOR DEBUGING SMART PROXY
public static final int THROTTLE_SLICE_SIZE = 16 * 1024;
public static final int DEFAULT_BYTE_BUFFER_SIZE = 16 * 1024;
diff --git a/src/main/java/com/tonikelope/megabasterd/MegaAPI.java b/src/main/java/com/tonikelope/megabasterd/MegaAPI.java
index d0d0110e8..fee057954 100644
--- a/src/main/java/com/tonikelope/megabasterd/MegaAPI.java
+++ b/src/main/java/com/tonikelope/megabasterd/MegaAPI.java
@@ -17,12 +17,15 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.io.Serializable;
import java.math.BigInteger;
+import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -634,6 +637,19 @@ public class MegaAPI implements Serializable {
return file_data;
}
+ private byte[] _encThumbAttr(byte[] attr_byte, byte[] key) {
+
+ try {
+
+ return aes_cbc_encrypt_pkcs7(attr_byte, key, AES_ZERO_IV);
+
+ } catch (Exception ex) {
+ LOG.log(Level.SEVERE, ex.getMessage());
+ }
+
+ return null;
+ }
+
private byte[] _encAttr(String attr, byte[] key) {
byte[] ret = null;
@@ -714,6 +730,115 @@ public class MegaAPI implements Serializable {
return ul_url;
}
+ public String uploadThumbnails(Upload upload, String node_handle, String filename0, String filename1) throws MegaAPIException {
+
+ String[] ul_url = new String[2];
+
+ String[] hash = new String[2];
+
+ try {
+
+ File[] files = new File[2];
+
+ files[0] = new File(filename0);
+
+ byte[][] file_bytes = new byte[2][];
+
+ file_bytes[0] = _encThumbAttr(Files.readAllBytes(files[0].toPath()), upload.getByte_file_key());
+
+ files[1] = new File(filename1);
+
+ file_bytes[1] = _encThumbAttr(Files.readAllBytes(files[1].toPath()), upload.getByte_file_key());
+
+ String request = "[{\"a\":\"ufa\", \"s\":" + String.valueOf(file_bytes[0].length) + ", \"ssl\":1}, {\"a\":\"ufa\", \"s\":" + String.valueOf(file_bytes[1].length) + ", \"ssl\":1}]";
+
+ System.out.println(request);
+ URL url_api = new URL(API_URL + "/cs?id=" + String.valueOf(_seqno) + (_sid != null ? "&sid=" + _sid : "") + (API_KEY != null ? "&ak=" + API_KEY : ""));
+
+ String res = _rawRequest(request, url_api);
+
+ System.out.println(res);
+
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ HashMap[] res_map = objectMapper.readValue(res, HashMap[].class);
+
+ ul_url[0] = (String) res_map[0].get("p");
+
+ ul_url[1] = (String) res_map[1].get("p");
+
+ int h = 0;
+
+ for (String u : ul_url) {
+
+ URL url = new URL(u);
+
+ HttpURLConnection con;
+
+ con = (HttpURLConnection) url.openConnection();
+
+ con.setConnectTimeout(Transference.HTTP_CONNECT_TIMEOUT);
+
+ con.setReadTimeout(Transference.HTTP_READ_TIMEOUT);
+
+ con.setRequestMethod("POST");
+
+ con.setDoOutput(true);
+
+ con.setUseCaches(false);
+
+ con.setRequestProperty("User-Agent", MainPanel.DEFAULT_USER_AGENT);
+
+ byte[] buffer = new byte[8192];
+
+ int reads;
+
+ try ( OutputStream out = new ThrottledOutputStream(con.getOutputStream(), upload.getMain_panel().getStream_supervisor())) {
+
+ out.write(file_bytes[h]);
+ }
+
+ try ( InputStream is = con.getInputStream(); ByteArrayOutputStream byte_res = new ByteArrayOutputStream()) {
+
+ while ((reads = is.read(buffer)) != -1) {
+ byte_res.write(buffer, 0, reads);
+ }
+
+ hash[h] = MiscTools.Bin2UrlBASE64(byte_res.toByteArray());
+
+ System.out.println(hash[h]);
+ }
+
+ h++;
+ }
+
+ request = "[{\"a\":\"pfa\", \"fa\":\"0*" + hash[0] + "/1*" + hash[1] + "\", \"n\":\"" + node_handle + "\"}]";
+
+ url_api = new URL(API_URL + "/cs?id=" + String.valueOf(_seqno) + (_sid != null ? "&sid=" + _sid : "") + (API_KEY != null ? "&ak=" + API_KEY : ""));
+
+ res = _rawRequest(request, url_api);
+
+ System.out.println(request);
+
+ objectMapper = new ObjectMapper();
+
+ String[] resp = objectMapper.readValue(res, String[].class);
+
+ System.out.println((String) resp[0]);
+
+ return (String) resp[0];
+
+ } catch (MegaAPIException mae) {
+
+ throw mae;
+
+ } catch (Exception ex) {
+ LOG.log(Level.SEVERE, ex.getMessage());
+ }
+
+ return "";
+ }
+
public HashMap finishUploadFile(String fbasename, int[] ul_key, int[] fkey, int[] meta_mac, String completion_handle, String mega_parent, byte[] master_key, String root_node, byte[] share_key) throws MegaAPIException {
HashMap[] res_map = null;
diff --git a/src/main/java/com/tonikelope/megabasterd/MiscTools.java b/src/main/java/com/tonikelope/megabasterd/MiscTools.java
index f128beb6f..9aee06d7d 100644
--- a/src/main/java/com/tonikelope/megabasterd/MiscTools.java
+++ b/src/main/java/com/tonikelope/megabasterd/MiscTools.java
@@ -17,12 +17,15 @@ import java.awt.Dialog;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Frame;
+import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
+import java.awt.Image;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
+import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -126,6 +129,28 @@ public class MiscTools {
return getFechaHoraActual(format);
}
+ public static boolean isVideoFile(Path path) {
+
+ try {
+ return Files.probeContentType(path).startsWith("video/");
+ } catch (IOException ex) {
+ Logger.getLogger(MiscTools.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ return false;
+ }
+
+ public static boolean isImageFile(Path path) {
+
+ try {
+ return Files.probeContentType(path).startsWith("image/");
+ } catch (IOException ex) {
+ Logger.getLogger(MiscTools.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ return false;
+ }
+
public static String getFechaHoraActual(String format) {
Date currentDate = new Date(System.currentTimeMillis());
@@ -241,6 +266,23 @@ public class MiscTools {
return bigi;
}
+ public static BufferedImage toBufferedImage(Image img) {
+ if (img instanceof BufferedImage) {
+ return (BufferedImage) img;
+ }
+
+ // Create a buffered image with transparency
+ BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
+
+ // Draw the image on to the buffered image
+ Graphics2D bGr = bimage.createGraphics();
+ bGr.drawImage(img, 0, 0, null);
+ bGr.dispose();
+
+ // Return the buffered image
+ return bimage;
+ }
+
public static String genID(int length) {
String pos = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
diff --git a/src/main/java/com/tonikelope/megabasterd/SettingsDialog.java b/src/main/java/com/tonikelope/megabasterd/SettingsDialog.java
index 65aa01cb0..c0fe823ac 100644
--- a/src/main/java/com/tonikelope/megabasterd/SettingsDialog.java
+++ b/src/main/java/com/tonikelope/megabasterd/SettingsDialog.java
@@ -2049,7 +2049,7 @@ public class SettingsDialog extends javax.swing.JDialog {
boolean error_2FA = false;
- if (ma.check2FA(email)) {
+ if (!_main_panel.getMega_active_accounts().containsKey(email) && ma.check2FA(email)) {
Get2FACode dialog = new Get2FACode((Frame) getParent(), true, email, _main_panel);
@@ -2065,37 +2065,40 @@ public class SettingsDialog extends javax.swing.JDialog {
}
if (!error_2FA) {
- ma.login(email, pass, pincode);
+ if (!_main_panel.getMega_active_accounts().containsKey(email)) {
+ ma.login(email, pass, pincode);
- ByteArrayOutputStream bs = new ByteArrayOutputStream();
+ ByteArrayOutputStream bs = new ByteArrayOutputStream();
- try ( ObjectOutputStream os = new ObjectOutputStream(bs)) {
- os.writeObject(ma);
+ try ( ObjectOutputStream os = new ObjectOutputStream(bs)) {
+ os.writeObject(ma);
+ }
+
+ if (_main_panel.getMaster_pass() != null) {
+
+ DBTools.insertMegaSession(email, CryptTools.aes_cbc_encrypt_pkcs7(bs.toByteArray(), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV), true);
+
+ } else {
+
+ DBTools.insertMegaSession(email, bs.toByteArray(), false);
+ }
+
+ _main_panel.getMega_active_accounts().put(email, ma);
+
+ String password = pass, password_aes = Bin2BASE64(i32a2bin(ma.getPassword_aes())), user_hash = ma.getUser_hash();
+
+ if (_main_panel.getMaster_pass_hash() != null) {
+
+ password = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(pass.getBytes("UTF-8"), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV));
+
+ password_aes = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(i32a2bin(ma.getPassword_aes()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV));
+
+ user_hash = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(UrlBASE642Bin(ma.getUser_hash()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV));
+ }
+
+ DBTools.insertMegaAccount(email, password, password_aes, user_hash);
}
- if (_main_panel.getMaster_pass() != null) {
-
- DBTools.insertMegaSession(email, CryptTools.aes_cbc_encrypt_pkcs7(bs.toByteArray(), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV), true);
-
- } else {
-
- DBTools.insertMegaSession(email, bs.toByteArray(), false);
- }
-
- _main_panel.getMega_active_accounts().put(email, ma);
-
- String password = pass, password_aes = Bin2BASE64(i32a2bin(ma.getPassword_aes())), user_hash = ma.getUser_hash();
-
- if (_main_panel.getMaster_pass_hash() != null) {
-
- password = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(pass.getBytes("UTF-8"), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV));
-
- password_aes = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(i32a2bin(ma.getPassword_aes()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV));
-
- user_hash = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(UrlBASE642Bin(ma.getUser_hash()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV));
- }
-
- DBTools.insertMegaAccount(email, password, password_aes, user_hash);
} else {
email_error.add(email);
}
@@ -2133,7 +2136,7 @@ public class SettingsDialog extends javax.swing.JDialog {
boolean error_2FA = false;
- if (ma.check2FA(email)) {
+ if (!_main_panel.getMega_active_accounts().containsKey(email) && ma.check2FA(email)) {
Get2FACode dialog = new Get2FACode((Frame) getParent(), true, email, _main_panel);
@@ -2149,40 +2152,41 @@ public class SettingsDialog extends javax.swing.JDialog {
}
if (!error_2FA) {
+ if (!_main_panel.getMega_active_accounts().containsKey(email)) {
+ ma.login(email, pass, pincode);
- ma.login(email, pass, pincode);
+ ByteArrayOutputStream bs = new ByteArrayOutputStream();
- ByteArrayOutputStream bs = new ByteArrayOutputStream();
+ try ( ObjectOutputStream os = new ObjectOutputStream(bs)) {
+ os.writeObject(ma);
+ }
- try ( ObjectOutputStream os = new ObjectOutputStream(bs)) {
- os.writeObject(ma);
+ if (_main_panel.getMaster_pass() != null) {
+
+ DBTools.insertMegaSession(email, CryptTools.aes_cbc_encrypt_pkcs7(bs.toByteArray(), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV), true);
+
+ } else {
+
+ DBTools.insertMegaSession(email, bs.toByteArray(), false);
+ }
+
+ _main_panel.getMega_active_accounts().put(email, ma);
+
+ password = pass;
+
+ String password_aes = Bin2BASE64(i32a2bin(ma.getPassword_aes())), user_hash = ma.getUser_hash();
+
+ if (_main_panel.getMaster_pass() != null) {
+
+ password = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(pass.getBytes("UTF-8"), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV));
+
+ password_aes = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(i32a2bin(ma.getPassword_aes()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV));
+
+ user_hash = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(UrlBASE642Bin(ma.getUser_hash()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV));
+ }
+
+ DBTools.insertMegaAccount(email, password, password_aes, user_hash);
}
-
- if (_main_panel.getMaster_pass() != null) {
-
- DBTools.insertMegaSession(email, CryptTools.aes_cbc_encrypt_pkcs7(bs.toByteArray(), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV), true);
-
- } else {
-
- DBTools.insertMegaSession(email, bs.toByteArray(), false);
- }
-
- _main_panel.getMega_active_accounts().put(email, ma);
-
- password = pass;
-
- String password_aes = Bin2BASE64(i32a2bin(ma.getPassword_aes())), user_hash = ma.getUser_hash();
-
- if (_main_panel.getMaster_pass() != null) {
-
- password = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(pass.getBytes("UTF-8"), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV));
-
- password_aes = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(i32a2bin(ma.getPassword_aes()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV));
-
- user_hash = Bin2BASE64(CryptTools.aes_cbc_encrypt_pkcs7(UrlBASE642Bin(ma.getUser_hash()), _main_panel.getMaster_pass(), CryptTools.AES_ZERO_IV));
- }
-
- DBTools.insertMegaAccount(email, password, password_aes, user_hash);
} else {
email_error.add(email);
}
diff --git a/src/main/java/com/tonikelope/megabasterd/Thumbnailer.java b/src/main/java/com/tonikelope/megabasterd/Thumbnailer.java
new file mode 100644
index 000000000..8595636ff
--- /dev/null
+++ b/src/main/java/com/tonikelope/megabasterd/Thumbnailer.java
@@ -0,0 +1,289 @@
+package com.tonikelope.megabasterd;
+
+import com.xuggle.xuggler.Global;
+import com.xuggle.xuggler.ICodec;
+import com.xuggle.xuggler.IContainer;
+import com.xuggle.xuggler.IPacket;
+import com.xuggle.xuggler.IPixelFormat;
+import com.xuggle.xuggler.IStream;
+import com.xuggle.xuggler.IStreamCoder;
+import com.xuggle.xuggler.IVideoPicture;
+import com.xuggle.xuggler.IVideoResampler;
+import com.xuggle.xuggler.Utils;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.imageio.ImageIO;
+
+public class Thumbnailer {
+
+ public Thumbnailer() {
+ }
+
+ public static final int IMAGE_THUMB_SIZE = 250;
+
+ /**
+ * The number of seconds between frames.
+ */
+ public static final double SECONDS_BETWEEN_FRAMES = 10;
+
+ /**
+ * The number of nano-seconds between frames.
+ */
+ public static final long NANO_SECONDS_BETWEEN_FRAMES
+ = (long) (Global.DEFAULT_PTS_PER_SECOND * SECONDS_BETWEEN_FRAMES);
+
+ /**
+ * Time of last frame write.
+ */
+ private long mLastPtsWrite = Global.NO_PTS;
+
+ private int conta_frames = 0;
+
+ /**
+ * Write the video frame out to a PNG file every once and a while. The files
+ * are written out to the system's temporary directory.
+ *
+ * @param picture the video frame which contains the time stamp.
+ * @param image the buffered image to write out
+ */
+ private String processFrame(IVideoPicture picture, BufferedImage image) {
+ try {
+ // if uninitialized, backdate mLastPtsWrite so we get the very
+ // first frame
+
+ if (mLastPtsWrite == Global.NO_PTS) {
+ mLastPtsWrite = picture.getPts() - NANO_SECONDS_BETWEEN_FRAMES;
+ }
+
+ // if it's time to write the next frame
+ if (picture.getPts() - mLastPtsWrite >= NANO_SECONDS_BETWEEN_FRAMES) {
+ // Make a temorary file name
+
+ if (conta_frames == 1) {
+
+ File file = File.createTempFile("megabasterd_thumbnail_" + MiscTools.genID(20), ".jpg");
+
+ // write out JPG
+ ImageIO.write(image, "jpg", file);
+
+ // indicate file written
+ //double seconds = ((double) picture.getPts()) / Global.DEFAULT_PTS_PER_SECOND;
+ //System.out.printf("at elapsed time of %6.3f seconds wrote: %s\n", seconds, file);
+ conta_frames++;
+
+ return file.getAbsolutePath();
+ }
+
+ conta_frames++;
+
+ // update last write time
+ mLastPtsWrite += NANO_SECONDS_BETWEEN_FRAMES;
+
+ return null;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ public String createImageThumbnail(String filename) {
+ try {
+
+ BufferedImage imagen_original = ImageIO.read(new File(filename));
+
+ if (imagen_original.getHeight() <= IMAGE_THUMB_SIZE) {
+ return filename;
+ }
+
+ int h = IMAGE_THUMB_SIZE;
+
+ int w = Math.round((((float) imagen_original.getWidth()) * h) / imagen_original.getHeight());
+
+ BufferedImage newImage = new BufferedImage(w, h, imagen_original.getType());
+
+ Graphics2D g = newImage.createGraphics();
+
+ g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+
+ g.drawImage(imagen_original, 0, 0, w, h, null);
+
+ g.dispose();
+
+ File file = File.createTempFile("megabasterd_thumbnail_" + MiscTools.genID(20), ".png");
+
+ ImageIO.write(newImage, "png", file);
+
+ return file.getAbsolutePath();
+
+ } catch (IOException ex) {
+ Logger.getLogger(Thumbnailer.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ return null;
+ }
+
+ /**
+ * Takes a media container (file) as the first argument, opens it, reads
+ * through the file and captures video frames periodically as specified by
+ * SECONDS_BETWEEN_FRAMES. The frames are written as PNG files into the
+ * system's temporary directory.
+ *
+ * @param args must contain one string which represents a filename
+ */
+ @SuppressWarnings("deprecation")
+ public String createVideoThumbnail(String filename) {
+
+ // make sure that we can actually convert video pixel formats
+ if (!IVideoResampler.isSupported(
+ IVideoResampler.Feature.FEATURE_COLORSPACECONVERSION)) {
+ throw new RuntimeException(
+ "you must install the GPL version of Xuggler (with IVideoResampler"
+ + " support) for this demo to work");
+ }
+
+ // create a Xuggler container object
+ IContainer container = IContainer.make();
+
+ // open up the container
+ if (container.open(filename, IContainer.Type.READ, null) < 0) {
+ throw new IllegalArgumentException("could not open file: " + filename);
+ }
+
+ // query how many streams the call to open found
+ int numStreams = container.getNumStreams();
+
+ // and iterate through the streams to find the first video stream
+ int videoStreamId = -1;
+ IStreamCoder videoCoder = null;
+ for (int i = 0; i < numStreams; i++) {
+ // find the stream object
+
+ IStream stream = container.getStream(i);
+
+ // get the pre-configured decoder that can decode this stream;
+ IStreamCoder coder = stream.getStreamCoder();
+
+ if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) {
+ videoStreamId = i;
+ videoCoder = coder;
+ break;
+ }
+ }
+
+ if (videoStreamId == -1) {
+ throw new RuntimeException("could not find video stream in container: " + filename);
+ }
+
+ // Now we have found the video stream in this file. Let's open up
+ // our decoder so it can do work
+ if (videoCoder.open() < 0) {
+ throw new RuntimeException(
+ "could not open video decoder for container: " + filename);
+ }
+
+ IVideoResampler resampler = null;
+ if (videoCoder.getPixelType() != IPixelFormat.Type.BGR24) {
+ // if this stream is not in BGR24, we're going to need to
+ // convert it. The VideoResampler does that for us.
+
+ resampler = IVideoResampler.make(
+ videoCoder.getWidth(), videoCoder.getHeight(), IPixelFormat.Type.BGR24,
+ videoCoder.getWidth(), videoCoder.getHeight(), videoCoder.getPixelType());
+ if (resampler == null) {
+ throw new RuntimeException(
+ "could not create color space resampler for: " + filename);
+ }
+ }
+
+ // Now, we start walking through the container looking at each packet.
+ IPacket packet = IPacket.make();
+
+ String frame_file = null;
+
+ while (container.readNextPacket(packet) >= 0 && conta_frames < 2) {
+
+ // Now we have a packet, let's see if it belongs to our video strea
+ if (packet.getStreamIndex() == videoStreamId) {
+ // We allocate a new picture to get the data out of Xuggle
+
+ IVideoPicture picture = IVideoPicture.make(videoCoder.getPixelType(),
+ videoCoder.getWidth(), videoCoder.getHeight());
+
+ int offset = 0;
+
+ while (offset < packet.getSize()) {
+ // Now, we decode the video, checking for any errors.
+
+ int bytesDecoded = videoCoder.decodeVideo(picture, packet, offset);
+ if (bytesDecoded < 0) {
+ throw new RuntimeException("got error decoding video in: " + filename);
+ }
+ offset += bytesDecoded;
+
+ // Some decoders will consume data in a packet, but will not
+ // be able to construct a full video picture yet. Therefore
+ // you should always check if you got a complete picture from
+ // the decode.
+ if (picture.isComplete()) {
+ IVideoPicture newPic = picture;
+
+ // If the resampler is not null, it means we didn't get the
+ // video in BGR24 format and need to convert it into BGR24
+ // format.
+ if (resampler != null) {
+ // we must resample
+ newPic = IVideoPicture.make(
+ resampler.getOutputPixelFormat(), picture.getWidth(),
+ picture.getHeight());
+ if (resampler.resample(newPic, picture) < 0) {
+ throw new RuntimeException(
+ "could not resample video from: " + filename);
+ }
+ }
+
+ if (newPic.getPixelType() != IPixelFormat.Type.BGR24) {
+ throw new RuntimeException(
+ "could not decode video as BGR 24 bit data in: " + filename);
+ }
+
+ // convert the BGR24 to an Java buffered image
+ BufferedImage javaImage = Utils.videoPictureToImage(newPic);
+
+ // process the video frame
+ frame_file = processFrame(newPic, javaImage);
+
+ }
+
+ }
+ } else {
+ // This packet isn't part of our video stream, so we just
+ // silently drop it.
+ do {
+ } while (false);
+ }
+
+ }
+
+ // Technically since we're exiting anyway, these will be cleaned up
+ // by the garbage collector... but because we're nice people and
+ // want to be invited places for Christmas, we're going to show how
+ // to clean up.
+ if (videoCoder != null) {
+ videoCoder.close();
+ videoCoder = null;
+ }
+ if (container != null) {
+ container.close();
+ container = null;
+ }
+
+ return frame_file;
+ }
+}
diff --git a/src/main/java/com/tonikelope/megabasterd/Upload.java b/src/main/java/com/tonikelope/megabasterd/Upload.java
index 4e87c5062..146551caf 100644
--- a/src/main/java/com/tonikelope/megabasterd/Upload.java
+++ b/src/main/java/com/tonikelope/megabasterd/Upload.java
@@ -16,6 +16,8 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import static java.lang.Integer.MAX_VALUE;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -929,40 +931,79 @@ public class Upload implements Transference, Runnable, SecureSingleThreadNotifia
} while (upload_res == null && !_exit);
if (upload_res != null && !_exit) {
- List files = (List) upload_res.get("f");
-
- _fid = (String) ((Map) files.get(0)).get("h");
-
try {
+ List files = (List) upload_res.get("f");
- _file_link = _ma.getPublicFileLink(_fid, i32a2bin(node_key));
+ _fid = (String) ((Map) files.get(0)).get("h");
- MiscTools.GUIRun(() -> {
- getView().getFile_link_button().setEnabled(true);
- });
+ if (MiscTools.isVideoFile(Paths.get(_file_name))) {
- } catch (Exception ex) {
- LOG.log(Level.SEVERE, ex.getMessage());
- }
+ getView().printStatusNormal("Creating and uploading thumbnails ... ***DO NOT EXIT MEGABASTERD NOW***");
- getView().printStatusOK(LabelTranslatorSingleton.getInstance().translate("File successfully uploaded! (") + _ma.getFull_email() + ")");
+ Thumbnailer thumbnailer = new Thumbnailer();
- synchronized (this.getMain_panel().getUpload_manager().getLog_file_lock()) {
+ String thumb_file = thumbnailer.createVideoThumbnail(_file_name);
- File upload_log = new File(MainPanel.MEGABASTERD_HOME_DIR + "/megabasterd_upload_" + _root_node + ".log");
+ if (thumb_file != null) {
- if (upload_log.exists()) {
+ _ma.uploadThumbnails(this, _fid, thumb_file, thumb_file);
- FileWriter fr;
- try {
- fr = new FileWriter(upload_log, true);
- fr.write("[" + MiscTools.getFechaHoraActual() + "] " + _file_name + " [" + MiscTools.formatBytes(_file_size) + "] " + _file_link + "\n");
- fr.close();
- } catch (IOException ex) {
- Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, ex.getMessage());
+ Files.deleteIfExists(Paths.get(thumb_file));
+ }
+
+ } else if (MiscTools.isImageFile(Paths.get(_file_name))) {
+
+ getView().printStatusNormal("Creating and uploading thumbnails ... ***DO NOT EXIT MEGABASTERD NOW***");
+
+ Thumbnailer thumbnailer = new Thumbnailer();
+
+ String thumb_file = thumbnailer.createImageThumbnail(_file_name);
+
+ if (thumb_file != null) {
+
+ _ma.uploadThumbnails(this, _fid, thumb_file, thumb_file);
+
+ Files.deleteIfExists(Paths.get(thumb_file));
}
}
+
+ try {
+
+ _file_link = _ma.getPublicFileLink(_fid, i32a2bin(node_key));
+
+ MiscTools.GUIRun(() -> {
+ getView().getFile_link_button().setEnabled(true);
+ });
+
+ } catch (Exception ex) {
+ LOG.log(Level.SEVERE, ex.getMessage());
+ }
+
+ getView().printStatusOK(LabelTranslatorSingleton.getInstance().translate("File successfully uploaded! (") + _ma.getFull_email() + ")");
+
+ synchronized (this.getMain_panel().getUpload_manager().getLog_file_lock()) {
+
+ File upload_log = new File(MainPanel.MEGABASTERD_HOME_DIR + "/megabasterd_upload_" + _root_node + ".log");
+
+ if (upload_log.exists()) {
+
+ FileWriter fr;
+ try {
+ fr = new FileWriter(upload_log, true);
+ fr.write("[" + MiscTools.getFechaHoraActual() + "] " + _file_name + " [" + MiscTools.formatBytes(_file_size) + "] " + _file_link + "\n");
+ fr.close();
+ } catch (IOException ex) {
+ Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, ex.getMessage());
+ }
+
+ }
+ }
+
+ } catch (MegaAPIException ex) {
+ Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (IOException ex) {
+ Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (_status_error != null) {
diff --git a/src/main/resources/images/mbasterd_screen.png b/src/main/resources/images/mbasterd_screen.png
index 243991d96..dd5809362 100644
Binary files a/src/main/resources/images/mbasterd_screen.png and b/src/main/resources/images/mbasterd_screen.png differ