[Metadata] Deprecate MetadataEditor module (#5837)
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.Metadata / MetadataEditor / MetadataEditor.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.IO;
19 using System.Runtime.InteropServices;
20
21 using Native = Interop.MetadataEditor;
22
23 namespace Tizen.Multimedia
24 {
25     /// <summary>
26     /// Provides a means to edit the metadata of MP3 and MP4 files.
27     /// Since 6.0, WAV, FLAC, OGG files are supported as well.
28     /// </summary>
29     /// <privilege>
30     /// If you want to access only an internal storage,
31     /// you should add privilege http://tizen.org/privilege/mediastorage.<br/>
32     /// Or if you want to access only an external storage,
33     /// you should add privilege http://tizen.org/privilege/externalstorage.
34     /// </privilege>
35     /// <since_tizen> 3 </since_tizen>
36     [Obsolete("Deprecated in API12; Will be removed in API14")]
37     public class MetadataEditor : IDisposable
38     {
39         private bool _disposed = false;
40         private IntPtr _handle = IntPtr.Zero;
41         private bool _isFileReadOnly;
42
43         private IntPtr Handle
44         {
45             get
46             {
47                 if (_handle == IntPtr.Zero)
48                 {
49                     throw new ObjectDisposedException(nameof(MetadataEditor));
50                 }
51
52                 return _handle;
53             }
54         }
55
56         /// <summary>
57         /// Initializes a new instance of the <see cref="MetadataEditor"/> class with the specified path.
58         /// </summary>
59         /// <since_tizen> 3 </since_tizen>
60         /// <param name="path">The path of the media file to edit the metadata.</param>
61         /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
62         /// <exception cref="ArgumentException"><paramref name="path"/> is a zero-length string, contains only white space.</exception>
63         /// <exception cref="FileFormatException">The file is not supported.</exception>
64         /// <exception cref="FileNotFoundException">The file does not exist.</exception>
65         /// <exception cref="UnauthorizedAccessException">The caller does not have required privilege to access the file.</exception>
66         [Obsolete("Deprecated in API12; Will be removed in API14")]
67         public MetadataEditor(string path)
68         {
69             if (path == null)
70             {
71                 throw new ArgumentNullException(nameof(path));
72             }
73
74             if (string.IsNullOrWhiteSpace(path))
75             {
76                 throw new ArgumentException($"{nameof(path)} is a zero-length string.", nameof(path));
77             }
78
79             Native.Create(out _handle).ThrowIfError("Failed to create metadata");
80
81             try
82             {
83                 Native.SetPath(Handle, path).ThrowIfError("Failed to set path");
84
85                 _isFileReadOnly = File.GetAttributes(path).HasFlag(FileAttributes.ReadOnly);
86             }
87             catch (Exception)
88             {
89                 Dispose(false);
90                 throw;
91             }
92         }
93
94         private string GetParam(MetadataEditorAttr attr)
95         {
96             IntPtr val = IntPtr.Zero;
97
98             try
99             {
100                 Native.GetMetadata(Handle, attr, out val)
101                     .ThrowIfError("Failed to get metadata");
102
103                 return Marshal.PtrToStringAnsi(val);
104             }
105             finally
106             {
107                 Marshal.FreeHGlobal(val);
108             }
109         }
110
111         private void SetParam(MetadataEditorAttr attr, string value)
112         {
113             if (_isFileReadOnly)
114             {
115                 throw new InvalidOperationException("The media file is read-only.");
116             }
117
118             Native.SetMetadata(Handle, attr, value).ThrowIfError("Failed to set value");
119         }
120
121         /// <summary>
122         /// Gets or sets the artist of media.
123         /// </summary>
124         /// <since_tizen> 3 </since_tizen>
125         /// <exception cref="InvalidOperationException">
126         /// The file is read-only.<br/>
127         /// -or-<br/>
128         /// The malformed file which cannot be updatable.<br/>
129         /// -or-<br/>
130         /// Internal error.
131         /// </exception>
132         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
133         [Obsolete("Deprecated in API12; Will be removed in API14")]
134         public string Artist
135         {
136             get
137             {
138                 return GetParam(MetadataEditorAttr.Artist);
139             }
140
141             set
142             {
143                 SetParam(MetadataEditorAttr.Artist, value);
144             }
145         }
146
147         /// <summary>
148         /// Gets or sets the title of media.
149         /// </summary>
150         /// <since_tizen> 3 </since_tizen>
151         /// <exception cref="InvalidOperationException">
152         /// The file is read-only.<br/>
153         /// -or-<br/>
154         /// The malformed file which cannot be updatable.<br/>
155         /// -or-<br/>
156         /// Internal error.
157         /// </exception>
158         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
159         [Obsolete("Deprecated in API12; Will be removed in API14")]
160         public string Title
161         {
162             get
163             {
164                 return GetParam(MetadataEditorAttr.Title);
165             }
166
167             set
168             {
169                 SetParam(MetadataEditorAttr.Title, value);
170             }
171         }
172
173         /// <summary>
174         /// Gets or sets the album name of media.
175         /// </summary>
176         /// <since_tizen> 3 </since_tizen>
177         /// <exception cref="InvalidOperationException">
178         /// The file is read-only.<br/>
179         /// -or-<br/>
180         /// The malformed file which cannot be updatable.<br/>
181         /// -or-<br/>
182         /// Internal error.
183         /// </exception>
184         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
185         [Obsolete("Deprecated in API12; Will be removed in API14")]
186         public string Album
187         {
188             get
189             {
190                 return GetParam(MetadataEditorAttr.Album);
191             }
192
193             set
194             {
195                 SetParam(MetadataEditorAttr.Album, value);
196             }
197         }
198
199         /// <summary>
200         /// Gets or sets the genre of media.
201         /// </summary>
202         /// <since_tizen> 3 </since_tizen>
203         /// <exception cref="InvalidOperationException">
204         /// The file is read-only.<br/>
205         /// -or-<br/>
206         /// The malformed file which cannot be updatable.<br/>
207         /// -or-<br/>
208         /// Internal error.
209         /// </exception>
210         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
211         [Obsolete("Deprecated in API12; Will be removed in API14")]
212         public string Genre
213         {
214             get
215             {
216                 return GetParam(MetadataEditorAttr.Genre);
217             }
218
219             set
220             {
221                 SetParam(MetadataEditorAttr.Genre, value);
222             }
223         }
224
225         /// <summary>
226         /// Gets or sets the author of media.
227         /// </summary>
228         /// <since_tizen> 3 </since_tizen>
229         /// <exception cref="InvalidOperationException">
230         /// The file is read-only.<br/>
231         /// -or-<br/>
232         /// The malformed file which cannot be updatable.<br/>
233         /// -or-<br/>
234         /// Internal error.
235         /// </exception>
236         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
237         [Obsolete("Deprecated in API12; Will be removed in API14")]
238         public string Author
239         {
240             get
241             {
242                 return GetParam(MetadataEditorAttr.Author);
243             }
244
245             set
246             {
247                 SetParam(MetadataEditorAttr.Author, value);
248             }
249         }
250
251         /// <summary>
252         /// Gets or sets the copyright of media.
253         /// </summary>
254         /// <since_tizen> 3 </since_tizen>
255         /// <exception cref="InvalidOperationException">
256         /// The file is read-only.<br/>
257         /// -or-<br/>
258         /// The malformed file which cannot be updatable.<br/>
259         /// -or-<br/>
260         /// Internal error.
261         /// </exception>
262         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
263         [Obsolete("Deprecated in API12; Will be removed in API14")]
264         public string Copyright
265         {
266             get
267             {
268                 return GetParam(MetadataEditorAttr.Copyright);
269             }
270
271             set
272             {
273                 SetParam(MetadataEditorAttr.Copyright, value);
274             }
275         }
276
277         /// <summary>
278         /// Gets or sets the date of media.
279         /// </summary>
280         /// <since_tizen> 3 </since_tizen>
281         /// <remarks>
282         /// If the media contains the ID3 tag, this refers to the recorded date.
283         /// If the media is a mp4 format, this refers to the year, and the value to set will be converted into integer.
284         /// </remarks>
285         /// <exception cref="InvalidOperationException">
286         /// The file is read-only.<br/>
287         /// -or-<br/>
288         /// The malformed file which cannot be updatable.<br/>
289         /// -or-<br/>
290         /// Internal error.
291         /// </exception>
292         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
293         [Obsolete("Deprecated in API12; Will be removed in API14")]
294         public string Date
295         {
296             get
297             {
298                 return GetParam(MetadataEditorAttr.Date);
299             }
300
301             set
302             {
303                 SetParam(MetadataEditorAttr.Date, value);
304             }
305         }
306
307         /// <summary>
308         /// Gets or sets the description of media.
309         /// </summary>
310         /// <since_tizen> 3 </since_tizen>
311         /// <exception cref="InvalidOperationException">
312         /// The file is read-only.<br/>
313         /// -or-<br/>
314         /// The malformed file which cannot be updatable.<br/>
315         /// -or-<br/>
316         /// Internal error.
317         /// </exception>
318         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
319         [Obsolete("Deprecated in API12; Will be removed in API14")]
320         public string Description
321         {
322             get
323             {
324                 return GetParam(MetadataEditorAttr.Description);
325             }
326
327             set
328             {
329                 SetParam(MetadataEditorAttr.Description, value);
330             }
331         }
332
333         /// <summary>
334         /// Gets or sets the comment of media.
335         /// </summary>
336         /// <since_tizen> 3 </since_tizen>
337         /// <exception cref="InvalidOperationException">
338         /// The file is read-only.<br/>
339         /// -or-<br/>
340         /// The malformed file which cannot be updatable.<br/>
341         /// -or-<br/>
342         /// Internal error.
343         /// </exception>
344         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
345         [Obsolete("Deprecated in API12; Will be removed in API14")]
346         public string Comment
347         {
348             get
349             {
350                 return GetParam(MetadataEditorAttr.Comment);
351             }
352
353             set
354             {
355                 SetParam(MetadataEditorAttr.Comment, value);
356             }
357         }
358
359         /// <summary>
360         /// Gets or sets the track number of media.
361         /// </summary>
362         /// <since_tizen> 3 </since_tizen>
363         /// <exception cref="InvalidOperationException">
364         /// The file is read-only.<br/>
365         /// -or-<br/>
366         /// The malformed file which cannot be updatable.<br/>
367         /// -or-<br/>
368         /// Internal error.
369         /// </exception>
370         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
371         [Obsolete("Deprecated in API12; Will be removed in API14")]
372         public string TrackNumber
373         {
374             get
375             {
376                 return GetParam(MetadataEditorAttr.TrackNumber);
377             }
378
379             set
380             {
381                 SetParam(MetadataEditorAttr.TrackNumber, value);
382             }
383         }
384
385         /// <summary>
386         /// Gets the count of album arts of media.
387         /// </summary>
388         /// <since_tizen> 3 </since_tizen>
389         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
390         [Obsolete("Deprecated in API12; Will be removed in API14")]
391         public int PictureCount
392         {
393             get => int.TryParse(GetParam(MetadataEditorAttr.PictureCount), out var value) ? value : 0;
394         }
395
396         /// <summary>
397         /// Gets or sets the conductor of media.
398         /// </summary>
399         /// <since_tizen> 3 </since_tizen>
400         /// <exception cref="InvalidOperationException">
401         /// The file is read-only.<br/>
402         /// -or-<br/>
403         /// The malformed file which cannot be updatable.<br/>
404         /// -or-<br/>
405         /// Internal error.
406         /// </exception>
407         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
408         [Obsolete("Deprecated in API12; Will be removed in API14")]
409         public string Conductor
410         {
411             get
412             {
413                 return GetParam(MetadataEditorAttr.Conductor);
414             }
415
416             set
417             {
418                 SetParam(MetadataEditorAttr.Conductor, value);
419             }
420         }
421
422         /// <summary>
423         /// Gets or sets the unsynchronized lyrics of media.
424         /// </summary>
425         /// <since_tizen> 3 </since_tizen>
426         /// <exception cref="InvalidOperationException">
427         /// The file is read-only.<br/>
428         /// -or-<br/>
429         /// The malformed file which cannot be updatable.<br/>
430         /// -or-<br/>
431         /// Internal error.
432         /// </exception>
433         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
434         [Obsolete("Deprecated in API12; Will be removed in API14")]
435         public string UnsyncLyrics
436         {
437             get
438             {
439                 return GetParam(MetadataEditorAttr.UnsyncLyrics);
440             }
441
442             set
443             {
444                 SetParam(MetadataEditorAttr.UnsyncLyrics, value);
445             }
446         }
447
448         /// <summary>
449         /// Writes the modified metadata to the media file.
450         /// </summary>
451         /// <exception cref="InvalidOperationException">
452         /// The file is read-only.<br/>
453         /// -or-<br/>
454         /// Internal error.<br/>
455         /// </exception>
456         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
457         /// <since_tizen> 3 </since_tizen>
458         [Obsolete("Deprecated in API12; Will be removed in API14")]
459         public void Commit()
460         {
461             if (_isFileReadOnly)
462             {
463                 throw new InvalidOperationException("The media file is read-only.");
464             }
465
466             Native.UpdateMetadata(Handle).ThrowIfError("Failed to update file");
467         }
468
469         /// <summary>
470         /// Gets the artwork image in the media file.
471         /// </summary>
472         /// <since_tizen> 3 </since_tizen>
473         /// <param name="index">The index of the picture to import.</param>
474         /// <returns>The artwork included in the media file.</returns>
475         /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
476         /// <exception cref="ArgumentOutOfRangeException">
477         ///     <paramref name="index"/> is less than zero.<br/>
478         ///     -or-<br/>
479         ///     <paramref name="index"/> is greater than or equal to <see cref="PictureCount"/>.
480         /// </exception>
481         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
482         [Obsolete("Deprecated in API12; Will be removed in API14")]
483         public Artwork GetPicture(int index)
484         {
485             if (index < 0)
486             {
487                 throw new ArgumentOutOfRangeException(nameof(index), index,
488                     "Index should not be less than zero.");
489             }
490
491             if (index >= PictureCount)
492             {
493                 throw new ArgumentOutOfRangeException(nameof(index), index,
494                     "Index should not be greater thor or equal to PictureCount.");
495             }
496
497             IntPtr data = IntPtr.Zero;
498             IntPtr mimeType = IntPtr.Zero;
499
500             try
501             {
502                 Native.GetPicture(Handle, index, out data, out var size, out mimeType).
503                     ThrowIfError("Failed to get the value");
504
505                 if (size > 0)
506                 {
507                     byte[] tmpBuf = new byte[size];
508                     Marshal.Copy(data, tmpBuf, 0, size);
509
510                     return new Artwork(tmpBuf, Marshal.PtrToStringAnsi(mimeType));
511                 }
512
513                 return null;
514             }
515             finally
516             {
517                 if (data != IntPtr.Zero)
518                 {
519                     Marshal.FreeHGlobal(data);
520                 }
521
522                 if (mimeType != IntPtr.Zero)
523                 {
524                     Marshal.FreeHGlobal(mimeType);
525                 }
526             }
527         }
528
529         /// <summary>
530         /// Appends the picture to the media file.
531         /// </summary>
532         /// <since_tizen> 3 </since_tizen>
533         /// <param name="path">The path of the picture for adding to the metadata.</param>
534         /// <exception cref="InvalidOperationException">
535         /// The file is read-only.<br/>
536         /// -or-<br/>
537         /// The malformed file which cannot be updatable.<br/>
538         /// -or-<br/>
539         /// Internal error.
540         /// </exception>
541         /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
542         /// <exception cref="FileNotFoundException">The file does not exist.</exception>
543         /// <exception cref="UnauthorizedAccessException">The caller does not have required privilege to access the file.</exception>
544         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
545         /// <exception cref="FileFormatException">The specified file is not supported.</exception>
546         [Obsolete("Deprecated in API12; Will be removed in API14")]
547         public void AddPicture(string path)
548         {
549             if (path == null)
550             {
551                 throw new ArgumentNullException(nameof(path));
552             }
553
554             if (File.Exists(path) == false)
555             {
556                 throw new FileNotFoundException("File does not exist.", path);
557             }
558
559             if (_isFileReadOnly)
560             {
561                 throw new InvalidOperationException("The media file is read-only.");
562             }
563
564             Native.AddPicture(Handle, path).
565                 ThrowIfError("Failed to append picture");
566         }
567
568         /// <summary>
569         /// Removes the picture from the media file.
570         /// </summary>
571         /// <since_tizen> 3 </since_tizen>
572         /// <param name="index">The index of the picture to remove.</param>
573         /// <exception cref="InvalidOperationException">
574         ///     An internal error occurs.<br/>
575         ///     -or-<br/>
576         ///     The media file is read-only.
577         /// </exception>
578         /// <exception cref="ArgumentOutOfRangeException">
579         ///     <paramref name="index"/> is less than zero.<br/>
580         ///     -or-<br/>
581         ///     <paramref name="index"/> is greater than or equal to <see cref="PictureCount"/>.
582         /// </exception>
583         /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
584         [Obsolete("Deprecated in API12; Will be removed in API14")]
585         public void RemovePicture(int index)
586         {
587             if (index < 0)
588             {
589                 throw new ArgumentOutOfRangeException("Index should be larger than 0 [" + index + "]");
590             }
591
592             if (index >= PictureCount)
593             {
594                 throw new ArgumentOutOfRangeException(nameof(index), index,
595                     "Index should not be greater thor or equal to PictureCount.");
596             }
597
598             if (_isFileReadOnly)
599             {
600                 throw new InvalidOperationException("The media file is read-only.");
601             }
602
603             Native.RemovePicture(Handle, index).ThrowIfError("Failed to remove picture");
604         }
605
606         /// <summary>
607         /// Finalizes an instance of the MetadataEditor class.
608         /// </summary>
609         ~MetadataEditor()
610         {
611             Dispose(false);
612         }
613
614         /// <summary>
615         /// Releases the resources used by the <see cref="MetadataEditor"/> object.
616         /// </summary>
617         /// <param name="disposing">
618         /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
619         /// </param>
620         /// <since_tizen> 3 </since_tizen>
621         protected virtual void Dispose(bool disposing)
622         {
623             if (!_disposed)
624             {
625                 if (_handle != IntPtr.Zero)
626                 {
627                     Native.Destroy(_handle);
628                     _handle = IntPtr.Zero;
629                 }
630
631                 _disposed = true;
632             }
633         }
634
635         /// <summary>
636         /// Releases all resources used by the <see cref="MetadataEditor"/> object.
637         /// </summary>
638         /// <since_tizen> 3 </since_tizen>
639         [Obsolete("Deprecated in API12; Will be removed in API14")]
640         public void Dispose()
641         {
642             Dispose(true);
643             GC.SuppressFinalize(this);
644         }
645     }
646 }