taged is a commandline utility that can create and modify ID3 data, usually found in .mp3 files. Besides supporting text frames like artist, title, track number, etc., it also supports attached pictures, play counters, and generated playlists. It aims at being quick and easy to use when many tags needs to be created/updated, and handles regular expression matching of tag data from filenames, as well as renaming files based on the tags.
| Tags | Utilities multimedia Sound/Audio |
|---|---|
| Licenses | GPL |
| Operating Systems | POSIX |
| Implementation | C |
- All comments
Recent commentsavoid core dump in --verbose mode
when using the --verbose option there might occur a core dump for some files. You may avoid it by using the following patch (generated with "diff -Naur src/desc.orig.c src/desc.c"). Use
# patch <<EOF
--- src/desc.orig.c 2004-12-19 20:40:38.000000000 +0100
+++ src/desc.c 2004-12-19 22:44:30.000000000 +0100
@@ -19,6 +19,7 @@
*/
#include "taged.h"
+#define nonzerostring(x) (((x)!=(const char*)NULL)?(x):"<-NULL-POINTER->")
const char *apic_types[] = {
"Other",
@@ -242,7 +243,7 @@
free(latin1);
}
} else if(frame->id[0] == 'W') {
- printf("%s\n", frame->fields[0].latin1.ptr);
+ printf("%s\n", nonzerostring(frame->fields[0].latin1.ptr) );
} else if(strcmp(frame->id, "USER") == 0) {
ucs4 = id3_field_getstring(&frame->fields[2]);
latin1 = id3_ucs4_latin1duplicate(ucs4);
@@ -308,8 +309,7 @@
printf("%splay counter: %s%s\n",
NC, FC, strint32plus(&frame->fields[2]));
} else if(strcmp(frame->id, "ZOBS") == 0) {
- printf("%s\n",
- id3_field_getframeid(&frame->fields[0]));
+ printf("%s\n", nonzerostring(id3_field_getframeid(&frame->fields[0])) );
} else {
printf(_("%sunsupported\n"), WC);
}
EOF
Patch not found [related to v2 tags longer than allowed for v1]
The pattern matching is an excellent feature. For ID3v1 tags a problem is known. Since I didn't find the patch, I added a short stub to fix it. It worked fine for all my tests.
Here is "diff -Naur src/fileio.c.orig src/fileio.c" use
# patch <<EOT
--- src/fileio.c.orig 2005-01-02 12:15:45.000000000 +0100
+++ src/fileio.c 2005-01-02 17:35:52.000000000 +0100
@@ -21,6 +21,54 @@
#include "taged.h"
#include <utime.h>
+typedef struct id3tag_s {
+ char magic[3];
+ char songname[30];
+ char artist[30];
+ char album[30];
+ char year[4];
+ char comment[28];
+ unsigned char style;
+ unsigned char track;
+ unsigned char genre;
+} id3tag_type;
+
+#define ID3_TAG_RENDER_NAME id3_tag_render_s
+#define set_id3v1_string(x,y,z,n) \
+ if( get_text_frame(y, z, 0) == 0 ) memset(id3v1_data->x,' ',n); \
+ else strncpy(id3v1_data->x,get_text_frame(y, z, 0),n);
+static
+int id3_tag_render_s(struct id3_tag*primary, struct id3tag_s*id3v1_data)
+{
+ int size=0;
+
+ /* magic */
+ id3v1_data->magic[0]='T';
+ id3v1_data->magic[1]='A';
+ id3v1_data->magic[2]='G';
+ /* songname */
+ set_id3v1_string(songname,primary,"TIT2",30);
+ /* artist */
+ set_id3v1_string(artist,primary,"TPE1",30);
+ /* album */
+ set_id3v1_string(album,primary,"TALB",30);
+ /* year */
+ set_id3v1_string(year,primary,"TDRC",4);
+ /* note */
+ memset(id3v1_data->comment,'\000',28);
+ /* style */
+ id3v1_data->style=0;
+ /* track */
+ if( get_text_frame(primary, "TRCK", 0) == 0 ) id3v1_data->track=0;
+ else id3v1_data->track = (unsigned char)atoi(get_text_frame(primary, "TRCK", 0));
+ /* genre */
+ if( get_text_frame(primary, "TCON", 0) == 0 ) id3v1_data->genre=0;
+ else id3v1_data->genre = find_genre_num(get_text_frame(primary, "TCON", 0));
+ /* return */
+ size=sizeof(*id3v1_data);
+ assert( sizeof(struct id3tag_s) <= sizeof(*id3v1_data) );
+ return size;
+}
/*
* NAME: query_tag()
* DESCRIPTION: check for a tag at a file's current position
@@ -63,23 +111,39 @@
id3_length_t size;
unsigned char id3v1_data[128];
+ /*
+ * When entering this function
+ * all exiting ID3v1 data
+ * will be overwritten/replaced
+ * with info stored in file->primary
+ */
file->primary->options |= ID3_TAG_OPTION_ID3V1;
size = id3_tag_render(file->primary, 0);
if(size) {
assert(size == sizeof(id3v1_data));
- size = id3_tag_render(file->primary, id3v1_data);
+ /* verify that the character array is zeroed */
+ memset(id3v1_data, '\000', sizeof(id3v1_data) );
+ /* verify that the character array is zeroed */
+ size = ID3_TAG_RENDER_NAME(file->primary, id3v1_data);
if(size) {
assert(size == sizeof(id3v1_data));
/* look for existing v1 tag */
size = 0;
+ /* move to end of file */
fseek(file->iofile, 0, SEEK_END);
+ /* move back 128 bytes=sizeof(id3tag_V1) */
if(fseek(file->iofile, -128, SEEK_END) == 0)
+ /* if the file is longer than the tag
+ read the info using lib and
+ reposition at writing position */
size = query_tag(file->iofile);
+ /* if something went wrong on positioning */
if(size == 0)
+ /* reposition to the very end of the file */
fseek(file->iofile, 0, SEEK_END);
- /* else overwrite old v1 tag */
+ /* (over)write v1 tag */
fwrite(id3v1_data, 1, 128, file->iofile);
} else
remove_v1_tag(file);
EOT