/* * 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 <http://www.gnu.org/licenses/>. * * Copyright 2009-2016 Caprica Software Limited. */ package uk.co.caprica.vlcj.component; import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import uk.co.caprica.vlcj.binding.internal.libvlc_media_t; import uk.co.caprica.vlcj.player.MediaPlayer; import uk.co.caprica.vlcj.player.MediaPlayerEventListener; import uk.co.caprica.vlcj.player.MediaPlayerFactory; import uk.co.caprica.vlcj.player.directaudio.AudioCallback; import uk.co.caprica.vlcj.player.directaudio.AudioCallbackAdapter; import uk.co.caprica.vlcj.player.directaudio.DirectAudioPlayer; import com.sun.jna.Pointer; /** * Encapsulation of a direct audio player. */ public class DirectAudioPlayerComponent implements MediaPlayerEventListener, AudioCallback { /** * Log. */ private final Logger logger = LoggerFactory.getLogger(DirectAudioPlayerComponent.class); /** * Default factory initialisation arguments. * <p> * Sub-classes may totally disregard these arguments and provide their own. * <p> * A sub-class has access to these default arguments so new ones could be merged with these if * required. */ protected static final String[] DEFAULT_FACTORY_ARGUMENTS = { "--quiet-synchro", "--intf=dummy" }; /** * Media player factory. */ private final MediaPlayerFactory mediaPlayerFactory; /** * Media player. */ private final DirectAudioPlayer mediaPlayer; /** * Create a direct audio player component. * * @param format decoded audio buffer format * @param rate decoded audio rate * @param channels decoded audio channels */ public DirectAudioPlayerComponent(String format, int rate, int channels) { mediaPlayerFactory = onGetMediaPlayerFactory(); mediaPlayer = mediaPlayerFactory.newDirectAudioPlayer(format, rate, channels, onGetAudioCallback()); // Register listeners mediaPlayer.addMediaPlayerEventListener(this); // Sub-class initialisation onAfterConstruct(); } /** * Get the media player factory reference. * * @return media player factory */ public final MediaPlayerFactory getMediaPlayerFactory() { return mediaPlayerFactory; } /** * Get the direct audio player reference. * <p> * An application uses this handle to control the media player, add listeners and so on. * * @return media player */ public final DirectAudioPlayer getMediaPlayer() { return mediaPlayer; } /** * Release the media player component and the associated native media player resources. * <p> * The associated media player factory will <em>not</em> be released, the client * application is responsible for releasing the factory at the appropriate time. */ public final void release() { onBeforeRelease(); mediaPlayer.release(); onAfterRelease(); } /** * Release the media player component and the associated media player factory. * <p> * Optionally release the media player factory. * <p> * This method invokes {@link #release()}, then depending on the value of the <code>releaseFactory</code> * parameter the associated factory will also be released. * * @param releaseFactory <code>true</code> if the factory should also be released; <code>false</code> if it should not */ public final void release(boolean releaseFactory) { release(); if(releaseFactory) { mediaPlayerFactory.release(); } } /** * Template method to create a media player factory. * <p> * The default implementation will invoke the {@link #onGetMediaPlayerFactoryArgs()} template * method. * * @return media player factory */ protected MediaPlayerFactory onGetMediaPlayerFactory() { String[] args = Arguments.mergeArguments(onGetMediaPlayerFactoryArgs(), onGetMediaPlayerFactoryExtraArgs()); logger.debug("args={}", Arrays.toString(args)); return new MediaPlayerFactory(args); } /** * Template method to obtain the initialisation arguments used to create the media player * factory instance. * <p> * This can be used to provide arguments to use <em>instead</em> of the defaults. * <p> * If a sub-class overrides the {@link #onGetMediaPlayerFactory()} template method there is no * guarantee that {@link #onGetMediaPlayerFactoryArgs()} will be called. * * @return media player factory initialisation arguments */ protected String[] onGetMediaPlayerFactoryArgs() { return DEFAULT_FACTORY_ARGUMENTS; } /** * Template method to obtain the extra initialisation arguments used to create the media player * factory instance. * <p> * This can be used to provide <em>additional</em> arguments to add to the hard-coded defaults. * <p> * If a sub-class overrides the {@link #onGetMediaPlayerFactory()} template method there is no * guarantee that {@link #onGetMediaPlayerFactoryExtraArgs()} will be called. * * @return media player factory initialisation arguments, or <code>null</code> */ protected String[] onGetMediaPlayerFactoryExtraArgs() { return null; } /** * Template method to obtain an audio callback implementation. * <p> * The default behaviour is simply to return this component instance itself. * <p> * A sub-class may provide any implementation of {@link AudioCallback} - including * {@link AudioCallbackAdapter}. * * @return audio callback implementation */ protected AudioCallback onGetAudioCallback() { return this; } /** * Template method invoked at the end of the media player constructor. */ protected void onAfterConstruct() { } /** * Template method invoked immediately prior to releasing the media player and media player * factory instances. */ protected void onBeforeRelease() { } /** * Template method invoked immediately after releasing the media player and media player factory * instances. */ protected void onAfterRelease() { } // === MediaPlayerEventListener ============================================= @Override public void mediaChanged(MediaPlayer mediaPlayer, libvlc_media_t media, String mrl) { } @Override public void opening(MediaPlayer mediaPlayer) { } @Override public void buffering(MediaPlayer mediaPlayer, float newCache) { } @Override public void playing(MediaPlayer mediaPlayer) { } @Override public void paused(MediaPlayer mediaPlayer) { } @Override public void stopped(MediaPlayer mediaPlayer) { } @Override public void forward(MediaPlayer mediaPlayer) { } @Override public void backward(MediaPlayer mediaPlayer) { } @Override public void finished(MediaPlayer mediaPlayer) { } @Override public void timeChanged(MediaPlayer mediaPlayer, long newTime) { } @Override public void positionChanged(MediaPlayer mediaPlayer, float newPosition) { } @Override public void seekableChanged(MediaPlayer mediaPlayer, int newSeekable) { } @Override public void pausableChanged(MediaPlayer mediaPlayer, int newPausable) { } @Override public void titleChanged(MediaPlayer mediaPlayer, int newTitle) { } @Override public void snapshotTaken(MediaPlayer mediaPlayer, String filename) { } @Override public void lengthChanged(MediaPlayer mediaPlayer, long newLength) { } @Override public void videoOutput(MediaPlayer mediaPlayer, int newCount) { } @Override public void scrambledChanged(MediaPlayer mediaPlayer, int newScrambled) { } @Override public void elementaryStreamAdded(MediaPlayer mediaPlayer, int type, int id) { } @Override public void elementaryStreamDeleted(MediaPlayer mediaPlayer, int type, int id) { } @Override public void elementaryStreamSelected(MediaPlayer mediaPlayer, int type, int id) { } @Override public void corked(MediaPlayer mediaPlayer, boolean corked) { } @Override public void muted(MediaPlayer mediaPlayer, boolean muted) { } @Override public void volumeChanged(MediaPlayer mediaPlayer, float volume) { } @Override public void audioDeviceChanged(MediaPlayer mediaPlayer, String audioDevice) { } @Override public void chapterChanged(MediaPlayer mediaPlayer, int newChapter) { } @Override public void error(MediaPlayer mediaPlayer) { } @Override public void mediaMetaChanged(MediaPlayer mediaPlayer, int metaType) { } @Override public void mediaSubItemAdded(MediaPlayer mediaPlayer, libvlc_media_t subItem) { } @Override public void mediaDurationChanged(MediaPlayer mediaPlayer, long newDuration) { } @Override public void mediaParsedChanged(MediaPlayer mediaPlayer, int newStatus) { } @Override public void mediaParsedStatus(MediaPlayer mediaPlayer, int newStatus) { } @Override public void mediaFreed(MediaPlayer mediaPlayer) { } @Override public void mediaStateChanged(MediaPlayer mediaPlayer, int newState) { } @Override public void mediaSubItemTreeAdded(MediaPlayer mediaPlayer, libvlc_media_t item) { } @Override public void newMedia(MediaPlayer mediaPlayer) { } @Override public void subItemPlayed(MediaPlayer mediaPlayer, int subItemIndex) { } @Override public void subItemFinished(MediaPlayer mediaPlayer, int subItemIndex) { } @Override public void endOfSubItems(MediaPlayer mediaPlayer) { } // === RenderCallback ======================================================= @Override public void play(DirectAudioPlayer mediaPlayer, Pointer samples, int sampleCount, long pts) { } @Override public void pause(DirectAudioPlayer mediaPlayer, long pts) { } @Override public void resume(DirectAudioPlayer mediaPlayer, long pts) { } @Override public void flush(DirectAudioPlayer mediaPlayer, long pts) { } @Override public void drain(DirectAudioPlayer mediaPlayer) { } }