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:
 

Attachment: signature.asc
Description: Digital signature

Reply via email to