Esempio n. 1
0
// returns buffer len; caller frees
int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), char **buffer, bool *endOfFile, const Tags *tags)
{
#ifdef USE_LIBID3TAG
   struct id3_tag *tp = id3_tag_new();

   for (const auto &pair : tags->GetRange()) {
      const auto &n = pair.first;
      const auto &v = pair.second;
      const char *name = "TXXX";

      if (n.CmpNoCase(TAG_TITLE) == 0) {
         name = ID3_FRAME_TITLE;
      }
      else if (n.CmpNoCase(TAG_ARTIST) == 0) {
         name = ID3_FRAME_ARTIST;
      }
      else if (n.CmpNoCase(TAG_ALBUM) == 0) {
         name = ID3_FRAME_ALBUM;
      }
      else if (n.CmpNoCase(TAG_YEAR) == 0) {
         // LLL:  Some apps do not like the newer frame ID (ID3_FRAME_YEAR),
         //       so we add old one as well.
         AddFrame(tp, n, v, "TYER");
         name = ID3_FRAME_YEAR;
      }
      else if (n.CmpNoCase(TAG_GENRE) == 0) {
         name = ID3_FRAME_GENRE;
      }
      else if (n.CmpNoCase(TAG_COMMENTS) == 0) {
         name = ID3_FRAME_COMMENT;
      }
      else if (n.CmpNoCase(TAG_TRACK) == 0) {
         name = ID3_FRAME_TRACK;
      }

      AddFrame(tp, n, v, name);
   }

   tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression

   // If this version of libid3tag supports it, use v2.3 ID3
   // tags instead of the newer, but less well supported, v2.4
   // that libid3tag uses by default.
   #ifdef ID3_TAG_HAS_TAG_OPTION_ID3V2_3
   tp->options |= ID3_TAG_OPTION_ID3V2_3;
   #endif

   *endOfFile = false;

   id3_length_t len;

   len = id3_tag_render(tp, 0);
   *buffer = (char *)malloc(len);
   len = id3_tag_render(tp, (id3_byte_t *)*buffer);

   id3_tag_delete(tp);

   return len;
#else //ifdef USE_LIBID3TAG
   return 0;
#endif
}
Esempio n. 2
0
// returns buffer len; caller frees
int Tags::ExportID3(char **buffer, bool *endOfFile)
{
#ifdef USE_LIBID3TAG 
   struct id3_tag *tp = id3_tag_new();
   
   if (mTitle != wxT(""))
      id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_TITLE, mTitle.mb_str()));

   if (mArtist != wxT(""))
      id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_ARTIST, mArtist.mb_str()));

   if (mAlbum != wxT(""))
      id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_ALBUM, mAlbum.mb_str()));

   if (mYear != wxT(""))
      id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_YEAR, mYear.mb_str()));

   if (mComments != wxT(""))
      id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_COMMENT, mComments.mb_str()));

   if (mTrackNum >= 0) {
      wxString trackNumStr;
      trackNumStr.Printf(wxT("%d"), mTrackNum);
      id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_TRACK, trackNumStr.mb_str()));
   }

   if (mGenre >= 0) {
      if (mID3V2) {
         wxString genreStr = GetGenreNum(mGenre);
         id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_GENRE, genreStr.mb_str()));
      }
      else {
         wxString genreStr;
         genreStr.Printf(wxT("%d"), mGenre);
         id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_GENRE, genreStr.mb_str()));
      }
   }

   if (mID3V2) {
      tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression

      // If this version of libid3tag supports it, use v2.3 ID3
      // tags instead of the newer, but less well supported, v2.4
      // that libid3tag uses by default.
      #ifdef ID3_TAG_OPTION_ID3V2_3
      tp->options |= ID3_TAG_OPTION_ID3V2_3;
      #endif

      *endOfFile = false;
   }
   else {
      tp->options |= ID3_TAG_OPTION_ID3V1;
      *endOfFile = true;
   }

   id3_length_t len;
   
   len = id3_tag_render(tp, 0);
   *buffer = (char *)malloc(len);
   len = id3_tag_render(tp, (id3_byte_t *)*buffer);

   id3_tag_delete(tp);

   return len;
#else //ifdef USE_LIBID3TAG 
   return 0;
