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