Package net.pms.dlna

Source Code of net.pms.dlna.MapFile

/*
* PS3 Media Server, for streaming any medias to your PS3.
* Copyright (C) 2008  A.Brochard
*
* 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; version 2
* of the License only.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package net.pms.dlna;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import net.pms.PMS;
import net.pms.configuration.MapFileConfiguration;
import net.pms.configuration.PmsConfiguration;
import net.pms.dlna.virtual.TranscodeVirtualFolder;
import net.pms.dlna.virtual.VirtualFolder;
import net.pms.formats.FormatFactory;
import net.pms.network.HTTPResource;
import net.pms.util.FileUtil;
import net.pms.util.UMSUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* TODO: Change all instance variables to private. For backwards compatibility
* with external plugin code the variables have all been marked as deprecated
* instead of changed to private, but this will surely change in the future.
* When everything has been changed to private, the deprecated note can be
* removed.
*/
public class MapFile extends DLNAResource {
  private static final Logger LOGGER = LoggerFactory.getLogger(MapFile.class);
  private static final PmsConfiguration configuration = PMS.getConfiguration();
  private List<File> discoverable;
  private String forcedName;

  private ArrayList<RealFile> searchList;

  /**
   * @deprecated Use standard getter and setter to access this variable.
   */
  @Deprecated
  public File potentialCover;

  /**
   * @deprecated Use standard getter and setter to access this variable.
   */
  @Deprecated
  protected MapFileConfiguration conf;

  public MapFile() {
    this.conf = new MapFileConfiguration();
    setLastModified(0);
    forcedName = null;
  }

  public MapFile(MapFileConfiguration conf) {
    this.conf = conf;
    setLastModified(0);
    forcedName = null;
  }

  public MapFile(MapFileConfiguration conf, List<File> list) {
    this.conf = conf;
    setLastModified(0);
    this.discoverable = list;
    forcedName = null;
  }

  private void manageFile(File f, String str) {
    if (f.isFile() || f.isDirectory()) {
      String lcFilename = f.getName().toLowerCase();

      if (!f.isHidden()) {
        if (configuration.isArchiveBrowsing() && (lcFilename.endsWith(".zip") || lcFilename.endsWith(".cbz"))) {
          addChild(new ZippedFile(f));
        } else if (configuration.isArchiveBrowsing() && (lcFilename.endsWith(".rar") || lcFilename.endsWith(".cbr"))) {
          addChild(new RarredFile(f));
        } else if (configuration.isArchiveBrowsing() && (lcFilename.endsWith(".tar") || lcFilename.endsWith(".gzip") || lcFilename.endsWith(".gz") || lcFilename.endsWith(".7z"))) {
          addChild(new SevenZipFile(f));
        } else if ((lcFilename.endsWith(".iso") || lcFilename.endsWith(".img")) || (f.isDirectory() && f.getName().toUpperCase().equals("VIDEO_TS"))) {
          addChild(new DVDISOFile(f));
        } else if (lcFilename.endsWith(".m3u") || lcFilename.endsWith(".m3u8") || lcFilename.endsWith(".pls")) {
          addChild(new PlaylistFolder(f));
        } else if (lcFilename.endsWith(".cue")) {
          addChild(new CueFolder(f));
        } else {
          /* Optionally ignore empty directories */
          if (f.isDirectory() && configuration.isHideEmptyFolders() && !FileUtil.isFolderRelevant(f, configuration)) {
            LOGGER.debug("Ignoring empty/non-relevant directory: " + f.getName());
          } else { // Otherwise add the file
            RealFile rf = new RealFile(f);
            if (searchList != null) {
              searchList.add(rf);
            }
            addChild(rf);
          }
        }
      }

      // FIXME this causes folder thumbnails to take precedence over file thumbnails
      if (f.isFile()) {
        if (lcFilename.equals("folder.jpg") || lcFilename.equals("folder.png") || (lcFilename.contains("albumart") && lcFilename.endsWith(".jpg"))) {
          potentialCover = f;
        }
      }
    }
  }

  private List<File> getFileList() {
    List<File> out = new ArrayList<>();

    for (File file : this.conf.getFiles()) {
      if (file != null && file.isDirectory()) {
        if (file.canRead()) {
          File[] files = file.listFiles();

          if (files == null) {
            LOGGER.warn("Can't read files from directory: {}", file.getAbsolutePath());
          } else {
            out.addAll(Arrays.asList(files));
          }
        } else {
          LOGGER.warn("Can't read directory: {}", file.getAbsolutePath());
        }
      }
    }

    return out;
  }

