예제 #1
0
  private static void assertFolderIsValid(File folder) throws IOException {
    if (!folder.isDirectory()) {
      throw new IOException("Temp directory must be a directory: " + folder);
    }

    if (!FileUtil.isDirectoryWritable(folder)) {
      throw new IOException("Temp directory is not writable: " + folder);
    }
  }
예제 #2
0
 @Override
 public boolean isValid() {
   checktype();
   setSrtFile(FileUtil.doesSubtitlesExists(pere, null));
   return getFormat() != null;
 }
예제 #3
0
 @Override
 public String getSystemName() {
   return FileUtil.getFileNameWithoutExtension(pere.getAbsolutePath())
       + "."
       + FileUtil.getExtension(name);
 }
예제 #4
0
  /**
   * This method populates the supplied {@link OutputParams} object with the correct subtitles (sid)
   * based on the given filename, its MediaInfo metadata and PMS configuration settings.
   *
   * <p>TODO: Rewrite this crazy method to be more concise and logical.
   *
   * @param fileName The file name used to determine the availability of subtitles.
   * @param media The MediaInfo metadata for the file.
   * @param params The parameters to populate.
   */
  public static void setSubtitleOutputParameters(
      String fileName, DLNAMediaInfo media, OutputParams params) {
    PmsConfiguration configuration = PMS.getConfiguration(params);
    String currentLang = null;
    DLNAMediaSubtitle matchedSub = null;

    if (params.aid != null) {
      currentLang = params.aid.getLang();
    }

    if (params.sid != null && params.sid.getId() == -1) {
      LOGGER.trace("Don't want subtitles!");
      params.sid = null;
      return;
    }

    /** Check for live subtitles */
    if (params.sid != null && !StringUtils.isEmpty(params.sid.getLiveSubURL())) {
      LOGGER.debug("Live subtitles " + params.sid.getLiveSubURL());
      try {
        matchedSub = params.sid;
        String file =
            OpenSubtitle.fetchSubs(matchedSub.getLiveSubURL(), matchedSub.getLiveSubFile());
        if (!StringUtils.isEmpty(file)) {
          matchedSub.setExternalFile(new File(file));
          params.sid = matchedSub;
          return;
        }
      } catch (IOException e) {
      }
    }

    StringTokenizer st = new StringTokenizer(configuration.getAudioSubLanguages(), ";");

    /** Check for external and internal subtitles matching the user's language preferences */
    boolean matchedInternalSubtitles = false;
    boolean matchedExternalSubtitles = false;
    while (st.hasMoreTokens()) {
      String pair = st.nextToken();
      if (pair.contains(",")) {
        String audio = pair.substring(0, pair.indexOf(','));
        String sub = pair.substring(pair.indexOf(',') + 1);
        audio = audio.trim();
        sub = sub.trim();
        LOGGER.trace(
            "Searching for a match for: " + currentLang + " with " + audio + " and " + sub);

        if (Iso639.isCodesMatching(audio, currentLang)
            || (currentLang != null && audio.equals("*"))) {
          if (sub.equals("off")) {
            /**
             * Ignore the "off" language for external subtitles if the user setting is enabled TODO:
             * Prioritize multiple external subtitles properly instead of just taking the first one
             * we load
             */
            if (configuration.isForceExternalSubtitles()) {
              for (DLNAMediaSubtitle present_sub : media.getSubtitleTracksList()) {
                if (present_sub.getExternalFile() != null) {
                  matchedSub = present_sub;
                  matchedExternalSubtitles = true;
                  LOGGER.trace(
                      "Ignoring the \"off\" language because there are external subtitles");
                  break;
                }
              }
            }
            if (!matchedExternalSubtitles) {
              matchedSub = new DLNAMediaSubtitle();
              matchedSub.setLang("off");
            }
          } else {
            for (DLNAMediaSubtitle present_sub : media.getSubtitleTracksList()) {
              if (present_sub.matchCode(sub) || sub.equals("*")) {
                if (present_sub.getExternalFile() != null) {
                  if (configuration.isAutoloadExternalSubtitles()) {
                    // Subtitle is external and we want external subtitles, look no further
                    matchedSub = present_sub;
                    LOGGER.trace("Matched external subtitles track: " + matchedSub);
                    break;
                  } else {
                    // Subtitle is external but we do not want external subtitles, keep searching
                    LOGGER.trace(
                        "External subtitles ignored because of user setting: " + present_sub);
                  }
                } else if (!matchedInternalSubtitles) {
                  matchedSub = present_sub;
                  LOGGER.trace("Matched internal subtitles track: " + matchedSub);
                  if (configuration.isAutoloadExternalSubtitles()) {
                    // Subtitle is internal and we will wait to see if an external one is available
                    // instead
                    matchedInternalSubtitles = true;
                  } else {
                    // Subtitle is internal and we will use it
                    break;
                  }
                }
              }
            }
          }

          if (matchedSub != null && !matchedInternalSubtitles) {
            break;
          }
        }
      }
    }

    /**
     * Check for external subtitles that were skipped in the above code block because they didn't
     * match language preferences, if there wasn't already a match and the user settings specify it.
     */
    if (matchedSub == null && configuration.isForceExternalSubtitles()) {
      for (DLNAMediaSubtitle present_sub : media.getSubtitleTracksList()) {
        if (present_sub.getExternalFile() != null) {
          matchedSub = present_sub;
          LOGGER.trace(
              "Matched external subtitles track that did not match language preferences: "
                  + matchedSub);
          break;
        }
      }
    }

    /**
     * Disable chosen subtitles if the user has disabled all subtitles or if the language
     * preferences have specified the "off" language.
     *
     * <p>TODO: Can't we save a bunch of looping by checking for isDisableSubtitles just after the
     * Live Subtitles check above?
     */
    if (matchedSub != null && params.sid == null) {
      if (configuration.isDisableSubtitles()
          || (matchedSub.getLang() != null && matchedSub.getLang().equals("off"))) {
        LOGGER.trace("Disabled the subtitles: " + matchedSub);
      } else {
        params.sid = matchedSub;
      }
    }

    /** Check for forced subtitles. */
    if (!configuration.isDisableSubtitles() && params.sid == null && media != null) {
      // Check for subtitles again
      File video = new File(fileName);
      FileUtil.isSubtitlesExists(video, media, false);

      if (configuration.isAutoloadExternalSubtitles()) {
        boolean forcedSubsFound = false;
        // Priority to external subtitles
        for (DLNAMediaSubtitle sub : media.getSubtitleTracksList()) {
          if (matchedSub != null
              && matchedSub.getLang() != null
              && matchedSub.getLang().equals("off")) {
            st = new StringTokenizer(configuration.getForcedSubtitleTags(), ",");

            while (sub.getSubtitlesTrackTitleFromMetadata() != null && st.hasMoreTokens()) {
              String forcedTags = st.nextToken();
              forcedTags = forcedTags.trim();

              if (sub.getSubtitlesTrackTitleFromMetadata().toLowerCase().contains(forcedTags)
                  && Iso639.isCodesMatching(
                      sub.getLang(), configuration.getForcedSubtitleLanguage())) {
                LOGGER.trace(
                    "Forcing preferred subtitles: "
                        + sub.getLang()
                        + "/"
                        + sub.getSubtitlesTrackTitleFromMetadata());
                LOGGER.trace("Forced subtitles track: " + sub);

                if (sub.getExternalFile() != null) {
                  LOGGER.trace(
                      "Found external forced file: " + sub.getExternalFile().getAbsolutePath());
                }
                params.sid = sub;
                forcedSubsFound = true;
                break;
              }
            }
            if (forcedSubsFound == true) {
              break;
            }
          } else {
            LOGGER.trace("Found subtitles track: " + sub);

            if (sub.getExternalFile() != null) {
              LOGGER.trace("Found external file: " + sub.getExternalFile().getAbsolutePath());
              params.sid = sub;
              break;
            }
          }
        }
      }
      if (matchedSub != null
          && matchedSub.getLang() != null
          && matchedSub.getLang().equals("off")) {
        return;
      }

      if (params.sid == null) {
        st = new StringTokenizer(UMSUtils.getLangList(params.mediaRenderer), ",");
        while (st.hasMoreTokens()) {
          String lang = st.nextToken();
          lang = lang.trim();
          LOGGER.trace("Looking for a subtitle track with lang: " + lang);
          for (DLNAMediaSubtitle sub : media.getSubtitleTracksList()) {
            if (sub.matchCode(lang)
                && !(!configuration.isAutoloadExternalSubtitles()
                    && sub.getExternalFile() != null)) {
              params.sid = sub;
              LOGGER.trace("Matched subtitles track: " + params.sid);
              return;
            }
          }
        }
      }
    }
  }
  @Override
  public void handle(HttpExchange t) throws IOException {
    if (RemoteUtil.deny(t)) {
      throw new IOException("Access denied");
    }
    RootFolder root = parent.getRoot(RemoteUtil.userName(t), t);
    if (root == null) {
      throw new IOException("Unknown root");
    }
    Headers h = t.getRequestHeaders();
    for (String h1 : h.keySet()) {
      LOGGER.debug("key " + h1 + "=" + h.get(h1));
    }
    String id = RemoteUtil.getId(path, t);
    id = RemoteUtil.strip(id);
    RendererConfiguration r = render;
    if (render == null) {
      r = root.getDefaultRenderer();
    }
    DLNAResource dlna = root.getDLNAResource(id, r);
    if (dlna == null) {
      // another error
      LOGGER.debug("media unkonwn");
      throw new IOException("Bad id");
    }
    if (!dlna.isCodeValid(dlna)) {
      LOGGER.debug("coded object with invalid code");
      throw new IOException("Bad code");
    }
    DLNAMediaSubtitle sid = null;
    long len = dlna.length();
    Range range = RemoteUtil.parseRange(t.getRequestHeaders(), len);
    String mime = root.getDefaultRenderer().getMimeType(dlna.mimeType());
    // DLNAResource dlna = res.get(0);
    WebRender render = (WebRender) r;
    DLNAMediaInfo m = dlna.getMedia();
    if (m == null) {
      m = new DLNAMediaInfo();
      dlna.setMedia(m);
    }
    if (mime.equals(FormatConfiguration.MIMETYPE_AUTO) && m.getMimeType() != null) {
      mime = m.getMimeType();
    }
    int code = 200;
    dlna.setDefaultRenderer(r);
    if (dlna.getFormat().isVideo()) {
      if (flash) {
        mime = "video/flash";
      } else if (!RemoteUtil.directmime(mime) || RemoteUtil.transMp4(mime, m)) {
        mime = render != null ? render.getVideoMimeType() : RemoteUtil.transMime();
        if (FileUtil.isUrl(dlna.getSystemName())) {
          dlna.setPlayer(new FFmpegWebVideo());
        } else {
          dlna.setPlayer(new FFMpegVideo());
        }
        // code = 206;
      }
      if (PMS.getConfiguration().getWebSubs()
          && dlna.getMediaSubtitle() != null
          && dlna.getMediaSubtitle().isExternal()) {
        // fetched on the side
        sid = dlna.getMediaSubtitle();
        dlna.setMediaSubtitle(null);
      }
    }

    if (!RemoteUtil.directmime(mime) && dlna.getFormat().isAudio()) {
      dlna.setPlayer(new FFmpegAudio());
      code = 206;
    }

    m.setMimeType(mime);
    LOGGER.debug("dumping media " + mime + " " + dlna);
    InputStream in = dlna.getInputStream(range, root.getDefaultRenderer());
    Headers hdr = t.getResponseHeaders();
    hdr.add("Content-Type", mime);
    hdr.add("Accept-Ranges", "bytes");
    if (range != null) {
      long end = range.asByteRange().getEnd();
      long start = range.asByteRange().getStart();
      String rStr = start + "-" + end + "/*";
      hdr.add("Content-Range", "bytes " + rStr);
      if (start != 0) {
        code = 206;
      }
    }
    hdr.add("Server", PMS.get().getServerName());
    hdr.add("Connection", "keep-alive");
    t.sendResponseHeaders(code, 0);
    OutputStream os = t.getResponseBody();
    render.start(dlna);
    if (sid != null) {
      dlna.setMediaSubtitle(sid);
    }
    RemoteUtil.dump(in, os, render);
  }