OSDN Git Service

Set creation/modified time of the encoded file the same value as the original file...
[lamexp/LameXP.git] / src / Model_AudioFile.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2015 LoRd_MuldeR <MuldeR2@GMX.de>
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, but always including the *additional*
9 // restrictions defined in the "License.txt" file.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 //
20 // http://www.gnu.org/licenses/gpl-2.0.txt
21 ///////////////////////////////////////////////////////////////////////////////
22
23 #include "Model_AudioFile.h"
24
25 //Internal
26 #include "Global.h"
27
28 //MUtils
29 #include <MUtils/Global.h>
30
31 //Qt
32 #include <QTime>
33 #include <QObject>
34 #include <QMutexLocker>
35 #include <QFile>
36
37 //CRT
38 #include <limits.h>
39
40 const unsigned int AudioFileModel::BITDEPTH_IEEE_FLOAT32 = UINT_MAX-1;
41
42 #define PRINT_S(VAR) do \
43 { \
44         if((VAR).isEmpty()) qDebug(#VAR " = N/A"); else qDebug(#VAR " = \"%s\"", MUTILS_UTF8((VAR))); \
45 } \
46 while(0)
47
48 #define PRINT_U(VAR) do \
49 { \
50         if((VAR) < 1) qDebug(#VAR " = N/A"); else qDebug(#VAR " = %u", (VAR)); \
51 } \
52 while(0)
53
54 //if((!(OTHER.NAME.isEmpty())) && ((FORCE) || (this.NAME.isEmpty()))) /*this.NAME = OTHER.NAME;*/ \
55
56 #define UPDATE_STR(OTHER, FORCE, NAME) do \
57 { \
58         if(!(((OTHER).NAME).isEmpty())) \
59         { \
60                 if((FORCE) || ((this->NAME).isEmpty())) (this->NAME) = ((OTHER).NAME); \
61         } \
62 } \
63 while(0)
64
65 #define UPDATE_INT(OTHER, FORCE, NAME) do \
66 { \
67         if(((OTHER).NAME) > 0) \
68         { \
69                 if((FORCE) || ((this->NAME) == 0)) (this->NAME) = ((OTHER).NAME); \
70         } \
71 } \
72 while(0)
73
74 #define ASSIGN_VAL(OTHER, NAME)  do \
75 { \
76         (this->NAME) = ((OTHER).NAME); \
77 } \
78 while(0)
79
80 ///////////////////////////////////////////////////////////////////////////////
81 // Audio File - Meta Info
82 ///////////////////////////////////////////////////////////////////////////////
83
84 AudioFileModel_MetaInfo::AudioFileModel_MetaInfo(void)
85 {
86         reset();
87 }
88
89 AudioFileModel_MetaInfo::AudioFileModel_MetaInfo(const AudioFileModel_MetaInfo &model)
90 {
91         ASSIGN_VAL(model, m_titel);
92         ASSIGN_VAL(model, m_artist);
93         ASSIGN_VAL(model, m_album);
94         ASSIGN_VAL(model, m_genre);
95         ASSIGN_VAL(model, m_comment);
96         ASSIGN_VAL(model, m_cover);
97         ASSIGN_VAL(model, m_year);
98         ASSIGN_VAL(model, m_position);
99 }
100
101 AudioFileModel_MetaInfo &AudioFileModel_MetaInfo::operator=(const AudioFileModel_MetaInfo &model)
102 {
103         ASSIGN_VAL(model, m_titel);
104         ASSIGN_VAL(model, m_artist);
105         ASSIGN_VAL(model, m_album);
106         ASSIGN_VAL(model, m_genre);
107         ASSIGN_VAL(model, m_comment);
108         ASSIGN_VAL(model, m_cover);
109         ASSIGN_VAL(model, m_year);
110         ASSIGN_VAL(model, m_position);
111
112         return (*this);
113 }
114
115 #define IS_EMPTY(X) ((X).isEmpty() ? "YES" : "NO")
116
117 void AudioFileModel_MetaInfo::update(const AudioFileModel_MetaInfo &model, const bool replace)
118 {
119         UPDATE_STR(model, replace, m_titel);
120         UPDATE_STR(model, replace, m_artist);
121         UPDATE_STR(model, replace, m_album);
122         UPDATE_STR(model, replace, m_genre);
123         UPDATE_STR(model, replace, m_comment);
124         UPDATE_STR(model, replace, m_cover);
125         UPDATE_INT(model, replace, m_year);
126         UPDATE_INT(model, replace, m_position);
127 }
128
129 AudioFileModel_MetaInfo::~AudioFileModel_MetaInfo(void)
130 {
131         /*nothing to do*/
132 }
133
134 void AudioFileModel_MetaInfo::reset(void)
135 {
136         m_titel.clear();
137         m_artist.clear();
138         m_album.clear();
139         m_genre.clear();
140         m_comment.clear();
141         m_cover.clear();
142         m_year = 0;
143         m_position = 0;
144 }
145
146 void AudioFileModel_MetaInfo::print(void) const
147 {
148         PRINT_S(m_titel);
149         PRINT_S(m_artist);
150         PRINT_S(m_album);
151         PRINT_S(m_genre);
152         PRINT_S(m_comment);
153         PRINT_S(m_cover.filePath());
154         PRINT_U(m_year);
155         PRINT_U(m_position);
156 }
157
158 bool  AudioFileModel_MetaInfo::empty(const bool &ignoreArtwork) const
159 {
160         bool isEmpty = true;
161
162         if(!m_titel.isEmpty())   isEmpty = false;
163         if(!m_artist.isEmpty())  isEmpty = false;
164         if(!m_album.isEmpty())   isEmpty = false;
165         if(!m_genre.isEmpty())   isEmpty = false;
166         if(!m_comment.isEmpty()) isEmpty = false;
167         if(m_year)               isEmpty = false;
168         if(m_position)           isEmpty = false;
169
170         if(!ignoreArtwork)
171         {
172                 if(!m_cover.isEmpty())
173                 {
174                         isEmpty = false;
175                 }
176         }
177
178         return isEmpty;
179 }
180
181 ///////////////////////////////////////////////////////////////////////////////
182 // Audio File - Technical Info
183 ///////////////////////////////////////////////////////////////////////////////
184
185 AudioFileModel_TechInfo::AudioFileModel_TechInfo(void)
186 {
187         reset();
188 }
189
190 AudioFileModel_TechInfo::AudioFileModel_TechInfo(const AudioFileModel_TechInfo &model)
191 {
192         ASSIGN_VAL(model, m_containerType);
193         ASSIGN_VAL(model, m_containerProfile);
194         ASSIGN_VAL(model, m_audioType);
195         ASSIGN_VAL(model, m_audioProfile);
196         ASSIGN_VAL(model, m_audioVersion);
197         ASSIGN_VAL(model, m_audioEncodeLib);
198         ASSIGN_VAL(model, m_audioSamplerate);
199         ASSIGN_VAL(model, m_audioChannels);
200         ASSIGN_VAL(model, m_audioBitdepth);
201         ASSIGN_VAL(model, m_audioBitrate);
202         ASSIGN_VAL(model, m_audioBitrateMode);
203         ASSIGN_VAL(model, m_duration);
204 }
205
206 AudioFileModel_TechInfo &AudioFileModel_TechInfo::operator=(const AudioFileModel_TechInfo &model)
207 {
208         ASSIGN_VAL(model, m_containerType);
209         ASSIGN_VAL(model, m_containerProfile);
210         ASSIGN_VAL(model, m_audioType);
211         ASSIGN_VAL(model, m_audioProfile);
212         ASSIGN_VAL(model, m_audioVersion);
213         ASSIGN_VAL(model, m_audioEncodeLib);
214         ASSIGN_VAL(model, m_audioSamplerate);
215         ASSIGN_VAL(model, m_audioChannels);
216         ASSIGN_VAL(model, m_audioBitdepth);
217         ASSIGN_VAL(model, m_audioBitrate);
218         ASSIGN_VAL(model, m_audioBitrateMode);
219         ASSIGN_VAL(model, m_duration);
220
221         return (*this);
222 }
223
224 AudioFileModel_TechInfo::~AudioFileModel_TechInfo(void)
225 {
226         /*nothing to do*/
227 }
228
229 void AudioFileModel_TechInfo::reset(void)
230 {
231         m_containerType.clear();
232         m_containerProfile.clear();
233         m_audioType.clear();
234         m_audioProfile.clear();
235         m_audioVersion.clear();
236         m_audioEncodeLib.clear();
237         m_audioSamplerate = 0;
238         m_audioChannels = 0;
239         m_audioBitdepth = 0;
240         m_audioBitrate = 0;
241         m_audioBitrateMode = 0;
242         m_duration = 0;
243 }
244
245 ////////////////////////////////////////////////////////////
246 // Audio File Model
247 ////////////////////////////////////////////////////////////
248
249 AudioFileModel::AudioFileModel(const QString &path)
250 :
251         m_filePath(path)
252 {
253         m_metaInfo.reset();
254         m_techInfo.reset();
255 }
256
257 AudioFileModel::AudioFileModel(const AudioFileModel &model)
258 {
259         ASSIGN_VAL(model, m_filePath);
260         ASSIGN_VAL(model, m_metaInfo);
261         ASSIGN_VAL(model, m_techInfo);
262 }
263
264 AudioFileModel &AudioFileModel::operator=(const AudioFileModel &model)
265 {
266         ASSIGN_VAL(model, m_filePath);
267         ASSIGN_VAL(model, m_metaInfo);
268         ASSIGN_VAL(model, m_techInfo);
269
270         return (*this);
271 }
272
273 AudioFileModel::~AudioFileModel(void)
274 {
275         /*nothing to do*/
276 }
277
278
279 void AudioFileModel::reset(void)
280 {
281         m_filePath.clear();
282         m_metaInfo.reset();
283         m_techInfo.reset();
284 }
285
286 /*------------------------------------*/
287 /* Helper functions
288 /*------------------------------------*/
289
290 const QString AudioFileModel::durationInfo(void) const
291 {
292         if(m_techInfo.duration())
293         {
294                 QTime time = QTime().addSecs(m_techInfo.duration());
295                 return time.toString("hh:mm:ss");
296         }
297         else
298         {
299                 return QString();
300         }
301 }
302
303 const QString AudioFileModel::containerInfo(void) const
304 {
305         if(!m_techInfo.containerType().isEmpty())
306         {
307                 QString info = m_techInfo.containerType();
308                 if(!m_techInfo.containerProfile().isEmpty()) info.append(QString(" (%1: %2)").arg(tr("Profile"), m_techInfo.containerProfile()));
309                 return info;
310         }
311         else
312         {
313                 return QString();
314         }
315 }
316
317 const QString AudioFileModel::audioBaseInfo(void) const
318 {
319         if(m_techInfo.audioSamplerate() || m_techInfo.audioChannels() || m_techInfo.audioBitdepth())
320         {
321                 QString info;
322                 if(m_techInfo.audioChannels())
323                 {
324                         if(!info.isEmpty()) info.append(", ");
325                         info.append(QString("%1: %2").arg(tr("Channels"), QString::number(m_techInfo.audioChannels())));
326                 }
327                 if(m_techInfo.audioSamplerate())
328                 {
329                         if(!info.isEmpty()) info.append(", ");
330                         info.append(QString("%1: %2 Hz").arg(tr("Samplerate"), QString::number(m_techInfo.audioSamplerate())));
331                 }
332                 if(m_techInfo.audioBitdepth())
333                 {
334                         if(!info.isEmpty()) info.append(", ");
335                         if(m_techInfo.audioBitdepth() == BITDEPTH_IEEE_FLOAT32)
336                         {
337                                 info.append(QString("%1: %2 Bit (IEEE Float)").arg(tr("Bitdepth"), QString::number(32)));
338                         }
339                         else
340                         {
341                                 info.append(QString("%1: %2 Bit").arg(tr("Bitdepth"), QString::number(m_techInfo.audioBitdepth())));
342                         }
343                 }
344                 return info;
345         }
346         else
347         {
348                 return QString();
349         }
350 }
351
352 const QString AudioFileModel::audioCompressInfo(void) const
353 {
354         if(!m_techInfo.audioType().isEmpty())
355         {
356                 QString info;
357                 if(!m_techInfo.audioProfile().isEmpty() || !m_techInfo.audioVersion().isEmpty())
358                 {
359                         info.append(QString("%1: ").arg(tr("Type")));
360                 }
361                 info.append(m_techInfo.audioType());
362                 if(!m_techInfo.audioProfile().isEmpty())
363                 {
364                         info.append(QString(", %1: %2").arg(tr("Profile"), m_techInfo.audioProfile()));
365                 }
366                 if(!m_techInfo.audioVersion().isEmpty())
367                 {
368                         info.append(QString(", %1: %2").arg(tr("Version"), m_techInfo.audioVersion()));
369                 }
370                 if(m_techInfo.audioBitrate() > 0)
371                 {
372                         switch(m_techInfo.audioBitrateMode())
373                         {
374                         case BitrateModeConstant:
375                                 info.append(QString(", %1: %2 kbps (%3)").arg(tr("Bitrate"), QString::number(m_techInfo.audioBitrate()), tr("Constant")));
376                                 break;
377                         case BitrateModeVariable:
378                                 info.append(MUTILS_QSTR(L", %1: \u2248%2 kbps (%3)").arg(tr("Bitrate"), QString::number(m_techInfo.audioBitrate()), tr("Variable")));
379                                 break;
380                         default:
381                                 info.append(QString(", %1: %2 kbps").arg(tr("Bitrate"), QString::number(m_techInfo.audioBitrate())));
382                                 break;
383                         }
384                 }
385                 if(!m_techInfo.audioEncodeLib().isEmpty())
386                 {
387                         info.append(QString(", %1: %2").arg(tr("Encoder"), m_techInfo.audioEncodeLib()));
388                 }
389                 return info;
390         }
391         else
392         {
393                 return QString();
394         }
395 }