/* * */ package application.tools; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.attribute.BasicFileAttributes; import java.time.LocalDate; import java.time.LocalTime; import java.util.Arrays; import java.util.HashSet; import java.util.Locale; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.UnsupportedAudioFileException; import org.apache.commons.io.FilenameUtils; import com.mpatric.mp3agic.ID3v2; import com.mpatric.mp3agic.InvalidDataException; import com.mpatric.mp3agic.Mp3File; import com.mpatric.mp3agic.UnsupportedTagException; import application.Main; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.stage.Screen; import xplayer.model.AudioType; /** * Provides useful methods for retrieving informations. * * @author GOXR3PLUS */ public final class InfoTool { /** Logger */ public static final Logger logger = Logger.getLogger(InfoTool.class.getName()); /** WebSite url */ public static final String WEBSITE = "http://goxr3plus.co.nf"; /** XR3Player Tutorials */ public static final String TUTORIALS = "https://www.youtube.com/playlist?list=PL-xqaiRUr_iRKDkpFWPfSRFmJvHSr1VJI"; /** The Constant images. */ public static final String IMAGES = "/image/"; /** The Constant styLes. */ public static final String STYLES = "/style/"; /** The Constant applicationCss. */ public static final String APPLICATIONCSS = "application.css"; /** The Constant sounds. */ //public static final String sounds = "/sound/" /** The Constant fxmls. */ public static final String FXMLS = "/fxml/"; /** The Constant radioStationsTable. */ public static final String RADIO_STATIONS_DATABASE_TABLE_NAME = "RADIOSTATIONS"; /** The Constant playedImage. */ public static final Image playedImage = getImageFromResourcesFolder("played.png"); /** Database folder name <b>with out</b> separator [example:XR3DataBase] */ private static final String DATABASE_FOLDER_NAME = "XR3DataBase"; /** The name of the application user [example:Alexander] */ private static String USERNAME; //-----------Lists of accepted extensions //Java 8 Way // private static final Set<String> ACCEPTED_AUDIO_EXTENSIONS = Stream.of("mp3", "wav", "ogg") // .collect(Collectors.toCollection(HashSet::new)) // private static final Set<String> ACCEPTED_VIDEO_EXTENSIONS = Stream.of("mp4", "flv") // .collect(Collectors.toCollection(HashSet::new)) // private static final Set<String> ACCEPTED_IMAGE_EXTENSIONS = Stream.of("png", "jpg", "jpeg") // .collect(Collectors.toCollection(HashSet::new)) //Java 7 Way and back private static final Set<String> ACCEPTED_AUDIO_EXTENSIONS = new HashSet<>(Arrays.asList("mp3", "wav", "ogg")); private static final Set<String> ACCEPTED_VIDEO_EXTENSIONS = new HashSet<>(Arrays.asList("mp4", "flv")); private static final Set<String> ACCEPTED_IMAGE_EXTENSIONS = new HashSet<>(Arrays.asList("png", "jpg", "jpeg", "gif")); // ------------------------------------Important------------------------------------------------------------------- /** The name of the application user [example:Alexander] */ public static String getUserName() { return USERNAME; } /** The name of the application user [example:Alexander] */ public static void setUserName(String uSERNAME) { USERNAME = uSERNAME; } //---- public static String getImagesFolderAbsolutePathPlain() { return getUserFolderAbsolutePathWithSeparator() + "Images"; } public static String getImagesFolderAbsolutePathWithSeparator() { return getImagesFolderAbsolutePathPlain() + File.separator; } //---- public static String getXPlayersImageFolderAbsolutePathPlain() { return getImagesFolderAbsolutePathWithSeparator() + "XPlayersImages"; } public static String getXPlayersImageFolderAbsolutePathWithSeparator() { return getImagesFolderAbsolutePathPlain() + File.separator; } //---- /** * @return Database folder name <b>with out</b> separator * [example:XR3DataBase] */ public static String getDatabaseFolderName() { return DATABASE_FOLDER_NAME; } /** @return Database folder name with separator [example:XR3DataBase/] */ public static String getDatabaseFolderNameWithSeparator() { return getDatabaseFolderName() + File.separator; } //---- /** * @return The current absolute path to the database <b>PARENT</b> folder * with separator[example:C:/Users/] */ public static String getAbsoluteDatabaseParentFolderPathWithSeparator() { return InfoTool.getBasePathForClass(InfoTool.class); } /** * @return The current absolute path to the database <b>PARENT</b> folder * without separator[example:C:/Users] */ public static String getAbsoluteDatabaseParentFolderPathPlain() { String parentName = getAbsoluteDatabaseParentFolderPathWithSeparator(); return parentName.substring(0, parentName.length() - 1); } //---- /** * @return The absolute path to the database folder<b>with out</b> separator * [example:C:/Users/XR3DataBase] */ public static String getAbsoluteDatabasePathPlain() { return getAbsoluteDatabaseParentFolderPathWithSeparator() + getDatabaseFolderName(); } /** * @return The absolute database path with separator * [example:C:/Users/XR3DataBase/] */ public static String getAbsoluteDatabasePathWithSeparator() { return getAbsoluteDatabasePathPlain() + File.separator; } //---- public static String getUserFolderAbsolutePathPlain() { return getAbsoluteDatabasePathWithSeparator() + getUserName(); } public static String getUserFolderAbsolutePathWithSeparator() { return getUserFolderAbsolutePathPlain() + File.separator; } //---- /** * @return XR3Database signature File , i am using this so the user can use * any name for the exported xr3database zip and has not too worry */ public static File getDatabaseSignatureFile() { return new File(getAbsoluteDatabasePathWithSeparator() + "xr3Original.sig"); } // -------------------------------------------------------------------------------------------------------------- /** * Private Constructor , we don't want instances of this class */ private InfoTool() { } /** * Gets the screen width. * * @return The screen <b>Width</b> based on the <b> bounds </b> of the * Screen. */ public static double getScreenWidth() { return Screen.getPrimary().getBounds().getWidth(); } /** * Gets the screen height. * * @return The screen <b>Height</b> based on the <b> bounds </b> of the * Screen. */ public static double getScreenHeight() { return Screen.getPrimary().getBounds().getHeight(); } /** * Gets the visual screen width. * * @return The screen <b>Width</b> based on the <b>visual bounds</b> of the * Screen.These bounds account for objects in the native windowing * system * such as task bars and menu bars. These bounds are contained by * Screen.bounds. */ public static double getVisualScreenWidth() { return Screen.getPrimary().getVisualBounds().getWidth(); } /** * Gets the visual screen height. * * @return The screen <b>Height</b> based on the <b>visual bounds</b> of the * Screen.These bounds account for objects in the native windowing * system such as task bars and menu bars. These bounds are * contained by Screen.bounds. */ public static double getVisualScreenHeight() { return Screen.getPrimary().getVisualBounds().getHeight(); } /** * Returns the absolute path of the current directory in which the given * class file is. * * @param classs * * @return The absolute path of the current directory in which the * class file is. <b>[it ends with File.Separator!!]</b> * @author GOXR3PLUS[StackOverFlow user] + bachden [StackOverFlow user] */ public static final String getBasePathForClass(Class<?> classs) { // Local variables File file; String basePath = ""; boolean failed = false; // Let's give a first try try { file = new File(classs.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); basePath = ( file.isFile() || file.getPath().endsWith(".jar") || file.getPath().endsWith(".zip") ) ? file.getParent() : file.getPath(); } catch (URISyntaxException ex) { failed = true; Logger.getLogger(classs.getName()).log(Level.WARNING, "Cannot firgue out base path for class with way (1): ", ex); } // The above failed? if (failed) try { file = new File(classs.getClassLoader().getResource("").toURI().getPath()); basePath = file.getAbsolutePath(); // the below is for testing purposes... // starts with File.separator? // String l = local.replaceFirst("[" + File.separator + // "/\\\\]", "") } catch (URISyntaxException ex) { Logger.getLogger(classs.getName()).log(Level.WARNING, "Cannot firgue out base path for class with way (2): ", ex); } // fix to run inside Eclipse if (basePath.endsWith(File.separator + "lib") || basePath.endsWith(File.separator + "bin") || basePath.endsWith("bin" + File.separator) || basePath.endsWith("lib" + File.separator)) { basePath = basePath.substring(0, basePath.length() - 4); } // fix to run inside NetBeans if (basePath.endsWith(File.separator + "build" + File.separator + "classes")) { basePath = basePath.substring(0, basePath.length() - 14); } // end fix if (!basePath.endsWith(File.separator)) basePath += File.separator; return basePath; } /** * Checks if a web site is reachable using ping command. * * @param host * the host * @return <b> true </b> if Connected on Internet,<b> false </b> if not. */ public static boolean isReachableByPing(String host) { try { // Start a new Process Process process = Runtime.getRuntime().exec("ping -" + ( System.getProperty("os.name").toLowerCase().startsWith("windows") ? "n" : "c" ) + " 1 " + host); //Wait for it to finish process.waitFor(); //Check the return value return process.exitValue() == 0; } catch (Exception ex) { Logger.getLogger(Main.class.getName()).log(Level.INFO, null, ex); return false; } } /** * Checks for Application Internet connection using Socket and * InetSocketAddress I combine this method with reachableByPing to check if * the * Operating System is connected to the Internet and this method to check if * the application can be connected to Internet, * * Because the admin my have blocked internet connection for this Java * application. * * @param host * the host * @param port * the port * @return <b> true </b> if Connected on Internet,<b> false </b> if not. */ @Deprecated public static boolean isReachableUsingSocket(String host , int port) { InetSocketAddress addr = new InetSocketAddress(host, port); //Check if it can be connected try (Socket sock = new Socket()) { sock.connect(addr, 2000); return true; } catch (IOException ex) { Logger.getLogger(Main.class.getName()).log(Level.INFO, null, ex); return false; } } /** * Return the imageView of mp3File in requested Width and Height. * * @param absolutePath * The File absolute path * @param width * the width * @param height * the height * @return an Image */ public static Image getMp3AlbumImage(String absolutePath , int width , int height) { if ("mp3".equals(getFileExtension(absolutePath))) try { Mp3File song = new Mp3File(absolutePath); if (song.hasId3v2Tag()) { // has id3v2 tag? ID3v2 id3v2Tag = song.getId3v2Tag(); if (id3v2Tag.getAlbumImage() != null) // image? return ( width == -1 && height == -1 ) ? new Image(new ByteArrayInputStream(id3v2Tag.getAlbumImage())) : new Image(new ByteArrayInputStream(id3v2Tag.getAlbumImage()), width, height, false, true); } } catch (UnsupportedTagException | InvalidDataException | IOException ex) { logger.log(Level.WARNING, "Can't get Album Image", ex); } return null;// fatal error here } /** * Returns the creation time. The creation time is the time that the file * was created. * * <p> * If the file system implementation does not support a time stamp to * indicate the time when the file was created then this method returns an * implementation specific default value, typically the * {@link #lastModifiedTime() last-modified-time} or a {@code FileTime} * representing the * epoch (1970-01-01T00:00:00Z). * * @param absolutePath * The File absolute path * @return The File Creation Date in String Format */ public static String getFileCreationDate(String absolutePath) { File file = new File(absolutePath); //exists? if (!file.exists()) return "file missing"; BasicFileAttributes attr; try { attr = Files.readAttributes(file.toPath(), BasicFileAttributes.class); } catch (IOException ex) { logger.log(Level.WARNING, ex.getMessage(), ex); return "error"; } return ( attr.creationTime() + "" ).replaceAll("T|Z", " "); } /** * Returns the time of last modification. * * <p> * If the file system implementation does not support a time stamp to * indicate the time of last modification then this method returns an * implementation specific default value, typically a {@code FileTime} * representing the epoch (1970-01-01T00:00:00Z). * * @param absolutePath * The File absolute path * @return The File Creation Date in String Format */ public static String getFileLastModifiedDate(String absolutePath) { File file = new File(absolutePath); //exists? if (!file.exists()) return "file missing"; BasicFileAttributes attr; try { attr = Files.readAttributes(file.toPath(), BasicFileAttributes.class); } catch (IOException ex) { logger.log(Level.WARNING, ex.getMessage(), ex); return "error"; } return ( attr.lastModifiedTime() + "" ).replaceAll("T|Z", " "); } /** * Returns the title of the file for example if file name is * <b>(club.mp3)</b> it returns <b>(club)</b> * * @param absolutePath * The File absolute path * @return the File title */ public static String getFileTitle(String absolutePath) { return FilenameUtils.getBaseName(absolutePath); } /** * Returns the name of the file for example if file path is <b>(C:/Give me * more/no no/media.ogg)</b> it returns <b>(media.ogg)</b> * * @param absolutePath * the path * @return the File title+extension */ public static String getFileName(String absolutePath) { return FilenameUtils.getName(absolutePath); } /** * Returns the extension of file(without (.)) for example * <b>(ai.mp3)->(mp3)</b> and to lowercase (Mp3 -> mp3) * * @param absolutePath * The File absolute path * @return the File extension */ public static String getFileExtension(String absolutePath) { return FilenameUtils.getExtension(absolutePath).toLowerCase(); // int i = path.lastIndexOf('.'); // characters contained before (.) // // if the name is not empty // if (i > 0 && i < path.length() - 1) // return path.substring(i + 1).toLowerCase() // // return null } /** * 1)Checks if this file is <b>audio</b><br> * 2)If is supported by the application. * * @param name * the name * @return true if the type is supported or else false * [[SuppressWarningsSpartan]] */ public static boolean isAudioSupported(String name) { String extension = getFileExtension(name); return extension != null && ACCEPTED_AUDIO_EXTENSIONS.contains(extension); } /** * 1)Checks if this file is <b>video</b><br> * 2)If is supported by the application. * * @param name * the name * @return true if the type is supported or else false * [[SuppressWarningsSpartan]] */ public static boolean isVideoSupported(String name) { String extension = getFileExtension(name); return extension != null && ACCEPTED_VIDEO_EXTENSIONS.contains(extension); } /** * 1)Checks if this file is <b>video</b><br> * 2)If is supported by the application. * * @param name * the name * @return true if the file is an Image [[SuppressWarningsSpartan]] */ public static boolean isImage(String name) { String extension = getFileExtension(name); return extension != null && ACCEPTED_IMAGE_EXTENSIONS.contains(extension); } /** * Use this method to retrieve an image from the resources of the * application. * * @param imageName * the image name * @return Returns an image which is already into the resources folder of * the application */ public static Image getImageFromResourcesFolder(String imageName) { return new Image(InfoTool.class.getResourceAsStream(IMAGES + imageName)); } /** * Use this method to retrieve an image from the resources of the * application. * * @param imageName * the image name * @return Returns an image which is already into the resources folder of * the application */ public static Image getImageFromCurrentFolder(String folderName , String imageName) { return new Image(InfoTool.class.getResourceAsStream("/" + folderName + "/" + imageName)); } /** * Use this method to retrieve an ImageView from the resources of the * application. * * @param imageName * the image name * @return Returns an ImageView using method * getImageFromResourcesFolder(String * imageName); */ public static ImageView getImageViewFromResourcesFolder(String imageName) { return new ImageView(new Image(InfoTool.class.getResourceAsStream(IMAGES + imageName))); } /** * Returns the current hour in format hh:mm:ss. * * @return the LocalTime */ public static String getLocalTime() { return LocalTime.now() + ""; } /** * Returns the Local Date in format YYYY-MM-DD. * * @return the local date in format YYYY-MM-DD */ public static String getCurrentDate() { return LocalDate.now() + ""; } /** * Returns a String with a fixed number of letters. * * @param s * the string * @param letters * the letters * @return A substring(or the current given string) based on the letters * that have to be cut */ public static String getMinString(String s , int letters) { return s.length() < letters ? s : s.substring(0, letters) + "..."; } /** * This method determines the duration of given data. * * @param input * The name of the input * @param audioType * URL, FILE, INPUTSTREAM, UNKOWN; * @return Returns the duration of URL/FILE/INPUTSTREAM in milliseconds */ public static long durationInMilliseconds(String input , AudioType audioType) { return audioType == AudioType.FILE ? durationInMilliseconds_Part2(new File(input)) : ( audioType == AudioType.URL || audioType == AudioType.INPUTSTREAM || audioType == AudioType.UNKNOWN ) ? -1 : -1; } /** * I am using this method to get mp3 duration in milliseconds * * @return Length of Mp3 song in milliseconds */ private static long tryWithMp3Agic(File file) { long milliseconds = -1; //try with mp3agic try { Mp3File song = new Mp3File(file); milliseconds = (int) song.getLengthInMilliseconds(); // System.out.println("Bitrate : " + song.getBitrate() + " Seconds: " + lengthInMilliseconds); return milliseconds; } catch (UnsupportedTagException | InvalidDataException | IOException ex1) { ex1.printStackTrace(); } return milliseconds; } /** * Used by method durationInMilliseconds() to get file duration. * * @param file * the file * @return the int */ private static long durationInMilliseconds_Part2(File file) { long milliseconds = -1; // exists? if (file.exists() && file.length() != 0) { // extension? String extension = InfoTool.getFileExtension(file.getName()); // MP3? if ("mp3".equals(extension)) { try { milliseconds = (int) ( (Long) AudioSystem.getAudioFileFormat(file).properties().get("duration") / 1000 ); //Get the result of mp3agic if the duration is bigger than 6 minutes // if (milliseconds / 1000 > 60 * 9) { // System.out.println("Entered.."); // milliseconds = tryWithMp3Agic(file); // } } catch (IOException | UnsupportedAudioFileException ex) { System.out.println(file.getAbsolutePath()); logger.log(Level.WARNING, ex.getMessage(), ex); //Try with mp3agic } //} } // WAVE || OGG? else if ("ogg".equals(extension) || "wav".equals(extension)) { try (AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file)) { AudioFormat format = audioInputStream.getFormat(); milliseconds = (int) ( file.length() / ( format.getFrameSize() * (int) format.getFrameRate() ) ) * 1000; } catch (IOException | UnsupportedAudioFileException ex) { System.out.println(file.getAbsolutePath()); logger.log(Level.WARNING, ex.getMessage(), ex); } } } // System.out.println("Passed with error") return milliseconds < 0 ? -1 : milliseconds; } /** * Returns the time of Audio to seconds * * @param name * the name * @param type * <br> * 1->URL <br> * 2->FILE <br> * 3->INPUTSTREAM * @return time in milliseconds */ public static int durationInSeconds(String name , AudioType type) { long time = durationInMilliseconds(name, type); return (int) ( ( time == 0 || time == -1 ) ? time : time / 1000 ); // Long microseconds = (Long)AudioSystem.getAudioFileFormat(new File(audio)).properties().get("duration") int mili = (int)(microseconds / 1000L); // int sec = milli / 1000 % 60; // int min = milli / 1000 / 60; } /** * /** Returns the time in format <b> %02d:%02d:%02d if( minutes >60 )</b> * or %02d:%02d. * * @param ms * The milliseconds * @return The Time edited in format <b> %02d:%02d:%02d if( minutes >60 * )</b> or %02d:%02d. * */ public static String millisecondsToTime(long ms) { int millis = (int) ( ( ms % 1000 ) / 100 ); // int seconds = (int) ((ms / 1000) % 60); // int minutes = (int) ((ms / (1000 * 60)) % 60); // int hours = (int) ((ms / (1000 * 60 * 60)) % 24); // if (minutes > 60) // return String.format("%02d:%02d:%02d.%d", hours, minutes, seconds, millis); // else // return String.format("%02d:%02d.%d", minutes, seconds, millis); return String.format(".%d", millis); } /** * Returns the time in format <b> %02d:%02d:%02d if( minutes >60 )</b> or * %02dsec if (seconds<60) %02d:%02d. * * @param seconds * the seconds * @return the time edited in format <b> %02d:%02d:%02d if( minutes >60 * )</b> or %02d:%02d. */ public static String getTimeEdited(int seconds) { return seconds < 60 ? String.format("%02ds", seconds % 60) // duration < 1 minute : ( seconds / 60 ) / 60 <= 0 ? String.format("%02dm:%02d", ( seconds / 60 ) % 60, seconds % 60) // duration < 1 hour : String.format("%02dh:%02dm:%02d", ( seconds / 60 ) / 60, ( seconds / 60 ) % 60, seconds % 60); //else } /** * Returns the time in format %02d:%02d. * * @param seconds * the seconds * @return the time edited on hours */ public static String getTimeEditedOnHours(int seconds) { return String.format("%02d:%02d", seconds / 60, seconds % 60); } /** * Gets the file size edited in format "x MiB , y KiB" * * @param file * the file * @return <b> a String representing the file size in MB and kB </b> */ public static String getFileSizeEdited(File file) { //file exists? if (!file.exists()) return "file missing"; //Get the size in bytes double bytes = file.length(); int kilobytes = (int) ( bytes / 1024 ) , megabytes = kilobytes / 1024; if (kilobytes < 1024) return kilobytes + " KiB"; else if (kilobytes > 1024) return megabytes + " MiB + " + ( kilobytes - ( megabytes * 1024 ) ) + " KiB"; return "error"; } /** * Returns a number with more than 3 digits [ Example 1000 as 1.000] with * dots every 3 digits * * @param number * @return A number with more than 3 digits [ Example 1000 as 1.000] with * dots every 3 digits */ public static String getNumberWithDots(int number) { return String.format(Locale.US, "%,d", number).replace(",", "."); } }