~ubuntu-branches/ubuntu/gutsy/audacity/gutsy-backports

« back to all changes in this revision

Viewing changes to src/export/ExportMP2.cpp

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2008-02-18 21:58:19 UTC
  • mfrom: (13.1.2 hardy)
  • Revision ID: james.westby@ubuntu.com-20080218215819-tmbcf1rx238r8gdv
Tags: 1.3.4-1.1ubuntu1~gutsy1
Automated backport upload; no source changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
58
58
#define LIBTWOLAME_STATIC
59
59
#include "twolame.h"
60
60
 
 
61
#ifdef USE_LIBID3TAG 
 
62
   #include <id3tag.h>
 
63
   // DM: the following functions were supposed to have been
 
64
   // included in id3tag.h - should be fixed in the next release
 
65
   // of mad.
 
66
   extern "C" {
 
67
      struct id3_frame *id3_frame_new(char const *);
 
68
      id3_length_t id3_latin1_length(id3_latin1_t const *);
 
69
      void id3_latin1_decode(id3_latin1_t const *, id3_ucs4_t *);
 
70
   } 
 
71
#endif
 
72
 
61
73
//----------------------------------------------------------------------------
62
74
// ExportMP2Options
63
75
//----------------------------------------------------------------------------
65
77
static int iBitrates[] = {
66
78
   16, 24, 32, 40, 48, 56, 64,
67
79
   80, 96, 112, 128, 160,
68
 
   192, 224, 256, 320 
 
80
   192, 224, 256, 320, 384
69
81
};
70
82
 
71
83
class ExportMP2Options : public wxDialog
126
138
      S.EndStatic();
127
139
   }
128
140
   S.EndHorizontalLay();
129
 
   S.StartHorizontalLay(wxALIGN_CENTER, false);
130
 
   {
131
 
#if defined(__WXGTK20__) || defined(__WXMAC__)
132
 
      S.Id(wxID_CANCEL).AddButton(_("&Cancel"));
133
 
      S.Id(wxID_OK).AddButton(_("&OK"))->SetDefault();
134
 
#else
135
 
      S.Id(wxID_OK).AddButton(_("&OK"))->SetDefault();
136
 
      S.Id(wxID_CANCEL).AddButton(_("&Cancel"));
137
 
#endif
138
 
   }
139
 
   GetSizer()->AddSpacer(5);
 
141
 
 
142
   S.AddStandardButtons();
 
143
 
140
144
   Layout();
141
145
   Fit();
142
146
   SetMinSize(GetSize());
177
181
               bool selectedOnly,
178
182
               double t0,
179
183
               double t1,
180
 
               MixerSpec *mixerSpec = NULL);
 
184
               MixerSpec *mixerSpec = NULL,
 
185
               bool use_meta=true);
 
186
 
 
187
private:
 
188
 
 
189
   int AddTags(AudacityProject *project, char **buffer, bool *endOfFile, Tags *tags);
 
190
 
181
191
};
182
192
 
183
193
ExportMP2::ExportMP2()
197
207
 
198
208
bool ExportMP2::Export(AudacityProject *project,
199
209
               int channels, wxString fName,
200
 
               bool selectionOnly, double t0, double t1, MixerSpec *mixerSpec)
 
210
               bool selectionOnly, double t0, double t1, MixerSpec *mixerSpec, bool use_meta)
201
211
{
202
212
   bool stereo = (channels == 2);
203
213
   long bitrate = gPrefs->Read(wxT("/FileFormats/MP2Bitrate"), 160);
221
231
      return false;
222
232
   }
223
233
 
224
 
   /* Put ID3 tags at beginning of file */
225
 
   /*lda Check ShowId3Dialog flag for CleanSpeech */
226
 
   bool showId3Dialog = project->GetShowId3Dialog();
 
234
   // Put ID3 tags at beginning of file 
227
235
   Tags *tags = project->GetTags();
228
 
   bool emptyTags = tags->IsEmpty();
229
 
   if (showId3Dialog && emptyTags) {
230
 
      if (!tags->ShowEditDialog(project,
231
 
                                _("Edit the ID3 tags for the MP3 file"),
232
 
                                true)) {
233
 
         return false;  // used selected "cancel"
234
 
      }
 
236
   if (!tags->ShowEditDialog(project,
 
237
                             _("Edit the ID3 tags for the MP2 file"))) {
 
238
      return false;  // user selected "cancel"
235
239
   }
236
240
 
237
241
   FileIO outFile(fName, FileIO::Output);
243
247
   char *id3buffer = NULL;
244
248
   int id3len;
245
249
   bool endOfFile;
246
 
   id3len = tags->ExportID3(&id3buffer, &endOfFile);
247
 
   if (!endOfFile)
 
250
   id3len = AddTags(project, &id3buffer, &endOfFile, tags);
 
251
   if (id3len && !endOfFile)
248
252
     outFile.Write(id3buffer, id3len);
249
253
 
250
254
   // Values taken from the twolame simple encoder sample
251
 
   const int pcmBufferSize = 16384 / 2; // number of samples
252
 
   const int mp2BufferSize = 9216; // bytes
 
255
   const int pcmBufferSize = 9216 / 2; // number of samples
 
256
   const int mp2BufferSize = 16384 ; // bytes
253
257
 
254
258
   // We allocate a buffer which is twice as big as the
255
259
   // input buffer, which should always be enough.
265
269
                            stereo? 2: 1, pcmBufferSize, true,
266
270
                            rate, int16Sample, true, mixerSpec);
267
271
 
