1 /*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
2  *
3  *  Use of this source code is governed by a BSD-style license that can
4  *  be found in the License.html file in the root of the source tree.
5  */
6 
7 import org.xvolks.jnative.JNative;
8 import org.xvolks.jnative.Type;
9 import org.xvolks.jnative.pointers.Pointer;
10 import org.xvolks.jnative.pointers.memory.MemoryBlockFactory;
11 import org.xvolks.jnative.exceptions.NativeException;
12 import org.xvolks.jnative.pointers.memory.NativeMemoryBlock;
13 
14 /**
15  * Class to retrieve info about media files.
16  * MediaInfo library (http://MediaArea.net/MediaInfo) is used
17  * by the help of JNative (http://jnative.sourceforge.net)
18  * to obtain technical the info about the files.
19  *
20  * @author bro3@users.sourceforge.net
21  * @author Info@MediaArea.net
22  */
23 class MediaInfo
24 {
25 
26     /* static_fields */
27 
28     final public static int Stream_General       = 0;
29     final public static int Stream_Video         = 1;
30     final public static int Stream_Audio         = 2;
31     final public static int Stream_Text          = 3;
32     final public static int Stream_Other         = 4;
33     final public static int Stream_Image         = 5;
34     final public static int Stream_Menu          = 6;
35     final public static int Stream_Max           = 7;
36 
37     final public static int Info_Name            = 0;
38     final public static int Info_Text            = 1;
39     final public static int Info_Measure         = 2;
40     final public static int Info_Options         = 3;
41     final public static int Info_Name_Text       = 4;
42     final public static int Info_Measure_Text    = 5;
43     final public static int Info_Info            = 6;
44     final public static int Info_HowTo           = 7;
45     final public static int Info_Max             = 8;
46 
47 
48     /* The MediaInfo handle */
49     private String handle = null;
50     private JNative new_jnative;
51 
52     /* The library to be used */
53     private static String libraryName = "";
54 
55 
56     /**
57      * Constructor that initializes the new MediaInfo object.
58      * @throws NativeException  JNative Exception.
59      */
MediaInfo()60     public MediaInfo() throws NativeException, Exception
61     {
62         setLibraryName();
63         New();
64     }
65 
66 
67     /**
68      * Constructor that initializes the new MediaInfo object.
69      * @param libraryName       name of libarary to be used
70      * @throws NativeException  JNative Exception
71      */
MediaInfo(String libraryName)72     public MediaInfo(String libraryName) throws NativeException, Exception
73     {
74         setLibraryName(libraryName);
75         New();
76     }
77 
78 
79     /**
80      * Method New initializes the MediaInfo handle
81      * @throws NativeException  JNative Exception
82      */
New()83     private void New() throws NativeException, Exception
84     {
85         /* Getting the handle */
86         new_jnative = new JNative(libraryName, "MediaInfoA_New");
87         new_jnative.setRetVal(Type.INT);
88         new_jnative.invoke();
89         handle = new_jnative.getRetVal();
90         Option("CharSet", "UTF-8");
91     }
92 
93 
94     /**
95      * Opens a media file.
96      * Overloads method {@link #Open(int, int, int, int)}
97      * @param  begin                          buffer with the beginning of datas
98      * @param  beginSize                      size of begin
99      * @return                                1 for success and 0 for failure
100      * @throws HandleNotInitializedException  if the handle is null
101      * @throws NativeException                JNative Exception
102      * @see                                   #Open(int, int, int, int)
103      */
Open(int begin, int beginSize)104     public int Open(int begin, int beginSize) throws HandleNotInitializedException, NativeException, Exception
105     {
106         return Open(begin, beginSize, 0, 0);
107     }
108 
109 
110     /**
111      * Opens a media file.
112      * @param  begin                          buffer with the beginning of datas
113      * @param  beginSize                      size of begin
114      * @param  end                            buffer with the end of datas
115      * @param  endSize                        size of end
116      * @return                                1 for success and 0 for failure
117      * @throws HandleNotInitializedException  if the handle is null
118      * @throws NativeException                JNative Exception
119      */
Open(int begin, int beginSize, int end, int endSize)120     public int Open(int begin, int beginSize, int end, int endSize) throws HandleNotInitializedException, NativeException, Exception
121     {
122         if (handle == null)
123             throw new HandleNotInitializedException("Handle is not initialized.");
124 
125         /*JNative call */
126         JNative jnative = new JNative(libraryName, "MediaInfoA_Open_Buffer");
127         jnative.setRetVal(Type.INT);
128         jnative.setParameter(0, Type.INT, handle);
129         jnative.setParameter(1, Type.INT, String.valueOf(begin));
130         jnative.setParameter(2, Type.INT, String.valueOf(beginSize));
131         jnative.setParameter(3, Type.INT, String.valueOf(end));
132         jnative.setParameter(4, Type.INT, String.valueOf(endSize));
133         jnative.invoke();
134 
135         /* Retrieving data */
136         int ret = Integer.parseInt(jnative.getRetVal());
137 
138         return ret;
139     }
140 
141 
142     /**
143      * Opens a media file.
144      * @param  filename                       the filename
145      * @return                                1 for success and 0 for failure
146      * @throws HandleNotInitializedException  if the handle is null
147      * @throws NativeException                JNative Exception
148      */
Open(String filename)149     public int Open(String filename) throws HandleNotInitializedException, NativeException, Exception
150     {
151         if (handle == null)
152             throw new HandleNotInitializedException("Handle is not initialized.");
153 
154         /* Setting the memory with the byte array returned in UTF-8 format */
155         Pointer fileNamePointer = createPointer(filename);
156 
157         /*JNative call */
158         JNative jnative = new JNative(libraryName, "MediaInfoA_Open");
159         jnative.setRetVal(Type.INT);
160         jnative.setParameter(0, Type.INT, handle);
161         jnative.setParameter(1, fileNamePointer);
162         jnative.invoke();
163 
164         /* Retrieving data */
165         int ret = Integer.parseInt(jnative.getRetVal());
166 
167         return ret;
168     }
169 
170 
171     /**
172      * Gets the file info, (if available) according to the previous options set by {@link #Option(String, String)}
173      * @return                                the file info
174      * @throws HandleNotInitializedException  if the handle is null
175      * @throws NativeException                JNative Exception
176      */
Inform()177     public String Inform() throws HandleNotInitializedException, NativeException, Exception
178     {
179         if (handle == null)
180             throw new HandleNotInitializedException("Handle is not initialized.");
181 
182         /*JNative call */
183         JNative jnative = new JNative(libraryName, "MediaInfoA_Inform");
184         jnative.setRetVal(Type.INT);
185         jnative.setParameter(0, Type.INT, handle);
186         jnative.setParameter(1, Type.INT, "0"); //Necessary for backward compatibility
187         jnative.invoke();
188 
189         /* Retrieving data */
190         String ret = retrieveString(jnative);
191 
192         return ret;
193     }
194 
195 
196     /**
197      * Gets the specific info according to the parameters.
198      * Overloads method {@link #Get(int, int, String, int, int)}.
199      * @param streamKind                      type of stream. Can be any of the Stream_XX values {@link <a href="#field_detail">Field details</a>}
200      * @param streamNumber                    stream number to process
201      * @param parameter                       parameter string (list of strings is available with Option("Info_Parameters");
202      * @return                                information
203      * @throws HandleNotInitializedException  if the handle is null
204      * @throws NativeException                JNative Exception
205      * @see                                   #Get(int, int, String, int, int)
206      */
Get(int streamKind, int streamNumber, String parameter)207     public String Get(int streamKind, int streamNumber, String parameter) throws HandleNotInitializedException, NativeException, Exception
208     {
209         return Get(streamKind, streamNumber, parameter, MediaInfo.Info_Name, MediaInfo.Info_Text);
210     }
211 
212 
213     /**
214      * Gets the specific info according to the parameters.
215      * Overloads method {@link #Get(int, int, String, int, int)}
216      * @param streamKind                      type of stream. Can be any of the Stream_XX values {@link <a href="#field_detail">Field details</a>}
217      * @param streamNumber                    stream to process
218      * @param parameter                       parameter string (list of strings is available with Option("Info_Parameters");
219      * @param infoKind                        type of info. Can be any of the Info_XX values {@link <a href="#field_detail">Field details</a>}
220      * @return                                desired information
221      * @throws HandleNotInitializedException  if the handle is null
222      * @throws NativeException                JNative Exception
223      * @see                                   #Get(int, int, String, int, int)
224      */
Get(int streamKind, int streamNumber, String parameter, int infoKind)225     public String Get(int streamKind, int streamNumber, String parameter, int infoKind) throws HandleNotInitializedException, NativeException, Exception
226     {
227         return Get(streamKind, streamNumber, parameter, infoKind, MediaInfo.Info_Name);
228     }
229 
230 
231     /**
232      * Gets the specific file info according to the parameters.
233      * @param streamKind                      type of stream. Can be any of the Stream_XX values {@link <a href="#field_detail">Field details</a>}
234      * @param streamNumber                    stream to process
235      * @param parameter                       parameter string (list of strings is available with Option("Info_Parameters");
236      * @param infoKind                        type of info. Can be any of the Info_XX values {@link <a href="#field_detail">Field details</a>}
237      * @param searchKind                      type of search. Can be any of the Info_XX values {@link <a href="#field_detail">Field details</a>}
238      * @return                                desired information
239      * @throws HandleNotInitializedException  if the handle is null
240      * @throws NativeException                JNative Exception
241      */
Get(int streamKind, int streamNumber, String parameter, int infoKind, int searchKind)242     public String Get(int streamKind, int streamNumber, String parameter, int infoKind, int searchKind) throws HandleNotInitializedException, NativeException, Exception
243     {
244         if (handle == null)
245             throw new HandleNotInitializedException("Handle is not initialized.");
246 
247         /* Setting the memory with the byte array returned in UTF-8 format */
248         Pointer parameterPointer = createPointer(parameter);
249 
250         /*JNative call */
251         JNative jnative = new JNative(libraryName, "MediaInfoA_Get");
252         jnative.setRetVal(Type.INT);
253         jnative.setParameter(0, Type.INT, handle);
254         jnative.setParameter(1, Type.INT, String.valueOf(streamKind));
255         jnative.setParameter(2, Type.INT, String.valueOf(streamNumber));
256         jnative.setParameter(3, parameterPointer);
257         jnative.setParameter(4, Type.INT, String.valueOf(infoKind));
258         jnative.setParameter(5, Type.INT, String.valueOf(searchKind));
259         jnative.invoke();
260 
261         /* Retrieving data */
262         String ret = retrieveString(jnative);
263 
264         return ret;
265     }
266 
267 
268     /**
269      * Gets the specific file info according to the parameters.
270      * Overloads method {@link #Get(int, int, int, int)}.
271      * @param streamKind                      type of stream. Can be any of the Stream_XX values {@link <a href="#field_detail">Field details</a>}
272      * @param streamNumber                    stream to process
273      * @param parameter                       parameter position (count of parameters is available with Count_Get(streamKind, streamNumber) )
274      * @return                                desired information
275      * @throws HandleNotInitializedException  if the handle is null
276      * @throws NativeException                JNative Exception
277      * @see                                   #Get(int, int, int, int)
278     */
Get(int streamKind, int streamNumber, int parameter)279     public String Get(int streamKind, int streamNumber, int parameter) throws HandleNotInitializedException, NativeException, Exception
280     {
281         return Get(streamKind, streamNumber, parameter, MediaInfo.Info_Text);
282     }
283 
284 
285     /**
286      * Gets the specific file info according to the parameters.
287      * @param streamKind                      type of stream. Can be any of the Stream_XX values {@link <a href="#field_detail">Field details</a>}
288      * @param streamNumber                    stream to process
289      * @param parameter                       parameter position (count of parameters is available with Count_Get(streamKind, streamNumber) )
290      * @param infoKind                        type of info. Can be any of the Info_XX values {@link <a href="#field_detail">Field details</a>}
291      * @return                                desired information
292      * @throws HandleNotInitializedException  if the handle is null
293      * @throws NativeException                JNative Exception
294     */
Get(int streamKind, int streamNumber, int parameter, int infoKind)295     public String Get(int streamKind, int streamNumber, int parameter, int infoKind) throws HandleNotInitializedException, NativeException, Exception
296     {
297         if (handle == null)
298             throw new HandleNotInitializedException("Handle is not initialized.");
299 
300         /*JNative call */
301         JNative jnative = new JNative(libraryName, "MediaInfoA_GetI");
302         jnative.setRetVal(Type.INT);
303         jnative.setParameter(0, Type.INT, handle);
304         jnative.setParameter(1, Type.INT, String.valueOf(streamKind));
305         jnative.setParameter(2, Type.INT, String.valueOf(streamNumber));
306         jnative.setParameter(3, Type.INT, String.valueOf(parameter));
307         jnative.setParameter(4, Type.INT, String.valueOf(infoKind));
308         jnative.invoke();
309 
310         /* Retrieving data */
311         String ret = retrieveString(jnative);
312 
313         return ret;
314     }
315 
316 
317     /**
318      * Sets the option
319      * Overloads method {@link #Option(String, String)}
320      * @param option                          name of option
321      * @return                                desired information or status of the option
322      * @throws HandleNotInitializedException  if the handle is null
323      * @throws NativeException                JNative Exception
324      * @see #Option(String, String)
325      */
Option(String option)326     public String Option(String option) throws HandleNotInitializedException, NativeException, Exception
327     {
328         return Option(option, "");
329     }
330 
331 
332     /**
333      * Sets the option with value
334      * @param option                          name of option
335      * @param value                           option value
336      * @return                                desired information or status of the option
337      * @throws HandleNotInitializedException  if the handle is null
338      * @throws NativeException                JNative Exception
339     */
Option(String option, String value)340     public String Option(String option, String value) throws HandleNotInitializedException, NativeException, Exception
341     {
342         if (handle == null)
343             throw new HandleNotInitializedException("Handle is not initialized.");
344 
345         /* Setting the memory with the byte array returned in UTF-8 format */
346         Pointer optionPointer = createPointer(option);
347         Pointer valuePointer = createPointer(value);
348 
349         /*JNative call */
350         JNative jnative = new JNative(libraryName, "MediaInfoA_Option");
351         jnative.setRetVal(Type.INT);
352         jnative.setParameter(0, Type.INT, handle);
353         jnative.setParameter(1, optionPointer);
354         jnative.setParameter(2, valuePointer);
355         jnative.invoke();
356 
357         /* Retrieving data */
358         String ret = retrieveString(jnative);
359 
360         return ret;
361     }
362 
363 
364     /**
365      * Sets the option (you do not need to create a MediaInfo handle)
366      * Overloads method {@link #Option_Static(String, String)}
367      * @param option                          name of option
368      * @return                                desired information or status of the option
369      * @throws HandleNotInitializedException  if the handle is null
370      * @throws NativeException                JNative Exception
371      * @see                                   #Option_Static(String, String)
372      */
Option_Static(String option)373     static public String Option_Static(String option) throws HandleNotInitializedException, NativeException, Exception
374     {
375         return Option_Static(option, "");
376     }
377 
378 
379     /**
380      * Sets the option (you do not need to create a MediaInfo handle)
381      * @param option                          name of option
382      * @param value                           option value
383      * @return                                desired information or status of the option
384      * @throws HandleNotInitializedException  if the handle is null
385      * @throws NativeException                JNative Exception
386     */
Option_Static(String option, String value)387     static public String Option_Static(String option, String value) throws HandleNotInitializedException, NativeException, Exception
388     {
389         if (libraryName.equals(""))
390             setLibraryName();
391 
392         /* Setting the memory with the byte array returned in UTF-8 format */
393         Pointer optionPointer = createPointer(option);
394         Pointer valuePointer = createPointer(value);
395 
396         /*JNative call */
397         JNative jnative = new JNative(libraryName, "MediaInfoA_Option");
398         jnative.setRetVal(Type.INT);
399         jnative.setParameter(0, Type.INT, "0");
400         jnative.setParameter(1, optionPointer);
401         jnative.setParameter(2, valuePointer);
402         jnative.invoke();
403 
404         /* Retrieving data */
405         String ret = retrieveString(jnative);
406 
407         return ret;
408     }
409 
410 
411     /**
412      * Gets the state of the libaray
413      * @return                                state of the library (between 0 and 10000)
414      * @throws HandleNotInitializedException  if the handle is null
415      * @throws NativeException                JNative Exception
416     */
State_Get()417     public int State_Get() throws HandleNotInitializedException, NativeException, Exception
418     {
419         if (handle == null)
420             throw new HandleNotInitializedException("Handle is not initialized.");
421 
422         /*JNative call */
423         JNative jnative = new JNative(libraryName, "MediaInfoA_State_Get");
424         jnative.setRetVal(Type.INT);
425         jnative.setParameter(0, Type.INT, handle);
426         jnative.invoke();
427 
428         /* Retrieving data */
429         int ret = Integer.parseInt(jnative.getRetVal());
430 
431         return ret;
432     }
433 
434 
435     /**
436      * Gets the count of streams
437      * Overloads method {@link #Count_Get(int, int)}.
438      * @param streamKind                      type of stream. Can be any of the Stream_XX values {@link <a href="#field_detail">Field details</a>}
439      * @return                                count of streams
440      * @throws HandleNotInitializedException  if the handle is null
441      * @throws NativeException                JNative Exception
442      * @see                                   #Count_Get(int, int)
443      */
Count_Get(int streamKind)444     public int Count_Get(int streamKind) throws HandleNotInitializedException, NativeException, Exception
445     {
446         return Count_Get(streamKind, -1);
447     }
448 
449 
450     /**
451      * Gets the count of streams
452      * @param streamKind                      type of stream. Can be any of the Stream_XX values {@link <a href="#field_detail">Field details</a>}
453      * @param streamNumber                    stream to process
454      * @return                                count of parameters for a specific stream
455      * @throws HandleNotInitializedException  if the handle is null
456      * @throws NativeException                JNative Exception
457      */
Count_Get(int streamKind, int streamNumber)458     public int Count_Get(int streamKind, int streamNumber) throws HandleNotInitializedException, NativeException, Exception
459     {
460         if (handle == null)
461             throw new HandleNotInitializedException("Handle is not initialized.");
462 
463         /*JNative call */
464         JNative jnative = new JNative(libraryName, "MediaInfoA_Count_Get");
465         jnative.setRetVal(Type.INT);
466         jnative.setParameter(0, Type.INT, handle);
467         jnative.setParameter(1, Type.INT, String.valueOf(streamKind));
468         jnative.setParameter(2, Type.INT, String.valueOf(streamNumber));
469         jnative.invoke();
470 
471         /* Retrieving data */
472         int retval = Integer.parseInt(jnative.getRetVal());
473 
474         return retval;
475     }
476 
477 
478     /**
479      * Deletes the handle
480      * @throws HandleNotInitializedException  if the handle is null
481      * @throws NativeException                JNative Exception
482      */
finalize()483     protected void finalize() throws HandleNotInitializedException, NativeException, Exception
484     {
485         if (handle == null)
486             throw new HandleNotInitializedException("Handle is not initialized.");
487 
488         /*JNative call */
489         JNative jnative = new JNative(libraryName, "MediaInfoA_Delete");
490         jnative.setParameter(0, Type.INT, handle);
491         jnative.invoke();
492     }
493 
494 
495     /**
496      * Closes the handle
497      * @throws HandleNotInitializedException  if the handle is null
498      * @throws NativeException                JNative Exception
499      */
Close()500     public void Close() throws HandleNotInitializedException, NativeException, Exception
501     {
502         if (handle == null)
503             throw new HandleNotInitializedException("Handle is not initialized.");
504 
505         /*JNative call */
506         JNative jnative = new JNative(libraryName, "MediaInfoA_Close");
507         jnative.setParameter(0, Type.INT, handle);
508         jnative.invoke();
509     }
510 
511 
512      /**
513      * Create a memory pointer for giving it to an external library
514      * @param value            The string to give
515       * @return                 A pointer to the memory
516     */
createPointer(String value)517     static Pointer createPointer(String value) throws Exception
518     {
519         value+="\0";
520         byte[] array=value.getBytes("UTF-8");
521         Pointer valuePointer = new Pointer(MemoryBlockFactory.createMemoryBlock(array.length));
522         valuePointer.setMemory(array);
523         return valuePointer;
524     }
525 
526      /**
527      * Create a string from a memory pointer
528      * @param jnative          The jnative handler
529       * @return                 A string
530     */
retrieveString(JNative jnative)531     static String retrieveString(JNative jnative) throws Exception
532     {
533         int address = Integer.parseInt(jnative.getRetVal());
534         byte[]  strEnd          ={0};
535         int     howFarToSearch  =10000;
536         int     length          =0;
537 
538         while (true)
539         {
540             int pos=JNative.searchNativePattern(address+length, strEnd, howFarToSearch);
541             if (pos == -1)
542                 howFarToSearch+=10000; //The strEnd wasn't found
543             else
544             {
545                 length+=pos;
546                 break;
547             }
548         }
549 
550         if (length > 0)
551         {
552             Pointer retPointer = new Pointer(new NativeMemoryBlock(address, length));
553             String fileInfo = new String(retPointer.getMemory(), "UTF-8");
554             retPointer.dispose();
555             return fileInfo;
556         }
557         else
558             return new String();
559     }
560 
561     /**
562      * Sets the default name of the library to be used.
563      * If windows -> "MediaInfo.dll" else -> "libmediainfo.so.0"
564      */
setLibraryName()565     public static void setLibraryName()
566     {
567         if (libraryName.equals(""))
568         {
569             String os=System.getProperty("os.name");
570             if (os!=null && os.toLowerCase().startsWith("windows"))
571                 setLibraryName("MediaInfo.dll");
572             else if (os!=null && os.toLowerCase().startsWith("mac"))
573                 setLibraryName("libmediainfo.dynlib.0");
574             else
575                 setLibraryName("libmediainfo.so.0");
576         }
577     }
578 
579 
580     /**
581      * Sets the name of the library to be used.
582      * @param libName            name of the library
583      */
setLibraryName(String libName)584     public static void setLibraryName(String libName)
585     {
586         libraryName = libName;
587     }
588 }
589 
590 
591 /**
592  * Exception thrown if the handle isn't initialized.
593  */
594 class HandleNotInitializedException extends Exception
595 {
596     private static final long serialVersionUID = 1L;
597 
HandleNotInitializedException(String msg)598     HandleNotInitializedException(String msg)
599     {
600         super(msg);
601     }
602 }
603