Search in sources :

Example 6 with ExternalListener

use of net.pms.external.ExternalListener in project UniversalMediaServer by UniversalMediaServer.

the class DLNAResource method stopPlaying.

/**
 * Plugin implementation. When this item is going to stop playing, it will notify all the StartStopListener
 * objects available.
 *
 * @see StartStopListener
 */
public void stopPlaying(final String rendererId, final RendererConfiguration incomingRenderer) {
    final DLNAResource self = this;
    final String requestId = getRequestId(rendererId);
    Runnable defer = new Runnable() {

        @Override
        public void run() {
            long start = startTime;
            try {
                Thread.sleep(STOP_PLAYING_DELAY);
            } catch (InterruptedException e) {
                LOGGER.error("stopPlaying sleep interrupted", e);
            }
            synchronized (requestIdToRefcount) {
                final Integer refCount = requestIdToRefcount.get(requestId);
                assert refCount != null;
                assert refCount > 0;
                requestIdToRefcount.put(requestId, refCount - 1);
                if (start != startTime) {
                    return;
                }
                Runnable r = new Runnable() {

                    @Override
                    public void run() {
                        if (refCount == 1) {
                            requestIdToRefcount.put(requestId, 0);
                            InetAddress rendererIp;
                            try {
                                rendererIp = InetAddress.getByName(rendererId);
                                RendererConfiguration renderer;
                                if (incomingRenderer == null) {
                                    renderer = RendererConfiguration.getRendererConfigurationBySocketAddress(rendererIp);
                                } else {
                                    renderer = incomingRenderer;
                                }
                                String rendererName = "unknown renderer";
                                try {
                                    // Reset only if another item hasn't already begun playing
                                    if (renderer.getPlayingRes() == self) {
                                        renderer.setPlayingRes(null);
                                    }
                                    rendererName = renderer.getRendererName();
                                } catch (NullPointerException e) {
                                }
                                if (!quietPlay()) {
                                    LOGGER.info("Stopped playing " + getName() + " on your " + rendererName);
                                    LOGGER.debug("The full filename of which is: " + getSystemName() + " and the address of the renderer is: " + rendererId);
                                }
                            } catch (UnknownHostException ex) {
                                LOGGER.debug("" + ex);
                            }
                            internalStop();
                            for (final ExternalListener listener : ExternalFactory.getExternalListeners()) {
                                if (listener instanceof StartStopListener) {
                                    // run these asynchronously for slow handlers (e.g. logging, scrobbling)
                                    Runnable fireStartStopEvent = new Runnable() {

                                        @Override
                                        public void run() {
                                            try {
                                                ((StartStopListener) listener).donePlaying(media, self);
                                            } catch (Throwable t) {
                                                LOGGER.error("Notification of donePlaying event failed for StartStopListener {}", listener.getClass(), t);
                                            }
                                        }
                                    };
                                    new Thread(fireStartStopEvent, "StopPlaying Event for " + listener.name()).start();
                                }
                            }
                        }
                    }
                };
                new Thread(r, "StopPlaying Event").start();
            }
        }
    };
    new Thread(defer, "StopPlaying Event Deferrer").start();
}
Also used : UnknownHostException(java.net.UnknownHostException) StartStopListener(net.pms.external.StartStopListener) RendererConfiguration(net.pms.configuration.RendererConfiguration) ExternalListener(net.pms.external.ExternalListener) InetAddress(java.net.InetAddress)

Example 7 with ExternalListener

use of net.pms.external.ExternalListener 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)

Example 8 with ExternalListener

use of net.pms.external.ExternalListener in project UniversalMediaServer by UniversalMediaServer.

the class PluginTab method addPlugins.

public void addPlugins() {
    FormLayout layout = new FormLayout("fill:10:grow", "p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p");
    pPlugins.setLayout(layout);
    List<ExternalListener> externalListeners = ExternalFactory.getExternalListeners();
    for (final ExternalListener listener : externalListeners) {
        if (!appendPlugin(listener)) {
            break;
        }
    }
    pPlugins.setVisible(externalListeners.size() > 0);
    installedPluginsSeparator.setVisible(externalListeners.size() > 0);
}
Also used : FormLayout(com.jgoodies.forms.layout.FormLayout) ExternalListener(net.pms.external.ExternalListener)

Aggregations

ExternalListener (net.pms.external.ExternalListener)8 RendererConfiguration (net.pms.configuration.RendererConfiguration)3 InetAddress (java.net.InetAddress)2 UnknownHostException (java.net.UnknownHostException)2 StartStopListener (net.pms.external.StartStopListener)2 LoggerContext (ch.qos.logback.classic.LoggerContext)1 FormLayout (com.jgoodies.forms.layout.FormLayout)1 File (java.io.File)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 DeviceConfiguration (net.pms.configuration.DeviceConfiguration)1 PmsConfiguration (net.pms.configuration.PmsConfiguration)1 MediaLibrary (net.pms.dlna.virtual.MediaLibrary)1 TranscodeVirtualFolder (net.pms.dlna.virtual.TranscodeVirtualFolder)1 VirtualFolder (net.pms.dlna.virtual.VirtualFolder)1