268
 
   GetActiveProject()->ProgressShow(selectionOnly ?
 
272
   GetActiveProject()->ProgressShow(wxFileName(fName).GetName(),
 
273
       selectionOnly ?
269
274
      wxString::Format(_("Exporting selected audio at %d kbps"), bitrate) :
270
 
      wxString::Format(_("Exporting entire file at %d kbps"), bitrate),
271
 
      wxFileName(fName).GetName());
 
275
      wxString::Format(_("Exporting entire file at %d kbps"), bitrate));
272
276
 
273
277
   bool cancelling = false;
274
278
   while(!cancelling) {
311
315
 
312
316
   /* Write ID3 tag if it was supposed to be at the end of the file */
313
317
   
314
 
   if (endOfFile)
 
318
   if (id3len && endOfFile)
315
319
      outFile.Write(id3buffer, id3len);
 
320
 
 
321
   if (id3buffer) {
316
322
   free(id3buffer);
 
323
   }
317
324
 
318
325
   /* Close file */
319
326
   
331
338
   return true;
332
339
}
333
340
 
 
341
// returns buffer len; caller frees
 
342
int ExportMP2::AddTags(AudacityProject *project, char **buffer, bool *endOfFile, Tags *tags)
 
343
{
 
344
#ifdef USE_LIBID3TAG 
 
345
   struct id3_tag *tp = id3_tag_new();
 
346
 
 
347
   bool v2 = tags->GetID3V2();
 
348
 
 
349
   wxString n, v;
 
350
   for (bool cont = tags->GetFirst(n, v); cont; cont = tags->GetNext(n, v)) {
 
351
      char *name = "TXXX";
 
352
 
 
353
      if (n.CmpNoCase(TAG_TITLE) == 0) {
 
354
         name = ID3_FRAME_TITLE;
 
355
      }
 
356
      else if (n.CmpNoCase(TAG_ARTIST) == 0) {
 
357
         name = ID3_FRAME_ARTIST;
 
358
      }
 
359
      else if (n.CmpNoCase(TAG_ALBUM) == 0) {
 
360
         name = ID3_FRAME_ALBUM;
 
361
      }
 
362
      else if (n.CmpNoCase(TAG_YEAR) == 0) {
 
363
         name = ID3_FRAME_YEAR;
 
364
      }
 
365
      else if (n.CmpNoCase(TAG_GENRE) == 0) {
 
366
         name = ID3_FRAME_GENRE;
 
367
         if (!v2) {
 
368
            v.Printf(wxT("%d"), tags->GetGenre(v));
 
369
         }
 
370
      }
 
371
      else if (n.CmpNoCase(TAG_COMMENTS) == 0) {
 
372
         name = ID3_FRAME_COMMENT;
 
373
      }
 
374
      else if (n.CmpNoCase(TAG_TRACK) == 0) {
 
375
         name = ID3_FRAME_TRACK;
 
376
      }
 
377
 
 
378
      struct id3_frame *frame = id3_frame_new(name);
 
379
 
 
380
      if (v2) {
 
381
         if (!n.IsAscii() || !v.IsAscii()) {
 
382
            id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_UTF_16);
 
383
         }
 
384
         else {
 
385
            id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1);
 
386
         }
 
387
      }
 
388
 
 
389
      id3_ucs4_t *ucs4 =
 
390
         id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8));
 
391
 
 
392
      if (strcmp(name, ID3_FRAME_COMMENT) == 0) {
 
393
         // A hack to get around iTunes not recognizing the comment.  The
 
394
         // language defaults to XXX and, since it's not a valid language,
 
395
         // iTunes just ignores the tag.  So, either set it to a valid language
 
396
         // (which one???) or just clear it.  Unfortunately, there's no supported
 
397
         // way of clearing the field, so do it directly.
 
398
         id3_field *f = id3_frame_field(frame, 1);
 
399
         memset(f->immediate.value, 0, sizeof(f->immediate.value));
 
400
         id3_field_setfullstring(id3_frame_field(frame, 3), ucs4);
 
401
      }
 
402
      else if (strcmp(name, "TXXX") == 0) {
 
403
         id3_field_setstring(id3_frame_field(frame, 2), ucs4);
 
404
         free(ucs4);
 
405
 
 
406
         ucs4 = id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8));
 
407
           
 
408
         id3_field_setstring(id3_frame_field(frame, 1), ucs4);
 
409
      }
 
410
      else {
 
411
         id3_field_setstrings(id3_frame_field(frame, 1), 1, &ucs4);
 
412
      }
 
413
 
 
414
      free(ucs4);
 
415
 
 
416
      id3_tag_attachframe(tp, frame);
 
417
   }
 
418
 
 
419
   if (v2) {
 
420
      tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression
 
421
 
 
422
      // If this version of libid3tag supports it, use v2.3 ID3
 
423
      // tags instead of the newer, but less well supported, v2.4
 
424
      // that libid3tag uses by default.
 
425
      #ifdef ID3_TAG_HAS_TAG_OPTION_ID3V2_3
 
426
      tp->options |= ID3_TAG_OPTION_ID3V2_3;
 
427
      #endif
 
428
 
 
429
      *endOfFile = false;
 
430
   }
 
431
   else {
 
432
      tp->options |= ID3_TAG_OPTION_ID3V1;
 
433
      *endOfFile = true;
 
434
   }
 
435
 
 
436
   id3_length_t len;
 
437
   
 
438
   len = id3_tag_render(tp, 0);
 
439
   *buffer = (char *)malloc(len);
 
440
   len = id3_tag_render(tp, (id3_byte_t *)*buffer);
 
441
 
 
442
   id3_tag_delete(tp);
 
443
 
 
444
   return len;
 
445
#else //ifdef USE_LIBID3TAG 
 
446
   return 0;
 
447
#endif
 
448
}
 
449
 
334
450
//----------------------------------------------------------------------------
335
451
// Constructor
336
452
//----------------------------------------------------------------------------