/*
* Copyright (C) 2014 Shashank Tulsyan
*
* 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 neembuu.release1.defaultImpl.file.multiVariant;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import jpfm.volume.vector.VectorDirectory;
import neembuu.release1.api.file.NFExceptionDescriptor;
import neembuu.release1.api.file.NeembuuFile;
import neembuu.release1.api.file.OnlineFile;
import neembuu.release1.api.linkgroup.LinkGroup;
import neembuu.release1.api.linkhandler.LinkHandler;
import neembuu.release1.api.linkhandler.LinkHandlerProviders;
import neembuu.release1.api.linkhandler.TrialLinkHandler;
import neembuu.release1.api.file.NeembuuFileCreator;
import neembuu.release1.api.log.LoggerUtil;
import neembuu.release1.api.ui.access.MinimalistFileSystem;
import neembuu.release1.defaultImpl.file.NeembuuFileWrapSCF;
import neembuu.vfs.file.ConstrainUtility;
import neembuu.vfs.file.SeekableConnectionFile;
/**
*
* @author Shashank Tulsyan
*/
public class MultiVariantFileCreator implements NeembuuFileCreator,NFExceptionDescriptor {
private final LinkGroup linkGroup;
private final MinimalistFileSystem root;
MultiVariantSession session = null;
private static final Logger L = LoggerUtil.getLogger(MultiVariantFileCreator.class.getName());
public MultiVariantFileCreator(LinkGroup linkGroup, MinimalistFileSystem root) {
this.linkGroup = linkGroup;
this.root = root;
}
@Override
public String explainLastError() {
try{
String s = "";
for(TrialLinkHandler tlh : linkGroup.getAbsorbedLinks()){
s+=tlh.getReferenceLinkString()+"\n";
}
return s;
}catch(Exception a){
a.printStackTrace();
return "";
}
}
@Override
public NeembuuFile create() throws Exception {
if(session!=null){
if(!session.isCompletelyClosed()){
session.closeCompletely();
throw new IllegalStateException("File not completely closed");
}
}
List<NeembuuFile> variants = new ArrayList<>();
VectorDirectory vd = checkLinks(variants);
try {
session = new MultiVariantSession(variants, vd, root, linkGroup.getSession());
} catch (Exception a) {
L.log(Level.INFO, "Could not handle splits", a);
}
return session;
}
private VectorDirectory checkLinks(List<NeembuuFile> connectionFiles)throws Exception{
TrialLinkHandler trialLinkHandler = linkGroup.getAbsorbedLinks().get(0);
LinkHandler linkHandler = LinkHandlerProviders.getHandler(trialLinkHandler);
if(linkHandler==null){
throw new Exception("It seems this website is not\n"
+ "supported anymore by Neembuu now.");
}
String directoryName = linkHandler.getGroupName();
directoryName = root.getSuitableFileName(directoryName);
VectorDirectory vd = new VectorDirectory(directoryName, null);
if(linkHandler.getFiles().size() == 1) {
L.info("MultiVariantFileCreator "+linkHandler+" has just one file when"
+ " it was expected to have many. Using only first file.");
}
for (OnlineFile f : linkHandler.getFiles()) {
SeekableConnectionFile scf = root.create(f,linkGroup.getSession());
vd.add(scf);
connectionFiles.add(new NeembuuFileWrapSCF(scf, root, null, f.getPropertyProvider(),new String[]{vd.getName()}));
}
//<editor-fold defaultstate="collapsed" desc="Why use contraint utility? Explanation : ">
// what this does is, let us say, user is watching 480p and
// not watching 1080p, 360p etc
// now these files, 1080p, 360p automatically download themselves
// in background. Why do they do this?
// they do this, because there is a concept of Main Connection.
// A main connection is NOT throttled (or slowed)
// 1 main connection per file always exists, which makes sure that
// the gaps between 2 downloaded regions are filled and the file is
// fully downloaded.
// This main connection is thus very useful.
// But for a group of files, like splits 001, 002, .... 003
// Only 1 main connection should exists for the entire group.
// This is also true for multi variant case.
// Only 1 main connection should exists for all of these.
// Otherwise, as discussed in earlier example,
// if user is watching 480p only and nothing else,
// even then 1080p, 360p etc will be downloaded in background
// this will waste a lot of bandwidth
//</editor-fold>
ConstrainUtility.constrain(vd);
//<editor-fold defaultstate="collapsed" desc="How to use contraint utility with youtube dash?">
// However we must also understand that using ConstrainUtility.constrain(vd);
// might not always be the best solution. The problem with this is will show up
// when we start supporting youtube dash format.
// In this, 2 connections are required to exist at the same time.
// 1 connection to download video, and 1 connection to download audio.
// In such a case, we will have to contraint all videos together,
// and all audios together. If we contraint all files, audios and video and subtitles
// as a single unit in case of dash, it will result in bad performance.
//</editor-fold>
return vd;
}
}