  @Override
  public boolean isValid() {
    return true;
  }

  @Override
  public boolean analyzeChildren(int count) {
    int currentChildrenCount = getChildren().size();
    int vfolder = 0;
    FileSearch fs = null;
    if (!discoverable.isEmpty() && configuration.getSearchInFolder()) {
      searchList = new ArrayList<>();
      fs = new FileSearch(searchList);
      addChild(new SearchFolder(fs));
    }
    while (((getChildren().size() - currentChildrenCount) < count) || (count == -1)) {
      if (vfolder < getConf().getChildren().size()) {
        addChild(new MapFile(getConf().getChildren().get(vfolder)));
        ++vfolder;
      } else {
        if (discoverable.isEmpty()) {
          break;
        }
        manageFile(discoverable.remove(0), null);
      }
    }
    if (fs != null) {
      fs.update(searchList);
    }
    return discoverable.isEmpty();
  }

  @Override
  public void discoverChildren() {
    discoverChildren(null);
  }

  @Override
  public void discoverChildren(String str) {
    //super.discoverChildren(str);

    if (discoverable == null) {
      discoverable = new ArrayList<>();
    } else {
      return;
    }

    int sm = configuration.getSortMethod(getPath());

    List<File> files = getFileList();

    // ATZ handling
    if (files.size() > configuration.getATZLimit() && StringUtils.isEmpty(forcedName)) {
      /*
       * Too many files to display at once, add A-Z folders
       * instead and let the filters begin
       *
       * Note: If we done this at the level directly above we don't do it again
       * since all files start with the same letter then
       */
      TreeMap<String, ArrayList<File>> map = new TreeMap<>();
      for (File f : files) {
        if ((!f.isFile() && !f.isDirectory()) || f.isHidden()) {
          // skip these
          continue;
        }
        if (f.isDirectory() && configuration.isHideEmptyFolders() && !FileUtil.isFolderRelevant(f, configuration)) {
          LOGGER.debug("Ignoring empty/non-relevant directory: " + f.getName());
          continue;
        }

        String filenameToSort = FileUtil.renameForSorting(f.getName());

        char c = filenameToSort.toUpperCase().charAt(0);

        if (!(c >= 'A' && c <= 'Z')) {
          // "other char"
          c = '#';
        }
        ArrayList<File> l = map.get(String.valueOf(c));
        if (l == null) {
          // new letter
          l = new ArrayList<>();
        }
        l.add(f);
        map.put(String.valueOf(c), l);
      }

      for (String letter : map.keySet()) {
        // loop over all letters, this avoids adding
        // empty letters
        ArrayList<File> l = map.get(letter);
        UMSUtils.sort(l, sm);
        MapFile mf = new MapFile(getConf(), l);
        mf.forcedName = letter;
        addChild(mf);
      }
      return;
    }

    UMSUtils.sort(files, (sm == UMSUtils.SORT_RANDOM ? UMSUtils.SORT_LOC_NAT : sm));

    for (File f : files) {
      if (f.isDirectory()) {
        discoverable.add(f); // manageFile(f);
      }
    }

    // For random sorting, we only randomize file entries
    if (sm == UMSUtils.SORT_RANDOM) {
      UMSUtils.sort(files, sm);
    }

    for (File f : files) {
      if (f.isFile()) {
        discoverable.add(f); // manageFile(f);
      }
    }
  }

  @Override
  public boolean isRefreshNeeded() {
    long modified = 0;

    for (File f : this.getConf().getFiles()) {
      if (f != null) {
        modified = Math.max(modified, f.lastModified());
      }
    }

    return (getLastRefreshTime() < modified);
  }

  @Override
  public void doRefreshChildren() {
    doRefreshChildren(null);
  }

