1 /* EasyTAG - Tag editor for audio files.
2  * Copyright (C) 2014-2015  David King <amigadave@amigadave.com>
3  * Copyright (C) 2007 Maarten Maathuis (madman2003@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 #ifdef ENABLE_WAVPACK
23 
24 #include <glib/gi18n.h>
25 #include <wavpack/wavpack.h>
26 
27 #include "et_core.h"
28 #include "misc.h"
29 #include "wavpack_header.h"
30 #include "wavpack_private.h"
31 
32 
33 gboolean
et_wavpack_header_read_file_info(GFile * file,ET_File_Info * ETFileInfo,GError ** error)34 et_wavpack_header_read_file_info (GFile *file,
35                                   ET_File_Info *ETFileInfo,
36                                   GError **error)
37 {
38     WavpackStreamReader reader = { wavpack_read_bytes, wavpack_get_pos,
39                                    wavpack_set_pos_abs, wavpack_set_pos_rel,
40                                    wavpack_push_back_byte, wavpack_get_length,
41                                    wavpack_can_seek, NULL /* No writing. */ };
42     EtWavpackState state;
43     WavpackContext *wpc;
44     gchar message[80];
45 
46     g_return_val_if_fail (file != NULL && ETFileInfo != NULL, FALSE);
47     g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
48 
49     state.error = NULL;
50     state.istream = g_file_read (file, NULL, &state.error);
51 
52     if (!state.istream)
53     {
54         g_propagate_error (error, state.error);
55         return FALSE;
56     }
57 
58     state.seekable = G_SEEKABLE (state.istream);
59 
60     /* NULL for the WavPack correction file. */
61     wpc = WavpackOpenFileInputEx (&reader, &state, NULL, message, 0, 0);
62 
63     if (wpc == NULL)
64     {
65         if (state.error)
66         {
67             g_propagate_error (error, state.error);
68         }
69         else
70         {
71             g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "%s",
72                          message);
73         }
74 
75         g_object_unref (state.istream);
76         return FALSE;
77     }
78 
79     ETFileInfo->version     = WavpackGetVersion(wpc);
80     /* .wvc correction file not counted */
81     ETFileInfo->bitrate     = WavpackGetAverageBitrate(wpc, 0)/1000;
82     ETFileInfo->samplerate  = WavpackGetSampleRate(wpc);
83     ETFileInfo->mode        = WavpackGetNumChannels(wpc);
84     ETFileInfo->layer = WavpackGetChannelMask (wpc);
85     ETFileInfo->size        = WavpackGetFileSize(wpc);
86     ETFileInfo->duration    = WavpackGetNumSamples(wpc)/ETFileInfo->samplerate;
87 
88     WavpackCloseFile(wpc);
89 
90     g_object_unref (state.istream);
91 
92     return TRUE;
93 }
94 
95 /*
96  * et_wavpack_channel_mask_to_string:
97  * @channels: total number of channels
98  * @mask: Microsoft channel mask
99  *
100  * Formats a number of channels and a channel mask into a string, suitable for
101  * display to the user.
102  *
103  * Returns: the formatted channel information
104  */
105 static gchar *
et_wavpack_channel_mask_to_string(gint channels,gint mask)106 et_wavpack_channel_mask_to_string (gint channels,
107                                    gint mask)
108 {
109     gboolean lfe;
110 
111     /* Low frequency effects channel is bit 3. */
112     lfe = mask & (1 << 3);
113 
114     if (lfe)
115     {
116         return g_strdup_printf ("%d.1", channels - 1);
117     }
118     else
119     {
120         return g_strdup_printf ("%d", channels);
121     }
122 }
123 
124 EtFileHeaderFields *
et_wavpack_header_display_file_info_to_ui(const ET_File * ETFile)125 et_wavpack_header_display_file_info_to_ui (const ET_File *ETFile)
126 {
127     EtFileHeaderFields *fields;
128     ET_File_Info *info;
129     gchar *time = NULL;
130     gchar *time1 = NULL;
131     gchar *size = NULL;
132     gchar *size1 = NULL;
133 
134     info = ETFile->ETFileInfo;
135     fields = g_slice_new (EtFileHeaderFields);
136 
137     fields->description = _("Wavpack File");
138 
139     /* Encoder version */
140     fields->version_label = _("Encoder:");
141     fields->version = g_strdup_printf ("%d", info->version);
142 
143     /* Bitrate */
144     fields->bitrate = g_strdup_printf (_("%d kb/s"), info->bitrate);
145 
146     /* Samplerate */
147     fields->samplerate = g_strdup_printf (_("%d Hz"), info->samplerate);
148 
149     /* Mode */
150     fields->mode_label = _("Channels:");
151     fields->mode = et_wavpack_channel_mask_to_string (info->mode,
152                                                       info->layer);
153 
154     /* Size */
155     size = g_format_size (info->size);
156     size1 = g_format_size (ETCore->ETFileDisplayedList_TotalSize);
157     fields->size = g_strdup_printf ("%s (%s)", size, size1);
158     g_free (size);
159     g_free (size1);
160 
161     /* Duration */
162     time = Convert_Duration (info->duration);
163     time1 = Convert_Duration (ETCore->ETFileDisplayedList_TotalDuration);
164     fields->duration = g_strdup_printf ("%s (%s)", time, time1);
165     g_free (time);
166     g_free (time1);
167 
168     return fields;
169 }
170 
171 void
et_wavpack_file_header_fields_free(EtFileHeaderFields * fields)172 et_wavpack_file_header_fields_free (EtFileHeaderFields *fields)
173 {
174     g_return_if_fail (fields != NULL);
175 
176     g_free (fields->version);
177     g_free (fields->bitrate);
178     g_free (fields->samplerate);
179     g_free (fields->mode);
180     g_free (fields->size);
181     g_free (fields->duration);
182     g_slice_free (EtFileHeaderFields, fields);
183 }
184 
185 #endif /* ENABLE_WAVPACK */
186