Package: vorbis-tools Version: 1.1.1-5 Severity: wishlist Tags: patch I often want to edit tags of ogg vorbis files using an editor, so I wrote a new option 'vorbiscomment -e' (similar to 'crontab -e').
I was a bit lazy, using the current directory for the temp file rather than getenv(TMPDIR), but I know some other apps do the same thing. Also, the patch is debian-specific as I use sensible-editor rather than getenv(VISUAL) etc. Peter
Index: vorbis-tools-1.1.1/vorbiscomment/vcomment.c
===================================================================
--- vorbis-tools-1.1.1.orig/vorbiscomment/vcomment.c 2006-04-25
02:28:09.000000000 -0500
+++ vorbis-tools-1.1.1/vorbiscomment/vcomment.c 2006-04-25 02:30:51.000000000
-0500
@@ -12,6 +12,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <unistd.h>
#include <locale.h>
#ifdef HAVE_CONFIG_H
@@ -29,6 +30,7 @@
struct option long_options[] = {
{"list",0,0,'l'},
{"write",0,0,'w'},
+ {"editor",0,0,'e'},
{"help",0,0,'h'},
{"quiet",0,0,'q'},
{"version", 0, 0, 'V'},
@@ -53,11 +55,13 @@
#define MODE_LIST 1
#define MODE_WRITE 2
#define MODE_APPEND 3
+#define MODE_EDITOR 4
/* prototypes */
void usage(void);
void print_comments(FILE *out, vorbis_comment *vc, int raw);
int add_comment(char *line, vorbis_comment *vc, int raw);
+int launch_editor(vorbis_comment *vc, int raw);
param_t *new_param(void);
void free_param(param_t *param);
@@ -125,7 +129,8 @@
return 0;
}
- if (param->mode == MODE_WRITE || param->mode == MODE_APPEND) {
+ if (param->mode == MODE_WRITE || param->mode == MODE_APPEND ||
+ param->mode == MODE_EDITOR) {
state = vcedit_new_state();
@@ -133,6 +138,7 @@
{
fprintf(stderr, _("Failed to open file as vorbis:
%s\n"),
vcedit_error(state));
+ error_cleanup:
close_files(param, 0);
free_param(param);
vcedit_clear(state);
@@ -141,7 +147,7 @@
/* grab and clear the exisiting comments */
vc = vcedit_comments(state);
- if(param->mode != MODE_APPEND)
+ if (param->mode == MODE_WRITE)
{
vorbis_comment_clear(vc);
vorbis_comment_init(vc);
@@ -154,7 +160,16 @@
}
/* build the replacement structure */
- if(param->commentcount==0)
+ if (param->mode == MODE_EDITOR)
+ {
+ if (!launch_editor(vc, param->raw))
+ {
+ fprintf(stderr,
+ _("editor returned non-zero
status, aborting\n"));
+ goto error_cleanup;
+ }
+ }
+ else if (param->commentcount==0)
{
/* FIXME should use a resizeable buffer! */
char *buf = (char *)malloc(sizeof(char)*1024);
@@ -278,6 +293,65 @@
}
+/**********
+
+ Create a temporary file with the comments in it, launch an editor
+ to allow the user to change this file, and replace the comments
+ with lines from the edited temporary file.
+
+***********/
+
+int launch_editor(vorbis_comment *vc, int raw)
+{
+ char tempfile[] = "vorbiscomment.XXXXXX";
+ char editor_cmd[64];
+ int fd;
+ FILE *fp;
+ char buf[1024]; /* FIXME should use a resizeable buffer! */
+
+ fd = mkstemp(tempfile);
+ if (fd < 0)
+ return 0;
+ fp = fdopen(fd, "wb");
+ if (!fp)
+ {
+ close(fd);
+ remove(tempfile);
+ return 0;
+ }
+ print_comments(fp, vc, raw);
+ fclose(fp);
+ close(fd);
+
+ /* 'sensible-editor' is Debian-specific. To support other OSes,
+ * one would need to getenv("VISUAL") then getenv("EDITOR") then
+ * fall back to a default like 'vi'.
+ */
+ snprintf(editor_cmd, sizeof(editor_cmd),
+ "sensible-editor %s", tempfile);
+ if (system(editor_cmd) != 0)
+ {
+ error_cleanup:
+ remove(tempfile);
+ return 0;
+ }
+ fp = fopen(tempfile, "rb");
+ if (!fp)
+ goto error_cleanup;
+
+ vorbis_comment_clear(vc);
+ vorbis_comment_init(vc);
+
+ while (fgets(buf, 1024, fp))
+ if (add_comment(buf, vc, raw) < 0)
+ fprintf(stderr, _("bad comment: \"%s\"\n"), buf);
+
+ fclose(fp);
+ remove(tempfile);
+ return 1;
+}
+
+
/*** ui-specific routines ***/
/**********
@@ -293,10 +367,11 @@
" vorbiscomment [-l] file.ogg (to list the comments)\n"
" vorbiscomment -a in.ogg out.ogg (to append comments)\n"
" vorbiscomment -w in.ogg out.ogg (to modify comments)\n"
+ " vorbiscomment -e in.ogg out.ogg (to edit comments with an
editor)\n"
" in the write case, a new set of comments in the form\n"
" 'TAG=value' is expected on stdin. This set will\n"
" completely replace the existing set.\n"
- " Either of -a and -w can take only a single filename,\n"
+ " -a, -w and -e can take only a single filename,\n"
" in which case a temporary file will be used.\n"
" -c can be used to take comments from a specified file\n"
" instead of stdin.\n"
@@ -369,7 +444,7 @@
setlocale(LC_ALL, "");
- while ((ret = getopt_long(argc, argv, "alwhqVc:t:R",
+ while ((ret = getopt_long(argc, argv, "alwehqVc:t:R",
long_options, &option_index)) != -1) {
switch (ret) {
case 0:
@@ -388,6 +463,9 @@
case 'a':
param->mode = MODE_APPEND;
break;
+ case 'e':
+ param->mode = MODE_EDITOR;
+ break;
case 'V':
fprintf(stderr, "Vorbiscomment " VERSION "\n");
exit(0);
@@ -415,14 +493,16 @@
/* remaining bits must be the filenames */
if((param->mode == MODE_LIST && (argc-optind) != 1) ||
- ((param->mode == MODE_WRITE || param->mode == MODE_APPEND) &&
+ ((param->mode == MODE_WRITE || param->mode == MODE_APPEND ||
+ param->mode == MODE_EDITOR) &&
((argc-optind) < 1 || (argc-optind) > 2))) {
usage();
exit(1);
}
param->infilename = strdup(argv[optind]);
- if (param->mode == MODE_WRITE || param->mode == MODE_APPEND)
+ if (param->mode == MODE_WRITE || param->mode == MODE_APPEND ||
+ param->mode == MODE_EDITOR)
{
if(argc-optind == 1)
{
@@ -464,7 +544,8 @@
exit(1);
}
- if (p->mode == MODE_WRITE || p->mode == MODE_APPEND) {
+ if (p->mode == MODE_WRITE || p->mode == MODE_APPEND ||
+ p->mode == MODE_EDITOR) {
/* open output for write mode */
if(!strcmp(p->infilename, p->outfilename)) {
Index: vorbis-tools-1.1.1/vorbiscomment/vorbiscomment.1
===================================================================
--- vorbis-tools-1.1.1.orig/vorbiscomment/vorbiscomment.1 2006-04-25
02:28:10.000000000 -0500
+++ vorbis-tools-1.1.1/vorbiscomment/vorbiscomment.1 2006-04-25
02:28:10.000000000 -0500
@@ -24,6 +24,9 @@
.RB [ -q ]
.I in.ogg
.I [out.ogg]
+.br
+.B vorbiscomment \-e [ \-c commentfile | \-t \*(lqtag=value\*(rq ]
+.I in.ogg [out.ogg]
.SH DESCRIPTION
.B vorbiscomment
@@ -44,6 +47,8 @@
Specify a new tag on the command line. Each tag is given as a single string.
The part before the '=' is treated as the tag name and the part after as the
value.
.IP "-w"
Replace comments with the new set given either on the command line with -t or
from a file with -c.
+.IP "-e"
+Edit the comments using an external editor.
.IP "-R"
Read and write comments in utf8, rather than converting to the user's
character set.
@@ -56,9 +61,7 @@
To edit those comments:
- vorbiscomment -l file.ogg > file.txt
- [edit the comments in file.txt to your satisfaction]
- vorbiscomment -w -c file.txt file.ogg newfile.ogg
+ vorbiscomment -e file.ogg
To simply add a comment:
signature.asc
Description: Digital signature

