2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 using System.Runtime.InteropServices;
21 using Native = Interop.MetadataEditor;
23 namespace Tizen.Multimedia
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.
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.
35 /// <since_tizen> 3 </since_tizen>
36 [Obsolete("Deprecated in API12; Will be removed in API14")]
37 public class MetadataEditor : IDisposable
39 private bool _disposed = false;
40 private IntPtr _handle = IntPtr.Zero;
41 private bool _isFileReadOnly;
47 if (_handle == IntPtr.Zero)
49 throw new ObjectDisposedException(nameof(MetadataEditor));
57 /// Initializes a new instance of the <see cref="MetadataEditor"/> class with the specified path.
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)
71 throw new ArgumentNullException(nameof(path));
74 if (string.IsNullOrWhiteSpace(path))
76 throw new ArgumentException($"{nameof(path)} is a zero-length string.", nameof(path));
79 Native.Create(out _handle).ThrowIfError("Failed to create metadata");
83 Native.SetPath(Handle, path).ThrowIfError("Failed to set path");
85 _isFileReadOnly = File.GetAttributes(path).HasFlag(FileAttributes.ReadOnly);
94 private string GetParam(MetadataEditorAttr attr)
96 IntPtr val = IntPtr.Zero;
100 Native.GetMetadata(Handle, attr, out val)
101 .ThrowIfError("Failed to get metadata");
103 return Marshal.PtrToStringAnsi(val);
107 Marshal.FreeHGlobal(val);
111 private void SetParam(MetadataEditorAttr attr, string value)
115 throw new InvalidOperationException("The media file is read-only.");
118 Native.SetMetadata(Handle, attr, value).ThrowIfError("Failed to set value");
122 /// Gets or sets the artist of media.
124 /// <since_tizen> 3 </since_tizen>
125 /// <exception cref="InvalidOperationException">
126 /// The file is read-only.<br/>
128 /// The malformed file which cannot be updatable.<br/>
132 /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
133 [Obsolete("Deprecated in API12; Will be removed in API14")]
138 return GetParam(MetadataEditorAttr.Artist);
143 SetParam(MetadataEditorAttr.Artist, value);
148 /// Gets or sets the title of media.
150 /// <since_tizen> 3 </since_tizen>
151 /// <exception cref="InvalidOperationException">
152 /// The file is read-only.<br/>
154 /// The malformed file which cannot be updatable.<br/>
158 /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
159 [Obsolete("Deprecated in API12; Will be removed in API14")]
164 return GetParam(MetadataEditorAttr.Title);
169 SetParam(MetadataEditorAttr.Title, value);
174 /// Gets or sets the album name of media.
176 /// <since_tizen> 3 </since_tizen>
177 /// <exception cref="InvalidOperationException">
178 /// The file is read-only.<br/>
180 /// The malformed file which cannot be updatable.<br/>
184 /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
185 [Obsolete("Deprecated in API12; Will be removed in API14")]
190 return GetParam(MetadataEditorAttr.Album);
195 SetParam(MetadataEditorAttr.Album, value);
200 /// Gets or sets the genre of media.
202 /// <since_tizen> 3 </since_tizen>
203 /// <exception cref="InvalidOperationException">
204 /// The file is read-only.<br/>
206 /// The malformed file which cannot be updatable.<br/>
210 /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
211 [Obsolete("Deprecated in API12; Will be removed in API14")]
216 return GetParam(MetadataEditorAttr.Genre);
221 SetParam(MetadataEditorAttr.Genre, value);
226 /// Gets or sets the author of media.
228 /// <since_tizen> 3 </since_tizen>
229 /// <exception cref="InvalidOperationException">
230 /// The file is read-only.<br/>
232 /// The malformed file which cannot be updatable.<br/>
236 /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
237 [Obsolete("Deprecated in API12; Will be removed in API14")]
242 return GetParam(MetadataEditorAttr.Author);
247 SetParam(MetadataEditorAttr.Author, value);
252 /// Gets or sets the copyright of media.
254 /// <since_tizen> 3 </since_tizen>
255 /// <exception cref="InvalidOperationException">
256 /// The file is read-only.<br/>
258 /// The malformed file which cannot be updatable.<br/>
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
268 return GetParam(MetadataEditorAttr.Copyright);
273 SetParam(MetadataEditorAttr.Copyright, value);
278 /// Gets or sets the date of media.
280 /// <since_tizen> 3 </since_tizen>
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.
285 /// <exception cref="InvalidOperationException">
286 /// The file is read-only.<br/>
288 /// The malformed file which cannot be updatable.<br/>
292 /// <exception cref="ObjectDisposedException">The <see cref="MetadataEditor"/> has already been disposed of.</exception>
293 [Obsolete("Deprecated in API12; Will be removed in API14")]
298 return GetParam(MetadataEditorAttr.Date);
303 SetParam(MetadataEditorAttr.Date, value);
308 /// Gets or sets the description of media.
310 /// <since_tizen> 3 </since_tizen>
311 /// <exception cref="InvalidOperationException">
312 /// The file is read-only.<br/>
314 /// The malformed file which cannot be updatable.<br/>
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
324 return GetParam(MetadataEditorAttr.Description);
329 SetParam(MetadataEditorAttr.Description, value);
334 /// Gets or sets the comment of media.
336 /// <since_tizen> 3 </since_tizen>
337 /// <exception cref="InvalidOperationException">
338 /// The file is read-only.<br/>
340 /// The malformed file which cannot be updatable.<br/>
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
350 return GetParam(MetadataEditorAttr.Comment);
355 SetParam(MetadataEditorAttr.Comment, value);
360 /// Gets or sets the track number of media.
362 /// <since_tizen> 3 </since_tizen>
363 /// <exception cref="InvalidOperationException">
364 /// The file is read-only.<br/>
366 /// The malformed file which cannot be updatable.<br/>
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
376 return GetParam(MetadataEditorAttr.TrackNumber);
381 SetParam(MetadataEditorAttr.TrackNumber, value);
386 /// Gets the count of album arts of media.
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
393 get => int.TryParse(GetParam(MetadataEditorAttr.PictureCount), out var value) ? value : 0;
397 /// Gets or sets the conductor of media.
399 /// <since_tizen> 3 </since_tizen>
400 /// <exception cref="InvalidOperationException">
401 /// The file is read-only.<br/>
403 /// The malformed file which cannot be updatable.<br/>
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
413 return GetParam(MetadataEditorAttr.Conductor);
418 SetParam(MetadataEditorAttr.Conductor, value);
423 /// Gets or sets the unsynchronized lyrics of media.
425 /// <since_tizen> 3 </since_tizen>
426 /// <exception cref="InvalidOperationException">
427 /// The file is read-only.<br/>
429 /// The malformed file which cannot be updatable.<br/>
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
439 return GetParam(MetadataEditorAttr.UnsyncLyrics);
444 SetParam(MetadataEditorAttr.UnsyncLyrics, value);
449 /// Writes the modified metadata to the media file.
451 /// <exception cref="InvalidOperationException">
452 /// The file is read-only.<br/>
454 /// Internal error.<br/>
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")]
463 throw new InvalidOperationException("The media file is read-only.");
466 Native.UpdateMetadata(Handle).ThrowIfError("Failed to update file");
470 /// Gets the artwork image in the media file.
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/>
479 /// <paramref name="index"/> is greater than or equal to <see cref="PictureCount"/>.
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)
487 throw new ArgumentOutOfRangeException(nameof(index), index,
488 "Index should not be less than zero.");
491 if (index >= PictureCount)
493 throw new ArgumentOutOfRangeException(nameof(index), index,
494 "Index should not be greater thor or equal to PictureCount.");
497 IntPtr data = IntPtr.Zero;
498 IntPtr mimeType = IntPtr.Zero;
502 Native.GetPicture(Handle, index, out data, out var size, out mimeType).
503 ThrowIfError("Failed to get the value");
507 byte[] tmpBuf = new byte[size];
508 Marshal.Copy(data, tmpBuf, 0, size);
510 return new Artwork(tmpBuf, Marshal.PtrToStringAnsi(mimeType));
517 if (data != IntPtr.Zero)
519 Marshal.FreeHGlobal(data);
522 if (mimeType != IntPtr.Zero)
524 Marshal.FreeHGlobal(mimeType);
530 /// Appends the picture to the media file.
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/>
537 /// The malformed file which cannot be updatable.<br/>
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)
551 throw new ArgumentNullException(nameof(path));
554 if (File.Exists(path) == false)
556 throw new FileNotFoundException("File does not exist.", path);
561 throw new InvalidOperationException("The media file is read-only.");
564 Native.AddPicture(Handle, path).
565 ThrowIfError("Failed to append picture");
569 /// Removes the picture from the media file.
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/>
576 /// The media file is read-only.
578 /// <exception cref="ArgumentOutOfRangeException">
579 /// <paramref name="index"/> is less than zero.<br/>
581 /// <paramref name="index"/> is greater than or equal to <see cref="PictureCount"/>.
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)
589 throw new ArgumentOutOfRangeException("Index should be larger than 0 [" + index + "]");
592 if (index >= PictureCount)
594 throw new ArgumentOutOfRangeException(nameof(index), index,
595 "Index should not be greater thor or equal to PictureCount.");
600 throw new InvalidOperationException("The media file is read-only.");
603 Native.RemovePicture(Handle, index).ThrowIfError("Failed to remove picture");
607 /// Finalizes an instance of the MetadataEditor class.
615 /// Releases the resources used by the <see cref="MetadataEditor"/> object.
617 /// <param name="disposing">
618 /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
620 /// <since_tizen> 3 </since_tizen>
621 protected virtual void Dispose(bool disposing)
625 if (_handle != IntPtr.Zero)
627 Native.Destroy(_handle);
628 _handle = IntPtr.Zero;
636 /// Releases all resources used by the <see cref="MetadataEditor"/> object.
638 /// <since_tizen> 3 </since_tizen>
639 [Obsolete("Deprecated in API12; Will be removed in API14")]
640 public void Dispose()
643 GC.SuppressFinalize(this);