1 /* EasyTAG - tag editor for audio files
2 * Copyright (C) 2014,2015 David King <amigadave@amigadave.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 51
16 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "file_tag.h"
20
21 #include "misc.h"
22
23 /*
24 * Create a new File_Tag structure.
25 */
26 File_Tag *
et_file_tag_new(void)27 et_file_tag_new (void)
28 {
29 File_Tag *file_tag;
30
31 file_tag = g_slice_new0 (File_Tag);
32 file_tag->key = et_undo_key_new ();
33
34 return file_tag;
35 }
36
37 /*
38 * Frees the list of 'other' field in a File_Tag item (contains attached gchar data).
39 */
40 static void
et_file_tag_free_other_field(File_Tag * file_tag)41 et_file_tag_free_other_field (File_Tag *file_tag)
42 {
43 g_list_free_full (file_tag->other, g_free);
44 file_tag->other = NULL;
45 }
46
47
48 /*
49 * Frees a File_Tag item.
50 */
51 void
et_file_tag_free(File_Tag * FileTag)52 et_file_tag_free (File_Tag *FileTag)
53 {
54 g_return_if_fail (FileTag != NULL);
55
56 g_free(FileTag->title);
57 g_free(FileTag->artist);
58 g_free(FileTag->album_artist);
59 g_free(FileTag->album);
60 g_free(FileTag->disc_number);
61 g_free (FileTag->disc_total);
62 g_free(FileTag->year);
63 g_free(FileTag->track);
64 g_free(FileTag->track_total);
65 g_free(FileTag->genre);
66 g_free(FileTag->comment);
67 g_free(FileTag->composer);
68 g_free(FileTag->orig_artist);
69 g_free(FileTag->copyright);
70 g_free(FileTag->url);
71 g_free(FileTag->encoded_by);
72 et_file_tag_set_picture (FileTag, NULL);
73 et_file_tag_free_other_field (FileTag);
74
75 g_slice_free (File_Tag, FileTag);
76 }
77
78 /*
79 * Duplicate the 'other' list, preserving the list already in @destination.
80 */
81 void
et_file_tag_copy_other_into(File_Tag * destination,const File_Tag * source)82 et_file_tag_copy_other_into (File_Tag *destination,
83 const File_Tag *source)
84 {
85 GList *l;
86 GList *new_other = NULL;
87
88 for (l = source->other; l != NULL; l = g_list_next (l))
89 {
90 new_other = g_list_prepend (new_other, g_strdup ((gchar *)l->data));
91 }
92
93 new_other = g_list_reverse (new_other);
94 destination->other = g_list_concat (destination->other, new_other);
95 }
96
97
98 /*
99 * Copy data of the File_Tag structure (of ETFile) to the FileTag item.
100 * Reallocate data if not null.
101 */
102 void
et_file_tag_copy_into(File_Tag * destination,const File_Tag * source)103 et_file_tag_copy_into (File_Tag *destination,
104 const File_Tag *source)
105 {
106 g_return_if_fail (source != NULL);
107 g_return_if_fail (destination != NULL);
108
109 /* Key for the item, may be overwritten. */
110 destination->key = et_undo_key_new ();
111
112 et_file_tag_set_title (destination, source->title);
113 et_file_tag_set_artist (destination, source->artist);
114 et_file_tag_set_album_artist (destination, source->album_artist);
115 et_file_tag_set_album (destination, source->album);
116 et_file_tag_set_disc_number (destination, source->disc_number);
117 et_file_tag_set_disc_total (destination, source->disc_total);
118 et_file_tag_set_year (destination, source->year);
119 et_file_tag_set_track_number (destination, source->track);
120 et_file_tag_set_track_total (destination, source->track_total);
121 et_file_tag_set_genre (destination, source->genre);
122 et_file_tag_set_comment (destination, source->comment);
123 et_file_tag_set_composer (destination, source->composer);
124 et_file_tag_set_orig_artist (destination, source->orig_artist);
125 et_file_tag_set_copyright (destination, source->copyright);
126 et_file_tag_set_url (destination, source->url);
127 et_file_tag_set_encoded_by (destination, source->encoded_by);
128 et_file_tag_set_picture (destination, source->picture);
129
130 if (source->other)
131 {
132 et_file_tag_copy_other_into (destination, source);
133 }
134 else
135 {
136 et_file_tag_free_other_field (destination);
137 }
138 }
139
140 /*
141 * Set the value of a field of a FileTag item (for ex, value of FileTag->title)
142 * Must be used only for the 'gchar *' components
143 */
144 static void
et_file_tag_set_field(gchar ** FileTagField,const gchar * value)145 et_file_tag_set_field (gchar **FileTagField,
146 const gchar *value)
147 {
148 g_return_if_fail (FileTagField != NULL);
149
150 if (*FileTagField != NULL)
151 {
152 g_free (*FileTagField);
153 *FileTagField = NULL;
154 }
155
156 if (value != NULL)
157 {
158 if (*value != '\0')
159 {
160 *FileTagField = g_strdup (value);
161 }
162 }
163 }
164
165 void
et_file_tag_set_title(File_Tag * file_tag,const gchar * title)166 et_file_tag_set_title (File_Tag *file_tag,
167 const gchar *title)
168 {
169 g_return_if_fail (file_tag != NULL);
170
171 et_file_tag_set_field (&file_tag->title, title);
172 }
173
174 void
et_file_tag_set_artist(File_Tag * file_tag,const gchar * artist)175 et_file_tag_set_artist (File_Tag *file_tag,
176 const gchar *artist)
177 {
178 g_return_if_fail (file_tag != NULL);
179
180 et_file_tag_set_field (&file_tag->artist, artist);
181 }
182
183 void
et_file_tag_set_album_artist(File_Tag * file_tag,const gchar * album_artist)184 et_file_tag_set_album_artist (File_Tag *file_tag,
185 const gchar *album_artist)
186 {
187 g_return_if_fail (file_tag != NULL);
188
189 et_file_tag_set_field (&file_tag->album_artist, album_artist);
190 }
191
192 void
et_file_tag_set_album(File_Tag * file_tag,const gchar * album)193 et_file_tag_set_album (File_Tag *file_tag,
194 const gchar *album)
195 {
196 g_return_if_fail (file_tag != NULL);
197
198 et_file_tag_set_field (&file_tag->album, album);
199 }
200
201 void
et_file_tag_set_disc_number(File_Tag * file_tag,const gchar * disc_number)202 et_file_tag_set_disc_number (File_Tag *file_tag,
203 const gchar *disc_number)
204 {
205 g_return_if_fail (file_tag != NULL);
206
207 et_file_tag_set_field (&file_tag->disc_number, disc_number);
208 }
209
210 void
et_file_tag_set_disc_total(File_Tag * file_tag,const gchar * disc_total)211 et_file_tag_set_disc_total (File_Tag *file_tag,
212 const gchar *disc_total)
213 {
214 g_return_if_fail (file_tag != NULL);
215
216 et_file_tag_set_field (&file_tag->disc_total, disc_total);
217 }
218
219 void
et_file_tag_set_year(File_Tag * file_tag,const gchar * year)220 et_file_tag_set_year (File_Tag *file_tag,
221 const gchar *year)
222 {
223 g_return_if_fail (file_tag != NULL);
224
225 et_file_tag_set_field (&file_tag->year, year);
226 }
227
228 void
et_file_tag_set_track_number(File_Tag * file_tag,const gchar * track_number)229 et_file_tag_set_track_number (File_Tag *file_tag,
230 const gchar *track_number)
231 {
232 g_return_if_fail (file_tag != NULL);
233
234 et_file_tag_set_field (&file_tag->track, track_number);
235 }
236
237 void
et_file_tag_set_track_total(File_Tag * file_tag,const gchar * track_total)238 et_file_tag_set_track_total (File_Tag *file_tag,
239 const gchar *track_total)
240 {
241 g_return_if_fail (file_tag != NULL);
242
243 et_file_tag_set_field (&file_tag->track_total, track_total);
244 }
245
246 void
et_file_tag_set_genre(File_Tag * file_tag,const gchar * genre)247 et_file_tag_set_genre (File_Tag *file_tag,
248 const gchar *genre)
249 {
250 g_return_if_fail (file_tag != NULL);
251
252 et_file_tag_set_field (&file_tag->genre, genre);
253 }
254
255 void
et_file_tag_set_comment(File_Tag * file_tag,const gchar * comment)256 et_file_tag_set_comment (File_Tag *file_tag,
257 const gchar *comment)
258 {
259 g_return_if_fail (file_tag != NULL);
260
261 et_file_tag_set_field (&file_tag->comment, comment);
262 }
263
264 void
et_file_tag_set_composer(File_Tag * file_tag,const gchar * composer)265 et_file_tag_set_composer (File_Tag *file_tag,
266 const gchar *composer)
267 {
268 g_return_if_fail (file_tag != NULL);
269
270 et_file_tag_set_field (&file_tag->composer, composer);
271 }
272
273 void
et_file_tag_set_orig_artist(File_Tag * file_tag,const gchar * orig_artist)274 et_file_tag_set_orig_artist (File_Tag *file_tag,
275 const gchar *orig_artist)
276 {
277 g_return_if_fail (file_tag != NULL);
278
279 et_file_tag_set_field (&file_tag->orig_artist, orig_artist);
280 }
281
282 void
et_file_tag_set_copyright(File_Tag * file_tag,const gchar * copyright)283 et_file_tag_set_copyright (File_Tag *file_tag,
284 const gchar *copyright)
285 {
286 g_return_if_fail (file_tag != NULL);
287
288 et_file_tag_set_field (&file_tag->copyright, copyright);
289 }
290
291 void
et_file_tag_set_url(File_Tag * file_tag,const gchar * url)292 et_file_tag_set_url (File_Tag *file_tag,
293 const gchar *url)
294 {
295 g_return_if_fail (file_tag != NULL);
296
297 et_file_tag_set_field (&file_tag->url, url);
298 }
299
300 void
et_file_tag_set_encoded_by(File_Tag * file_tag,const gchar * encoded_by)301 et_file_tag_set_encoded_by (File_Tag *file_tag,
302 const gchar *encoded_by)
303 {
304 g_return_if_fail (file_tag != NULL);
305
306 et_file_tag_set_field (&file_tag->encoded_by, encoded_by);
307 }
308
309 /*
310 * et_file_tag_set_picture:
311 * @file_tag: the #File_Tag on which to set the image
312 * @pic: the image to set
313 *
314 * Set the images inside @file_tag to be @pic, freeing existing images as
315 * necessary. Copies @pic with et_picture_copy_all().
316 */
317 void
et_file_tag_set_picture(File_Tag * file_tag,const EtPicture * pic)318 et_file_tag_set_picture (File_Tag *file_tag,
319 const EtPicture *pic)
320 {
321 g_return_if_fail (file_tag != NULL);
322
323 if (file_tag->picture != NULL)
324 {
325 et_picture_free (file_tag->picture);
326 file_tag->picture = NULL;
327 }
328
329 if (pic)
330 {
331 file_tag->picture = et_picture_copy_all (pic);
332 }
333 }
334
335 /*
336 * Compares two File_Tag items and returns TRUE if there aren't the same.
337 * Notes:
338 * - if field is '' or NULL => will be removed
339 */
340 gboolean
et_file_tag_detect_difference(const File_Tag * FileTag1,const File_Tag * FileTag2)341 et_file_tag_detect_difference (const File_Tag *FileTag1,
342 const File_Tag *FileTag2)
343 {
344 const EtPicture *pic1;
345 const EtPicture *pic2;
346
347 g_return_val_if_fail (FileTag1 != NULL && FileTag2 != NULL, FALSE);
348
349 if ( ( FileTag1 && !FileTag2)
350 || (!FileTag1 && FileTag2) )
351 return TRUE;
352
353 /* Title */
354 if (et_normalized_strcmp0 (FileTag1->title, FileTag2->title) != 0)
355 {
356 return TRUE;
357 }
358
359 /* Artist */
360 if (et_normalized_strcmp0 (FileTag1->artist, FileTag2->artist) != 0)
361 {
362 return TRUE;
363 }
364
365 /* Album Artist */
366 if (et_normalized_strcmp0 (FileTag1->album_artist,
367 FileTag2->album_artist) != 0)
368 {
369 return TRUE;
370 }
371
372 /* Album */
373 if (et_normalized_strcmp0 (FileTag1->album, FileTag2->album) != 0)
374 {
375 return TRUE;
376 }
377
378 /* Disc Number */
379 if (et_normalized_strcmp0 (FileTag1->disc_number,
380 FileTag2->disc_number) != 0)
381 {
382 return TRUE;
383 }
384
385 /* Discs Total */
386 if (et_normalized_strcmp0 (FileTag1->disc_total,
387 FileTag2->disc_total) != 0)
388 {
389 return TRUE;
390 }
391
392 /* Year */
393 if (et_normalized_strcmp0 (FileTag1->year, FileTag2->year) != 0)
394 {
395 return TRUE;
396 }
397
398 /* Track */
399 if (et_normalized_strcmp0 (FileTag1->track, FileTag2->track) != 0)
400 {
401 return TRUE;
402 }
403
404 /* Track Total */
405 if (et_normalized_strcmp0 (FileTag1->track_total,
406 FileTag2->track_total) != 0)
407 {
408 return TRUE;
409 }
410
411 /* Genre */
412 if (et_normalized_strcmp0 (FileTag1->genre, FileTag2->genre) != 0)
413 {
414 return TRUE;
415 }
416
417 /* Comment */
418 if (et_normalized_strcmp0 (FileTag1->comment, FileTag2->comment) != 0)
419 {
420 return TRUE;
421 }
422
423 /* Composer */
424 if (et_normalized_strcmp0 (FileTag1->composer, FileTag2->composer) != 0)
425 {
426 return TRUE;
427 }
428
429 /* Original artist */
430 if (et_normalized_strcmp0 (FileTag1->orig_artist,
431 FileTag2->orig_artist) != 0)
432 {
433 return TRUE;
434 }
435
436 /* Copyright */
437 if (et_normalized_strcmp0 (FileTag1->copyright, FileTag2->copyright) != 0)
438 {
439 return TRUE;
440 }
441
442 /* URL */
443 if (et_normalized_strcmp0 (FileTag1->url, FileTag2->url) != 0)
444 {
445 return TRUE;
446 }
447
448 /* Encoded by */
449 if (et_normalized_strcmp0 (FileTag1->encoded_by,
450 FileTag2->encoded_by) != 0)
451 {
452 return TRUE;
453 }
454
455 /* Picture */
456 for (pic1 = FileTag1->picture, pic2 = FileTag2->picture;
457 pic1 || pic2;
458 pic1 = pic1->next, pic2 = pic2->next)
459 {
460 if (et_picture_detect_difference (pic1, pic2))
461 {
462 return TRUE;
463 }
464 }
465
466 return FALSE; /* No changes */
467 }
468