All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.co.caprica.vlcj.factory.MediaPlayerFactory Maven / Gradle / Ivy

There is a newer version: 5.0.0-M1
Show newest version
/*
 * This file is part of VLCJ.
 *
 * VLCJ 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.
 *
 * VLCJ 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 VLCJ.  If not, see .
 *
 * Copyright 2009-2019 Caprica Software Limited.
 */

package uk.co.caprica.vlcj.factory;

import com.sun.jna.Native;
import uk.co.caprica.vlcj.binding.LibVlc;
import uk.co.caprica.vlcj.binding.LinuxNativeInit;
import uk.co.caprica.vlcj.binding.RuntimeUtil;
import uk.co.caprica.vlcj.binding.internal.libvlc_instance_t;
import uk.co.caprica.vlcj.factory.discovery.NativeDiscovery;
import uk.co.caprica.vlcj.support.eventmanager.TaskExecutor;
import uk.co.caprica.vlcj.support.version.LibVlcVersion;

import java.util.Collection;

/**
 * Factory for creating media player instances and associated components.
 * 

* When using VLC options/arguments to initialise the factory, generally any options that enable/disable modules (e.g. * video/audio filters) must be set via the factory instance and not when invoking * {@link uk.co.caprica.vlcj.player.base.MediaApi#play(String, String...)}. However, the module-specific * options may be able to be passed as media options and be effective via that play call. *

* The factory will attempt to automatically discover the location of the required LibVLC native library, so it should * just work by default (at least for the most common/likely environment configurations). If you have other requirements * for the native library discovery mechanism, you can pass in your own implementation of {@link NativeDiscovery} when * you create the factory. *

* You should explicitly {@link #release()} the factory when your application terminates to properly clean up native * resources. *

* The factory also provides access to the native libvlc Logger and other resources such as the list of audio outputs, * and the list of available audio and video filters. *

* You must make sure you keep a hard reference to the components created by this factory to prevent them from * going out of scope and being garbage-collected. If you allow one of these components to go out of scope, then * unpredictable behaviour will occur (such as events no longer seeming to fire) even though the video playback may * continue (since that happens via native code). You will also likely suffer fatal JVM crashes. *

* It is always a better strategy to reuse media player instances, rather than repeatedly creating * and destroying them. */ public class MediaPlayerFactory { /** * Custom one-time initialisation required for Linux. */ static { if (RuntimeUtil.isNix()) { LinuxNativeInit.init(); } } /** * Native library. */ protected final LibVlc libvlc; /** * Native library instance. */ protected final libvlc_instance_t libvlcInstance; /** * Single-threaded service to execute tasks that need to be off-loaded from a native callback thread. *

* See {@link #submit(Runnable)}. */ private final TaskExecutor executor = new TaskExecutor(); private final ApplicationApi applicationApi; private final AudioApi audioApi; private final DialogsApi dialogsApi; private final MediaDiscovererApi mediaDiscovererApi; private final EqualizerApi equalizerApi; private final MediaPlayerApi mediaPlayerApi; private final MediaApi mediaApi; private final RendererApi rendererApi; private final VideoSurfaceApi videoSurfaceApi; /** * Create a new media player factory. * * @param discovery native discovery used to locate the native LibVLC library, may be null * @param libvlcArgs array of options/arguments to pass to LibVLC for initialisation of the native library */ public MediaPlayerFactory(NativeDiscovery discovery, String... libvlcArgs) { this.libvlc = discoverNativeLibrary(discovery); this.libvlcInstance = newLibVlcInstance(libvlcArgs != null ? libvlcArgs : new String[0]); this.applicationApi = new ApplicationApi (this); this.audioApi = new AudioApi (this); this.dialogsApi = new DialogsApi (this); this.mediaDiscovererApi = new MediaDiscovererApi(this); this.equalizerApi = new EqualizerApi (this); this.mediaPlayerApi = new MediaPlayerApi (this); this.mediaApi = new MediaApi (this); this.rendererApi = new RendererApi (this); this.videoSurfaceApi = new VideoSurfaceApi (this); } /** * Create a new media player factory with default native discovery. *

* If you do not want to use native discovery, use the {@link #MediaPlayerFactory(NativeDiscovery, String...)} * constructor instead, passing null. * * @param libvlcArgs array of options/arguments to pass to LibVLC for initialisation of the native library */ public MediaPlayerFactory(String... libvlcArgs) { this(new NativeDiscovery(), libvlcArgs); } /** * Create a new media player factory. *

* If you do not want to use native discovery, pass null for the discovery parameter. * * @param discovery native discovery used to locate the native LibVLC library, may be null * @param libvlcArgs collection of options/arguments to pass to LibVLC for initialisation of the native library */ public MediaPlayerFactory(NativeDiscovery discovery, Collection libvlcArgs) { this(discovery, libvlcArgs.toArray(new String[libvlcArgs.size()])); } /** * Create a new media player factory with default native discovery. *

* If you do not want to use native discovery, use the {@link #MediaPlayerFactory(NativeDiscovery, Collection)} * constructor instead, passing null. * * @param libvlcArgs collection of options/arguments to pass to LibVLC for initialisation of the native library */ public MediaPlayerFactory(Collection libvlcArgs) { this(new NativeDiscovery(), libvlcArgs); } /** * Create a new media player factory with default native discovery and no initialisation options. */ public MediaPlayerFactory() { this(new NativeDiscovery()); } /** * Run native discovery, if set, and attempt to load the native library. * * @param discovery native discovery used to find the native library, may be null * @return native library */ private LibVlc discoverNativeLibrary(NativeDiscovery discovery) { if (discovery != null) { // The discover method return value is not currently used, since we try and load the native library whether // discovery worked or not discovery.discover(); } LibVlc nativeLibrary = Native.load(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class); checkVersion(nativeLibrary); // A synchronised library is required since there are multiple asynchronous task queues in use that could // potentially call into LibVLC concurrently return (LibVlc) Native.synchronizedLibrary(nativeLibrary); } /** * Runtime LibVLC version check. *

* This check must be done here even though the default {@link NativeDiscovery} implementation already does it, * simply because using the default {@link NativeDiscovery} is optional. * * @param nativeLibrary */ private void checkVersion(LibVlc nativeLibrary) { LibVlcVersion version = new LibVlcVersion(nativeLibrary); if (!version.isSupported()) { throw new RuntimeException(String.format("Failed to find minimum required VLC version %s, found %s in %s", version.getRequiredVersion(), version.getVersion(), NativeLibraryPath.getNativeLibraryPath(nativeLibrary))); } } /** * Get a new LibVLC instance. * * @param libvlcArgs native library initialisation arguments/options * @return native library instance */ private libvlc_instance_t newLibVlcInstance(String... libvlcArgs) { libvlc_instance_t result = libvlc.libvlc_new(libvlcArgs.length, libvlcArgs); if (result != null) { return result; } else { throw new RuntimeException("Failed to get a new native library instance"); } } public final ApplicationApi application() { return applicationApi; } public final AudioApi audio() { return audioApi; } public final DialogsApi dialogs() { return dialogsApi; } public final MediaDiscovererApi mediaDiscoverers() { return mediaDiscovererApi; } public final EqualizerApi equalizers() { return equalizerApi; } public final MediaPlayerApi mediaPlayers() { return mediaPlayerApi; } public final MediaApi media() { return mediaApi; } public final RendererApi renderers() { return rendererApi; } public final VideoSurfaceApi videoSurfaces() { return videoSurfaceApi; } /** * Submit a task for asynchronous execution. *

* This is useful in particular for event handling code as native events are generated on a native event callback * thread and it is not allowed to call back into LibVLC from this callback thread. If you do, either the call will * be ineffective, strange behaviour will happen, or a fatal JVM crash may occur. *

* To mitigate this, those tasks can be offloaded from the native thread, serialised and executed using this method. * * @param r task to execute */ public final void submit(Runnable r) { executor.submit(r); } /** * Get, if available, the path to where the native library was loaded from. *

* This is provided primarily for diagnostic reasons. *

* The mechanism to get the native library path is implementation dependent and may not always be available. * * @return native library path */ public final String nativeLibraryPath() { return NativeLibraryPath.getNativeLibraryPath(libvlc); } /** * Release all native resources associated with this factory. *

* The factory must not be used again after it has been released. */ public final void release() { executor.release(); onBeforeRelease(); applicationApi .release(); audioApi .release(); dialogsApi .release(); mediaDiscovererApi.release(); equalizerApi .release(); mediaPlayerApi .release(); mediaApi .release(); rendererApi .release(); videoSurfaceApi .release(); libvlc.libvlc_release(this.libvlcInstance); onAfterRelease(); } /** * Template method invoked immediately prior to the factory being released. *

* A factory sub-class can override this to perform its own clean-up before the factory goes away. */ protected void onBeforeRelease() { } /** * Template method invoked immediately after the factory has been released. *

* A factory subclass can override this to perform its own clean-up after the factory goes away. */ protected void onAfterRelease() { } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy