Пример #1
0
wxString GetGenreNum(int i)
{
#ifdef USE_LIBID3TAG
  id3_latin1_t      i_latin1[50];
  id3_ucs4_t       *i_ucs4;
  const id3_ucs4_t *genre_ucs4;

  sprintf((char *)i_latin1, "%d", i);
  i_ucs4 =
     (id3_ucs4_t *)malloc((id3_latin1_length(i_latin1) + 1) *
                          sizeof(*i_ucs4));
  if (i_ucs4) {
    id3_latin1_decode(i_latin1, i_ucs4);
    genre_ucs4 = id3_genre_name(i_ucs4);
    char *genre_char = (char *)id3_ucs4_utf8duplicate(genre_ucs4);
    wxString genreStr = UTF8CTOWX(genre_char);
    free(genre_char);
    free(i_ucs4);
    return genreStr;    
  }   

#endif // ifdef USE_LIBID3TAG 

  return wxT("");
}
Пример #2
0
bool XMLTagHandler::ReadXMLTag(const char *tag, const char **attrs)
{
   wxArrayString tmp_attrs;

   while (*attrs) {
      const char *s = *attrs++;
      tmp_attrs.Add(UTF8CTOWX(s));
   }

// JKC: Previously the next line was:
// const char **out_attrs = new char (const char *)[tmp_attrs.GetCount()+1];
// however MSVC doesn't like the constness in this position, so this is now 
// added by a cast after creating the array of pointers-to-non-const chars.
   const wxChar **out_attrs = (const wxChar**)new wxChar *[tmp_attrs.GetCount()+1];
   for (size_t i=0; i<tmp_attrs.GetCount(); i++) {
      out_attrs[i] = tmp_attrs[i].c_str();
   }
   out_attrs[tmp_attrs.GetCount()] = 0;

   bool result = HandleXMLTag(UTF8CTOWX(tag).c_str(), out_attrs);

   delete[] out_attrs;
   return result;
}
Пример #3
0
void ODFLACFile::metadata_callback(const FLAC__StreamMetadata *metadata)
{
   switch (metadata->type)
   {
      case FLAC__METADATA_TYPE_VORBIS_COMMENT:
         for (FLAC__uint32 i = 0; i < metadata->data.vorbis_comment.num_comments; i++) {
            mComments.Add(UTF8CTOWX((char *)metadata->data.vorbis_comment.comments[i].entry));
         }
      break;

      case FLAC__METADATA_TYPE_STREAMINFO:
         mDecoder->mSampleRate=metadata->data.stream_info.sample_rate;
         mDecoder->mNumChannels=metadata->data.stream_info.channels;
         mDecoder->mBitsPerSample=metadata->data.stream_info.bits_per_sample;
         mDecoder->mNumSamples=metadata->data.stream_info.total_samples;

         if (mDecoder->mBitsPerSample<=16) {
            if (mDecoder->mFormat<int16Sample) {
               mDecoder->mFormat=int16Sample;
            }
         } else if (mDecoder->mBitsPerSample<=24) {
            if (mDecoder->mFormat<int24Sample) {
               mDecoder->mFormat=int24Sample;
            }
         } else {
            mDecoder->mFormat=floatSample;
         }
         mDecoder->mStreamInfoDone=true;
      break;
      // handle the other types we do nothing with to avoid a warning
      case FLAC__METADATA_TYPE_PADDING:	// do nothing with padding
      case FLAC__METADATA_TYPE_APPLICATION:	// no idea what to do with this
      case FLAC__METADATA_TYPE_SEEKTABLE:	// don't need a seektable here
      case FLAC__METADATA_TYPE_CUESHEET:	// convert this to labels?
      case FLAC__METADATA_TYPE_PICTURE:		// ignore pictures
      case FLAC__METADATA_TYPE_UNDEFINED:	// do nothing with this either

      case FLAC__MAX_METADATA_TYPE: // quiet compiler warning with this line

      break;
   }
}
Пример #4
0
wxString GetID3FieldStr(struct id3_tag *tp, const char *name)
{
   struct id3_frame *frame;

   frame = id3_tag_findframe(tp, name, 0);
   if (frame) {
      const id3_ucs4_t *ustr;

      if (strcmp(name, ID3_FRAME_COMMENT) == 0)
	 ustr = id3_field_getfullstring(&frame->fields[3]);
      else
	 ustr = id3_field_getstrings(&frame->fields[1], 0);

      if (ustr) {
	 char *str = (char *)id3_ucs4_utf8duplicate(ustr);
	 wxString s = UTF8CTOWX(str);
	 free(str);
	 return s;
      }
   }

   return wxT("");
}
Пример #5
0
bool OggImportFileHandle::Import(TrackFactory *trackFactory, Track ***outTracks,
                                 int *outNumTracks, Tags *tags)
{
   wxASSERT(mFile->IsOpened());

   /* -1 is for the current logical bitstream */
   vorbis_info *vi = ov_info(mVorbisFile, -1);
   vorbis_comment *vc = ov_comment(mVorbisFile, -1);

   WaveTrack **channels = new WaveTrack *[vi->channels];

   int c;
   for (c = 0; c < vi->channels; c++) {
      channels[c] = trackFactory->NewWaveTrack(int16Sample, vi->rate);

      if (vi->channels == 2) {
         switch (c) {
         case 0:
            channels[c]->SetChannel(Track::LeftChannel);
            channels[c]->SetLinked(true);
            break;
         case 1:
            channels[c]->SetChannel(Track::RightChannel);
            channels[c]->SetTeamed(true);
            break;
         }
   }
      else {
         channels[c]->SetChannel(Track::MonoChannel);
      }
   }

/* The number of bytes to get from the codec in each run */
#define CODEC_TRANSFER_SIZE 4096

/* The number of samples to read between calls to the callback.
 * Balance between responsiveness of the GUI and throughput of import. */
#define SAMPLES_PER_CALLBACK 100000

   short *mainBuffer = new short[CODEC_TRANSFER_SIZE];

   /* determine endianness (clever trick courtesy of Nicholas Devillard,
    * (http://www.eso.org/~ndevilla/endian/) */
   int testvar = 1, endian;
   if(*(char *)&testvar)
      endian = 0;  // little endian
   else
      endian = 1;  // big endian

   /* number of samples currently in each channel's buffer */
   bool cancelled = false;
   long bytesRead = 0;
   long samplesRead = 0;
   int bitstream = 0;
   int samplesSinceLastCallback = 0;

   // You would think that the stream would already be seeked to 0, and
   // indeed it is if the file is legit.  But I had several ogg files on
   // my hard drive that have malformed headers, and this added call
   // causes them to be read correctly.  Otherwise they have lots of
   // zeros inserted at the beginning
   ov_pcm_seek(mVorbisFile, 0);
   
   do {
      /* get data from the decoder */
      bytesRead = ov_read(mVorbisFile, (char *) mainBuffer,
                          CODEC_TRANSFER_SIZE,
                          endian,
                          2,    // word length (2 for 16 bit samples)
                          1,    // signed
                          &bitstream);

      if (bytesRead < 0) {
         /* Malformed Ogg Vorbis file. */
         /* TODO: Return some sort of meaningful error. */
         break;
      }

      samplesRead = bytesRead / vi->channels / sizeof(short);

      /* give the data to the wavetracks */
      for (c = 0; c < vi->channels; c++)
          channels[c]->Append((char *)(mainBuffer + c),
                              int16Sample,
                              samplesRead,
                              vi->channels);

      samplesSinceLastCallback += samplesRead;
      if (samplesSinceLastCallback > SAMPLES_PER_CALLBACK) {
          if( mProgressCallback )
             cancelled = mProgressCallback(mUserData,
                                           ov_time_tell(mVorbisFile) /
                                           ov_time_total(mVorbisFile, bitstream));
          samplesSinceLastCallback -= SAMPLES_PER_CALLBACK;
      }

   } while (!cancelled && bytesRead != 0 && bitstream == 0);

   delete[]mainBuffer;

   bool res = (!cancelled && bytesRead >= 0);

   if (!res) {
      for(c = 0; c < vi->channels; c++) {
         delete channels[c];
      }
      delete[] channels;

      return false;
   }

   *outNumTracks = vi->channels;
   *outTracks = new Track *[vi->channels];
   for (c = 0; c < vi->channels; c++) {
      channels[c]->Flush();
         (*outTracks)[c] = channels[c];
   }
      delete[] channels;

   if (vc) {
      tags->Clear();
      for (c = 0; c < vc->comments; c++) {
         wxString comment = UTF8CTOWX(vc->user_comments[c]);
         tags->SetTag(comment.BeforeFirst(wxT('=')),
                      comment.AfterFirst(wxT('=')));
      }
   }

   return true;
}
Пример #6
0
int OggImportFileHandle::Import(TrackFactory *trackFactory, Track ***outTracks,
                                int *outNumTracks, Tags *tags)
{
   wxASSERT(mFile->IsOpened());

   CreateProgress();

   //Number of streams used may be less than mVorbisFile->links,
   //but this way bitstream matches array index.
   mChannels = new WaveTrack **[mVorbisFile->links];

   int i,c;
   for (i = 0; i < mVorbisFile->links; i++)
   {
      //Stream is not used
      if (mStreamUsage[i] == 0)
      {
         //This is just a padding to keep bitstream number and
         //array indices matched.
         mChannels[i] = NULL;
         continue;
      }

      vorbis_info *vi = ov_info(mVorbisFile, i);
      vorbis_comment *vc = ov_comment(mVorbisFile, i);

      mChannels[i] = new WaveTrack *[vi->channels];

      for (c = 0; c < vi->channels; c++) {
         mChannels[i][c] = trackFactory->NewWaveTrack(int16Sample, vi->rate);

         if (vi->channels == 2) {
            switch (c) {
         case 0:
            mChannels[i][c]->SetChannel(Track::LeftChannel);
            mChannels[i][c]->SetLinked(true);
            break;
         case 1:
            mChannels[i][c]->SetChannel(Track::RightChannel);
            mChannels[i][c]->SetTeamed(true);
            break;
            }
         }
         else {
            mChannels[i][c]->SetChannel(Track::MonoChannel);
         }
      }
   }

/* The number of bytes to get from the codec in each run */
#define CODEC_TRANSFER_SIZE 4096

/* The number of samples to read between calls to the callback.
 * Balance between responsiveness of the GUI and throughput of import. */
#define SAMPLES_PER_CALLBACK 100000

   short *mainBuffer = new short[CODEC_TRANSFER_SIZE];

   /* determine endianness (clever trick courtesy of Nicholas Devillard,
    * (http://www.eso.org/~ndevilla/endian/) */
   int testvar = 1, endian;
   if(*(char *)&testvar)
      endian = 0;  // little endian
   else
      endian = 1;  // big endian

   /* number of samples currently in each channel's buffer */
   bool cancelled = false;
   long bytesRead = 0;
   long samplesRead = 0;
   int bitstream = 0;
   int samplesSinceLastCallback = 0;

   // You would think that the stream would already be seeked to 0, and
   // indeed it is if the file is legit.  But I had several ogg files on
   // my hard drive that have malformed headers, and this added call
   // causes them to be read correctly.  Otherwise they have lots of
   // zeros inserted at the beginning
   ov_pcm_seek(mVorbisFile, 0);
   
   do {
      /* get data from the decoder */
      bytesRead = ov_read(mVorbisFile, (char *) mainBuffer,
                          CODEC_TRANSFER_SIZE,
                          endian,
                          2,    // word length (2 for 16 bit samples)
                          1,    // signed
                          &bitstream);

      if (bytesRead < 0) {
         /* Malformed Ogg Vorbis file. */
         /* TODO: Return some sort of meaningful error. */
         break;
      }

      samplesRead = bytesRead / mVorbisFile->vi[bitstream].channels / sizeof(short);

      /* give the data to the wavetracks */
      if (mStreamUsage[bitstream] != 0)
      {
         for (c = 0; c < mVorbisFile->vi[bitstream].channels; c++)
            mChannels[bitstream][c]->Append((char *)(mainBuffer + c),
            int16Sample,
            samplesRead,
            mVorbisFile->vi[bitstream].channels);
      }

      samplesSinceLastCallback += samplesRead;
      if (samplesSinceLastCallback > SAMPLES_PER_CALLBACK) {
          cancelled = !mProgress->Update(ov_time_tell(mVorbisFile),
                                         ov_time_total(mVorbisFile, bitstream));
          samplesSinceLastCallback -= SAMPLES_PER_CALLBACK;

      }
   } while (!cancelled && bytesRead != 0);

   delete[]mainBuffer;

   bool res = (!cancelled && bytesRead >= 0);

   if (!res) {
      for (i = 0; i < mVorbisFile->links; i++)
      {
         if (mChannels[i])
         {
            for(c = 0; c < mVorbisFile->vi[bitstream].channels; c++) {
               if (mChannels[i][c])
                  delete mChannels[i][c];
            }
            delete[] mChannels[i];
         }
      }
      delete[] mChannels;
      return (cancelled ? eImportCancelled : eImportFailed);
   }

   *outNumTracks = 0;
   for (int s = 0; s < mVorbisFile->links; s++)
   {
      if (mStreamUsage[s] != 0)
         *outNumTracks += mVorbisFile->vi[s].channels;
   }

   *outTracks = new Track *[*outNumTracks];
   
   int trackindex = 0;
   for (i = 0; i < mVorbisFile->links; i++)
   {
      if (mChannels[i])
      {
         for (c = 0; c < mVorbisFile->vi[i].channels; c++) {
            mChannels[i][c]->Flush();
            (*outTracks)[trackindex++] = mChannels[i][c];
         }
         delete[] mChannels[i];
      }      
   }
   delete[] mChannels;

   //\todo { Extract comments from each stream? }
   if (mVorbisFile->vc[0].comments > 0) {
      tags->Clear();
      for (c = 0; c < mVorbisFile->vc[0].comments; c++) {
         wxString comment = UTF8CTOWX(mVorbisFile->vc[0].user_comments[c]);
         wxString name = comment.BeforeFirst(wxT('='));
         wxString value = comment.AfterFirst(wxT('='));
         if (name.Upper() == wxT("DATE") && !tags->HasTag(TAG_YEAR)) {
            long val;
            if (value.Length() == 4 && value.ToLong(&val)) {
               name = TAG_YEAR;
            }
         }
         tags->SetTag(name, value);
      }
   }

   return eImportSuccess;
}
Пример #7
0
XMLTagHandler *XMLTagHandler::ReadXMLChild(const char *tag)
{
   return HandleXMLChild(UTF8CTOWX(tag).c_str());
}
Пример #8
0
void XMLTagHandler::ReadXMLEndTag(const char *tag)
{
   HandleXMLEndTag(UTF8CTOWX(tag).c_str());
}
Пример #9
0
void MP3ImportFileHandle::ImportID3(Tags *tags)
{
#ifdef USE_LIBID3TAG 
   struct id3_file *fp = id3_file_open(OSFILENAME(mFilename), ID3_FILE_MODE_READONLY);
   if (!fp) {
      return;
   }

   struct id3_tag *tp = id3_file_tag(fp);
   if (!tp) {
      id3_file_close(fp);
      return;
   }

   tags->Clear();
   tags->SetID3V2( tp->options & ID3_TAG_OPTION_ID3V1 ? false : true );

   // Loop through all frames
   for (int i = 0; i < (int) tp->nframes; i++) {
      struct id3_frame *frame = tp->frames[i];

      // printf("ID: %08x '%4s'\n", (int) *(int *)frame->id, frame->id);
      // printf("Desc: %s\n", frame->description);
      // printf("Num fields: %d\n", frame->nfields);

      // for (int j = 0; j < (int) frame->nfields; j++) {
      //    printf("field %d type %d\n", j, frame->fields[j].type );
      //    if (frame->fields[j].type == ID3_FIELD_TYPE_STRINGLIST) {
      //       printf("num strings %d\n", frame->fields[j].stringlist.nstrings);
      //    }
      // }

      wxString n, v;

      // Determine the tag name
      if (strcmp(frame->id, ID3_FRAME_TITLE) == 0) {
         n = TAG_TITLE;
      }
      else if (strcmp(frame->id, ID3_FRAME_ARTIST) == 0) {
         n = TAG_ARTIST;
      }
      else if (strcmp(frame->id, ID3_FRAME_ALBUM) == 0) {
         n = TAG_ALBUM;
      }
      else if (strcmp(frame->id, ID3_FRAME_TRACK) == 0) {
         n = TAG_TRACK;
      }
      else if (strcmp(frame->id, "TYER") == 0) {
         n = TAG_YEAR;
      }
      else if (strcmp(frame->id, ID3_FRAME_YEAR) == 0) {
         n = TAG_YEAR;
      }
      else if (strcmp(frame->id, ID3_FRAME_COMMENT) == 0) {
         n = TAG_COMMENTS;
      }
      else if (strcmp(frame->id, ID3_FRAME_GENRE) == 0) {
         n = TAG_GENRE;
      }
   else {
         // Use frame description as default tag name.  The descriptions
         // may include several "meanings" separated by "/" characters, so
         // we just use the first meaning
         n = UTF8CTOWX(frame->description).BeforeFirst(wxT('/'));
      }

      const id3_ucs4_t *ustr = NULL;

      if (n == TAG_COMMENTS) {
         ustr = id3_field_getfullstring(&frame->fields[3]);
      }
      else if (frame->nfields == 3) {
         ustr = id3_field_getstring(&frame->fields[1]);
         if (ustr) {
            char *str = (char *)id3_ucs4_utf8duplicate(ustr);
            n = UTF8CTOWX(str);
            free(str);
         }

         ustr = id3_field_getstring(&frame->fields[2]);
      }
      else if (frame->nfields >= 2) {
         ustr = id3_field_getstrings(&frame->fields[1], 0);
      }

      if (ustr) {
         char *str = (char *)id3_ucs4_utf8duplicate(ustr);
         v = UTF8CTOWX(str);
         free(str);
      }

      if (!n.IsEmpty() && !v.IsEmpty()) {
         tags->SetTag(n, v);
   }
}

   // Convert v1 genre to name
   if (tags->HasTag(TAG_GENRE)) {
      long g = -1;
      if (tags->GetTag(TAG_GENRE).ToLong(&g)) {
         tags->SetTag(TAG_GENRE, tags->GetGenre(g));
   }
}

   id3_file_close(fp);
#endif // ifdef USE_LIBID3TAG 
}
Пример #10
0
void MP3ImportFileHandle::ImportID3(Tags *tags)
{
#ifdef USE_LIBID3TAG
   wxFile f;   // will be closed when it goes out of scope
   struct id3_file *fp = NULL;

   if (f.Open(mFilename)) {
      // Use id3_file_fdopen() instead of id3_file_open since wxWidgets can open a
      // file with a Unicode name and id3_file_open() can't (under Windows).
      fp = id3_file_fdopen(f.fd(), ID3_FILE_MODE_READONLY);
   }

   if (!fp) {
      return;
   }

   // The file descriptor is now owned by "fp", so we must tell "f" to forget
   // about it.
   f.Detach();

   struct id3_tag *tp = id3_file_tag(fp);
   if (!tp) {
      id3_file_close(fp);
      return;
   }

   tags->Clear();

   // Loop through all frames
   bool have_year = false;
   for (int i = 0; i < (int) tp->nframes; i++) {
      struct id3_frame *frame = tp->frames[i];

      // printf("ID: %08x '%4s'\n", (int) *(int *)frame->id, frame->id);
      // printf("Desc: %s\n", frame->description);
      // printf("Num fields: %d\n", frame->nfields);

      // for (int j = 0; j < (int) frame->nfields; j++) {
      //    printf("field %d type %d\n", j, frame->fields[j].type );
      //    if (frame->fields[j].type == ID3_FIELD_TYPE_STRINGLIST) {
      //       printf("num strings %d\n", frame->fields[j].stringlist.nstrings);
      //    }
      // }

      wxString n, v;

      // Determine the tag name
      if (strcmp(frame->id, ID3_FRAME_TITLE) == 0) {
         n = TAG_TITLE;
      }
      else if (strcmp(frame->id, ID3_FRAME_ARTIST) == 0) {
         n = TAG_ARTIST;
      }
      else if (strcmp(frame->id, ID3_FRAME_ALBUM) == 0) {
         n = TAG_ALBUM;
      }
      else if (strcmp(frame->id, ID3_FRAME_TRACK) == 0) {
         n = TAG_TRACK;
      }
      else if (strcmp(frame->id, ID3_FRAME_YEAR) == 0) {
         // LLL:  When libid3tag encounters the "TYER" tag, it converts it to a
         //       "ZOBS" (obsolete) tag and adds a "TDRC" tag at the end of the
         //       list of tags using the first 4 characters of the "TYER" tag.
         //       Since we write both the "TDRC" and "TYER" tags, the "TDRC" tag
         //       will always be encountered first in the list.  We want use it
         //       since the converted "TYER" tag may have been truncated.
         if (have_year) {
            continue;
         }
         n = TAG_YEAR;
         have_year = true;
      }
      else if (strcmp(frame->id, ID3_FRAME_COMMENT) == 0) {
         n = TAG_COMMENTS;
      }
      else if (strcmp(frame->id, ID3_FRAME_GENRE) == 0) {
         n = TAG_GENRE;
      }
   else {
         // Use frame description as default tag name.  The descriptions
         // may include several "meanings" separated by "/" characters, so
         // we just use the first meaning
         n = UTF8CTOWX(frame->description).BeforeFirst(wxT('/'));
      }

      const id3_ucs4_t *ustr = NULL;

      if (n == TAG_COMMENTS) {
         ustr = id3_field_getfullstring(&frame->fields[3]);
      }
      else if (frame->nfields == 3) {
         ustr = id3_field_getstring(&frame->fields[1]);
         if (ustr) {
            char *str = (char *)id3_ucs4_utf8duplicate(ustr);
            n = UTF8CTOWX(str);
            free(str);
         }

         ustr = id3_field_getstring(&frame->fields[2]);
      }
      else if (frame->nfields >= 2) {
         ustr = id3_field_getstrings(&frame->fields[1], 0);
      }

      if (ustr) {
         char *str = (char *)id3_ucs4_utf8duplicate(ustr);
         v = UTF8CTOWX(str);
         free(str);
      }

      if (!n.IsEmpty() && !v.IsEmpty()) {
         tags->SetTag(n, v);
   }
}

   // Convert v1 genre to name
   if (tags->HasTag(TAG_GENRE)) {
      long g = -1;
      if (tags->GetTag(TAG_GENRE).ToLong(&g)) {
         tags->SetTag(TAG_GENRE, tags->GetGenre(g));
   }
}

   id3_file_close(fp);
#endif // ifdef USE_LIBID3TAG
}
Пример #11
0
bool EffectNyquist::ProcessOne()
{
   nyx_rval rval;

   if (GetEffectFlags() & INSERT_EFFECT) {
      nyx_set_audio_params(mCurTrack[0]->GetRate(), 0);
   }
   else {
      nyx_set_audio_params(mCurTrack[0]->GetRate(), mCurLen);

      nyx_set_input_audio(StaticGetCallback, (void *)this,
                          mCurNumChannels,
                          mCurLen, mCurTrack[0]->GetRate());
   }

   wxString cmd;

   if (mDebug) {
      cmd += wxT("(setf *tracenable* T)\n");
      if (mExternal) {
         cmd += wxT("(setf *breakenable* T)\n");
      }
   }

   for (unsigned int j = 0; j < mControls.GetCount(); j++) {
      if (mControls[j].type == NYQ_CTRL_REAL) {
         // We use Internat::ToString() rather than "%f" here because we
         // always have to use the dot as decimal separator when giving
         // numbers to Nyquist, whereas using "%f" will use the user's
         // decimal separator which may be a comma in some countries.
         cmd += wxString::Format(wxT("(setf %s %s)\n"),
                                 mControls[j].var.c_str(),
                                 Internat::ToString(mControls[j].val).c_str());
      }
      else if (mControls[j].type == NYQ_CTRL_INT || 
            mControls[j].type == NYQ_CTRL_CHOICE) {
         cmd += wxString::Format(wxT("(setf %s %d)\n"),
                                 mControls[j].var.c_str(),
                                 (int)(mControls[j].val));
      }
      else if (mControls[j].type == NYQ_CTRL_STRING) {
         wxString str = mControls[j].valStr;
         str.Replace(wxT("\\"), wxT("\\\\"));
         str.Replace(wxT("\""), wxT("\\\""));
         cmd += wxT("(setf ");
         // restrict variable names to 7-bit ASCII:
         cmd += mControls[j].var.c_str();
         cmd += wxT(" \"");
         cmd += str; // unrestricted value will become quoted UTF-8
         cmd += wxT("\")\n");
      }
   }

   if (mIsSal) {
      wxString str = mCmd;
      str.Replace(wxT("\\"), wxT("\\\\"));
      str.Replace(wxT("\""), wxT("\\\""));
      // this is tricky: we need SAL to call main so that we can get a
      // SAL traceback in the event of an error (sal-compile catches the
      // error and calls sal-error-output), but SAL does not return values.
      // We will catch the value in a special global aud:result and if no
      // error occurs, we will grab the value with a LISP expression
      str += wxT("\nset aud:result = main()\n");

      if (mDebug) {
         // since we're about to evaluate SAL, remove LISP trace enable and
         // break enable (which stops SAL processing) and turn on SAL stack
         // trace
         cmd += wxT("(setf *tracenable* nil)\n");
         cmd += wxT("(setf *breakenable* nil)\n");
         cmd += wxT("(setf *sal-traceback* t)\n");
      }

      if (mCompiler) {
         cmd += wxT("(setf *sal-compiler-debug* t)\n");
      }

      cmd += wxT("(setf *sal-call-stack* nil)\n");
      // if we do not set this here and an error occurs in main, another
      // error will be raised when we try to return the value of aud:result
      // which is unbound
      cmd += wxT("(setf aud:result nil)\n");
      cmd += wxT("(sal-compile-audacity \"") + str + wxT("\" t t nil)\n");
      // Capture the value returned by main (saved in aud:result), but
      // set aud:result to nil so sound results can be evaluated without
      // retaining audio in memory
      cmd += wxT("(prog1 aud:result (setf aud:result nil))\n");
   }
   else {
      cmd += mCmd;
   }

   int i;
	for (i = 0; i < mCurNumChannels; i++) {
		mCurBuffer[i] = NULL;
   }

   rval = nyx_eval_expression(cmd.mb_str(wxConvUTF8));

   if (rval == nyx_string) {
       wxMessageBox(NyquistToWxString(nyx_get_string()), 
                    wxT("Nyquist"),
                    wxOK | wxCENTRE, mParent);
      return true;
   }

   if (rval == nyx_double) {
      wxString str;
      str.Printf(_("Nyquist returned the value:") + wxString(wxT(" %f")),
                 nyx_get_double());
      wxMessageBox(str, wxT("Nyquist"),
                   wxOK | wxCENTRE, mParent);
      return true;
   }

   if (rval == nyx_int) {
      wxString str;
      str.Printf(_("Nyquist returned the value:") + wxString(wxT(" %d")),
                 nyx_get_int());
      wxMessageBox(str, wxT("Nyquist"),
                   wxOK | wxCENTRE, mParent);
      return true;
   }

   if (rval == nyx_labels) {
      unsigned int numLabels = nyx_get_num_labels();
      unsigned int l;
      LabelTrack *ltrack = NULL;

      TrackListIterator iter(mOutputTracks);
      for (Track *t = iter.First(); t; t = iter.Next()) {
         if (t->GetKind() == Track::Label) {
            ltrack = (LabelTrack *)t;
            break;
         }
      }
      
      if (!ltrack) {
         ltrack = mFactory->NewLabelTrack();
         this->AddToOutputTracks((Track *)ltrack);
      }

      for (l = 0; l < numLabels; l++) {
         double t0, t1;
         const char *str;

         nyx_get_label(l, &t0, &t1, &str);

         ltrack->AddLabel(t0 + mT0, t1 + mT0, UTF8CTOWX(str));
      }
      return true;
   }

   if (rval != nyx_audio) {
      wxMessageBox(_("Nyquist did not return audio.\n"), wxT("Nyquist"),
                   wxOK | wxCENTRE, mParent);
      return false;
   }
   
   int outChannels;

   outChannels = nyx_get_audio_num_channels();
   if (outChannels > mCurNumChannels) {
      wxMessageBox(_("Nyquist returned too many audio channels.\n"),
                   wxT("Nyquist"),
                   wxOK | wxCENTRE, mParent);
      return false;
   }

   double rate = mCurTrack[0]->GetRate();
   for (i = 0; i < outChannels; i++) {
      sampleFormat format = mCurTrack[i]->GetSampleFormat();

      if (outChannels == mCurNumChannels) {
         rate = mCurTrack[i]->GetRate();
      }

      mOutputTrack[i] = mFactory->NewWaveTrack(format, rate);
      mCurBuffer[i] = NULL;
   }

   int success = nyx_get_audio(StaticPutCallback, (void *)this);

   if (!success) {
      for(i = 0; i < outChannels; i++) {
         delete mOutputTrack[i];
         mOutputTrack[i] = NULL;
      }
      return false;
   }

   for (i = 0; i < outChannels; i++) {
      mOutputTrack[i]->Flush();
      if (mCurBuffer[i]) {
         DeleteSamples(mCurBuffer[i]);
      }
      mOutputTime = mOutputTrack[i]->GetEndTime();
   }

   for (i = 0; i < mCurNumChannels; i++) {
      WaveTrack *out;

      if (outChannels == mCurNumChannels) {
         out = mOutputTrack[i];
      }
      else {
         out = mOutputTrack[0];
      }

      mCurTrack[i]->ClearAndPaste(mT0, mT1, out, false, false);
      // If we were first in the group adjust non-selected group tracks
      if (mFirstInGroup) {
         SyncLockedTracksIterator git(mOutputTracks);
         Track *t;
         for (t = git.First(mCurTrack[i]); t; t = git.Next())
         {
            if (!t->GetSelected() && t->IsSyncLockSelected()) {
               t->SyncLockAdjust(mT1, mT0 + out->GetEndTime());
            }
         }
      }

      // Only the first channel can be first in its group
      mFirstInGroup = false;
   }

   for (i = 0; i < outChannels; i++) {
      delete mOutputTrack[i];
      mOutputTrack[i] = NULL;
   }

   return true;
}
Пример #12
0
void Tags::ImportID3(wxString fileName)
{
#ifdef USE_LIBID3TAG 

   struct id3_file *fp = id3_file_open(OSFILENAME(fileName),
                                          ID3_FILE_MODE_READONLY);
   if (!fp) return;

   struct id3_tag *tp = id3_file_tag(fp);
   if (!tp) return;

   mTitle = GetID3FieldStr(tp, ID3_FRAME_TITLE);
   mArtist = GetID3FieldStr(tp, ID3_FRAME_ARTIST);
   mAlbum = GetID3FieldStr(tp, ID3_FRAME_ALBUM);   
   mYear = GetID3FieldStr(tp, ID3_FRAME_YEAR);
   mComments = GetID3FieldStr(tp, ID3_FRAME_COMMENT);

   long l;
   wxString s;
   if ((s = GetID3FieldStr(tp, ID3_FRAME_TRACK)).ToLong(&l))
      mTrackNum = l;

   mID3V2 = ( tp->options & ID3_TAG_OPTION_ID3V1 ) ? false : true;
   
   s = GetID3FieldStr(tp, ID3_FRAME_GENRE);

   if( mID3V2 ) {
      int numGenres = GetNumGenres();
      for(int i=0; i<numGenres; i++)
         if (0 == s.CmpNoCase(GetGenreNum(i)))
            mGenre = i;
   }
   else {
      if( s.ToLong( &l ) )
         mGenre = l;
   }

   // Loop through all remaining frames
   int i;
   for(i=0; i<(int)tp->nframes; i++) {
      struct id3_frame *frame = tp->frames[i];

      //printf("ID: %08x '%4s'\n", (int) *(int *)frame->id, frame->id);
      //printf("Desc: %s\n", frame->description);
      //printf("Num fields: %d\n", frame->nfields);
      
      if (!strcmp(frame->id, ID3_FRAME_TITLE) ||
          !strcmp(frame->id, ID3_FRAME_ARTIST) ||
          !strcmp(frame->id, ID3_FRAME_ALBUM) ||
          !strcmp(frame->id, ID3_FRAME_YEAR) ||
          !strcmp(frame->id, ID3_FRAME_COMMENT) ||
          !strcmp(frame->id, ID3_FRAME_GENRE) ||
          !strcmp(frame->id, ID3_FRAME_TRACK)) {
         continue;
      }

      const id3_ucs4_t *ustr;

      if (frame->nfields>=2) {
         ustr = id3_field_getstrings(&frame->fields[1], 0);
         if (ustr) {
            wxString name = UTF8CTOWX(frame->description);
            
            char *str = (char *)id3_ucs4_utf8duplicate(ustr);
            wxString value = UTF8CTOWX(str);
            free(str);
            
            mExtraNames.Add(name);
            mExtraValues.Add(value);
         }
      }

      if (frame->nfields==3) {
         wxString name, value;

         ustr = id3_field_getstring(&frame->fields[2]);
         if (ustr) {
            char *str = (char *)id3_ucs4_utf8duplicate(ustr);
            value = UTF8CTOWX(str);
            free(str);
         }

         ustr = id3_field_getstring(&frame->fields[1]);
         if (ustr) {
            char *str = (char *)id3_ucs4_utf8duplicate(ustr);
            name = UTF8CTOWX(str);
            free(str);
         }

         mExtraNames.Add(name);
         mExtraValues.Add(value);
      }

   }

   id3_file_close(fp);
#endif // ifdef USE_LIBID3TAG 
}
Пример #13
0
int PCMImportFileHandle::Import(TrackFactory *trackFactory,
                                Track ***outTracks,
                                int *outNumTracks,
                                Tags *tags)
{
    wxASSERT(mFile);

    CreateProgress();

    WaveTrack **channels = new WaveTrack *[mInfo.channels];

    int c;
    for (c = 0; c < mInfo.channels; c++) {
        channels[c] = trackFactory->NewWaveTrack(mFormat, mInfo.samplerate);

        if (mInfo.channels > 1)
            switch (c) {
            case 0:
                channels[c]->SetChannel(Track::LeftChannel);
                break;
            case 1:
                channels[c]->SetChannel(Track::RightChannel);
                break;
            default:
                channels[c]->SetChannel(Track::MonoChannel);
            }
    }

    if (mInfo.channels == 2) {
        channels[0]->SetLinked(true);
        channels[1]->SetTeamed(true);
    }

    sampleCount fileTotalFrames = (sampleCount)mInfo.frames;
    sampleCount maxBlockSize = channels[0]->GetMaxBlockSize();
    bool cancelled = false;

    wxString copyEdit =
        gPrefs->Read(wxT("/FileFormats/CopyOrEditUncompressedData"), wxT("edit"));

    // Fall back to "edit" if it doesn't match anything else
    bool doEdit = true;
    if (copyEdit.IsSameAs(wxT("copy"), false))
        doEdit = false;

    // If the format is not seekable, we must use 'copy' mode,
    // because 'edit' mode depends on the ability to seek to an
    // arbitrary location in the file.
    if (!mInfo.seekable)
        doEdit = false;

    if (doEdit) {
        wxLogDebug(wxT("Importing PCM Start\n"));

        // If this mode has been selected, we form the tracks as
        // aliases to the files we're editing, i.e. ("foo.wav", 12000-18000)
        // instead of actually making fresh copies of the samples.

        for (sampleCount i = 0; i < fileTotalFrames; i += maxBlockSize) {

            sampleCount blockLen = maxBlockSize;
            if (i + blockLen > fileTotalFrames)
                blockLen = fileTotalFrames - i;

            for (c = 0; c < mInfo.channels; c++)
                channels[c]->AppendAlias(mFilename, i, blockLen, c);

            cancelled = !mProgress->Update(i, fileTotalFrames);
            if (cancelled)
                break;
        }

#ifdef EXPERIMENTAL_ONDEMAND
        //now go over the wavetrack/waveclip/sequence and load all the blockfiles into a ComputeSummaryTask.
        //Add this task to the ODManager and the Track itself.
        wxLogDebug(wxT("Importing PCM \n"));
        for (c = 0; c < mInfo.channels; c++)
        {
            ODComputeSummaryTask* computeTask;
            computeTask=new ODComputeSummaryTask;

            computeTask->SetWaveTrack(channels[c]);

            ODManager::Instance()->AddTaskToWaveTrack(computeTask,channels[c]);
        }


#endif

    }
    else {
        // Otherwise, we're in the "copy" mode, where we read in the actual
        // samples from the file and store our own local copy of the
        // samples in the tracks.

        samplePtr srcbuffer = NewSamples(maxBlockSize * mInfo.channels,
                                         mFormat);
        samplePtr buffer = NewSamples(maxBlockSize, mFormat);

        unsigned long framescompleted = 0;

        long block;
        do {
            block = maxBlockSize;

            if (mFormat == int16Sample)
                block = sf_readf_short(mFile, (short *)srcbuffer, block);
            else
                block = sf_readf_float(mFile, (float *)srcbuffer, block);

            if (block) {
                for(c=0; c<mInfo.channels; c++) {
                    if (mFormat==int16Sample) {
                        for(int j=0; j<block; j++)
                            ((short *)buffer)[j] =
                                ((short *)srcbuffer)[mInfo.channels*j+c];
                    }
                    else {
                        for(int j=0; j<block; j++)
                            ((float *)buffer)[j] =
                                ((float *)srcbuffer)[mInfo.channels*j+c];
                    }

                    channels[c]->Append(buffer, mFormat, block);
                }
                framescompleted += block;
            }

            cancelled = !mProgress->Update((long long unsigned)framescompleted,
                                           (long long unsigned)fileTotalFrames);
            if (cancelled)
                break;

        } while (block > 0);
    }

    if (cancelled) {
        for (c = 0; c < mInfo.channels; c++)
            delete channels[c];
        delete[] channels;

        return eImportCancelled;
    }

    *outNumTracks = mInfo.channels;
    *outTracks = new Track *[mInfo.channels];
    for(c = 0; c < mInfo.channels; c++) {
        channels[c]->Flush();
        (*outTracks)[c] = channels[c];
    }
    delete[] channels;

    const char *str;

    str = sf_get_string(mFile, SF_STR_TITLE);
    if (str) {
        tags->SetTag(TAG_TITLE, UTF8CTOWX(str));
    }

    str = sf_get_string(mFile, SF_STR_ARTIST);
    if (str) {
        tags->SetTag(TAG_ARTIST, UTF8CTOWX(str));
    }

    str = sf_get_string(mFile, SF_STR_COMMENT);
    if (str) {
        tags->SetTag(TAG_COMMENTS, UTF8CTOWX(str));
    }

    str = sf_get_string(mFile, SF_STR_DATE);
    if (str) {
        tags->SetTag(TAG_YEAR, UTF8CTOWX(str));
    }

    str = sf_get_string(mFile, SF_STR_COPYRIGHT);
    if (str) {
        tags->SetTag(wxT("Copyright"), UTF8CTOWX(str));
    }

    str = sf_get_string(mFile, SF_STR_SOFTWARE);
    if (str) {
        tags->SetTag(wxT("Software"), UTF8CTOWX(str));
    }

    return eImportSuccess;
}
Пример #14
0
int OggImportFileHandle::Import(TrackFactory *trackFactory, TrackHolders &outTracks,
                                Tags *tags)
{
   outTracks.clear();

   wxASSERT(mFile->IsOpened());

   CreateProgress();

   //Number of streams used may be less than mVorbisFile->links,
   //but this way bitstream matches array index.
   mChannels.resize(mVorbisFile->links);

   int i = -1;
   for (auto &link: mChannels)
   {
      ++i;

      //Stream is not used
      if (mStreamUsage[i] == 0)
      {
         //This is just a padding to keep bitstream number and
         //array indices matched.
         continue;
      }

      vorbis_info *vi = ov_info(mVorbisFile, i);

      link.resize(vi->channels);

      int c = - 1;
      for (auto &channel : link) {
         ++c;

         channel = trackFactory->NewWaveTrack(mFormat, vi->rate);

         if (vi->channels == 2) {
            switch (c) {
         case 0:
            channel->SetChannel(Track::LeftChannel);
            channel->SetLinked(true);
            break;
         case 1:
            channel->SetChannel(Track::RightChannel);
            break;
            }
         }
         else {
            channel->SetChannel(Track::MonoChannel);
         }
      }
   }

/* The number of bytes to get from the codec in each run */
#define CODEC_TRANSFER_SIZE 4096

/* The number of samples to read between calls to the callback.
 * Balance between responsiveness of the GUI and throughput of import. */
#define SAMPLES_PER_CALLBACK 100000

   short *mainBuffer = new short[CODEC_TRANSFER_SIZE];

   /* determine endianness (clever trick courtesy of Nicholas Devillard,
    * (http://www.eso.org/~ndevilla/endian/) */
   int testvar = 1, endian;
   if(*(char *)&testvar)
      endian = 0;  // little endian
   else
      endian = 1;  // big endian

   /* number of samples currently in each channel's buffer */
   int updateResult = eProgressSuccess;
   long bytesRead = 0;
   long samplesRead = 0;
   int bitstream = 0;
   int samplesSinceLastCallback = 0;

   // You would think that the stream would already be seeked to 0, and
   // indeed it is if the file is legit.  But I had several ogg files on
   // my hard drive that have malformed headers, and this added call
   // causes them to be read correctly.  Otherwise they have lots of
   // zeros inserted at the beginning
   ov_pcm_seek(mVorbisFile, 0);

   do {
      /* get data from the decoder */
      bytesRead = ov_read(mVorbisFile, (char *) mainBuffer,
                          CODEC_TRANSFER_SIZE,
                          endian,
                          2,    // word length (2 for 16 bit samples)
                          1,    // signed
                          &bitstream);

      if (bytesRead == OV_HOLE) {
         wxFileName ff(mFilename);
         wxLogError(wxT("Ogg Vorbis importer: file %s is malformed, ov_read() reported a hole"),
                    ff.GetFullName().c_str());
         /* http://lists.xiph.org/pipermail/vorbis-dev/2001-February/003223.html
          * is the justification for doing this - best effort for malformed file,
          * hence the message.
          */
         continue;
      } else if (bytesRead < 0) {
         /* Malformed Ogg Vorbis file. */
         /* TODO: Return some sort of meaningful error. */
         wxLogError(wxT("Ogg Vorbis importer: ov_read() returned error %i"),
                    bytesRead);
         break;
      }

      samplesRead = bytesRead / mVorbisFile->vi[bitstream].channels / sizeof(short);

      /* give the data to the wavetracks */
      auto iter = mChannels.begin();
      std::advance(iter, bitstream);
      if (mStreamUsage[bitstream] != 0)
      {
         auto iter2 = iter->begin();
         for (int c = 0; c < mVorbisFile->vi[bitstream].channels; ++iter2, ++c)
            iter2->get()->Append((char *)(mainBuffer + c),
            int16Sample,
            samplesRead,
            mVorbisFile->vi[bitstream].channels);
      }

      samplesSinceLastCallback += samplesRead;
      if (samplesSinceLastCallback > SAMPLES_PER_CALLBACK) {
          updateResult = mProgress->Update(ov_time_tell(mVorbisFile),
                                         ov_time_total(mVorbisFile, bitstream));
          samplesSinceLastCallback -= SAMPLES_PER_CALLBACK;

      }
   } while (updateResult == eProgressSuccess && bytesRead != 0);

   delete[]mainBuffer;

   int res = updateResult;
   if (bytesRead < 0)
     res = eProgressFailed;

   if (res == eProgressFailed || res == eProgressCancelled) {
      return res;
   }

   for (auto &link : mChannels)
   {
      for (auto &channel : link) {
         channel->Flush();
         outTracks.push_back(std::move(channel));
      }
   }

   //\todo { Extract comments from each stream? }
   if (mVorbisFile->vc[0].comments > 0) {
      tags->Clear();
      for (int c = 0; c < mVorbisFile->vc[0].comments; c++) {
         wxString comment = UTF8CTOWX(mVorbisFile->vc[0].user_comments[c]);
         wxString name = comment.BeforeFirst(wxT('='));
         wxString value = comment.AfterFirst(wxT('='));
         if (name.Upper() == wxT("DATE") && !tags->HasTag(TAG_YEAR)) {
            long val;
            if (value.Length() == 4 && value.ToLong(&val)) {
               name = TAG_YEAR;
            }
         }
         tags->SetTag(name, value);
      }
   }

   return res;
}