#endif
}
Esempio n. 3
0
int BarFlyID3WriteFile(char const* file_path, struct id3_tag const* tag,
		BarSettings_t const* settings)
{
	/*
	 * './' + artist + '/' + album + '/' + BAR_FLY_TMP_MP3_FILE_NAME + '\0'
	 */
	int const TMP_FILE_PATH_LENGTH = 2 + BAR_FLY_NAME_LENGTH + 1 + 
			BAR_FLY_NAME_LENGTH + 1 + strlen(BAR_FLY_TMP_MP3_FILE_NAME) + 1;

	int exit_status = 0;
	int status_int;
	id3_length_t size1;
	id3_length_t size2;
	id3_byte_t* tag_buffer = NULL;
	FILE* audio_file = NULL;
	FILE* tmp_file = NULL;
	uint8_t audio_buffer[BAR_FLY_COPY_BLOCK_SIZE];
	char tmp_file_path[TMP_FILE_PATH_LENGTH];
	size_t read_count;
	size_t write_count;

	tmp_file_path[0] = '\0';

	/*
	 * For starters libid3tag kinda sucks.  It will only write a tag to a file 
	 * if the new tag is the same size as the old tag.  Which in this case,
	 * since there is no tag, will never work.  So writing of the tag to the
	 * file has to be done manually.
	 */

	/*
	 * Render the tag to a buffer that can then be written to the audio file.
	 */
	size1 = id3_tag_render(tag, NULL);
	tag_buffer = malloc(size1);
	if (tag_buffer == NULL) {
		BarUiMsg(settings, MSG_ERR, "Failed to allocate memory (bytes = %d).\n",
				size1);
		goto error;
	}

	size2 = id3_tag_render(tag, tag_buffer);
	if (size1 != size2) {
		BarUiMsg(settings, MSG_ERR, "Invalid tag size (expected = %d, "
				"recevied = %d).\n", size1, size2);
		goto error;
	}

	/*
	 * Prepending data to a file is not trivial in C.  Here the approach taken
	 * is to create a temporary file, write the tag to the beginning of the
	 * file, copy the audio file block by block to the tmp file, then overwrite
	 * the audio file with the tmp file.  This was done in order to minimize the
	 * chance of ending up with a broken audio file in case the program stopped
	 * durring this process.
	 */

	/*
	 * Open the audio file.
	 */
	audio_file = fopen(file_path, "rb");
	if (audio_file == NULL) {
		BarUiMsg(settings, MSG_ERR, "Could not read the audio file (%s) "
				"(%d:%s).\n", file_path, errno, strerror(errno));
		goto error;
	}

	/*
	 * Open the tmp file.
	 */
	if (strchr(file_path, '/') == NULL) {
		strcpy(tmp_file_path, BAR_FLY_TMP_MP3_FILE_NAME);
	} else {
		strncpy(tmp_file_path, file_path, TMP_FILE_PATH_LENGTH);
		tmp_file_path[TMP_FILE_PATH_LENGTH - 1] = '\0';
		dirname(tmp_file_path);
		strcat(tmp_file_path, "/");
		strcat(tmp_file_path, BAR_FLY_TMP_MP3_FILE_NAME);
	}

	tmp_file = fopen(tmp_file_path, "w+b");
	if (tmp_file == NULL) {
		BarUiMsg(settings, MSG_ERR, "Could not open the temporary file (%s) "
				"(%d:%s).\n", tmp_file_path, errno, strerror(errno));
		goto error;
	}

	/*
	 * Write the tag to the tmp file.
	 */
	write_count = fwrite(tag_buffer, 1, size2, tmp_file);
	if (write_count != size2) {
		BarUiMsg(settings, MSG_ERR, "Could not write the tag to the file (%s) "
				"(%d:%s).\n", tmp_file_path, errno, strerror(errno));
		goto error;
	}

	/*
	 * Read the audio file block by block until the end is reached.  Each block
	 * is written to the tmp file.
	 */
	while (feof(audio_file) == 0) {
		read_count = fread(audio_buffer, 1, BAR_FLY_COPY_BLOCK_SIZE,
				audio_file);
		if ((read_count != BAR_FLY_COPY_BLOCK_SIZE) &&
			(feof(audio_file) == 0)) {
			BarUiMsg(settings, MSG_ERR, "Failed to read the audio file (%s) "
					"(%d:%s).\n", file_path, errno, strerror(errno));
			goto error;
		}

		write_count = fwrite(audio_buffer, 1, read_count, tmp_file);
		if (write_count != read_count) {
			BarUiMsg(settings, MSG_ERR, "Failed to write to the tmp file "
					"(%s).\n", tmp_file_path);
			goto error;
		}
	}

	/*
	 * The entire contents of the audio file was copied to the tmp file.  Close
	 * the two files.
	 */
	fclose(tmp_file);
	tmp_file = NULL;

	fclose(audio_file);
	audio_file = NULL;

	/*
	 * Overwrite the audio file with the tmp file.
	 */
	status_int = rename(tmp_file_path, file_path);
	if (status_int != 0) {
		BarUiMsg(settings, MSG_ERR, "Could not overwrite the audio file "
				"(%d:%s).\n", errno, strerror(errno));
		goto error;
	}

	goto end;

error:
	/*
	 * Delete the tmp file if it exists.
	 */
	unlink(tmp_file_path);

	exit_status = -1;

end:
	if (tag_buffer != NULL) {
		free(tag_buffer);
	}

	if (audio_file != NULL) {
		fclose(audio_file);
	}

	if (tmp_file != NULL) {
		fclose(tmp_file);
	}

	return exit_status;
}
Esempio n. 4
0
int BarFlyID3WriteFile(char const* file_path, struct id3_tag const* tag,
		BarSettings_t const* settings)
{
	int exit_status = 0;
	int status_int;
	id3_length_t size1;
	id3_length_t size2;
	id3_byte_t* tag_buffer = NULL;
	FILE* audio_file = NULL;
	int tmp_file = -1;
	uint8_t audio_buffer[BAR_FLY_COPY_BLOCK_SIZE];
	char tmp_file_path[FILENAME_MAX];
	strncpy(tmp_file_path, settings->audioFileDir, strlen(settings->audioFileDir)+1);
	strncat(tmp_file_path, "/pianobarfly-XXXXXX", 19+1);
	size_t read_count;
	size_t write_count;

	/*
	 * For starters libid3tag kinda sucks.  It will only write a tag to a file 
	 * if the new tag is the same size as the old tag.  Which in this case,
	 * since there is no tag, will never work.  So writing of the tag to the
	 * file has to be done manually.
	 */

	/*
	 * Render the tag to a buffer that can then be written to the audio file.
	 */
	size1 = id3_tag_render(tag, NULL);
	tag_buffer = malloc(size1);
	if (tag_buffer == NULL) {
		BarUiMsg(settings, MSG_ERR, "Failed to allocate memory (bytes = %li).\n",
				size1);
		goto error;
	}

	size2 = id3_tag_render(tag, tag_buffer);
	if (size1 != size2) {
		BarUiMsg(settings, MSG_ERR, "Invalid tag size (expected = %li, "
				"recevied = %li).\n", size1, size2);
		goto error;
	}

	/*
	 * Prepending data to a file is not trivial in C.  Here the approach taken
	 * is to create a temporary file, write the tag to the beginning of the
	 * file, copy the audio file block by block to the tmp file, then overwrite
	 * the audio file with the tmp file.  This was done in order to minimize the
	 * chance of ending up with a broken audio file in case the program stopped
	 * durring this process.
	 */

	/*
	 * Open the audio file.
	 */
	audio_file = fopen(file_path, "rb");
	if (audio_file == NULL) {
		BarUiMsg(settings, MSG_ERR, "Could not read the audio file (%s) "
				"(%d:%s).\n", file_path, errno, strerror(errno));
		goto error;
	}

	/*
	 * Open the tmp file.
	 *
	 * Assigning the return value of tmpnam() to a junk pointer to get the
	 * compiler to be quiet.
	 */
	tmp_file = mkstemp(tmp_file_path);
	if (tmp_file == -1) {
		BarUiMsg(settings, MSG_ERR, "Could not open the temporary file (%s) "
				"(%d:%s).\n", tmp_file_path, errno, strerror(errno));
		goto error;
	}

	/*
	 * Write the tag to the tmp file.
	 */
	write_count = write(tmp_file, tag_buffer, size2);
	if (write_count != size2) {
		BarUiMsg(settings, MSG_ERR, "Could not write the tag to the file (%s) "
				"(%d:%s).\n", tmp_file_path, errno, strerror(errno));
		goto error;
	}

	/*
	 * Read the audio file block by block until the end is reached.  Each block
	 * is written to the tmp file.
	 */
	while (feof(audio_file) == 0) {
		read_count = fread(audio_buffer, 1, BAR_FLY_COPY_BLOCK_SIZE,
				audio_file);
		if ((read_count != BAR_FLY_COPY_BLOCK_SIZE) &&
			(feof(audio_file) == 0)) {
			BarUiMsg(settings, MSG_ERR, "Failed to read the audio file (%s) "
					"(%d:%s).\n", file_path, errno, strerror(errno));
			goto error;
		}

		write_count = write(tmp_file, audio_buffer, read_count);
		if (write_count != read_count) {
			BarUiMsg(settings, MSG_ERR, "Failed to write to the tmp file "
					"(%s).\n", tmp_file_path);
			goto error;
		}
	}

	/*
	 * The entire contents of the audio file was copied to the tmp file.  Close
	 * the two files.
	 */
	close(tmp_file);
	tmp_file = -1;

	fclose(audio_file);
	audio_file = NULL;

	/*
	 * Overwrite the audio file with the tmp file.
	 */
	status_int = rename(tmp_file_path, file_path);
	if (status_int != 0) {
		BarUiMsg(settings, MSG_ERR, "Could not overwrite the audio file "
				"(%d:%s).\n", errno, strerror(errno));
		goto error;
	}

	goto end;

error:
	/*
	 * Delete the tmp file if it exists.
	 */
	unlink(tmp_file_path);

	exit_status = -1;

end:
	if (tag_buffer != NULL) {
		free(tag_buffer);
	}

	if (audio_file != NULL) {
		fclose(audio_file);
	}

	if (tmp_file != -1) {
		close(tmp_file);
	}

	return exit_status;
}