1 /* EasyTAG - Tag editor for MP3 and Ogg Vorbis files
2 * Copyright (C) 2014 David King <amigadave@amigadave.com>
3 * Copyright (C) 2000-2003 Jerome Couderc <easytag@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21
22 #if defined ENABLE_MP3 && defined ENABLE_ID3LIB
23
24 #include <glib/gi18n.h>
25 #include <errno.h>
26
27 #include "id3_tag.h"
28 #include "mpeg_header.h"
29 #include "misc.h"
30
31 #include <id3.h>
32 #include "id3lib/id3_bugfix.h"
33
34
35
36 /****************
37 * Declarations *
38 ****************/
39 static const gchar *layer_names[3] =
40 {
41 "I", /* Layer 1 */
42 "II", /* Layer 2 */
43 "III" /* Layer 3 */
44 };
45
46 static const gchar *
channel_mode_name(int mode)47 channel_mode_name (int mode)
48 {
49 static const gchar * const channel_mode[] =
50 {
51 N_("Stereo"),
52 N_("Joint stereo"),
53 N_("Dual channel"),
54 N_("Single channel")
55 };
56
57 if (mode < 0 || mode > 3)
58 {
59 return "";
60 }
61
62 return _(channel_mode[mode]);
63 }
64
65 /*
66 * Read infos into header of first frame
67 */
68 gboolean
et_mpeg_header_read_file_info(GFile * file,ET_File_Info * ETFileInfo,GError ** error)69 et_mpeg_header_read_file_info (GFile *file,
70 ET_File_Info *ETFileInfo,
71 GError **error)
72 {
73 GFileInfo *info;
74 gchar *filename;
75 /*
76 * With id3lib, the header frame couldn't be read if the file contains an ID3v2 tag with an APIC frame
77 */
78 ID3Tag *id3_tag = NULL; /* Tag defined by the id3lib */
79 const Mp3_Headerinfo* headerInfo = NULL;
80
81 g_return_val_if_fail (file != NULL || ETFileInfo != NULL, FALSE);
82 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
83
84 /* Check if the file is corrupt. */
85 if (!et_id3tag_check_if_file_is_valid (file, error))
86 {
87 return FALSE;
88 }
89
90 /* Get size of file */
91 info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE,
92 G_FILE_QUERY_INFO_NONE, NULL, error);
93
94 if (!info)
95 {
96 return FALSE;
97 }
98
99 ETFileInfo->size = g_file_info_get_size (info);
100 g_object_unref (info);
101
102 /* Get data from tag */
103 if ((id3_tag = ID3Tag_New()) == NULL)
104 {
105 g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOMEM, "%s",
106 g_strerror (ENOMEM));
107 g_object_unref (info);
108 return FALSE;
109 }
110
111 /* Link the file to the tag (uses ID3TT_ID3V2 to get header if APIC is present in Tag) */
112 filename = g_file_get_path (file);
113 #ifdef G_OS_WIN32
114 /* On Windows, id3lib expects filenames to be in the system codepage. */
115 {
116 gchar *locale_filename;
117
118 locale_filename = g_win32_locale_filename_from_utf8 (filename);
119
120 if (!locale_filename)
121 {
122 g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, "%s",
123 g_strerror (EINVAL));
124 g_free (filename);
125 return FALSE;
126 }
127
128 ID3Tag_LinkWithFlags (id3_tag, locale_filename, ID3TT_ID3V2);
129
130 g_free (locale_filename);
131 }
132 #else
133 ID3Tag_LinkWithFlags (id3_tag, filename, ID3TT_ID3V2);
134 #endif
135
136 g_free (filename);
137
138 if ( (headerInfo = ID3Tag_GetMp3HeaderInfo(id3_tag)) )
139 {
140 switch (headerInfo->version)
141 {
142 case MPEGVERSION_1:
143 ETFileInfo->version = 1;
144 ETFileInfo->mpeg25 = FALSE;
145 break;
146 case MPEGVERSION_2:
147 ETFileInfo->version = 2;
148 ETFileInfo->mpeg25 = FALSE;
149 break;
150 case MPEGVERSION_2_5:
151 ETFileInfo->version = 2;
152 ETFileInfo->mpeg25 = TRUE;
153 break;
154 case MPEGVERSION_FALSE:
155 case MPEGVERSION_Reserved:
156 default:
157 break;
158 }
159
160 switch (headerInfo->layer)
161 {
162 case MPEGLAYER_I:
163 ETFileInfo->layer = 1;
164 break;
165 case MPEGLAYER_II:
166 ETFileInfo->layer = 2;
167 break;
168 case MPEGLAYER_III:
169 ETFileInfo->layer = 3;
170 break;
171 case MPEGLAYER_FALSE:
172 case MPEGLAYER_UNDEFINED:
173 default:
174 break;
175 }
176
177 // Samplerate
178 ETFileInfo->samplerate = headerInfo->frequency;
179
180 // Mode -> Seems to be detected but incorrect?!
181 switch (headerInfo->modeext)
182 {
183 case MP3CHANNELMODE_STEREO:
184 ETFileInfo->mode = 0;
185 break;
186 case MP3CHANNELMODE_JOINT_STEREO:
187 ETFileInfo->mode = 1;
188 break;
189 case MP3CHANNELMODE_DUAL_CHANNEL:
190 ETFileInfo->mode = 2;
191 break;
192 case MP3CHANNELMODE_SINGLE_CHANNEL:
193 ETFileInfo->mode = 3;
194 break;
195 case MP3CHANNELMODE_FALSE:
196 default:
197 break;
198 }
199
200 // Bitrate
201 if (headerInfo->vbr_bitrate <= 0)
202 {
203 ETFileInfo->variable_bitrate = FALSE;
204 ETFileInfo->bitrate = headerInfo->bitrate/1000;
205 }else
206 {
207 ETFileInfo->variable_bitrate = TRUE;
208 ETFileInfo->bitrate = headerInfo->vbr_bitrate/1000;
209 }
210
211 // Duration
212 ETFileInfo->duration = headerInfo->time;
213 }
214
215 /* Free allocated data */
216 ID3Tag_Delete(id3_tag);
217
218 return TRUE;
219 }
220
221 /* For displaying header information in the main window. */
222 EtFileHeaderFields *
et_mpeg_header_display_file_info_to_ui(const ET_File * ETFile)223 et_mpeg_header_display_file_info_to_ui (const ET_File *ETFile)
224 {
225 EtFileHeaderFields *fields;
226 ET_File_Info *info;
227 gchar *time = NULL;
228 gchar *time1 = NULL;
229 gchar *size = NULL;
230 gchar *size1 = NULL;
231 gsize ln_num = G_N_ELEMENTS (layer_names);
232
233 info = ETFile->ETFileInfo;
234 fields = g_slice_new (EtFileHeaderFields);
235
236 if (ETFile->ETFileDescription->FileType == MP3_FILE)
237 {
238 fields->description = _("MP3 File");
239 }
240 else if (ETFile->ETFileDescription->FileType == MP2_FILE)
241 {
242 fields->description = _("MP2 File");
243 }
244 else
245 {
246 g_assert_not_reached ();
247 }
248
249 /* MPEG, Layer versions */
250 fields->version_label = _("MPEG");
251
252 if (info->mpeg25)
253 {
254 fields->version = g_strdup_printf ("2.5, Layer %s",
255 (info->layer >= 1
256 && info->layer <= ln_num)
257 ? layer_names[info->layer - 1] : "?");
258 }
259 else
260 {
261 fields->version = g_strdup_printf ("%d, Layer %s", info->version,
262 (info->layer >= 1
263 && info->layer <= ln_num)
264 ? layer_names[info->layer - 1] : "?");
265 }
266
267 /* Bitrate */
268 if (info->variable_bitrate)
269 {
270 fields->bitrate = g_strdup_printf (_("~%d kb/s"), info->bitrate);
271 }
272 else
273 {
274 fields->bitrate = g_strdup_printf (_("%d kb/s"), info->bitrate);
275 }
276
277
278 /* Samplerate */
279 fields->samplerate = g_strdup_printf (_("%d Hz"), info->samplerate);
280
281 /* Mode */
282 fields->mode_label = _("Mode:");
283 fields->mode = _(channel_mode_name (info->mode));
284
285 /* Size */
286 size = g_format_size (info->size);
287 size1 = g_format_size (ETCore->ETFileDisplayedList_TotalSize);
288 fields->size = g_strdup_printf ("%s (%s)", size, size1);
289 g_free (size);
290 g_free (size1);
291
292 /* Duration */
293 time = Convert_Duration (info->duration);
294 time1 = Convert_Duration (ETCore->ETFileDisplayedList_TotalDuration);
295 fields->duration = g_strdup_printf ("%s (%s)", time, time1);
296 g_free (time);
297 g_free (time1);
298
299 return fields;
300 }
301
302 void
et_mpeg_file_header_fields_free(EtFileHeaderFields * fields)303 et_mpeg_file_header_fields_free (EtFileHeaderFields *fields)
304 {
305 g_return_if_fail (fields != NULL);
306
307 g_free (fields->version);
308 g_free (fields->bitrate);
309 g_free (fields->samplerate);
310 g_free (fields->size);
311 g_free (fields->duration);
312 g_slice_free (EtFileHeaderFields, fields);
313 }
314
315 #endif /* defined ENABLE_MP3 && defined ENABLE_ID3LIB */
316