aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-02-05 18:03:32 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2009-02-05 18:03:32 +0200
commit9b5fb2470499d0d054e6dfab55611057d669ad76 (patch)
treed759a6b838c2f1db0b53c1399b25b45437da2811
parenta8c4e813eb17fb28adda734c37ee0c4005601936 (diff)
downloadidest-9b5fb2470499d0d054e6dfab55611057d669ad76.tar.gz
idest-9b5fb2470499d0d054e6dfab55611057d669ad76.tar.bz2
Switch to using libid3tag
-rw-r--r--configure.ac4
-rw-r--r--src/Makefile.am2
-rw-r--r--src/cmdline.opt28
-rw-r--r--src/id3ed.h20
-rw-r--r--src/id3v1.c133
-rw-r--r--src/id3v1.h20
-rw-r--r--src/id3v2.c33
-rw-r--r--src/main.c134
8 files changed, 254 insertions, 120 deletions
diff --git a/configure.ac b/configure.ac
index 3b35567..9f5d8fd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,7 +16,7 @@ gl_EARLY
# Checks for header files.
AC_HEADER_STDC
-AC_CHECK_HEADERS([stdlib.h])
+AC_CHECK_HEADERS([id3tag.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
@@ -25,6 +25,8 @@ AC_TYPE_SIZE_T
# Checks for library functions.
AC_FUNC_MEMCMP
AC_CHECK_FUNCS([memset strcasecmp strerror strncasecmp])
+AC_CHECK_LIB(id3tag, id3_file_tag,,
+ [AC_MSG_ERROR([Required library libid3tag not found])])
gl_INIT
diff --git a/src/Makefile.am b/src/Makefile.am
index 9ea4af7..c4205a8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,5 @@
bin_PROGRAMS=id3ed
-id3ed_SOURCES=id3ed.h id3v1.c id3v1.h main.c cmdline.h
+id3ed_SOURCES=id3ed.h id3v1.c id3v1.h id3v2.c main.c cmdline.h
BUILT_SOURCES=cmdline.h
EXTRA_DIST=cmdline.opt getopt.m4
INCLUDES=-I$(top_srcdir)/gnu -I$(top_builddir)/gnu
diff --git a/src/cmdline.opt b/src/cmdline.opt
index b4ba979..27a8298 100644
--- a/src/cmdline.opt
+++ b/src/cmdline.opt
@@ -5,55 +5,49 @@ OPTIONS_BEGIN(gnu, "id3ed",
OPTION(title,t,NUMBER,
[<set song title>])
BEGIN
- ID3_COPY(id, title, optarg);
+ title = optarg;
mode = MODE_MOD;
END
OPTION(artist,a,NAME,
[<set artist name>])
BEGIN
- ID3_COPY(id, artist, optarg);
+ artist = optarg;
mode = MODE_MOD;
END
OPTION(album,A,NAME,
[<set album name>])
BEGIN
- ID3_COPY(id, album, optarg);
+ album = optarg;
mode = MODE_MOD;
END
OPTION(year,y,YEAR,
[<set year>])
BEGIN
- ID3_COPY(id, year, optarg);
+ year = optarg;
mode = MODE_MOD;
END
OPTION(comment,c,TEXT,
[<set comment>])
BEGIN
- ID3_COPY(id, comment, optarg);
+ comment = optarg;
mode = MODE_MOD;
END
OPTION(track,T,NUMBER,
[<set track number>])
BEGIN
- id.pad[0] = 0;
- id.track[0] = atoi(optarg);
+ track = atoi(optarg);
mode = MODE_MOD;
END
OPTION(genre,g,NAME,
[<set genre>])
BEGIN
- int n = id3v1_genre_to_n(optarg);
- if (n == -1)
- error(1, 0, "%s: unknown genre", optarg);
- else if (n == -2)
- error(1, 0, "%s: ambiguous genre", optarg);
- id.genre[0] = n;
+ genre = optarg;
mode = MODE_MOD;
END
@@ -63,6 +57,14 @@ BEGIN
mode = MODE_QUERY;
END
+OPTION(id-version,V,VERSION,
+ [<set ID3 version>])
+BEGIN
+ version_option = atoi(optarg);
+ if (version_option > 2)
+ error(1, 0, "unsupported version");
+END
+
OPTIONS_END
void
diff --git a/src/id3ed.h b/src/id3ed.h
index e51a55a..52f724d 100644
--- a/src/id3ed.h
+++ b/src/id3ed.h
@@ -6,9 +6,27 @@
#include <error.h>
#include <progname.h>
+#include <id3tag.h>
+
#define _(s) s
#define N_(s) s
#include "id3v1.h"
-
+extern struct id3v1_block v1_block;
+extern char *title;
+extern char *artist;
+extern char *album;
+extern char *year;
+extern char *comment;
+extern unsigned track;
+extern char *genre;
+
+void set_id3v1(const char *name);
+void query_id3v1(const char *name);
+void del_id3v1(const char *name);
+
+void set_id3v2(const char *name);
+void query_id3v2(const char *name);
+void del_id3v2(const char *name);
+
diff --git a/src/id3v1.c b/src/id3v1.c
index cd7b7ae..9093eb8 100644
--- a/src/id3v1.c
+++ b/src/id3v1.c
@@ -192,6 +192,139 @@ id3v1_genre_to_n(const char *genre)
return index;
}
+void
+id3v1_copy_string(const char *name, char *ptr, size_t size, const char *arg)
+{
+ size_t len = strlen(arg);
+ if (len > size) {
+ error(0, 0, "%s truncated", name);
+ len = size;
+ }
+ memcpy(ptr, arg, len);
+}
+int
+id3v1_read(FILE *fp, struct id3v1_block *blk)
+{
+ struct id3v1_block id;
+ if (fseek(fp, -sizeof(id), SEEK_END))
+ return -1;
+ if (fread(blk, sizeof(id), 1, fp) != 1)
+ return -1;
+ if (memcmp(id.header, ID3V1_TAG, ID3V1_HEADER_LEN))
+ return 1;
+ memcpy(blk, &id, sizeof(blk[0]));
+ return 0;
+}
+int
+id3v1_write(FILE *fp, struct id3v1_block *blk)
+{
+ struct id3v1_block id;
+ long offset;
+ switch (id3v1_read(fp, &id)) {
+ case 0:
+ offset = -sizeof(id);
+ break;
+ case 1:
+ offset = 0;
+ break;
+ default:
+ return -1;
+ }
+ memcpy(blk, ID3V1_TAG, ID3V1_HEADER_LEN);
+ if (fseek(fp, offset, SEEK_END))
+ return -1;
+ if (fwrite(&blk, sizeof(blk), 1, fp) != 1)
+ return -1;
+ return 0;
+}
+
+#define ID3_MERGE_FIELD(new,old,fld) do { \
+ if (new->fld[0] == 0 && old->fld) \
+ memcpy(new->fld, old->fld, sizeof(new->fld)); \
+ } while (0)
+
+void
+id3v1_merge(struct id3v1_block *id, const struct id3v1_block *old)
+{
+ ID3_MERGE_FIELD(id,old,title);
+ ID3_MERGE_FIELD(id,old,artist);
+ ID3_MERGE_FIELD(id,old,album);
+ ID3_MERGE_FIELD(id,old,year);
+ ID3_MERGE_FIELD(id,old,comment);
+}
+
+void
+id3v1_init(struct id3v1_block *blk)
+{
+ memset(blk, 0, sizeof(blk[0]));
+ memcpy(blk, ID3V1_TAG, ID3V1_HEADER_LEN);
+}
+
+
+void
+set_id3v1(const char *name)
+{
+ int rc;
+ struct id3v1_block old;
+ FILE *fp = fopen(name, "r+");
+ if (!fp)
+ error(1, errno, "cannot open file %s", name);
+
+ verify_mp3(fp, name);
+ switch (id3v1_read(fp, &old)) {
+ case 0:
+ id3v1_merge(&v1_block, &old);
+ break;
+ case 1:
+ break;
+ default:
+ error(1, errno, "%s: read error", name);
+ }
+ if (id3v1_write(fp, &v1_block))
+ error(1, errno, "%s: write error", name);
+
+ fclose(fp);
+}
+
+void
+query_id3v1(const char *name)
+{
+ struct id3v1_block id;
+ FILE *fp = fopen(name, "r");
+ int rc;
+ if (!fp)
+ error(1, errno, "cannot open file %s", name);
+
+ verify_mp3(fp, name);
+ rc = id3v1_read(fp, &id);
+ fclose(fp);
+
+ switch (rc) {
+ case 0:
+ printf("title: %-.30s\n", id.title);
+ printf("artist: %-.30s\n", id.artist);
+ printf("album: %-.30s\n", id.album);
+ printf("year: %-.4s\n", id.year);
+ printf("comment: %-.28s\n", id.comment);
+ printf("genre: %s\n", id3v1_n_to_genre(id.genre[0]));
+ if (id.pad[0] == 0)
+ printf("track: %d\n", id.track[0]);
+ break;
+ case 1:
+ break;
+ case -1:
+ error(1, errno, "%s: read error", name);
+ }
+}
+
+void
+del_id3v1(const char *name)
+{
+ error(1, 0, "Delete is not implemented");
+}
+
+
+
diff --git a/src/id3v1.h b/src/id3v1.h
index 86a2776..6df52ff 100644
--- a/src/id3v1.h
+++ b/src/id3v1.h
@@ -1,4 +1,4 @@
-struct id3_block {
+struct id3v1_block {
char header[3];
char title[30];
char artist[30];
@@ -10,8 +10,22 @@ struct id3_block {
char genre[1];
};
-#define ID3_TAG "TAG"
-#define ID3_HEADER_LEN 3
+#define ID3V1_TAG "TAG"
+#define ID3V1_HEADER_LEN 3
+#define ID3V1_SET(blk, name, value) do { \
+ if (value) \
+ id3v1_copy_string(#name, (blk)->name, \
+ sizeof((blk)->name), value); \
+ } while(0)
+
const char *id3v1_n_to_genre(unsigned n);
int id3v1_genre_to_n(const char *genre);
+void id3v1_init(struct id3v1_block *blk);
+void id3v1_copy_string(const char *name, char *ptr, size_t size,
+ const char *arg);
+int id3v1_read(FILE *fp, struct id3v1_block *blk);
+int id3v1_write(FILE *fp, struct id3v1_block *blk);
+void id3v1_merge(struct id3v1_block *id, const struct id3v1_block *old);
+
+
diff --git a/src/id3v2.c b/src/id3v2.c
new file mode 100644
index 0000000..f37606f
--- /dev/null
+++ b/src/id3v2.c
@@ -0,0 +1,33 @@
+#include "id3ed.h"
+
+void
+set_id3v2(const char *name)
+{
+}
+
+static void
+show_tag(struct id3_tag *tag)
+{
+}
+
+void
+query_id3v2(const char *name)
+{
+ struct id3_file *file;
+ struct id3_tag *tag;
+
+ file = id3_file_open(name, ID3_FILE_MODE_READONLY);
+ if (!file)
+ error(1, errno, "cannot open file %s", name);
+
+ tag = id3_file_tag(file);
+ if (tag)
+ show_tag(tag);
+
+ id3_file_close(file);
+}
+
+void
+del_id3v2(const char *name)
+{
+}
diff --git a/src/main.c b/src/main.c
index 690d743..a08c7db 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,16 +1,15 @@
#include "id3ed.h"
-void
-copy_string(const char *name, char *ptr, size_t size, const char *arg)
-{
- size_t len = strlen(arg);
- if (len > size) {
- error(0, 0, "%s truncated", name);
- len = size;
- }
- memcpy(ptr, arg, len);
-}
-
+unsigned version_option = 2;
+struct id3v1_block v1_block;
+char *title;
+char *artist;
+char *album;
+char *year;
+char *comment;
+unsigned track;
+char *genre;
+
void
verify_mp3(FILE *fp, const char *name)
@@ -31,7 +30,7 @@ verify_mp3(FILE *fp, const char *name)
switch (sig & 0xFFFE) {
case 0xFFFA: /* MPEG ADTS, layer III, v1 */
case 0xFFF2: /* MPEG ADTS, layer III, v2 */
- case 0xFFFE: /* MPEG ADTS, layer III, v2.5 */
+ case 0xFFFE: /* MPEG ADTS, layer III, v2.5 */
break;
default:
@@ -39,99 +38,17 @@ verify_mp3(FILE *fp, const char *name)
}
}
-void
-read_id3(FILE *fp, const char *name, struct id3_block *blk)
-{
- if (fseek(fp, -sizeof(blk[0]), SEEK_END))
- error(1, errno, "%s: seek error", name);
- if (fread(blk, sizeof(blk[0]), 1, fp) != 1)
- error(1, errno, "%s: read error: %s", name);
-}
-
-#define ID3_MERGE_FIELD(new,old,fld) do { \
- if (new->fld[0] == 0 && old->fld) \
- memcpy(new->fld, old->fld, sizeof(new->fld)); \
- } while (0)
-
-void
-id3_merge(struct id3_block *id, const struct id3_block *old)
-{
- ID3_MERGE_FIELD(id,old,title);
- ID3_MERGE_FIELD(id,old,artist);
- ID3_MERGE_FIELD(id,old,album);
- ID3_MERGE_FIELD(id,old,year);
- ID3_MERGE_FIELD(id,old,comment);
-}
-
-void
-set_id3(const char *name, const struct id3_block *id)
-{
- int rc;
- struct id3_block old, new;
- FILE *fp = fopen(name, "r+");
- if (!fp)
- error(1, errno, "cannot open file %s", name);
-
- verify_mp3(fp, name);
- read_id3(fp, name, &old);
-
- memcpy(&new, id, sizeof(new));
- if (memcmp(old.header, ID3_TAG, ID3_HEADER_LEN) == 0) {
- id3_merge(&new, &old);
- rc = fseek(fp, -sizeof(id[0]), SEEK_END);
- } else
- rc = fseek(fp, 0, SEEK_END);
- if (rc)
- error(1, errno, "%s: seek error", name);
-
- if (fwrite(&new, sizeof(new), 1, fp) != 1)
- error(1, errno, "%s: write error", name);
-
- fclose(fp);
-}
-
-void
-query_id3(const char *name, const struct id3_block *blk_unused)
-{
- struct id3_block id;
- FILE *fp = fopen(name, "r");
- if (!fp)
- error(1, errno, "cannot open file %s", name);
-
- verify_mp3(fp, name);
- read_id3(fp, name, &id);
- fclose(fp);
- if (memcmp(id.header, ID3_TAG, ID3_HEADER_LEN))
- return;
- printf("title: %-.30s\n", id.title);
- printf("artist: %-.30s\n", id.artist);
- printf("album: %-.30s\n", id.album);
- printf("year: %-.4s\n", id.year);
- printf("comment: %-.28s\n", id.comment);
- printf("genre: %s\n", id3v1_n_to_genre(id.genre[0]));
- if (id.pad[0] == 0)
- printf("track: %d\n", id.track[0]);
-}
-
-#define ID3_COPY(blk, fld, arg) \
- copy_string(#fld, blk.fld, sizeof(blk.fld), arg)
-
-void
-del_id3(const char *name, const struct id3_block *blk_unused)
-{
-}
#define MODE_QUERY 0
#define MODE_MOD 1
#define MODE_DELETE 2
-void (*id3_mode[])(const char *, const struct id3_block *) = {
- query_id3,
- set_id3,
- del_id3
+void (*id3_mode[][2])(const char *) = {
+ { query_id3v1, query_id3v2 },
+ { set_id3v1, set_id3v2 },
+ { del_id3v1, del_id3v2 }
};
-struct id3_block id;
int mode = MODE_QUERY;
#include "cmdline.h"
@@ -142,8 +59,6 @@ main(int argc, char **argv)
int c, n;
set_program_name(argv[0]);
- memset(&id, 0, sizeof(id));
- memcpy(id.header, ID3_TAG, ID3_HEADER_LEN);
get_options(argc, argv);
@@ -153,8 +68,25 @@ main(int argc, char **argv)
if (argc == 0)
error(1, 0, "no files");
+ if (version_option == 1) {
+ int n;
+
+ id3v1_init(&v1_block);
+ ID3V1_SET(&v1_block, title, title);
+ ID3V1_SET(&v1_block, artist, artist);
+ ID3V1_SET(&v1_block, album, album);
+ ID3V1_SET(&v1_block, year, year);
+ ID3V1_SET(&v1_block, comment, comment);
+ n = id3v1_genre_to_n(genre);
+ if (n == -1)
+ error(1, 0, "%s: unknown genre", genre);
+ else if (n == -2)
+ error(1, 0, "%s: ambiguous genre", genre);
+ v1_block.track[0] = n;
+ }
+
while (argc--)
- id3_mode[mode](*argv++, &id);
+ id3_mode[mode][version_option - 1](*argv++);
exit(0);
}

Return to:

Send suggestions and report system problems to the System administrator.