Search in sources :

Example 1 with MediaLibrary

use of net.pms.dlna.virtual.MediaLibrary in project UniversalMediaServer by UniversalMediaServer.

the class PMS method init.

/**
 * Initialization procedure for UMS.
 *
 * @return <code>true</code> if the server has been initialized correctly.
 *         <code>false</code> if initialization was aborted.
 * @throws Exception
 */
private boolean init() throws Exception {
    // Gather and log system information from a separate thread
    LogSystemInformationMode logSystemInfo = configuration.getLogSystemInformation();
    if (logSystemInfo == LogSystemInformationMode.ALWAYS || logSystemInfo == LogSystemInformationMode.TRACE_ONLY && LOGGER.isTraceEnabled()) {
        new SystemInformation().start();
    }
    // Show the language selection dialog before displayBanner();
    if (!isHeadless() && (configuration.getLanguageRawString() == null || !Languages.isValid(configuration.getLanguageRawString()))) {
        LanguageSelection languageDialog = new LanguageSelection(null, PMS.getLocale(), false);
        languageDialog.show();
        if (languageDialog.isAborted()) {
            return false;
        }
    }
    // Initialize splash screen
    Splash splash = null;
    if (!isHeadless()) {
        splash = new Splash(configuration);
    }
    // Call this as early as possible
    displayBanner();
    // Initialize database
    Tables.checkTables();
    // Log registered ImageIO plugins
    if (LOGGER.isTraceEnabled()) {
        LOGGER.trace("");
        LOGGER.trace("Registered ImageIO reader classes:");
        Iterator<ImageReaderSpi> readerIterator = IIORegistry.getDefaultInstance().getServiceProviders(ImageReaderSpi.class, true);
        while (readerIterator.hasNext()) {
            ImageReaderSpi reader = readerIterator.next();
            LOGGER.trace("Reader class: {}", reader.getPluginClassName());
        }
        LOGGER.trace("");
        LOGGER.trace("Registered ImageIO writer classes:");
        Iterator<ImageWriterSpi> writerIterator = IIORegistry.getDefaultInstance().getServiceProviders(ImageWriterSpi.class, true);
        while (writerIterator.hasNext()) {
            ImageWriterSpi writer = writerIterator.next();
            LOGGER.trace("Writer class: {}", writer.getPluginClassName());
        }
        LOGGER.trace("");
    }
    // Wizard
    if (configuration.isRunWizard() && !isHeadless()) {
        // Hide splash screen
        if (splash != null) {
            splash.setVisible(false);
        }
        // Run wizard
        Wizard.run(configuration);
        // Unhide splash screen
        if (splash != null) {
            splash.setVisible(true);
        }
    }
    // The public VERSION field is deprecated.
    // This is a temporary fix for backwards compatibility
    VERSION = getVersion();
    fileWatcher = new FileWatcher();
    globalRepo = new GlobalIdRepo();
    AutoUpdater autoUpdater = null;
    if (Build.isUpdatable()) {
        String serverURL = Build.getUpdateServerURL();
        autoUpdater = new AutoUpdater(serverURL, getVersion());
    }
    registry = createSystemUtils();
    // Create SleepManager
    sleepManager = new SleepManager();
    if (!isHeadless()) {
        frame = new LooksFrame(autoUpdater, configuration);
    } else {
        LOGGER.info("Graphics environment not available or headless mode is forced");
        LOGGER.info("Switching to console mode");
        frame = new DummyFrame();
    }
    // Close splash screen
    if (splash != null) {
        splash.dispose();
        splash = null;
    }
    /*
		 * we're here:
		 *
		 *     main() -> createInstance() -> init()
		 *
		 * which means we haven't created the instance returned by get()
		 * yet, so the frame appender can't access the frame in the
		 * standard way i.e. PMS.get().getFrame(). we solve it by
		 * inverting control ("don't call us; we'll call you") i.e.
		 * we notify the appender when the frame is ready rather than
		 * e.g. making getFrame() static and requiring the frame
		 * appender to poll it.
		 *
		 * XXX an event bus (e.g. MBassador or Guava EventBus
		 * (if they fix the memory-leak issue)) notification
		 * would be cleaner and could support other lifecycle
		 * notifications (see above).
		 */
    FrameAppender.setFrame(frame);
    configuration.addConfigurationListener(new ConfigurationListener() {

        @Override
        public void configurationChanged(ConfigurationEvent event) {
            if ((!event.isBeforeUpdate()) && PmsConfiguration.NEED_RELOAD_FLAGS.contains(event.getPropertyName())) {
                frame.setReloadable(true);
            }
        }
    });
    // Web stuff
    if (configuration.useWebInterface()) {
        try {
            web = new RemoteWeb(configuration.getWebPort());
        } catch (BindException b) {
            LOGGER.error("FATAL ERROR: Unable to bind web interface on port: " + configuration.getWebPort() + ", because: " + b.getMessage());
            LOGGER.info("Maybe another process is running or the hostname is wrong.");
        }
    }
    // init Credentials
    credMgr = new CredMgr(configuration.getCredFile());
    // init dbs
    keysDb = new UmsKeysDb();
    infoDb = new InfoDb();
    codes = new CodeDb();
    masterCode = null;
    RendererConfiguration.loadRendererConfigurations(configuration);
    // Now that renderer confs are all loaded, we can start searching for renderers
    UPNPHelper.getInstance().init();
    // launch ChromecastMgr
    jmDNS = null;
    launchJmDNSRenderers();
    OutputParams outputParams = new OutputParams(configuration);
    // Prevent unwanted GUI buffer artifacts (and runaway timers)
    outputParams.hidebuffer = true;
    // Make sure buffer is destroyed
    outputParams.cleanup = true;
    // Initialize MPlayer and FFmpeg to let them generate fontconfig cache/s
    if (!configuration.isDisableSubtitles()) {
        LOGGER.info("Checking the fontconfig cache in the background, this can take two minutes or so.");
        ProcessWrapperImpl mplayer = new ProcessWrapperImpl(new String[] { configuration.getMplayerPath(), "dummy" }, outputParams);
        mplayer.runInNewThread();
        /**
         * Note: Different versions of fontconfig and bitness require
         * different caches, which is why here we ask FFmpeg (64-bit
         * if possible) to create a cache.
         * This should result in all of the necessary caches being built.
         */
        if (!Platform.isWindows() || Platform.is64Bit()) {
            ProcessWrapperImpl ffmpeg = new ProcessWrapperImpl(new String[] { configuration.getFfmpegPath(), "-y", "-f", "lavfi", "-i", "nullsrc=s=720x480:d=1:r=1", "-vf", "ass=DummyInput.ass", "-target", "ntsc-dvd", "-" }, outputParams);
            ffmpeg.runInNewThread();
        }
    }
    frame.setStatusCode(0, Messages.getString("PMS.130"), "icon-status-connecting.png");
    // Check the existence of VSFilter / DirectVobSub
    if (registry.isAvis() && registry.getAvsPluginsDir() != null) {
        LOGGER.debug("AviSynth plugins directory: " + registry.getAvsPluginsDir().getAbsolutePath());
        File vsFilterDLL = new File(registry.getAvsPluginsDir(), "VSFilter.dll");
        if (vsFilterDLL.exists()) {
            LOGGER.debug("VSFilter / DirectVobSub was found in the AviSynth plugins directory.");
        } else {
            File vsFilterDLL2 = new File(registry.getKLiteFiltersDir(), "vsfilter.dll");
            if (vsFilterDLL2.exists()) {
                LOGGER.debug("VSFilter / DirectVobSub was found in the K-Lite Codec Pack filters directory.");
            } else {
                LOGGER.info("VSFilter / DirectVobSub was not found. This can cause problems when trying to play subtitled videos with AviSynth.");
            }
        }
    }
    // Check if VLC is found
    String vlcVersion = registry.getVlcVersion();
    String vlcPath = registry.getVlcPath();
    if (vlcVersion != null && vlcPath != null) {
        LOGGER.info("Found VLC version " + vlcVersion + " at: " + vlcPath);
        Version vlc = new Version(vlcVersion);
        Version requiredVersion = new Version("2.0.2");
        if (vlc.compareTo(requiredVersion) <= 0) {
            LOGGER.error("Only VLC versions 2.0.2 and above are supported");
        }
    }
    // Check if Kerio is installed
    if (registry.isKerioFirewall()) {
        LOGGER.info("Detected Kerio firewall");
    }
    // Force use of specific DVR-MS muxer when it's installed in the right place
    File dvrsMsffmpegmuxer = new File("win32/dvrms/ffmpeg_MPGMUX.exe");
    if (dvrsMsffmpegmuxer.exists()) {
        configuration.setFfmpegAlternativePath(dvrsMsffmpegmuxer.getAbsolutePath());
    }
    // Disable jaudiotagger logging
    LogManager.getLogManager().readConfiguration(new ByteArrayInputStream("org.jaudiotagger.level=OFF".getBytes(StandardCharsets.US_ASCII)));
    // Wrap System.err
    System.setErr(new PrintStream(new SystemErrWrapper(), true, StandardCharsets.UTF_8.name()));
    server = new HTTPServer(configuration.getServerPort());
    /*
		 * XXX: keep this here (i.e. after registerExtensions and before registerPlayers) so that plugins
		 * can register custom players correctly (e.g. in the GUI) and/or add/replace custom formats
		 *
		 * XXX: if a plugin requires initialization/notification even earlier than
		 * this, then a new external listener implementing a new callback should be added
		 * e.g. StartupListener.registeredExtensions()
		 */
    try {
        ExternalFactory.lookup();
    } catch (Exception e) {
        LOGGER.error("Error loading plugins", e);
    }
    // Initialize a player factory to register all players
    PlayerFactory.initialize();
    // Instantiate listeners that require registered players.
    ExternalFactory.instantiateLateListeners();
    // a static block in Player doesn't work (i.e. is called too late).
    // this must always be called *after* the plugins have loaded.
    // here's as good a place as any
    Player.initializeFinalizeTranscoderArgsListeners();
    // Any plugin-defined players are now registered, create the gui view.
    frame.addEngines();
    // file AFTER plugins are started
    if (!isHeadless()) {
        // but only if we got a GUI of course
        ((LooksFrame) frame).getPt().init();
    }
    boolean binding = false;
    try {
        binding = server.start();
    } catch (BindException b) {
        LOGGER.error("FATAL ERROR: Unable to bind on port: " + configuration.getServerPort() + ", because: " + b.getMessage());
        LOGGER.info("Maybe another process is running or the hostname is wrong.");
    }
    new Thread("Connection Checker") {

        @Override
        public void run() {
            try {
                Thread.sleep(7000);
            } catch (InterruptedException e) {
            }
            if (foundRenderers.isEmpty()) {
                frame.setStatusCode(0, Messages.getString("PMS.0"), "icon-status-notconnected.png");
            } else {
                frame.setStatusCode(0, Messages.getString("PMS.18"), "icon-status-connected.png");
            }
        }
    }.start();
    if (!binding) {
        return false;
    }
    if (web != null && web.getServer() != null) {
        LOGGER.info("WEB interface is available at: " + web.getUrl());
    }
    // initialize the cache
    if (configuration.getUseCache()) {
        mediaLibrary = new MediaLibrary();
        LOGGER.info("A tiny cache admin interface is available at: http://" + server.getHost() + ":" + server.getPort() + "/console/home");
    }
    // XXX: this must be called:
    // a) *after* loading plugins i.e. plugins register root folders then RootFolder.discoverChildren adds them
    // b) *after* mediaLibrary is initialized, if enabled (above)
    getRootFolder(RendererConfiguration.getDefaultConf());
    frame.serverReady();
    ready = true;
    // UPNPHelper.sendByeBye();
    Runtime.getRuntime().addShutdownHook(new Thread("UMS Shutdown") {

        @Override
        public void run() {
            try {
                for (ExternalListener l : ExternalFactory.getExternalListeners()) {
                    l.shutdown();
                }
                UPNPHelper.shutDownListener();
                UPNPHelper.sendByeBye();
                LOGGER.debug("Forcing shutdown of all active processes");
                for (Process p : currentProcesses) {
                    try {
                        p.exitValue();
                    } catch (IllegalThreadStateException ise) {
                        LOGGER.trace("Forcing shutdown of process: " + p);
                        ProcessUtil.destroy(p);
                    }
                }
                get().getServer().stop();
                Thread.sleep(500);
            } catch (InterruptedException e) {
                LOGGER.debug("Caught exception", e);
            }
            LOGGER.info("Stopping " + PropertiesUtil.getProjectProperties().get("project.name") + " " + getVersion());
            /**
             * Stopping logging gracefully (flushing logs)
             * No logging is available after this point
             */
            ILoggerFactory iLoggerContext = LoggerFactory.getILoggerFactory();
            if (iLoggerContext instanceof LoggerContext) {
                ((LoggerContext) iLoggerContext).stop();
            } else {
                LOGGER.error("Unable to shut down logging gracefully");
            }
        }
    });
    configuration.setAutoSave();
    UPNPHelper.sendByeBye();
    LOGGER.trace("Waiting 250 milliseconds...");
    Thread.sleep(250);
    UPNPHelper.sendAlive();
    LOGGER.trace("Waiting 250 milliseconds...");
    Thread.sleep(250);
    UPNPHelper.listen();
    // Initiate a library scan in case files were added to folders while UMS was closed.
    if (getConfiguration().getUseCache() && getConfiguration().isScanSharedFoldersOnStartup()) {
        getDatabase().scanLibrary();
    }
    return true;
}
Also used : ConfigurationEvent(org.apache.commons.configuration.event.ConfigurationEvent) MediaLibrary(net.pms.dlna.virtual.MediaLibrary) RemoteWeb(net.pms.remote.RemoteWeb) ConfigurationListener(org.apache.commons.configuration.event.ConfigurationListener) ImageReaderSpi(javax.imageio.spi.ImageReaderSpi) BindException(java.net.BindException) LoggerContext(ch.qos.logback.classic.LoggerContext) AccessControlException(java.security.AccessControlException) UnsupportedCharsetException(java.nio.charset.UnsupportedCharsetException) ConfigurationException(org.apache.commons.configuration.ConfigurationException) BindException(java.net.BindException) SQLException(java.sql.SQLException) IllegalCharsetNameException(java.nio.charset.IllegalCharsetNameException) HTTPServer(net.pms.network.HTTPServer) ILoggerFactory(org.slf4j.ILoggerFactory) ExternalListener(net.pms.external.ExternalListener) ImageWriterSpi(javax.imageio.spi.ImageWriterSpi) AutoUpdater(net.pms.update.AutoUpdater)

Aggregations

LoggerContext (ch.qos.logback.classic.LoggerContext)1 BindException (java.net.BindException)1 IllegalCharsetNameException (java.nio.charset.IllegalCharsetNameException)1 UnsupportedCharsetException (java.nio.charset.UnsupportedCharsetException)1 AccessControlException (java.security.AccessControlException)1 SQLException (java.sql.SQLException)1 ImageReaderSpi (javax.imageio.spi.ImageReaderSpi)1 ImageWriterSpi (javax.imageio.spi.ImageWriterSpi)1 MediaLibrary (net.pms.dlna.virtual.MediaLibrary)1 ExternalListener (net.pms.external.ExternalListener)1 HTTPServer (net.pms.network.HTTPServer)1 RemoteWeb (net.pms.remote.RemoteWeb)1 AutoUpdater (net.pms.update.AutoUpdater)1 ConfigurationException (org.apache.commons.configuration.ConfigurationException)1 ConfigurationEvent (org.apache.commons.configuration.event.ConfigurationEvent)1 ConfigurationListener (org.apache.commons.configuration.event.ConfigurationListener)1 ILoggerFactory (org.slf4j.ILoggerFactory)1