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