1 /** 2 * Object oriented wrapper for $(LINK2 http://mediainfo.sourceforge.net/Support/SDK, MediaInfo) 3 * License: 4 * This wrapper $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 5 * MediaInfo $(LINK2 http://www.gnu.org/licenses/lgpl-3.0.txt, LGPL 3.0) 6 * Authors: Johannes Pfau, Carsten Schlote 7 */ 8 module mediainfo; 9 10 import std.string; 11 import std.conv; 12 import std.typecons; 13 14 import mediainfodll; 15 16 //public alias MediaInfo_stream_t Stream; 17 //public alias MediaInfo_info_t Info; 18 19 /** A exception of the mediainfo wrapper */ 20 public class MediaInfoException : Exception 21 { 22 /// Constuctor 23 public this(string msg) 24 { 25 super(msg); 26 } 27 } 28 29 /** This is the UTF Wrapper for libmediainfo */ 30 public struct MediaInfo 31 { 32 private: 33 struct Payload 34 { 35 void* _payload; 36 this(void* h) 37 { 38 _payload = h; 39 } 40 ~this() 41 { 42 if(_payload) 43 { 44 mediainfo_FunctionTable.MediaInfo_Delete(_payload); 45 _payload = null; 46 MediaInfoDLL_UnLoad(); 47 } 48 } 49 // Should never perform these operations 50 this(this) { assert(false); } 51 void opAssign(MediaInfo.Payload rhs) { assert(false); } 52 } 53 54 alias Data = RefCounted!(Payload, RefCountedAutoInitialize.no); 55 Data _data; 56 57 @property void* handle() 58 { 59 return _data._payload; 60 } 61 62 public: 63 64 /** Use call operator to initialize resource */ 65 static MediaInfo opCall() 66 { 67 MediaInfo info; 68 const auto rc = MediaInfoDLL_Load(); 69 if(rc != 1) { 70 throw new MediaInfoException("Couldn't open mediainfo library"); 71 } 72 73 const auto h = mediainfo_FunctionTable.MediaInfo_New(); 74 info._data.refCountedStore.ensureInitialized(); 75 info._data._payload = cast(void*)h; 76 return info; 77 } 78 79 /** 80 * Open a file. 81 * Open a file and collect information about it (technical information and tags) 82 * 83 * Parameters: 84 * fileName = Full name of file to open 85 */ 86 void open(string fileName) 87 { 88 version(Workaround_UTF_Bug) { 89 import std.stdio : File; 90 auto fh = File(fileName); 91 scope(exit) fh.close; 92 this.openBufferInit(fh.size, 0); 93 94 //The parsing loop 95 ubyte[4096] rawbuffer; 96 ubyte[] buffer; 97 do 98 { 99 // Read some data to buffer... 100 buffer = fh.rawRead(rawbuffer); 101 // Sending the buffer to MediaInfo 102 const auto status = this.openBufferContinue(buffer.ptr, buffer.length); 103 if (status&0x08) //Bit3=Finished 104 break; 105 // Testing if there is a MediaInfo request to go elsewhere 106 if (this.openBufferContinueGoToGet() != -1 ) 107 { 108 // Position the file 109 import core.stdc.stdio : SEEK_SET; 110 fh.seek(this.openBufferContinueGoToGet(), SEEK_SET); 111 // Informing MediaInfo we have seek 112 this.openBufferInit(fh.size, fh.tell); 113 } 114 } 115 while (buffer.length > 0); 116 //This is the end of the stream, MediaInfo must finnish some work 117 this.openBufferFinalize(); 118 } 119 else { 120 static MediaInfo_Char* _fileNameRef; 121 import std.utf : toUTFz; 122 auto filename = fileName.toUTFz!(MediaInfo_Char*); 123 const auto rc = mediainfo_FunctionTable.MediaInfo_Open(handle, filename); 124 if(!rc) 125 { 126 throw new MediaInfoException("Couldn't open file: " ~ fileName); 127 } 128 _fileNameRef = fileName; 129 } 130 } 131 /+ /** 132 * Open a buffer. 133 * Open a Buffer (Begin and end of the stream) and collect information about it (technical information and tags) 134 * Params: 135 * begin = First bytes of the buffer 136 * begin_size = Size of Begin 137 * end = Last bytes of the buffer 138 * end_size = Size of End 139 * file_size = Total size of the file 140 */ 141 void open(ubyte* begin, size_t begin_size, ubyte* end, size_t end_size) 142 { 143 if(MediaInfo_Open_Buffer(handle, begin, begin_size, end, end_size)) 144 { 145 throw new MediaInfoException("Couldn't open file from buffer"); 146 } 147 } 148 +/ 149 /** 150 * Open a stream (Init). 151 * 152 * Open a stream and collect information about it (technical information and tags) 153 * 154 * Params: 155 * fileSize = Estimated file size 156 * fileOffset = Offset of the file (if we don't have the beginning of the file) 157 */ 158 size_t openBufferInit(long fileSize = -1, long fileOffset = 0) 159 { 160 return mediainfo_FunctionTable.MediaInfo_Open_Buffer_Init(handle, fileSize, fileOffset); 161 } 162 /** 163 * Open a stream (Continue). 164 * 165 * Open a stream and collect information about it (technical information and tags) 166 * 167 * Params: 168 * buffer = pointer to the stream 169 * size =Count of bytes to read 170 */ 171 size_t openBufferContinue(ubyte* buffer, size_t size) 172 { 173 return mediainfo_FunctionTable.MediaInfo_Open_Buffer_Continue(handle, buffer, size); 174 } 175 /** 176 * Open a stream (Get the needed file Offset). 177 * 178 * Open a stream and collect information about it (technical information and tags) 179 * 180 * Returns: 181 * the needed offset of the file 182 * File size if no more bytes are needed 183 */ 184 long openBufferContinueGoToGet() 185 { 186 return mediainfo_FunctionTable.MediaInfo_Open_Buffer_Continue_GoTo_Get(handle); 187 } 188 /** 189 * Open a stream (Finalize). 190 * 191 * Open a stream and collect information about it (technical information and tags) 192 */ 193 size_t openBufferFinalize() 194 { 195 return mediainfo_FunctionTable.MediaInfo_Open_Buffer_Finalize(handle); 196 } 197 /+ /** 198 * (NOT IMPLEMENTED YET) Save the file 199 * 200 * (NOT IMPLEMENTED YET) Save the file opened before with Open() (modifications of tags) 201 */ 202 void save() 203 { 204 if(mediainfo_FunctionTable.MediaInfo_Save(handle)) 205 { 206 throw new MediaInfoException("Couldn't save file"); 207 } 208 } 209 +/ 210 /** 211 * Close a file. 212 * 213 * Close a file opened before with Open() (without saving) 214 * 215 * Warning: 216 * without have saved before, modifications are lost 217 */ 218 void close() 219 { 220 mediainfo_FunctionTable.MediaInfo_Close(handle); 221 version(Workaround_UTF_Bug) {} else _fileNameRef = null; 222 } 223 /** 224 * String MediaInfoLib::MediaInfo::Inform ( size_t Reserved = 0 ) 225 * Get all details about a file. 226 * 227 * Get all details about a file in one string 228 * 229 * Precondition: 230 * You can change default presentation with Inform_Set() 231 */ 232 string inform(size_t reserved = 0) 233 { 234 import std.utf : toUTFz; 235 const auto strptr = mediainfo_FunctionTable.MediaInfo_Inform(handle, reserved); 236 auto str = strptr.fromStringz; 237 return to!string(str); 238 } 239 /** 240 * Get a piece of information about a file (parameter is an integer). 241 * 242 * Get a piece of information about a file (parameter is an integer) 243 * 244 * Params: 245 * streamKind = Kind of stream (general, video, audio...) 246 * streamNumber = Stream number in Kind of stream (first, second...) 247 * parameter = Parameter you are looking for in the stream (Codec, width, bitrate...), in integer format (first parameter, second parameter...) 248 * infoKind = Kind of information you want about the parameter (the text, the measure, the help...) 249 * Returns: 250 * a string about information you search 251 * an empty string if there is a problem 252 */ 253 string get(MediaInfo_stream_t streamKind, size_t streamNumber, size_t parameter, 254 MediaInfo_info_t infoKind = MediaInfo_info_t.MediaInfo_Info_Text) 255 { 256 import std.utf : toUTFz; 257 const auto strptr = mediainfo_FunctionTable.MediaInfo_GetI(handle, streamKind, streamNumber, 258 parameter, infoKind); 259 auto str = strptr.fromStringz; 260 return to!string(str); 261 } 262 /** 263 * Get a piece of information about a file (parameter is a string). 264 * 265 * Get a piece of information about a file (parameter is a string) 266 * 267 * Params: 268 * streamKind = Kind of stream (general, video, audio...) 269 * streamNumber = Stream number in Kind of stream (first, second...) 270 * parameter = Parameter you are looking for in the stream (Codec, width, bitrate...), in string format ("Codec", "Width"...) 271 * See MediaInfo::Option("Info_Parameters") to have the full list 272 * infoKind = Kind of information you want about the parameter (the text, the measure, the help...) 273 * searchKind = Where to look for the parameter 274 * Returns: 275 * a string about information you search 276 * an empty string if there is a problem 277 */ 278 string get(MediaInfo_stream_t streamKind, size_t streamNumber, 279 string parameter, MediaInfo_info_t infoKind = MediaInfo_info_t.MediaInfo_Info_Text, 280 MediaInfo_info_t searchKind = MediaInfo_info_t.MediaInfo_Info_Name) 281 { 282 import std.utf : toUTFz; 283 MediaInfo_Char* parameterZ = parameter.toUTFz!(MediaInfo_Char*); 284 const auto strptr = mediainfo_FunctionTable.MediaInfo_Get(handle, 285 streamKind, streamNumber, parameterZ, infoKind, searchKind); 286 auto str = strptr.fromStringz; 287 return to!string(str); 288 } 289 /+ /** 290 * (NOT IMPLEMENTED YET) Set a piece of information about a file (parameter is an int) 291 * 292 * (NOT IMPLEMENTED YET) Set a piece of information about a file (parameter is an integer) 293 * 294 * Warning: 295 * Not yet implemented, do not use it 296 * Params: 297 * toSet = Piece of information 298 * streamKind = Kind of stream (general, video, audio...) 299 * streamNumber = Stream number in Kind of stream (first, second...) 300 * parameter = Parameter you are looking for in the stream (Codec, width, bitrate...), in integer format (first parameter, second parameter...) 301 * oldValue = The old value of the parameter 302 * if OldValue is empty and ToSet is filled: tag is added 303 * if OldValue is filled and ToSet is filled: tag is replaced 304 * if OldValue is filled and ToSet is empty: tag is deleted 305 */ 306 void set(const(string) toSet, Stream streamKind, size_t streamNumber, 307 size_t parameter, const(string) oldValue = "") 308 { 309 if(!mediainfo_FunctionTable.MediaInfo_SetI(handle, toStringz(toSet), streamKind, streamNumber, 310 parameter, toStringz(oldValue))) 311 { 312 throw new MediaInfoException("Couldn't set parameter"); 313 } 314 } 315 /** 316 * (NOT IMPLEMENTED YET) Set information about a file (parameter is a string) 317 * 318 * (NOT IMPLEMENTED YET) Set a piece of information about a file (parameter is a string) 319 * 320 * Warning: 321 * Not yet implemented, do not use it 322 * Params: 323 * toSet = Piece of information 324 * streamKind = Kind of stream (general, video, audio...) 325 * streamNumber = Stream number in Kind of stream (first, second...) 326 * parameter = Parameter you are looking for in the stream (Codec, width, bitrate...), in string format 327 * oldValue = The old value of the parameter 328 * if OldValue is empty and ToSet is filled: tag is added 329 * if OldValue is filled and ToSet is filled: tag is replaced 330 * if OldValue is filled and ToSet is empty: tag is deleted 331 */ 332 void set(const(string) toSet, Stream streamKind, size_t streamNumber, 333 const(string) parameter, const(string) oldValue = "") 334 { 335 if(!mediainfo_FunctionTable.MediaInfo_Set(handle, toStringz(toSet), streamKind, streamNumber, 336 toStringz(parameter), toStringz(oldValue))) 337 { 338 throw new MediaInfoException("Couldn't set parameter"); 339 } 340 } 341 +/ 342 /** 343 * Output the written size when "File_Duplicate" option is used. 344 * 345 * Output the written size when "File_Duplicate" option is used. 346 * 347 * Params: 348 * value = The unique name of the duplicated stream (begin with "memory://") 349 * Returns: 350 * The size of the used buffer 351 */ 352 size_t outputBufferGet(const(string) value) 353 { 354 import std.utf : toUTFz; 355 MediaInfo_Char* valueZ = value.toUTFz!(MediaInfo_Char*); 356 return mediainfo_FunctionTable.MediaInfo_Output_Buffer_Get(handle, valueZ); 357 } 358 /** 359 * Output the written size when "File_Duplicate" option is used. 360 * 361 * Output the written size when "File_Duplicate" option is used. 362 * 363 * Params: 364 * pos = The position ? 365 * Returns: 366 * The size of the used buffer 367 */ 368 size_t outputBufferGet(size_t pos) 369 { 370 return mediainfo_FunctionTable.MediaInfo_Output_Buffer_GetI(handle, pos); 371 } 372 /** 373 * Configure or get information about MediaInfoLib 374 * 375 * Params: 376 * option = The name of option 377 * value = The value of option 378 * Returns: 379 * Depend of the option: by default "" (nothing) means No, other means Yes 380 */ 381 string option(const(string) option, const(string) value = "") 382 { 383 import std.utf : toUTFz; 384 MediaInfo_Char* optionZ = option.toUTFz!(MediaInfo_Char*); 385 MediaInfo_Char* valueZ = value.toUTFz!(MediaInfo_Char*); 386 const auto strptr = mediainfo_FunctionTable.MediaInfo_Option(handle, optionZ, valueZ); 387 auto str = strptr.fromStringz; 388 return to!string(str); 389 } 390 391 /* 392 static string optionStatic(const(string) option, const(string) value = "") 393 { 394 return to!string(mediainfo_FunctionTable.MediaInfo_Option_Static(handle, toStringz(option), toStringz(value))); 395 }*/ 396 397 /** 398 * (NOT IMPLEMENTED YET) Get the state of the library 399 * 400 * Return values: 401 * <1000 No information is available for the file yet 402 * >=1000_<5000 Only local (into the file) information is available, getting Internet information (titles only) is no finished yet 403 * 5000 (only if Internet connection is accepted) User interaction is needed (use Option() with "Internet_Title_Get") 404 * Warning: even there is only one possible, user interaction (or the software) is needed 405 * >5000<=10000 Only local (into the file) information is available, getting Internet information (all) is no finished yet 406 * <10000 Done 407 */ 408 size_t getState() 409 { 410 return mediainfo_FunctionTable.MediaInfo_State_Get(handle); 411 } 412 /** 413 * Count of streams of a stream kind (StreamNumber not filled), or count of piece of information in this stream. 414 * 415 * Params: 416 * streamKind = Kind of stream (general, video, audio...) 417 * streamNumber = Stream number in this kind of stream (first, second...) 418 */ 419 size_t getCount(MediaInfo_stream_t streamKind, size_t streamNumber = -1) 420 { 421 return mediainfo_FunctionTable.MediaInfo_Count_Get(handle, streamKind, streamNumber); 422 } 423 }