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