/*
* Copyright (c) 2009 Levente Farkas
* Copyright (c) 2007, 2008 Wayne Meissner
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
* 2005 Wim Taymans <wim@fluendo.com>
*
* This file is part of gstreamer-java.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 3 only, as
* published by the Free Software Foundation.
*
* This code 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 Lesser General Public License
* version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
*/
package org.gstreamer;
import java.util.EventListener;
import java.util.EventListenerProxy;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.gstreamer.lowlevel.GstNative;
import org.gstreamer.lowlevel.GstObjectAPI;
import com.sun.jna.Pointer;
/**
* Base class for the GStreamer object hierarchy
*
* GstObject provides a root for the object hierarchy tree filed in by the
* GStreamer library. It is currently a thin wrapper on top of
* {@link GObject}. It is an abstract class that is not very usable on its own.
*
*/
public class GstObject extends GObject {
private static Logger logger = Logger.getLogger(GstObject.class.getName());
private static final GstObjectAPI gst = GstNative.load(GstObjectAPI.class);
/**
* Wraps an underlying C GstObject with a Java proxy
*
* @param init Initialization data
*/
public GstObject(Initializer init) {
super(init);
if (init.ownsHandle && init.needRef) {
// Lose the floating ref so when this object is destroyed
// and it is the last ref, the C object gets freed
sink();
}
}
protected static Initializer initializer(Pointer ptr) {
return initializer(ptr, true, true);
}
protected static Initializer initializer(Pointer ptr, boolean needRef) {
return initializer(ptr, needRef, true);
}
/**
* Steal the native peer from another GstObject.
* After calling this, the victim object is disconnected from the native object
* and any attempt to use it will throw an exception.
*
* @param victim The GstObject to takeover.
* @return An Initializer that can be passed to {@link #GstObject}
*/
protected static Initializer steal(GstObject victim) {
Initializer init = new Initializer(victim.handle(), false, true);
victim.invalidate();
return init;
}
/**
* Sets the name of this object, or gives this object a guaranteed unique
* name (if name is null).
*
* Returns: TRUE if the name could be set. Since Objects that have
* a parent cannot be renamed, this function returns FALSE in those
* cases.
*
* MT safe.
*
* @param name new name of object
* @return true if the name was set. Since Objects that have
* a parent cannot be renamed, this function returns false in those
* cases.
*/
public boolean setName(String name) {
logger.entering("GstObject", "setName", name);
return gst.gst_object_set_name(this, name);
}
/**
* Returns a copy of the name of this object.
*
* For a nameless object, this returns null.
*
* @return the name of this object.
*/
public String getName() {
logger.entering("GstObject", "getName");
return gst.gst_object_get_name(this);
}
@Override
public String toString() {
return String.format("%s: [%s]", getClass().getSimpleName(), getName());
}
@Override
protected void ref() {
gst.gst_object_ref(this);
}
@Override
protected void unref() {
gst.gst_object_unref(this);
}
void sink() {
gst.gst_object_sink(this);
}
public GstObject getParent() {
return gst.gst_object_get_parent(this);
}
/**
* Adds an {@link EventListenerProxy} on this object.
* This is used by subclasses that wish to map between java style event listeners
* and gstreamer signals.
*
* @param listenerClass Class of the listener being added.
* @param listener The listener being added.
* @param proxy Proxy for the event listener.
*/
@SuppressWarnings("rawtypes")
protected synchronized void addListenerProxy(Class<? extends EventListener> listenerClass, EventListener listener, EventListenerProxy proxy) {
Map<EventListener, EventListenerProxy> map = getListenerMap().get(listenerClass);
/*
* Create the map for this class if it doesn't exist
*/
if (map == null) {
map = new HashMap<EventListener, EventListenerProxy>();
getListenerMap().put(listenerClass, map);
}
map.put(listener, proxy);
}
/**
* Removes an {@link EventListenerProxy} from this object.
* This is used by subclasses that wish to map between java style event listeners
* and gstreamer signals.
*
* @param listenerClass The class of listener the proxy was added for.
* @param listener The listener the proxy was added for.
* @return The proxy that was removed, or null if no proxy was found.
*/
@SuppressWarnings("rawtypes")
protected synchronized EventListenerProxy removeListenerProxy(Class<? extends EventListener> listenerClass, EventListener listener) {
Map<EventListener, EventListenerProxy> map = getListenerMap().get(listenerClass);
if (map == null) {
return null;
}
EventListenerProxy proxy = map.remove(listener);
/*
* Reclaim memory if this listener class is no longer used
*/
if (map.isEmpty()) {
listenerMap.remove(listenerClass);
if (listenerMap.isEmpty()) {
listenerMap = null;
}
}
return proxy;
}
@SuppressWarnings("rawtypes")
private Map<Class<? extends EventListener>, Map<EventListener, EventListenerProxy>> getListenerMap() {
if (listenerMap == null) {
listenerMap = new HashMap<Class<? extends EventListener>, Map<EventListener, EventListenerProxy>>();
}
return listenerMap;
}
@SuppressWarnings("rawtypes")
private Map<Class<? extends EventListener>, Map<EventListener, EventListenerProxy>> listenerMap;
}