|
@@ -1,481 +1,481 @@
|
|
|
-/*
|
|
|
- * Copyright (C) 2015 iZc
|
|
|
- *
|
|
|
- * This program is free software: you can redistribute it and/or modify
|
|
|
- * it under the terms of the GNU General Public License as published by
|
|
|
- * the Free Software Foundation, either version 3 of the License, or
|
|
|
- * (at your option) any later version.
|
|
|
- *
|
|
|
- * This program is distributed in the hope that it will be useful,
|
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
- * GNU General Public License for more details.
|
|
|
- *
|
|
|
- * You should have received a copy of the GNU General Public License
|
|
|
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
- */
|
|
|
-
|
|
|
-package de.nplusc.izc.izpl.plugins.gameradio;
|
|
|
-
|
|
|
-import de.nplusc.izc.iZpl.API.FeaturePlugin;
|
|
|
-import de.nplusc.izc.iZpl.API.IZPLApi;
|
|
|
-import de.nplusc.izc.iZpl.API.shared.PlayListItem;
|
|
|
-import de.nplusc.izc.iZpl.API.ProgressWindow;
|
|
|
-import de.nplusc.izc.iZpl.API.shared.SinglePlayListItem;
|
|
|
-import de.nplusc.izc.tools.IOtools.FileTK;
|
|
|
-import de.nplusc.izc.tools.WinToolz.Commands;
|
|
|
-import de.nplusc.izc.tools.baseTools.Detectors;
|
|
|
-import de.nplusc.izc.tools.baseTools.Tools;
|
|
|
-import de.schlichtherle.truezip.file.TFile;
|
|
|
-import java.awt.EventQueue;
|
|
|
-import java.io.File;
|
|
|
-import java.io.IOException;
|
|
|
-import java.util.Arrays;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.LinkedList;
|
|
|
-import java.util.List;
|
|
|
-import javax.swing.JOptionPane;
|
|
|
-import org.apache.logging.log4j.Level;
|
|
|
-import org.apache.logging.log4j.LogManager;
|
|
|
-import org.apache.logging.log4j.Logger;
|
|
|
-import org.apache.logging.log4j.io.IoBuilder;
|
|
|
-
|
|
|
-/**
|
|
|
- *
|
|
|
- * @author iZc <nplusc.de>
|
|
|
- */
|
|
|
-public class RadioManager implements FeaturePlugin
|
|
|
-{
|
|
|
- private final HashMap<SinglePlayListItem,String> ConvertLookupCache = new HashMap<>();
|
|
|
- private static final Logger l = LogManager.getLogger(RadioManager.class.getName());
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- //header:rbSym:rbCopy:rbInter:Stations:Stationsasfile:Tracks:cxMergeTracks:StationBaseName:RadioPath
|
|
|
- //radio:B:B:B:I:B:I:B:S:P
|
|
|
- private boolean GUIOpen=false;
|
|
|
- private enum Mode{
|
|
|
- SYMLINKED,COPY,INTERACTIVE;
|
|
|
- }
|
|
|
-
|
|
|
- private static final String jarschiv = RadioManager.class.getProtectionDomain().getCodeSource().getLocation().getPath();
|
|
|
-
|
|
|
-
|
|
|
- @Override
|
|
|
- public void parseParameter(String param)
|
|
|
- {
|
|
|
- Thread t = new Thread(()->
|
|
|
- {
|
|
|
- ProgressWindow.setTitle("RadioMake progress");
|
|
|
-
|
|
|
-
|
|
|
- if(param!=null&&!(param.equals(""))&¶m.startsWith("radio:"))
|
|
|
- {
|
|
|
- String[] cstring = param.split(":");
|
|
|
- if(cstring.length<10)//patsh can cause that more than 10 :s appear, that error is handled later
|
|
|
- {
|
|
|
- l.error("DERP the string was invalid");
|
|
|
- l.error("Not enough Sections");
|
|
|
- }
|
|
|
- l.trace(Arrays.toString(cstring));
|
|
|
- Mode m=null;
|
|
|
- String mode=param.substring(6,11);
|
|
|
- switch(mode)
|
|
|
- {
|
|
|
- case "T:F:F":
|
|
|
- m=Mode.SYMLINKED;
|
|
|
- break;
|
|
|
- case "F:T:F":
|
|
|
- m=Mode.COPY;
|
|
|
- break;
|
|
|
- case "F:F:T":
|
|
|
- m=Mode.INTERACTIVE;
|
|
|
- break;
|
|
|
- default:
|
|
|
- l.error("DERP the string was invalid");
|
|
|
- l.error("Invalid Mode block");
|
|
|
- IZPLApi.quickQuitWithoutSaving();
|
|
|
- }
|
|
|
- int stations=0;
|
|
|
- int tracks=0;
|
|
|
- try
|
|
|
- {
|
|
|
- l.trace(cstring[4]);
|
|
|
- l.trace(cstring[6]);
|
|
|
- stations=Integer.valueOf(cstring[4]);
|
|
|
- tracks=Integer.valueOf(cstring[6]);
|
|
|
- }
|
|
|
- catch(NumberFormatException x)
|
|
|
- {
|
|
|
- l.error("DERP the string was invalid");
|
|
|
- l.error("Numeric Literals are wrong");
|
|
|
- IZPLApi.quickQuitWithoutSaving();
|
|
|
- }
|
|
|
- boolean fileStations=cstring[5].equals("T");
|
|
|
- boolean mergeTracks=cstring[7].equals("T");
|
|
|
-
|
|
|
- String stationBase = cstring[8];
|
|
|
-
|
|
|
- String baseDir = param.substring((cstring[0]+":"+cstring[1]+":"+cstring[2]+":"+cstring[3]+
|
|
|
- cstring[4]+":"+cstring[5]+":"+cstring[6]+":"+cstring[7]+":"+cstring[8]+":").length()+1);
|
|
|
- l.trace(baseDir);
|
|
|
- baseDir=new File(baseDir).getAbsolutePath();//Hack der später wichtig wird
|
|
|
- if(!(new File(baseDir).exists()))
|
|
|
- {
|
|
|
-
|
|
|
- l.error("DERP the string was invalid");
|
|
|
- l.error("Basedir must be valid");
|
|
|
- IZPLApi.quickQuitWithoutSaving();
|
|
|
- }
|
|
|
- //end simple checks
|
|
|
- //validate inter-selection stuff
|
|
|
-
|
|
|
- if(fileStations&&!mergeTracks)
|
|
|
- {
|
|
|
- l.error("DERP the string was invalid");
|
|
|
- l.error("fileStations requires merged Tracks");
|
|
|
- IZPLApi.quickQuitWithoutSaving();
|
|
|
- }
|
|
|
-
|
|
|
- if(m==Mode.SYMLINKED&&mergeTracks)
|
|
|
- {
|
|
|
- l.error("DERP the string was invalid");
|
|
|
- l.error("YOu cannot symlink and merge tracks at once");
|
|
|
- IZPLApi.quickQuitWithoutSaving();
|
|
|
- }
|
|
|
-
|
|
|
- if(stations>65535)
|
|
|
- {
|
|
|
- l.error("DERP the string was invalid");
|
|
|
- l.error("Stations can be at 65535 maximum due to Filesystem constraints");
|
|
|
- IZPLApi.quickQuitWithoutSaving();
|
|
|
- }
|
|
|
- if((tracks>65535&&!mergeTracks))
|
|
|
- {
|
|
|
- l.error("DERP the string was invalid");
|
|
|
- l.error("more than 65535 tracks require merged Tracks");
|
|
|
- IZPLApi.quickQuitWithoutSaving();
|
|
|
- }
|
|
|
-
|
|
|
- l.log(Level.TRACE,"Selected Settings:\n"+"Mode: {}"+"\n"
|
|
|
- + "Amount of tracks: {}"+"\n"+"Tracks merged: {}"
|
|
|
- + "\n"+"Amount of stations: {}"+"\n"
|
|
|
- + "Stations as file: {}"+"\n"+"Station name base: {}"
|
|
|
- + "\n"+"Base directory: {}", new Object[]{m, tracks, mergeTracks,
|
|
|
- stations, fileStations, stationBase, baseDir});
|
|
|
-
|
|
|
- if(!checkConsent(baseDir, stationBase, stations))
|
|
|
- {
|
|
|
- l.warn("User abort on overwriting");
|
|
|
- IZPLApi.quickQuitWithoutSaving();
|
|
|
- }
|
|
|
-
|
|
|
- if(!interner_ratzeputz(baseDir, stationBase, stations))
|
|
|
- {
|
|
|
- l.error("Unable to delete files");
|
|
|
- System.exit(9263);
|
|
|
- }
|
|
|
-
|
|
|
- if(GUIOpen)
|
|
|
- {
|
|
|
- rc.disableButtons();
|
|
|
- }
|
|
|
-
|
|
|
- if(m==Mode.COPY)
|
|
|
- {
|
|
|
- if(!mergeTracks)
|
|
|
- {
|
|
|
- for(int i=0;i<stations;i++)
|
|
|
- {
|
|
|
- for(int j=0;j<tracks;j++)
|
|
|
- {
|
|
|
- String pli = getPlayListItemPath();
|
|
|
- File d = new File(baseDir+File.separator+stationBase+"_"+i+
|
|
|
- File.separator+FileTK.getFileName(pli));
|
|
|
- d.getParentFile().mkdirs();
|
|
|
- FileTK.kopierpaste(new File(pli), d);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- ProgressWindow.setWindowState(true);
|
|
|
- ProgressWindow.setUpperMax(tracks*2*stations);
|
|
|
- ProgressWindow.setLowerProgressStatus(false);//not in use yet
|
|
|
- for(int i=0;i<stations;i++)
|
|
|
- {
|
|
|
- File d = new File(baseDir+File.separator+stationBase+"_"+i+(fileStations?".mp3":
|
|
|
- (File.separator+"1.mp3")));
|
|
|
- d.getParentFile().mkdirs();
|
|
|
- createMergedMp3(d,tracks,stations,i);
|
|
|
- }
|
|
|
- ProgressWindow.setStatusBarText("Done");
|
|
|
- ProgressWindow.setUpperValue(tracks*2*stations);
|
|
|
- try
|
|
|
- {
|
|
|
- Thread.sleep(1000);
|
|
|
- }
|
|
|
- catch (InterruptedException ex)
|
|
|
- {
|
|
|
- }
|
|
|
- ProgressWindow.setWindowState(false);
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if(m==Mode.SYMLINKED)
|
|
|
- {
|
|
|
- String mklink_bätsch=baseDir.substring(0,2)+"\n";//LW-buchstaben
|
|
|
-
|
|
|
- for(int i=0;i<stations;i++)
|
|
|
- {
|
|
|
- mklink_bätsch+="cd \""+baseDir+File.separator+stationBase+"_"+i+"\"\n";
|
|
|
- for(int j=0;j<tracks;j++)
|
|
|
- {
|
|
|
-
|
|
|
- String pli = getPlayListItemPath();
|
|
|
- File d = new File(baseDir+File.separator+stationBase+"_"+i+
|
|
|
- File.separator+FileTK.getFileName(pli));
|
|
|
- d.getParentFile().mkdirs();
|
|
|
- mklink_bätsch+="mklink \""+FileTK.getFileName(d.getPath()) +"\" \""+ pli+"\"\n";
|
|
|
- }
|
|
|
- }
|
|
|
- l.trace("\n-----------------------------------\n"+mklink_bätsch+"\n--------------------------------------\n");
|
|
|
- String bätschpfad = System.getenv("temp")+File.separator+"izpl-symlink.bat";
|
|
|
- l.trace(bätschpfad);
|
|
|
- FileTK.writeFile(mklink_bätsch, bätschpfad);
|
|
|
- Commands.executeAsAdministrator("cmd", "/c "+bätschpfad);
|
|
|
- l.info("Batch started");
|
|
|
- }
|
|
|
- }
|
|
|
- if(!GUIOpen)
|
|
|
- {
|
|
|
- IZPLApi.quickQuitWithoutSaving();
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- openUserInterface();
|
|
|
- }
|
|
|
- });
|
|
|
- t.setName("RadioManager_Core");
|
|
|
- t.start();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public boolean hasUserInterface()
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- private RadioConfig rc;
|
|
|
-
|
|
|
-
|
|
|
- @Override
|
|
|
- public void openUserInterface()
|
|
|
- {
|
|
|
- EventQueue.invokeLater(()->
|
|
|
- {
|
|
|
- GUIOpen=true;
|
|
|
- rc=new RadioConfig(this);
|
|
|
- rc.setVisible(true);
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public String getPluginName()
|
|
|
- {
|
|
|
- return "GameRadioManager";
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void initializePlugin()
|
|
|
- {
|
|
|
- l.info("extracting GameRadio natives");
|
|
|
- String[] osmetadata = Detectors.getSystemClassification();
|
|
|
- l.info("Os-data:"+Arrays.toString(osmetadata));
|
|
|
- if (osmetadata[0].equals("windows"))
|
|
|
- {
|
|
|
-
|
|
|
- File target = new File(IZPLApi.PLUGINPATH+File.separator+"GameRadioManager"
|
|
|
- +File.separator+"binaries"+File.separator+"ffmpeg.exe");
|
|
|
- target.getParentFile().mkdirs();
|
|
|
- if (!target.exists())
|
|
|
- {
|
|
|
- TFile zippo = new TFile(jarschiv + "\\binaries\\"+osmetadata[0]+"\\ffmpeg.exe");
|
|
|
- try
|
|
|
- {
|
|
|
- zippo.cp(target);
|
|
|
- TFile jarschcrap = new TFile(jarschiv + "\\binaries\\");
|
|
|
- jarschcrap.rm_r();//removal of the embedded FFMPEG binary after init
|
|
|
- }
|
|
|
- catch (IOException ex)
|
|
|
- {
|
|
|
-
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- throw new UnsupportedOperationException("ERROR! invalid OSType detected, embedded VLC doesnt work here");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void prepareUpgrade()
|
|
|
- {
|
|
|
- if(new TFile(jarschiv + "\\binaries").exists()) //nullroute falls reinit nicht möglich da files schon ausgepackt wurden
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- //killen der alten vlc-natives
|
|
|
- TFile f = new TFile(IZPLApi.PLUGINPATH+File.separator+"GameRadioManager"+File.separator+"binaries");
|
|
|
- if(f.exists())
|
|
|
- f.rm_r();
|
|
|
- }
|
|
|
- catch (IOException ex)
|
|
|
- {
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- l.warn("");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private String getPlayListItemPath()
|
|
|
- {
|
|
|
- PlayListItem itm = IZPLApi.getNextItem();
|
|
|
- while (!(itm instanceof SinglePlayListItem))
|
|
|
- {
|
|
|
- itm = IZPLApi.getNextItem();
|
|
|
- }
|
|
|
- return ((SinglePlayListItem) itm).getPath();
|
|
|
- }
|
|
|
-
|
|
|
- private SinglePlayListItem getPlayListItem()
|
|
|
- {
|
|
|
- PlayListItem itm = IZPLApi.getNextItem();
|
|
|
- while (!(itm instanceof SinglePlayListItem))
|
|
|
- {
|
|
|
- itm = IZPLApi.getNextItem();
|
|
|
- }
|
|
|
- return ((SinglePlayListItem) itm);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- private boolean checkConsent(String baseDir,String stationBase,int stationcount)
|
|
|
- {
|
|
|
- boolean existingDir=false;
|
|
|
- for (int i = 0; i < stationcount; i++)
|
|
|
- {
|
|
|
- existingDir|= new File(baseDir+File.separator+stationBase+"_"+i).exists();
|
|
|
- }
|
|
|
- if(existingDir)
|
|
|
- {
|
|
|
- return JOptionPane.showConfirmDialog(null, "Delete existing stations", "Existing stations detected",
|
|
|
- JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE)==JOptionPane.YES_OPTION;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- private boolean interner_ratzeputz(String baseDir,String stationBase,int stationcount)
|
|
|
- {
|
|
|
-
|
|
|
- for (int i = 0; i < stationcount; i++)
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- TFile kf = new TFile(baseDir+File.separator+stationBase+"_"+i);
|
|
|
- if(kf.exists())
|
|
|
- kf.rm_r();
|
|
|
- }
|
|
|
- catch (IOException ex)
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- private void createMergedMp3(File destination,int trackcount,int stationmax,int currentstation)
|
|
|
- {
|
|
|
- int progressBase = trackcount*2*currentstation;
|
|
|
- ProgressWindow.setUpperValue(progressBase);
|
|
|
-
|
|
|
- new File(IZPLApi.TEMPDIR).mkdirs();
|
|
|
- List<String> orderOfFiles = new LinkedList<>();
|
|
|
- l.info("Starting to convert to MP3 for later merging");
|
|
|
- for (int i = 0; i < trackcount; i++)
|
|
|
- {
|
|
|
- l.info(i+" of "+trackcount+" done");
|
|
|
- SinglePlayListItem plir = getPlayListItem();
|
|
|
- String pli = plir.getPath();
|
|
|
- if(ConvertLookupCache.containsKey(plir))
|
|
|
- {
|
|
|
- l.trace("Cache hit!");
|
|
|
- orderOfFiles.add(ConvertLookupCache.get(plir));
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- l.trace("cache miss!");
|
|
|
- if(FileTK.getFileExt(pli).equalsIgnoreCase("mp3"))
|
|
|
- {
|
|
|
- //HACK, ffmpeg --fick-dich-mit-dateinamen
|
|
|
- String tempPath = IZPLApi.TEMPDIR+File.separator+pli.hashCode()+"-"+
|
|
|
- (FileTK.getFileName(pli).hashCode()+".mp3");
|
|
|
- FileTK.kopierpaste(new File(pli), new File(tempPath));
|
|
|
- ConvertLookupCache.put(plir, tempPath);
|
|
|
- orderOfFiles.add(tempPath);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- l.info("converting new Track: "+pli);
|
|
|
- String tempPath = IZPLApi.TEMPDIR+File.separator+pli.hashCode()+"-"+
|
|
|
- (FileTK.getFileName(pli).hashCode()+".mp3");
|
|
|
- convertToMp3(new File(pli), new File(tempPath));
|
|
|
- ConvertLookupCache.put(plir,tempPath);
|
|
|
- orderOfFiles.add(tempPath);
|
|
|
- }
|
|
|
- }
|
|
|
- ProgressWindow.setUpperValue(progressBase+i);
|
|
|
- ProgressWindow.setStatusBarText("Stations done:"+currentstation+",Tracks done: "+i);
|
|
|
- }
|
|
|
- l.info("Convert successful, merge started");
|
|
|
- ProgressWindow.setStatusBarText("Stations done:"+currentstation+",Merging tracks....");
|
|
|
- String mergeList = "";
|
|
|
- for (String item : orderOfFiles)
|
|
|
- {
|
|
|
- mergeList+="file '"+item+"'\n";
|
|
|
- }
|
|
|
- String mergelistfile = IZPLApi.TEMPDIR+File.separator+"files.txt";
|
|
|
- FileTK.writeFile(mergeList, mergelistfile);
|
|
|
-
|
|
|
- Tools.runCmdWithPassthru(IoBuilder.forLogger("External.FFMPEGMerge").buildPrintStream(),
|
|
|
- IZPLApi.PLUGINPATH+File.separator+"GameRadioManager"+File.separator+"binaries"+File.separator+"ffmpeg.exe","-stats",
|
|
|
- "-f","concat","-i",mergelistfile,"-c","copy",destination.getAbsolutePath());
|
|
|
-
|
|
|
-
|
|
|
- //ffmpeg -f concat -i mylist.txt -c copy output
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- private void convertToMp3(File inFile,File destination)
|
|
|
- {
|
|
|
- Tools.runCmdWithPassthru(IoBuilder.forLogger("External.FFMPEG").buildPrintStream(),
|
|
|
- IZPLApi.PLUGINPATH+File.separator+"GameRadioManager"+File.separator+"binaries"+File.separator+"ffmpeg.exe","-stats","-n",
|
|
|
- "-i",inFile.getAbsolutePath(),"-ab","320k",destination.getAbsolutePath());
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-}
|
|
|
+/*
|
|
|
+ * Copyright (C) 2015 iZc
|
|
|
+ *
|
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
|
+ * the Free Software Foundation, either version 3 of the License, or
|
|
|
+ * (at your option) any later version.
|
|
|
+ *
|
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
+ * GNU General Public License for more details.
|
|
|
+ *
|
|
|
+ * You should have received a copy of the GNU General Public License
|
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
+ */
|
|
|
+
|
|
|
+package de.nplusc.izc.izpl.plugins.gameradio;
|
|
|
+
|
|
|
+import de.nplusc.izc.iZpl.API.FeaturePlugin;
|
|
|
+import de.nplusc.izc.iZpl.API.IZPLApi;
|
|
|
+import de.nplusc.izc.iZpl.API.shared.PlayListItem;
|
|
|
+import de.nplusc.izc.iZpl.API.ProgressWindow;
|
|
|
+import de.nplusc.izc.iZpl.API.shared.SinglePlayListItem;
|
|
|
+import de.nplusc.izc.tools.IOtools.FileTK;
|
|
|
+import de.nplusc.izc.tools.WinToolz.Commands;
|
|
|
+import de.nplusc.izc.tools.baseTools.Detectors;
|
|
|
+import de.nplusc.izc.tools.baseTools.Tools;
|
|
|
+import net.java.truevfs.access.TFile;
|
|
|
+import java.awt.EventQueue;
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.LinkedList;
|
|
|
+import java.util.List;
|
|
|
+import javax.swing.JOptionPane;
|
|
|
+import org.apache.logging.log4j.Level;
|
|
|
+import org.apache.logging.log4j.LogManager;
|
|
|
+import org.apache.logging.log4j.Logger;
|
|
|
+import org.apache.logging.log4j.io.IoBuilder;
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @author iZc <nplusc.de>
|
|
|
+ */
|
|
|
+public class RadioManager implements FeaturePlugin
|
|
|
+{
|
|
|
+ private final HashMap<SinglePlayListItem,String> ConvertLookupCache = new HashMap<>();
|
|
|
+ private static final Logger l = LogManager.getLogger(RadioManager.class.getName());
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //header:rbSym:rbCopy:rbInter:Stations:Stationsasfile:Tracks:cxMergeTracks:StationBaseName:RadioPath
|
|
|
+ //radio:B:B:B:I:B:I:B:S:P
|
|
|
+ private boolean GUIOpen=false;
|
|
|
+ private enum Mode{
|
|
|
+ SYMLINKED,COPY,INTERACTIVE;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static final String jarschiv = RadioManager.class.getProtectionDomain().getCodeSource().getLocation().getPath();
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void parseParameter(String param)
|
|
|
+ {
|
|
|
+ Thread t = new Thread(()->
|
|
|
+ {
|
|
|
+ ProgressWindow.setTitle("RadioMake progress");
|
|
|
+
|
|
|
+
|
|
|
+ if(param!=null&&!(param.equals(""))&¶m.startsWith("radio:"))
|
|
|
+ {
|
|
|
+ String[] cstring = param.split(":");
|
|
|
+ if(cstring.length<10)//patsh can cause that more than 10 :s appear, that error is handled later
|
|
|
+ {
|
|
|
+ l.error("DERP the string was invalid");
|
|
|
+ l.error("Not enough Sections");
|
|
|
+ }
|
|
|
+ l.trace(Arrays.toString(cstring));
|
|
|
+ Mode m=null;
|
|
|
+ String mode=param.substring(6,11);
|
|
|
+ switch(mode)
|
|
|
+ {
|
|
|
+ case "T:F:F":
|
|
|
+ m=Mode.SYMLINKED;
|
|
|
+ break;
|
|
|
+ case "F:T:F":
|
|
|
+ m=Mode.COPY;
|
|
|
+ break;
|
|
|
+ case "F:F:T":
|
|
|
+ m=Mode.INTERACTIVE;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ l.error("DERP the string was invalid");
|
|
|
+ l.error("Invalid Mode block");
|
|
|
+ IZPLApi.quickQuitWithoutSaving();
|
|
|
+ }
|
|
|
+ int stations=0;
|
|
|
+ int tracks=0;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ l.trace(cstring[4]);
|
|
|
+ l.trace(cstring[6]);
|
|
|
+ stations=Integer.valueOf(cstring[4]);
|
|
|
+ tracks=Integer.valueOf(cstring[6]);
|
|
|
+ }
|
|
|
+ catch(NumberFormatException x)
|
|
|
+ {
|
|
|
+ l.error("DERP the string was invalid");
|
|
|
+ l.error("Numeric Literals are wrong");
|
|
|
+ IZPLApi.quickQuitWithoutSaving();
|
|
|
+ }
|
|
|
+ boolean fileStations=cstring[5].equals("T");
|
|
|
+ boolean mergeTracks=cstring[7].equals("T");
|
|
|
+
|
|
|
+ String stationBase = cstring[8];
|
|
|
+
|
|
|
+ String baseDir = param.substring((cstring[0]+":"+cstring[1]+":"+cstring[2]+":"+cstring[3]+
|
|
|
+ cstring[4]+":"+cstring[5]+":"+cstring[6]+":"+cstring[7]+":"+cstring[8]+":").length()+1);
|
|
|
+ l.trace(baseDir);
|
|
|
+ baseDir=new File(baseDir).getAbsolutePath();//Hack der später wichtig wird
|
|
|
+ if(!(new File(baseDir).exists()))
|
|
|
+ {
|
|
|
+
|
|
|
+ l.error("DERP the string was invalid");
|
|
|
+ l.error("Basedir must be valid");
|
|
|
+ IZPLApi.quickQuitWithoutSaving();
|
|
|
+ }
|
|
|
+ //end simple checks
|
|
|
+ //validate inter-selection stuff
|
|
|
+
|
|
|
+ if(fileStations&&!mergeTracks)
|
|
|
+ {
|
|
|
+ l.error("DERP the string was invalid");
|
|
|
+ l.error("fileStations requires merged Tracks");
|
|
|
+ IZPLApi.quickQuitWithoutSaving();
|
|
|
+ }
|
|
|
+
|
|
|
+ if(m==Mode.SYMLINKED&&mergeTracks)
|
|
|
+ {
|
|
|
+ l.error("DERP the string was invalid");
|
|
|
+ l.error("YOu cannot symlink and merge tracks at once");
|
|
|
+ IZPLApi.quickQuitWithoutSaving();
|
|
|
+ }
|
|
|
+
|
|
|
+ if(stations>65535)
|
|
|
+ {
|
|
|
+ l.error("DERP the string was invalid");
|
|
|
+ l.error("Stations can be at 65535 maximum due to Filesystem constraints");
|
|
|
+ IZPLApi.quickQuitWithoutSaving();
|
|
|
+ }
|
|
|
+ if((tracks>65535&&!mergeTracks))
|
|
|
+ {
|
|
|
+ l.error("DERP the string was invalid");
|
|
|
+ l.error("more than 65535 tracks require merged Tracks");
|
|
|
+ IZPLApi.quickQuitWithoutSaving();
|
|
|
+ }
|
|
|
+
|
|
|
+ l.log(Level.TRACE,"Selected Settings:\n"+"Mode: {}"+"\n"
|
|
|
+ + "Amount of tracks: {}"+"\n"+"Tracks merged: {}"
|
|
|
+ + "\n"+"Amount of stations: {}"+"\n"
|
|
|
+ + "Stations as file: {}"+"\n"+"Station name base: {}"
|
|
|
+ + "\n"+"Base directory: {}", new Object[]{m, tracks, mergeTracks,
|
|
|
+ stations, fileStations, stationBase, baseDir});
|
|
|
+
|
|
|
+ if(!checkConsent(baseDir, stationBase, stations))
|
|
|
+ {
|
|
|
+ l.warn("User abort on overwriting");
|
|
|
+ IZPLApi.quickQuitWithoutSaving();
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!interner_ratzeputz(baseDir, stationBase, stations))
|
|
|
+ {
|
|
|
+ l.error("Unable to delete files");
|
|
|
+ System.exit(9263);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(GUIOpen)
|
|
|
+ {
|
|
|
+ rc.disableButtons();
|
|
|
+ }
|
|
|
+
|
|
|
+ if(m==Mode.COPY)
|
|
|
+ {
|
|
|
+ if(!mergeTracks)
|
|
|
+ {
|
|
|
+ for(int i=0;i<stations;i++)
|
|
|
+ {
|
|
|
+ for(int j=0;j<tracks;j++)
|
|
|
+ {
|
|
|
+ String pli = getPlayListItemPath();
|
|
|
+ File d = new File(baseDir+File.separator+stationBase+"_"+i+
|
|
|
+ File.separator+FileTK.getFileName(pli));
|
|
|
+ d.getParentFile().mkdirs();
|
|
|
+ FileTK.kopierpaste(new File(pli), d);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ProgressWindow.setWindowState(true);
|
|
|
+ ProgressWindow.setUpperMax(tracks*2*stations);
|
|
|
+ ProgressWindow.setLowerProgressStatus(false);//not in use yet
|
|
|
+ for(int i=0;i<stations;i++)
|
|
|
+ {
|
|
|
+ File d = new File(baseDir+File.separator+stationBase+"_"+i+(fileStations?".mp3":
|
|
|
+ (File.separator+"1.mp3")));
|
|
|
+ d.getParentFile().mkdirs();
|
|
|
+ createMergedMp3(d,tracks,stations,i);
|
|
|
+ }
|
|
|
+ ProgressWindow.setStatusBarText("Done");
|
|
|
+ ProgressWindow.setUpperValue(tracks*2*stations);
|
|
|
+ try
|
|
|
+ {
|
|
|
+ Thread.sleep(1000);
|
|
|
+ }
|
|
|
+ catch (InterruptedException ex)
|
|
|
+ {
|
|
|
+ }
|
|
|
+ ProgressWindow.setWindowState(false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if(m==Mode.SYMLINKED)
|
|
|
+ {
|
|
|
+ String mklink_bätsch=baseDir.substring(0,2)+"\n";//LW-buchstaben
|
|
|
+
|
|
|
+ for(int i=0;i<stations;i++)
|
|
|
+ {
|
|
|
+ mklink_bätsch+="cd \""+baseDir+File.separator+stationBase+"_"+i+"\"\n";
|
|
|
+ for(int j=0;j<tracks;j++)
|
|
|
+ {
|
|
|
+
|
|
|
+ String pli = getPlayListItemPath();
|
|
|
+ File d = new File(baseDir+File.separator+stationBase+"_"+i+
|
|
|
+ File.separator+FileTK.getFileName(pli));
|
|
|
+ d.getParentFile().mkdirs();
|
|
|
+ mklink_bätsch+="mklink \""+FileTK.getFileName(d.getPath()) +"\" \""+ pli+"\"\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ l.trace("\n-----------------------------------\n"+mklink_bätsch+"\n--------------------------------------\n");
|
|
|
+ String bätschpfad = System.getenv("temp")+File.separator+"izpl-symlink.bat";
|
|
|
+ l.trace(bätschpfad);
|
|
|
+ FileTK.writeFile(mklink_bätsch, bätschpfad);
|
|
|
+ Commands.executeAsAdministrator("cmd", "/c "+bätschpfad);
|
|
|
+ l.info("Batch started");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(!GUIOpen)
|
|
|
+ {
|
|
|
+ IZPLApi.quickQuitWithoutSaving();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ openUserInterface();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ t.setName("RadioManager_Core");
|
|
|
+ t.start();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean hasUserInterface()
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private RadioConfig rc;
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void openUserInterface()
|
|
|
+ {
|
|
|
+ EventQueue.invokeLater(()->
|
|
|
+ {
|
|
|
+ GUIOpen=true;
|
|
|
+ rc=new RadioConfig(this);
|
|
|
+ rc.setVisible(true);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getPluginName()
|
|
|
+ {
|
|
|
+ return "GameRadioManager";
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void initializePlugin()
|
|
|
+ {
|
|
|
+ l.info("extracting GameRadio natives");
|
|
|
+ String[] osmetadata = Detectors.getSystemClassification();
|
|
|
+ l.info("Os-data:"+Arrays.toString(osmetadata));
|
|
|
+ if (osmetadata[0].equals("windows"))
|
|
|
+ {
|
|
|
+
|
|
|
+ File target = new File(IZPLApi.PLUGINPATH+File.separator+"GameRadioManager"
|
|
|
+ +File.separator+"binaries"+File.separator+"ffmpeg.exe");
|
|
|
+ target.getParentFile().mkdirs();
|
|
|
+ if (!target.exists())
|
|
|
+ {
|
|
|
+ TFile zippo = new TFile(jarschiv + "\\binaries\\"+osmetadata[0]+"\\ffmpeg.exe");
|
|
|
+ try
|
|
|
+ {
|
|
|
+ zippo.cp(target);
|
|
|
+ TFile jarschcrap = new TFile(jarschiv + "\\binaries\\");
|
|
|
+ jarschcrap.rm_r();//removal of the embedded FFMPEG binary after init
|
|
|
+ }
|
|
|
+ catch (IOException ex)
|
|
|
+ {
|
|
|
+
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ throw new UnsupportedOperationException("ERROR! invalid OSType detected, embedded VLC doesnt work here");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void prepareUpgrade()
|
|
|
+ {
|
|
|
+ if(new TFile(jarschiv + "\\binaries").exists()) //nullroute falls reinit nicht möglich da files schon ausgepackt wurden
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //killen der alten vlc-natives
|
|
|
+ TFile f = new TFile(IZPLApi.PLUGINPATH+File.separator+"GameRadioManager"+File.separator+"binaries");
|
|
|
+ if(f.exists())
|
|
|
+ f.rm_r();
|
|
|
+ }
|
|
|
+ catch (IOException ex)
|
|
|
+ {
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ l.warn("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getPlayListItemPath()
|
|
|
+ {
|
|
|
+ PlayListItem itm = IZPLApi.getNextItem();
|
|
|
+ while (!(itm instanceof SinglePlayListItem))
|
|
|
+ {
|
|
|
+ itm = IZPLApi.getNextItem();
|
|
|
+ }
|
|
|
+ return ((SinglePlayListItem) itm).getPath();
|
|
|
+ }
|
|
|
+
|
|
|
+ private SinglePlayListItem getPlayListItem()
|
|
|
+ {
|
|
|
+ PlayListItem itm = IZPLApi.getNextItem();
|
|
|
+ while (!(itm instanceof SinglePlayListItem))
|
|
|
+ {
|
|
|
+ itm = IZPLApi.getNextItem();
|
|
|
+ }
|
|
|
+ return ((SinglePlayListItem) itm);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private boolean checkConsent(String baseDir,String stationBase,int stationcount)
|
|
|
+ {
|
|
|
+ boolean existingDir=false;
|
|
|
+ for (int i = 0; i < stationcount; i++)
|
|
|
+ {
|
|
|
+ existingDir|= new File(baseDir+File.separator+stationBase+"_"+i).exists();
|
|
|
+ }
|
|
|
+ if(existingDir)
|
|
|
+ {
|
|
|
+ return JOptionPane.showConfirmDialog(null, "Delete existing stations", "Existing stations detected",
|
|
|
+ JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE)==JOptionPane.YES_OPTION;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private boolean interner_ratzeputz(String baseDir,String stationBase,int stationcount)
|
|
|
+ {
|
|
|
+
|
|
|
+ for (int i = 0; i < stationcount; i++)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ TFile kf = new TFile(baseDir+File.separator+stationBase+"_"+i);
|
|
|
+ if(kf.exists())
|
|
|
+ kf.rm_r();
|
|
|
+ }
|
|
|
+ catch (IOException ex)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void createMergedMp3(File destination,int trackcount,int stationmax,int currentstation)
|
|
|
+ {
|
|
|
+ int progressBase = trackcount*2*currentstation;
|
|
|
+ ProgressWindow.setUpperValue(progressBase);
|
|
|
+
|
|
|
+ new File(IZPLApi.TEMPDIR).mkdirs();
|
|
|
+ List<String> orderOfFiles = new LinkedList<>();
|
|
|
+ l.info("Starting to convert to MP3 for later merging");
|
|
|
+ for (int i = 0; i < trackcount; i++)
|
|
|
+ {
|
|
|
+ l.info(i+" of "+trackcount+" done");
|
|
|
+ SinglePlayListItem plir = getPlayListItem();
|
|
|
+ String pli = plir.getPath();
|
|
|
+ if(ConvertLookupCache.containsKey(plir))
|
|
|
+ {
|
|
|
+ l.trace("Cache hit!");
|
|
|
+ orderOfFiles.add(ConvertLookupCache.get(plir));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ l.trace("cache miss!");
|
|
|
+ if(FileTK.getFileExt(pli).equalsIgnoreCase("mp3"))
|
|
|
+ {
|
|
|
+ //HACK, ffmpeg --fick-dich-mit-dateinamen
|
|
|
+ String tempPath = IZPLApi.TEMPDIR+File.separator+pli.hashCode()+"-"+
|
|
|
+ (FileTK.getFileName(pli).hashCode()+".mp3");
|
|
|
+ FileTK.kopierpaste(new File(pli), new File(tempPath));
|
|
|
+ ConvertLookupCache.put(plir, tempPath);
|
|
|
+ orderOfFiles.add(tempPath);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ l.info("converting new Track: "+pli);
|
|
|
+ String tempPath = IZPLApi.TEMPDIR+File.separator+pli.hashCode()+"-"+
|
|
|
+ (FileTK.getFileName(pli).hashCode()+".mp3");
|
|
|
+ convertToMp3(new File(pli), new File(tempPath));
|
|
|
+ ConvertLookupCache.put(plir,tempPath);
|
|
|
+ orderOfFiles.add(tempPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ProgressWindow.setUpperValue(progressBase+i);
|
|
|
+ ProgressWindow.setStatusBarText("Stations done:"+currentstation+",Tracks done: "+i);
|
|
|
+ }
|
|
|
+ l.info("Convert successful, merge started");
|
|
|
+ ProgressWindow.setStatusBarText("Stations done:"+currentstation+",Merging tracks....");
|
|
|
+ String mergeList = "";
|
|
|
+ for (String item : orderOfFiles)
|
|
|
+ {
|
|
|
+ mergeList+="file '"+item+"'\n";
|
|
|
+ }
|
|
|
+ String mergelistfile = IZPLApi.TEMPDIR+File.separator+"files.txt";
|
|
|
+ FileTK.writeFile(mergeList, mergelistfile);
|
|
|
+
|
|
|
+ Tools.runCmdWithPassthru(IoBuilder.forLogger("External.FFMPEGMerge").buildPrintStream(),
|
|
|
+ IZPLApi.PLUGINPATH+File.separator+"GameRadioManager"+File.separator+"binaries"+File.separator+"ffmpeg.exe","-stats",
|
|
|
+ "-f","concat","-i",mergelistfile,"-c","copy",destination.getAbsolutePath());
|
|
|
+
|
|
|
+
|
|
|
+ //ffmpeg -f concat -i mylist.txt -c copy output
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ private void convertToMp3(File inFile,File destination)
|
|
|
+ {
|
|
|
+ Tools.runCmdWithPassthru(IoBuilder.forLogger("External.FFMPEG").buildPrintStream(),
|
|
|
+ IZPLApi.PLUGINPATH+File.separator+"GameRadioManager"+File.separator+"binaries"+File.separator+"ffmpeg.exe","-stats","-n",
|
|
|
+ "-i",inFile.getAbsolutePath(),"-ab","320k",destination.getAbsolutePath());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|