add tag merging
[flac.git] / src / plugin_common / canonical_tag.c
1 /* plugin_common - Routines common to several plugins
2  * Copyright (C) 2002  Josh Coalson
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 #include <stdlib.h>
20 #include <stdio.h>
21
22 #include "canonical_tag.h"
23 #include "FLAC/assert.h"
24
25 static void local__safe_free(void *object)
26 {
27         if(0 != object)
28                 free(object);
29 }
30
31 static void local__copy_field(char **dest, const char *src, unsigned n)
32 {
33         if(n > 0) {
34                 const char *p = src + n;
35                 while(p > src && *(--p) == ' ')
36                         ;
37                 n = p - src + 1;
38                 if(0 != (*dest = malloc(n+1))) {
39                         memcpy(*dest, src, n);
40                         (*dest)[n] = '\0';
41                 }
42         }
43         else
44                 *dest = 0;
45 }
46
47 FLAC_Plugin__CanonicalTag *FLAC_plugin__canonical_tag_new()
48 {
49         FLAC_Plugin__CanonicalTag *object = (FLAC_Plugin__CanonicalTag*)malloc(sizeof(FLAC_Plugin__CanonicalTag));
50         if(0 != object)
51                 FLAC_plugin__canonical_tag_init(object);
52         return object;
53 }
54
55 void FLAC_plugin__canonical_tag_delete(FLAC_Plugin__CanonicalTag *object)
56 {
57         FLAC__ASSERT(0 != object);
58         FLAC_plugin__canonical_tag_clear(object);
59         free(object);
60 }
61
62 void FLAC_plugin__canonical_tag_init(FLAC_Plugin__CanonicalTag *object)
63 {
64         FLAC__ASSERT(0 != object);
65         object->title = 0;
66         object->composer = 0;
67         object->performer = 0;
68         object->album = 0;
69         object->year_recorded = 0;
70         object->year_performed = 0;
71         object->track_number = 0;
72         object->tracks_in_album = 0;
73         object->genre = 0;
74         object->comment = 0;
75 }
76
77 void FLAC_plugin__canonical_tag_clear(FLAC_Plugin__CanonicalTag *object)
78 {
79         FLAC__ASSERT(0 != object);
80         local__safe_free(object->title);
81         local__safe_free(object->composer);
82         local__safe_free(object->performer);
83         local__safe_free(object->album);
84         local__safe_free(object->year_recorded);
85         local__safe_free(object->year_performed);
86         local__safe_free(object->track_number);
87         local__safe_free(object->tracks_in_album);
88         local__safe_free(object->genre);
89         local__safe_free(object->comment);
90         FLAC_plugin__canonical_tag_init(object);
91 }
92
93 static void local__grab(char **dest, char **src)
94 {
95         if(0 == *dest) {
96                 *dest = *src;
97                 *src = 0;
98         }
99 }
100
101 void FLAC_plugin__canonical_tag_merge(FLAC_Plugin__CanonicalTag *dest, FLAC_Plugin__CanonicalTag *src)
102 {
103         local__grab(&dest->title, &src->title);
104         local__grab(&dest->composer, &src->composer);
105         local__grab(&dest->performer, &src->performer);
106         local__grab(&dest->album, &src->album);
107         local__grab(&dest->year_recorded, &src->year_recorded);
108         local__grab(&dest->year_performed, &src->year_performed);
109         local__grab(&dest->track_number, &src->track_number);
110         local__grab(&dest->tracks_in_album, &src->tracks_in_album);
111         local__grab(&dest->genre, &src->genre);
112         local__grab(&dest->comment, &src->comment);
113 }
114
115 void FLAC_plugin__canonical_tag_convert_from_id3v1(FLAC_Plugin__CanonicalTag *object, const FLAC_Plugin__Id3v1_Tag *id3v1_tag)
116 {
117         local__copy_field(&object->title, id3v1_tag->title, 30);
118         local__copy_field(&object->composer, id3v1_tag->artist, 30);
119         local__copy_field(&object->performer, id3v1_tag->artist, 30);
120         local__copy_field(&object->album, id3v1_tag->album, 30);
121         local__copy_field(&object->year_performed, id3v1_tag->year, 4);
122
123         /* Check for v1.1 tags. */
124         if (id3v1_tag->comment.v1_1.zero == 0) {
125                 if(0 != (object->track_number = malloc(4)))
126                         sprintf(object->track_number, "%u", (unsigned)id3v1_tag->comment.v1_1.track);
127                 local__copy_field(&object->comment, id3v1_tag->comment.v1_1.comment, 28);
128         }
129         else {
130                 object->track_number = strdup("0");
131                 local__copy_field(&object->comment, id3v1_tag->comment.v1_0.comment, 30);
132         }
133
134         object->genre = strdup(FLAC_plugin__id3v1_tag_get_genre_as_string(id3v1_tag->genre));
135 }