  @Override
  public void doRefreshChildren(String str) {
    List<File> files = getFileList();
    List<File> addedFiles = new ArrayList<>();
    List<DLNAResource> removedFiles = new ArrayList<>();

    for (DLNAResource d : getChildren()) {
      boolean isNeedMatching = !(d.getClass() == MapFile.class || (d instanceof VirtualFolder && !(d instanceof DVDISOFile)));
      boolean found = foundInList(files, d);

      if (isNeedMatching && !found) {
        removedFiles.add(d);
      }
    }

    for (File f : files) {
      if (!f.isHidden() && (f.isDirectory() || FormatFactory.getAssociatedFormat(f.getName()) != null)) {
        addedFiles.add(f);
      }
    }

    for (DLNAResource f : removedFiles) {
      LOGGER.debug("File automatically removed: " + f.getName());
    }

    for (File f : addedFiles) {
      LOGGER.debug("File automatically added: " + f.getName());
    }

    // false: don't create the folder if it doesn't exist i.e. find the folder
    TranscodeVirtualFolder transcodeFolder = getTranscodeFolder(false);

    for (DLNAResource f : removedFiles) {
      getChildren().remove(f);

      if (transcodeFolder != null) {
        for (int j = transcodeFolder.getChildren().size() - 1; j >= 0; j--) {
          if (transcodeFolder.getChildren().get(j).getName().equals(f.getName())) {
            transcodeFolder.getChildren().remove(j);
          }
        }
      }
    }

    for (File f : addedFiles) {
      manageFile(f, str);
    }

    for (MapFileConfiguration f : this.getConf().getChildren()) {
      addChild(new MapFile(f));
    }
  }

  private boolean foundInList(List<File> files, DLNAResource dlna) {
    for (Iterator<File> it = files.iterator(); it.hasNext();) {
      File file = it.next();
      if (!file.isHidden() && isNameMatch(dlna, file) && (isRealFolder(dlna) || isSameLastModified(dlna, file))) {
        it.remove();
        return true;
      }
    }
    return false;
  }

  private boolean isSameLastModified(DLNAResource dlna, File file) {
    return dlna.getLastModified() == file.lastModified();
  }

  private boolean isRealFolder(DLNAResource dlna) {
    return dlna instanceof RealFile && dlna.isFolder();
  }

  private boolean isNameMatch(DLNAResource dlna, File file) {
    return (dlna.getName().equals(file.getName()) || isDVDIsoMatch(dlna, file));
  }

  private boolean isDVDIsoMatch(DLNAResource dlna, File file) {
    if (dlna instanceof DVDISOFile) {
      DVDISOFile dvdISOFile = (DVDISOFile) dlna;
      return dvdISOFile.getFilename().equals(file.getName());
    } else {
      return false;
    }
  }

  @Override
  public String getSystemName() {
    return getName();
  }

  @Override
  public String getThumbnailContentType() {
    String thumbnailIcon = this.getConf().getThumbnailIcon();
    if (thumbnailIcon != null && thumbnailIcon.toLowerCase().endsWith(".png")) {
      return HTTPResource.PNG_TYPEMIME;
    }
    return super.getThumbnailContentType();
  }

  @Override
  public InputStream getThumbnailInputStream() throws IOException {
    return this.getConf().getThumbnailIcon() != null
      ? getResourceInputStream(this.getConf().getThumbnailIcon())
      : super.getThumbnailInputStream();
  }

  @Override
  public long length() {
    return 0;
  }

  @Override
  public String getName() {
    if (StringUtils.isEmpty(forcedName)) {
      return this.getConf().getName();
    }
    return forcedName;
  }

  @Override
  public boolean isFolder() {
    return true;
  }

  @Override
  public InputStream getInputStream() throws IOException {
    return null;
  }

  @Override
  public boolean allowScan() {
    return isFolder();
  }

  /* (non-Javadoc)
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return "MapFile [name=" + getName() + ", id=" + getResourceId() + ", format=" + getFormat() + ", children=" + getChildren() + "]";
  }

  /**
   * @return the conf
   * @since 1.50
   */
  protected MapFileConfiguration getConf() {
    return conf;
  }

  /**
   * @param conf the conf to set
   * @since 1.50
   */
  protected void setConf(MapFileConfiguration conf) {
    this.conf = conf;
  }

  /**
   * @return the potentialCover
   * @since 1.50
   */
  public File getPotentialCover() {
    return potentialCover;
  }

  /**
   * @param potentialCover the potentialCover to set
   * @since 1.50
   */
  public void setPotentialCover(File potentialCover) {
    this.potentialCover = potentialCover;
  }

  @Override
  public boolean isSearched() {
    return (getParent() instanceof SearchFolder);
  }

  private File getPath() {
    if (this instanceof RealFile) {
      return ((RealFile) this).getFile();
    }
    return null;
  }
}
TOP

Related Classes of net.pms.dlna.MapFile

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.