/* Copyright (c) MediaArea.net SARL. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license that can
* be found in the License.html file in the root of the source tree.
*/
import org.xvolks.jnative.JNative;
import org.xvolks.jnative.Type;
import org.xvolks.jnative.pointers.Pointer;
import org.xvolks.jnative.pointers.memory.MemoryBlockFactory;
import org.xvolks.jnative.exceptions.NativeException;
import org.xvolks.jnative.pointers.memory.NativeMemoryBlock;
/**
* Class to retrieve info about media files.
* MediaInfo library (http://MediaArea.net/MediaInfo) is used
* by the help of JNative (http://jnative.sourceforge.net)
* to obtain technical the info about the files.
*
* @author bro3@users.sourceforge.net
* @author Info@MediaArea.net
*/
class MediaInfo
{
/* static_fields */
final public static int Stream_General = 0;
final public static int Stream_Video = 1;
final public static int Stream_Audio = 2;
final public static int Stream_Text = 3;
final public static int Stream_Other = 4;
final public static int Stream_Image = 5;
final public static int Stream_Menu = 6;
final public static int Stream_Max = 7;
final public static int Info_Name = 0;
final public static int Info_Text = 1;
final public static int Info_Measure = 2;
final public static int Info_Options = 3;
final public static int Info_Name_Text = 4;
final public static int Info_Measure_Text = 5;
final public static int Info_Info = 6;
final public static int Info_HowTo = 7;
final public static int Info_Max = 8;
/* The MediaInfo handle */
private String handle = null;
private JNative new_jnative;
/* The library to be used */
private static String libraryName = "";
/**
* Constructor that initializes the new MediaInfo object.
* @throws NativeException JNative Exception.
*/
public MediaInfo() throws NativeException, Exception
{
setLibraryName();
New();
}
/**
* Constructor that initializes the new MediaInfo object.
* @param libraryName name of libarary to be used
* @throws NativeException JNative Exception
*/
public MediaInfo(String libraryName) throws NativeException, Exception
{
setLibraryName(libraryName);
New();
}
/**
* Method New initializes the MediaInfo handle
* @throws NativeException JNative Exception
*/
private void New() throws NativeException, Exception
{
/* Getting the handle */
new_jnative = new JNative(libraryName, "MediaInfoA_New");
new_jnative.setRetVal(Type.INT);
new_jnative.invoke();
handle = new_jnative.getRetVal();
Option("CharSet", "UTF-8");
}
/**
* Opens a media file.
* Overloads method {@link #Open(int, int, int, int)}
* @param begin buffer with the beginning of datas
* @param beginSize size of begin
* @return 1 for success and 0 for failure
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
* @see #Open(int, int, int, int)
*/
public int Open(int begin, int beginSize) throws HandleNotInitializedException, NativeException, Exception
{
return Open(begin, beginSize, 0, 0);
}
/**
* Opens a media file.
* @param begin buffer with the beginning of datas
* @param beginSize size of begin
* @param end buffer with the end of datas
* @param endSize size of end
* @return 1 for success and 0 for failure
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
*/
public int Open(int begin, int beginSize, int end, int endSize) throws HandleNotInitializedException, NativeException, Exception
{
if (handle == null)
throw new HandleNotInitializedException("Handle is not initialized.");
/*JNative call */
JNative jnative = new JNative(libraryName, "MediaInfoA_Open_Buffer");
jnative.setRetVal(Type.INT);
jnative.setParameter(0, Type.INT, handle);
jnative.setParameter(1, Type.INT, String.valueOf(begin));
jnative.setParameter(2, Type.INT, String.valueOf(beginSize));
jnative.setParameter(3, Type.INT, String.valueOf(end));
jnative.setParameter(4, Type.INT, String.valueOf(endSize));
jnative.invoke();
/* Retrieving data */
int ret = Integer.parseInt(jnative.getRetVal());
return ret;
}
/**
* Opens a media file.
* @param filename the filename
* @return 1 for success and 0 for failure
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
*/
public int Open(String filename) throws HandleNotInitializedException, NativeException, Exception
{
if (handle == null)
throw new HandleNotInitializedException("Handle is not initialized.");
/* Setting the memory with the byte array returned in UTF-8 format */
Pointer fileNamePointer = createPointer(filename);
/*JNative call */
JNative jnative = new JNative(libraryName, "MediaInfoA_Open");
jnative.setRetVal(Type.INT);
jnative.setParameter(0, Type.INT, handle);
jnative.setParameter(1, fileNamePointer);
jnative.invoke();
/* Retrieving data */
int ret = Integer.parseInt(jnative.getRetVal());
return ret;
}
/**
* Gets the file info, (if available) according to the previous options set by {@link #Option(String, String)}
* @return the file info
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
*/
public String Inform() throws HandleNotInitializedException, NativeException, Exception
{
if (handle == null)
throw new HandleNotInitializedException("Handle is not initialized.");
/*JNative call */
JNative jnative = new JNative(libraryName, "MediaInfoA_Inform");
jnative.setRetVal(Type.INT);
jnative.setParameter(0, Type.INT, handle);
jnative.setParameter(1, Type.INT, "0"); //Necessary for backward compatibility
jnative.invoke();
/* Retrieving data */
String ret = retrieveString(jnative);
return ret;
}
/**
* Gets the specific info according to the parameters.
* Overloads method {@link #Get(int, int, String, int, int)}.
* @param streamKind type of stream. Can be any of the Stream_XX values {@link Field details}
* @param streamNumber stream number to process
* @param parameter parameter string (list of strings is available with Option("Info_Parameters");
* @return information
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
* @see #Get(int, int, String, int, int)
*/
public String Get(int streamKind, int streamNumber, String parameter) throws HandleNotInitializedException, NativeException, Exception
{
return Get(streamKind, streamNumber, parameter, MediaInfo.Info_Name, MediaInfo.Info_Text);
}
/**
* Gets the specific info according to the parameters.
* Overloads method {@link #Get(int, int, String, int, int)}
* @param streamKind type of stream. Can be any of the Stream_XX values {@link Field details}
* @param streamNumber stream to process
* @param parameter parameter string (list of strings is available with Option("Info_Parameters");
* @param infoKind type of info. Can be any of the Info_XX values {@link Field details}
* @return desired information
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
* @see #Get(int, int, String, int, int)
*/
public String Get(int streamKind, int streamNumber, String parameter, int infoKind) throws HandleNotInitializedException, NativeException, Exception
{
return Get(streamKind, streamNumber, parameter, infoKind, MediaInfo.Info_Name);
}
/**
* Gets the specific file info according to the parameters.
* @param streamKind type of stream. Can be any of the Stream_XX values {@link Field details}
* @param streamNumber stream to process
* @param parameter parameter string (list of strings is available with Option("Info_Parameters");
* @param infoKind type of info. Can be any of the Info_XX values {@link Field details}
* @param searchKind type of search. Can be any of the Info_XX values {@link Field details}
* @return desired information
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
*/
public String Get(int streamKind, int streamNumber, String parameter, int infoKind, int searchKind) throws HandleNotInitializedException, NativeException, Exception
{
if (handle == null)
throw new HandleNotInitializedException("Handle is not initialized.");
/* Setting the memory with the byte array returned in UTF-8 format */
Pointer parameterPointer = createPointer(parameter);
/*JNative call */
JNative jnative = new JNative(libraryName, "MediaInfoA_Get");
jnative.setRetVal(Type.INT);
jnative.setParameter(0, Type.INT, handle);
jnative.setParameter(1, Type.INT, String.valueOf(streamKind));
jnative.setParameter(2, Type.INT, String.valueOf(streamNumber));
jnative.setParameter(3, parameterPointer);
jnative.setParameter(4, Type.INT, String.valueOf(infoKind));
jnative.setParameter(5, Type.INT, String.valueOf(searchKind));
jnative.invoke();
/* Retrieving data */
String ret = retrieveString(jnative);
return ret;
}
/**
* Gets the specific file info according to the parameters.
* Overloads method {@link #Get(int, int, int, int)}.
* @param streamKind type of stream. Can be any of the Stream_XX values {@link Field details}
* @param streamNumber stream to process
* @param parameter parameter position (count of parameters is available with Count_Get(streamKind, streamNumber) )
* @return desired information
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
* @see #Get(int, int, int, int)
*/
public String Get(int streamKind, int streamNumber, int parameter) throws HandleNotInitializedException, NativeException, Exception
{
return Get(streamKind, streamNumber, parameter, MediaInfo.Info_Text);
}
/**
* Gets the specific file info according to the parameters.
* @param streamKind type of stream. Can be any of the Stream_XX values {@link Field details}
* @param streamNumber stream to process
* @param parameter parameter position (count of parameters is available with Count_Get(streamKind, streamNumber) )
* @param infoKind type of info. Can be any of the Info_XX values {@link Field details}
* @return desired information
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
*/
public String Get(int streamKind, int streamNumber, int parameter, int infoKind) throws HandleNotInitializedException, NativeException, Exception
{
if (handle == null)
throw new HandleNotInitializedException("Handle is not initialized.");
/*JNative call */
JNative jnative = new JNative(libraryName, "MediaInfoA_GetI");
jnative.setRetVal(Type.INT);
jnative.setParameter(0, Type.INT, handle);
jnative.setParameter(1, Type.INT, String.valueOf(streamKind));
jnative.setParameter(2, Type.INT, String.valueOf(streamNumber));
jnative.setParameter(3, Type.INT, String.valueOf(parameter));
jnative.setParameter(4, Type.INT, String.valueOf(infoKind));
jnative.invoke();
/* Retrieving data */
String ret = retrieveString(jnative);
return ret;
}
/**
* Sets the option
* Overloads method {@link #Option(String, String)}
* @param option name of option
* @return desired information or status of the option
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
* @see #Option(String, String)
*/
public String Option(String option) throws HandleNotInitializedException, NativeException, Exception
{
return Option(option, "");
}
/**
* Sets the option with value
* @param option name of option
* @param value option value
* @return desired information or status of the option
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
*/
public String Option(String option, String value) throws HandleNotInitializedException, NativeException, Exception
{
if (handle == null)
throw new HandleNotInitializedException("Handle is not initialized.");
/* Setting the memory with the byte array returned in UTF-8 format */
Pointer optionPointer = createPointer(option);
Pointer valuePointer = createPointer(value);
/*JNative call */
JNative jnative = new JNative(libraryName, "MediaInfoA_Option");
jnative.setRetVal(Type.INT);
jnative.setParameter(0, Type.INT, handle);
jnative.setParameter(1, optionPointer);
jnative.setParameter(2, valuePointer);
jnative.invoke();
/* Retrieving data */
String ret = retrieveString(jnative);
return ret;
}
/**
* Sets the option (you do not need to create a MediaInfo handle)
* Overloads method {@link #Option_Static(String, String)}
* @param option name of option
* @return desired information or status of the option
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
* @see #Option_Static(String, String)
*/
static public String Option_Static(String option) throws HandleNotInitializedException, NativeException, Exception
{
return Option_Static(option, "");
}
/**
* Sets the option (you do not need to create a MediaInfo handle)
* @param option name of option
* @param value option value
* @return desired information or status of the option
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
*/
static public String Option_Static(String option, String value) throws HandleNotInitializedException, NativeException, Exception
{
if (libraryName.equals(""))
setLibraryName();
/* Setting the memory with the byte array returned in UTF-8 format */
Pointer optionPointer = createPointer(option);
Pointer valuePointer = createPointer(value);
/*JNative call */
JNative jnative = new JNative(libraryName, "MediaInfoA_Option");
jnative.setRetVal(Type.INT);
jnative.setParameter(0, Type.INT, "0");
jnative.setParameter(1, optionPointer);
jnative.setParameter(2, valuePointer);
jnative.invoke();
/* Retrieving data */
String ret = retrieveString(jnative);
return ret;
}
/**
* Gets the state of the libaray
* @return state of the library (between 0 and 10000)
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
*/
public int State_Get() throws HandleNotInitializedException, NativeException, Exception
{
if (handle == null)
throw new HandleNotInitializedException("Handle is not initialized.");
/*JNative call */
JNative jnative = new JNative(libraryName, "MediaInfoA_State_Get");
jnative.setRetVal(Type.INT);
jnative.setParameter(0, Type.INT, handle);
jnative.invoke();
/* Retrieving data */
int ret = Integer.parseInt(jnative.getRetVal());
return ret;
}
/**
* Gets the count of streams
* Overloads method {@link #Count_Get(int, int)}.
* @param streamKind type of stream. Can be any of the Stream_XX values {@link Field details}
* @return count of streams
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
* @see #Count_Get(int, int)
*/
public int Count_Get(int streamKind) throws HandleNotInitializedException, NativeException, Exception
{
return Count_Get(streamKind, -1);
}
/**
* Gets the count of streams
* @param streamKind type of stream. Can be any of the Stream_XX values {@link Field details}
* @param streamNumber stream to process
* @return count of parameters for a specific stream
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
*/
public int Count_Get(int streamKind, int streamNumber) throws HandleNotInitializedException, NativeException, Exception
{
if (handle == null)
throw new HandleNotInitializedException("Handle is not initialized.");
/*JNative call */
JNative jnative = new JNative(libraryName, "MediaInfoA_Count_Get");
jnative.setRetVal(Type.INT);
jnative.setParameter(0, Type.INT, handle);
jnative.setParameter(1, Type.INT, String.valueOf(streamKind));
jnative.setParameter(2, Type.INT, String.valueOf(streamNumber));
jnative.invoke();
/* Retrieving data */
int retval = Integer.parseInt(jnative.getRetVal());
return retval;
}
/**
* Deletes the handle
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
*/
protected void finalize() throws HandleNotInitializedException, NativeException, Exception
{
if (handle == null)
throw new HandleNotInitializedException("Handle is not initialized.");
/*JNative call */
JNative jnative = new JNative(libraryName, "MediaInfoA_Delete");
jnative.setParameter(0, Type.INT, handle);
jnative.invoke();
}
/**
* Closes the handle
* @throws HandleNotInitializedException if the handle is null
* @throws NativeException JNative Exception
*/
public void Close() throws HandleNotInitializedException, NativeException, Exception
{
if (handle == null)
throw new HandleNotInitializedException("Handle is not initialized.");
/*JNative call */
JNative jnative = new JNative(libraryName, "MediaInfoA_Close");
jnative.setParameter(0, Type.INT, handle);
jnative.invoke();
}
/**
* Create a memory pointer for giving it to an external library
* @param value The string to give
* @return A pointer to the memory
*/
static Pointer createPointer(String value) throws Exception
{
value+="\0";
byte[] array=value.getBytes("UTF-8");
Pointer valuePointer = new Pointer(MemoryBlockFactory.createMemoryBlock(array.length));
valuePointer.setMemory(array);
return valuePointer;
}
/**
* Create a string from a memory pointer
* @param jnative The jnative handler
* @return A string
*/
static String retrieveString(JNative jnative) throws Exception
{
int address = Integer.parseInt(jnative.getRetVal());
byte[] strEnd ={0};
int howFarToSearch =10000;
int length =0;
while (true)
{
int pos=JNative.searchNativePattern(address+length, strEnd, howFarToSearch);
if (pos == -1)
howFarToSearch+=10000; //The strEnd wasn't found
else
{
length+=pos;
break;
}
}
if (length > 0)
{
Pointer retPointer = new Pointer(new NativeMemoryBlock(address, length));
String fileInfo = new String(retPointer.getMemory(), "UTF-8");
retPointer.dispose();
return fileInfo;
}
else
return new String();
}
/**
* Sets the default name of the library to be used.
* If windows -> "MediaInfo.dll" else -> "libmediainfo.so.0"
*/
public static void setLibraryName()
{
if (libraryName.equals(""))
{
String os=System.getProperty("os.name");
if (os!=null && os.toLowerCase().startsWith("windows"))
setLibraryName("MediaInfo.dll");
else if (os!=null && os.toLowerCase().startsWith("mac"))
setLibraryName("libmediainfo.dynlib.0");
else
setLibraryName("libmediainfo.so.0");
}
}
/**
* Sets the name of the library to be used.
* @param libName name of the library
*/
public static void setLibraryName(String libName)
{
libraryName = libName;
}
}
/**
* Exception thrown if the handle isn't initialized.
*/
class HandleNotInitializedException extends Exception
{
private static final long serialVersionUID = 1L;
HandleNotInitializedException(String msg)
{
super(msg);
}
}