[xiph-commits] r15395 - in trunk/vorbis-tools: . oggenc oggenc/man

ivo at svn.xiph.org ivo at svn.xiph.org
Mon Oct 13 12:12:23 PDT 2008


Author: ivo
Date: 2008-10-13 12:12:22 -0700 (Mon, 13 Oct 2008)
New Revision: 15395

Modified:
   trunk/vorbis-tools/README
   trunk/vorbis-tools/configure.ac
   trunk/vorbis-tools/oggenc/Makefile.am
   trunk/vorbis-tools/oggenc/audio.c
   trunk/vorbis-tools/oggenc/encode.c
   trunk/vorbis-tools/oggenc/encode.h
   trunk/vorbis-tools/oggenc/man/oggenc.1
   trunk/vorbis-tools/oggenc/oggenc.c
Log:
Move preliminary Kate support to repository to avoid losing work.

Modified: trunk/vorbis-tools/README
===================================================================
--- trunk/vorbis-tools/README	2008-10-12 20:06:55 UTC (rev 15394)
+++ trunk/vorbis-tools/README	2008-10-13 19:12:22 UTC (rev 15395)
@@ -25,9 +25,9 @@
 All of the tools require libogg and libvorbis to be installed (along
 with the header files).  Additionally, ogg123 requires libao, libcurl,
 and a POSIX-compatible thread library.  Ogg123 can optionally compiled
-to use libFLAC, libOggFLAC, and libspeex.  Oggenc can be optionally
-compiled with libFLAC and libOggFLAC.  The libraries libogg,
-libvorbis, and libao are all available at
+to use libFLAC, and libspeex.  Oggenc can be optionally compiled with
+libFLAC, and libkate.  The libraries libogg, libvorbis, and libao are
+all available at
   http://www.vorbis.com/download.psp
 
 The libcurl library is packaged with most Linux distributions.  The
@@ -40,6 +40,9 @@
 Speex is available at:
   http://www.speex.org/
 
+libkate is available at:
+  http://libkate.googlecode.com/
+
 CONTACT:
 
 The Ogg Vorbis homepage is located at 'http://www.vorbis.com'. Up to

Modified: trunk/vorbis-tools/configure.ac
===================================================================
--- trunk/vorbis-tools/configure.ac	2008-10-12 20:06:55 UTC (rev 15394)
+++ trunk/vorbis-tools/configure.ac	2008-10-13 19:12:22 UTC (rev 15395)
@@ -414,7 +414,7 @@
 will NOT be built with http support.])
     fi
     if test "x$HAVE_KATE" != xyes; then
-        AC_MSG_WARN([Kate libraries and/or headers missing, ogginfo 
-will be built with LIMITED Kate read support.])
+        AC_MSG_WARN([Kate libraries and/or headers missing, oggenc 
+will NOT be built with Kate lyrics support.])
     fi
 fi

Modified: trunk/vorbis-tools/oggenc/Makefile.am
===================================================================
--- trunk/vorbis-tools/oggenc/Makefile.am	2008-10-12 20:06:55 UTC (rev 15394)
+++ trunk/vorbis-tools/oggenc/Makefile.am	2008-10-13 19:12:22 UTC (rev 15395)
@@ -13,16 +13,16 @@
 
 bin_PROGRAMS = oggenc
 
-INCLUDES = @SHARE_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@ @I18N_CFLAGS@
+INCLUDES = @SHARE_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@ @KATE_CFLAGS@ @I18N_CFLAGS@
 
 oggenc_LDADD = @SHARE_LIBS@ \
-	       @VORBISENC_LIBS@ @VORBIS_LIBS@ @OGG_LIBS@ \
+	       @VORBISENC_LIBS@ @VORBIS_LIBS@ @KATE_LIBS@ @OGG_LIBS@ \
 	       @LIBICONV@ @I18N_LIBS@ @FLAC_LIBS@
 
 oggenc_DEPENDENCIES = @SHARE_LIBS@
 
 oggenc_SOURCES = $(flac_sources) \
-                 oggenc.c audio.c encode.c platform.c \
+                 oggenc.c audio.c encode.c platform.c lyrics.c \
                  audio.h encode.h platform.h resample.c resample.h skeleton.c skeleton.h
 
 

Modified: trunk/vorbis-tools/oggenc/audio.c
===================================================================
--- trunk/vorbis-tools/oggenc/audio.c	2008-10-12 20:06:55 UTC (rev 15394)
+++ trunk/vorbis-tools/oggenc/audio.c	2008-10-13 19:12:22 UTC (rev 15395)
@@ -47,7 +47,7 @@
 
 /* Define the supported formats here */
 input_format formats[] = {
-    {wav_id, 12, wav_open, wav_close, "wav", N_("WAV file reader")},
+    {wav_id, 12, wav_open, wav_close, "wav", N_("Wave file reader")},
     {aiff_id, 12, aiff_open, wav_close, "aiff", N_("AIFF/AIFC file reader")},
 #ifdef HAVE_LIBFLAC
     {flac_id,     4, flac_open, flac_close, "flac", N_("FLAC file reader")},

Modified: trunk/vorbis-tools/oggenc/encode.c
===================================================================
--- trunk/vorbis-tools/oggenc/encode.c	2008-10-12 20:06:55 UTC (rev 15394)
+++ trunk/vorbis-tools/oggenc/encode.c	2008-10-13 19:12:22 UTC (rev 15395)
@@ -25,6 +25,11 @@
 #include "i18n.h"
 #include "skeleton.h"
 
+#ifdef HAVE_KATE
+#include "lyrics.h"
+#include <kate/oggkate.h>
+#endif
+
 #define READSIZE 1024
 
 
@@ -116,7 +121,7 @@
 #endif
 }
 
-void add_fishead_packet (ogg_stream_state *os) {
+static void add_fishead_packet (ogg_stream_state *os) {
 
    fishead_packet fp;
 
@@ -130,9 +135,9 @@
 }
 
 /*
- * Adds the fishead packets in the skeleton output stream along with the e_o_s packet
+ * Adds the fishead packets in the skeleton output stream
  */
-void add_fisbone_packet (ogg_stream_state *os, oe_enc_opt *opt) {
+static void add_vorbis_fisbone_packet (ogg_stream_state *os, oe_enc_opt *opt) {
 
    fisbone_packet fp;
 
@@ -150,11 +155,53 @@
    add_fisbone_to_stream(os, &fp);
 }
 
+#ifdef HAVE_KATE
+static void add_kate_fisbone_packet (ogg_stream_state *os, oe_enc_opt *opt, kate_info *ki) {
+
+   fisbone_packet fp;
+
+   memset(&fp, 0, sizeof(fp));
+   fp.serial_no = opt->kate_serialno;
+   fp.nr_header_packet = ki->num_headers;
+   fp.granule_rate_n = ki->gps_numerator;
+   fp.granule_rate_d = ki->gps_denominator;
+   fp.start_granule = 0;
+   fp.preroll = 0;
+   fp.granule_shift = ki->granule_shift;
+
+   add_message_header_field(&fp, "Content-Type", "application/x-kate");
+
+   add_fisbone_to_stream(os, &fp);
+}
+#endif
+
+#ifdef HAVE_KATE
+static void add_kate_karaoke_style(kate_info *ki,unsigned char r,unsigned char g,unsigned char b,unsigned char a)
+{
+    kate_style *ks;
+    int ret;
+
+    if (!ki) return;
+
+    ks=(kate_style*)malloc(sizeof(kate_style));
+    kate_style_init(ks);
+    ks->text_color.r = r;
+    ks->text_color.g = g;
+    ks->text_color.b = b;
+    ks->text_color.a = a;
+    ret=kate_info_add_style(ki,ks);
+    if (ret<0) {
+      fprintf(stderr, _("WARNING: failed to add Kate karaoke style\n"));
+    }
+}
+#endif
+
 int oe_encode(oe_enc_opt *opt)
 {
 
     ogg_stream_state os;
     ogg_stream_state so; /* stream for skeleton bitstream */
+    ogg_stream_state ko; /* stream for kate bitstream */
     ogg_page         og;
     ogg_packet       op;
 
@@ -162,6 +209,15 @@
     vorbis_block     vb;
     vorbis_info      vi;
 
+#ifdef HAVE_KATE
+    kate_info        ki;
+    kate_comment     kc;
+    kate_state       k;
+    oe_lyrics        *lyrics=NULL;
+    size_t           lyrics_index=0;
+    double           vorbis_time = 0.0;
+#endif
+
     long samplesdone=0;
     int eos;
     long bytes_written = 0, packetsdone=0;
@@ -293,13 +349,41 @@
     vorbis_analysis_init(&vd,&vi);
     vorbis_block_init(&vd,&vb);
 
+#ifdef HAVE_KATE
+    if (opt->lyrics) {
+        /* load lyrics */
+        lyrics=load_lyrics(opt->lyrics);
+        /* if it fails, don't do anything else for lyrics */
+        if (!lyrics) {
+            opt->lyrics = NULL;
+        } else {
+            /* init kate for encoding */
+            kate_info_init(&ki);
+            kate_info_set_category(&ki, "lyrics");
+            if (opt->lyrics_language)
+              kate_info_set_language(&ki, opt->lyrics_language);
+            else
+              fprintf(stderr, _("WARNING: no language specified for %s\n"), opt->lyrics);
+            kate_comment_init(&kc);
+            kate_encode_init(&k,&ki);
+
+            /* if we're in karaoke mode (we have syllable level timing info),
+               add style info in case some graphical player is used */
+            add_kate_karaoke_style(&ki, 255, 255, 255, 255);
+            add_kate_karaoke_style(&ki, 255, 128, 128, 255);
+        }
+    }
+#endif
+
     ogg_stream_init(&os, opt->serialno);
-    if (opt->with_skeleton) 
+    if (opt->with_skeleton)
         ogg_stream_init(&so, opt->skeleton_serialno);
+    if (opt->lyrics)
+        ogg_stream_init(&ko, opt->kate_serialno);
 
     /* create the skeleton fishead packet and output it */ 
-    if (opt->with_skeleton) { 
-        add_fishead_packet(&so); 
+    if (opt->with_skeleton) {
+        add_fishead_packet(&so);
         if ((ret = flush_ogg_stream_to_file(&so, opt->out))) {
             opt->error(_("Failed writing fishead packet to output stream\n"));
             goto cleanup; 
@@ -319,9 +403,9 @@
                 &header_main,&header_comments,&header_codebooks);
 
         /* And stream them out */
-        /* output the vorbis bos first, then the fisbone packets */
+        /* output the vorbis bos first, then the kate bos, then the fisbone packets */
         ogg_stream_packetin(&os,&header_main);
-	while((result = ogg_stream_flush(&os, &og)))
+        while((result = ogg_stream_flush(&os, &og)))
         {
             if(!result) break;
             ret = oe_write_page(&og, opt->out);
@@ -333,13 +417,48 @@
             }
         }
 
+#ifdef HAVE_KATE
+        if (opt->lyrics) {
+            ogg_packet kate_op;
+            ret = kate_ogg_encode_headers(&k, &kc, &kate_op);
+            if (ret < 0) {
+                opt->error(_("Failed encoding Kate header\n"));
+                goto cleanup;
+            }
+            ogg_stream_packetin(&ko,&kate_op);
+            while((result = ogg_stream_flush(&ko, &og)))
+            {
+                if(!result) break;
+                ret = oe_write_page(&og, opt->out);
+                if(ret != og.header_len + og.body_len)
+                {
+                    opt->error(_("Failed writing header to output stream\n"));
+                    ret = 1;
+                    goto cleanup; /* Bail and try to clean up stuff */
+                }
+            }
+            ogg_packet_clear(&kate_op);
+        }
+#endif
+
         if (opt->with_skeleton) {
-            add_fisbone_packet(&so, opt);
+            add_vorbis_fisbone_packet(&so, opt);
             if ((ret = flush_ogg_stream_to_file(&so, opt->out))) {
                 opt->error(_("Failed writing fisbone header packet to output stream\n"));
-                goto cleanup; 
-           }
+                goto cleanup;
+            }
+#ifdef HAVE_KATE
+            if (opt->lyrics) {
+                add_kate_fisbone_packet(&so, opt, &ki);
+                if ((ret = flush_ogg_stream_to_file(&so, opt->out))) {
+                    opt->error(_("Failed writing fisbone header packet to output stream\n"));
+                    goto cleanup;
+                }
+            }
+#endif
         }
+
+        /* write the next Vorbis headers */
         ogg_stream_packetin(&os,&header_comments);
         ogg_stream_packetin(&os,&header_codebooks);
 
@@ -356,9 +475,30 @@
         }
     }
 
-    if (opt->with_skeleton) { 
-        add_eos_packet_to_stream(&so); 
-        if ((ret = flush_ogg_stream_to_file(&so, opt->out))) { 
+    /* build kate headers if requested */
+#ifdef HAVE_KATE
+    if (opt->lyrics) {
+        while (kate_ogg_encode_headers(&k,&kc,&op)==0) {
+          ogg_stream_packetin(&ko,&op);
+          ogg_packet_clear(&op);
+        }
+        while((result = ogg_stream_flush(&ko, &og)))
+        {
+            if(!result) break;
+            ret = oe_write_page(&og, opt->out);
+            if(ret != og.header_len + og.body_len)
+            {
+                opt->error(_("Failed writing header to output stream\n"));
+                ret = 1;
+                goto cleanup; /* Bail and try to clean up stuff */
+            }
+        }
+    }
+#endif
+
+    if (opt->with_skeleton) {
+        add_eos_packet_to_stream(&so);
+        if ((ret = flush_ogg_stream_to_file(&so, opt->out))) {
             opt->error(_("Failed writing skeleton eos packet to output stream\n"));
             goto cleanup;
         }
@@ -420,6 +560,53 @@
                     int result = ogg_stream_pageout(&os,&og);
                     if(!result) break;
 
+                    /* now that we have a new Vorbis page, we scan lyrics for any that is due */
+#ifdef HAVE_KATE
+                    if (opt->lyrics && ogg_page_granulepos(&og)>=0) {
+                        vorbis_time = vorbis_granule_time(&vd, ogg_page_granulepos(&og));
+                        const oe_lyrics_item *item;
+                        while ((item = get_lyrics(lyrics, vorbis_time, &lyrics_index))) {
+                            ogg_packet kate_op;
+                            if (item->km) {
+                                ret = kate_encode_set_style_index(&k, 0);
+                                if (ret < 0) {
+                                    opt->error(_("Failed encoding karaoke style - continuing anyway\n"));
+                                }
+                                ret = kate_encode_set_secondary_style_index(&k, 1);
+                                if (ret < 0) {
+                                    opt->error(_("Failed encoding karaoke style - continuing anyway\n"));
+                                }
+                                ret = kate_encode_add_motion(&k, item->km, 0);
+                                if (ret < 0) {
+                                    opt->error(_("Failed encoding karaoke motion - continuing anyway\n"));
+                                }
+                            }
+                            ret = kate_ogg_encode_text(&k, item->t0, item->t1, item->text, strlen(item->text)+1, &kate_op);
+                            if (ret < 0) {
+                                opt->error(_("Failed encoding lyrics - continuing anyway\n"));
+                            }
+                            else {
+                                ogg_stream_packetin(&ko, &kate_op);
+                                ogg_packet_clear(&kate_op);
+                                while (1) {
+                                    ogg_page ogk;
+                                    int result=ogg_stream_flush(&ko,&ogk);
+                                    if (!result) break;
+                                    ret = oe_write_page(&ogk, opt->out);
+                                    if(ret != ogk.header_len + ogk.body_len)
+                                    {
+                                        opt->error(_("Failed writing data to output stream\n"));
+                                        ret = 1;
+                                        goto cleanup; /* Bail */
+                                    }
+                                    else
+                                        bytes_written += ret;
+                                }
+                            }
+                        }
+                    }
+#endif
+
                     ret = oe_write_page(&og, opt->out);
                     if(ret != og.header_len + og.body_len)
                     {
@@ -437,12 +624,58 @@
         }
     }
 
-    ret = 0; /* Success, set return value to 0 since other things reuse it
+    /* if encoding lyrics, signal EOS and cleanup the kate state */
+#ifdef HAVE_KATE
+    if (opt->lyrics) {
+        ogg_packet kate_op;
+        ret = kate_ogg_encode_finish(&k, vorbis_time, &kate_op);
+        if (ret < 0) {
+            opt->error(_("Failed encoding Kate EOS packet\n"));
+        }
+        else {
+            ogg_stream_packetin(&ko,&kate_op);
+            packetsdone++;
+            ogg_packet_clear(&kate_op);
+
+            eos = 0;
+            while(!eos)
+            {
+                int result = ogg_stream_pageout(&ko,&og);
+                if(!result) break;
+
+                ret = oe_write_page(&og, opt->out);
+                if(ret != og.header_len + og.body_len)
+                {
+                    opt->error(_("Failed writing data to output stream\n"));
+                    ret = 1;
+                    goto cleanup; /* Bail */
+                }
+                else
+                    bytes_written += ret;
+
+                if(ogg_page_eos(&og))
+                    eos = 1;
+            }
+        }
+    }
+#endif
+
+    ret = 0; /* Success.  Set return value to 0 since other things reuse it
               * for nefarious purposes. */
 
     /* Cleanup time */
 cleanup:
 
+#ifdef HAVE_KATE
+    if (opt->lyrics) {
+       ogg_stream_clear(&ko);
+        kate_clear(&k);
+        kate_info_clear(&ki);
+        kate_comment_clear(&kc);
+        free_lyrics(lyrics);
+    }
+#endif
+
     ogg_stream_clear(&os);
 
     vorbis_block_clear(&vb);

Modified: trunk/vorbis-tools/oggenc/encode.h
===================================================================
--- trunk/vorbis-tools/oggenc/encode.h	2008-10-12 20:06:55 UTC (rev 15394)
+++ trunk/vorbis-tools/oggenc/encode.h	2008-10-13 19:12:22 UTC (rev 15395)
@@ -54,14 +54,18 @@
     int date_count;
     char **genre;
     int genre_count;
+    char **lyrics;
+    int lyrics_count;
+    char **lyrics_language;
+    int lyrics_language_count;
     adv_opt *advopt;
     int advopt_count;
+
     int copy_comments;
     int with_skeleton;
-
     int quiet;
+    int rawmode;
 
-    int rawmode;
     int raw_samplesize;
     int raw_samplerate;
     int raw_channels;
@@ -70,6 +74,7 @@
     char *namefmt;
     char *namefmt_remove;
     char *namefmt_replace;
+
     char *outfile;
 
     /* All 3 in kbps */
@@ -88,7 +93,8 @@
 
     unsigned int serial;
     unsigned int skeleton_serial;
-        int fixedserial;
+    unsigned int kate_serial;
+    int fixedserial;
     int ignorelength;
 
     int isutf8;
@@ -99,6 +105,7 @@
     vorbis_comment *comments;
     unsigned int serialno;
     unsigned int skeleton_serialno;
+    unsigned int kate_serialno;
 
     audio_read_func read_samples;
     progress_func progress_update;
@@ -131,6 +138,9 @@
     char *filename;
     char *infilename;
     int ignorelength;
+
+    char *lyrics;
+    char *lyrics_language;
 } oe_enc_opt;
 
 

Modified: trunk/vorbis-tools/oggenc/man/oggenc.1
===================================================================
--- trunk/vorbis-tools/oggenc/man/oggenc.1	2008-10-12 20:06:55 UTC (rev 15394)
+++ trunk/vorbis-tools/oggenc/man/oggenc.1	2008-10-13 19:12:22 UTC (rev 15395)
@@ -1,7 +1,7 @@
 .\" Process this file with
 .\" groff -man -Tascii oggenc.1
 .\"
-.TH oggenc 1 "2008 September 9" "Xiph.Org Foundation" "Vorbis Tools"
+.TH oggenc 1 "2008 October 05" "Xiph.Org Foundation" "Vorbis Tools"
 
 .SH NAME
 oggenc \- encode audio into the Ogg Vorbis format
@@ -78,6 +78,14 @@
 .B -G
 .I genre
 ]
+[
+.B -L
+.I lyrics file
+]
+[
+.B -Y
+.I language-string
+]
 .I input_files \fR...
 
 .SH DESCRIPTION
@@ -94,14 +102,20 @@
 .B -o
 option is used to redirect the output.  By default, disk files are
 output to Ogg Vorbis files of the same name, with the extension
-changed to ".ogg".  This naming convention can be overridden by the
+changed to ".ogg" or ".oga".  This naming convention can be overridden
+by the
 .B -o
 option (in the case of one file) or the
 .B -n
 option (in the case of several files). Finally, if none of these
 are available, the output filename will be the input filename with the
 extension (that part after the final dot) replaced with ogg, so file.wav
-will become file.ogg
+will become file.ogg.
+.br
+Optionally, lyrics may be embedded in the Ogg file, if Kate support was compiled in.
+.br
+Note that some old players mail fail to play streams with more than a single Vorbis stream
+(the so called "Vorbis I" simple profile).
 
 .SH OPTIONS
 .IP "-h, --help"
@@ -199,11 +213,35 @@
 .IP "-l album, --album album"
 Set the album comment field to
 .I album.
+
+.IP "-L filename, --lyrics filename"
+Loads lyrics from
+.I filename
+and encodes them into a Kate stream multiplexed with the Vorbis stream.
+Lyrics may be in LRC or SRT format, and should be encoded in UTF-8 or
+plain ASCII. Other encodings may be converted using tools such as iconv
+or recode. Alternatively, the same system as for comments will be used
+for conversion between encodings.
+So called "enhanced LRC" files are supported, and a simple karaoke style
+change will be saved with the lyrics. For more complex karaoke setups,
+.B kateenc(1)
+should be used instead.
+When embedding lyrics, the default output file extention is ".oga".
+
+.IP "-Y language-string, --lyrics-language language-string"
+Sets the language for the corresponding lyrics file to
+.I language-string.
+This should be an ISO 639-1 language code (eg, "en"), or a RFC 3066 language tag
+(eg, "en_US"),
+.B not
+a free form language name. Players will typically recognize this standard tag
+and display the language name in your own language.
+Note that the maximum length of this tag is 15 characters.
 .PP
 
-Note that the \fB-a\fR, \fB-t\fR, and \fB-l\fR options can be given
-multiple times.  They will be applied, one to each file, in the order
-given.  If there are fewer album, title, or artist comments given than
+Note that the \fB-a\fR, \fB-t\fR, \fB-l\fR, \fB-L\fR, and \fB-Y\fR  options
+can be given multiple times.  They will be applied, one to each file, in the
+order given.  If there are fewer album, title, or artist comments given than
 there are input files,
 .B oggenc
 will reuse the final one for the remaining files, and issue a warning
@@ -299,27 +337,27 @@
 .RE
 .PP
 
-Specifying a high-quality encoding averaging 256 kbps (but still VBR).
+Specifying a high-quality encoding averaging 256 kbps (but still VBR):
 .RS
-oggenc infile.wav -b 256 out.ogg
+oggenc infile.wav -b 256 -o out.ogg
 .RE
 .PP
 
-Specifying a maximum and average bitrate, and enforcing these.
+Specifying a maximum and average bitrate, and enforcing these:
 .RS
-oggenc infile.wav --managed -b 128 -M 160 out.ogg
+oggenc infile.wav --managed -b 128 -M 160 -o out.ogg
 .RE
 .PP
 
-Specifying quality rather than bitrate (to a very high quality mode)
+Specifying quality rather than bitrate (to a very high quality mode):
 .RS
-oggenc infile.wav -q 6 out.ogg
+oggenc infile.wav -q 6 -o out.ogg
 .RE
 .PP
 
-Downsampling and downmixing to 11 kHz mono before encoding.
+Downsampling and downmixing to 11 kHz mono before encoding:
 .RS
-oggenc --resample 11025 --downmix infile.wav -q 1 out.ogg
+oggenc --resample 11025 --downmix infile.wav -q 1 -o out.ogg
 .RE
 .PP
 
@@ -331,6 +369,12 @@
 .RE
 .PP
 
+Adding embedded lyrics:
+.RS
+oggenc somefile.wav --lyrics lyrics.lrc --lyrics-language en -o out.oga
+.RE
+.PP
+
 This encodes the three files, each with the
 same artist/album tag, but with different title tags on each one. The
 string given as an argument to -n is used to generate filenames, as shown
@@ -367,4 +411,4 @@
 .SH "SEE ALSO"
 
 .PP
-\fBvorbiscomment\fR(1), \fBogg123\fR(1), \fBflac\fR(1), \fBspeexenc\fR(1), \fBffmpeg2theora\fR(1)
+\fBvorbiscomment\fR(1), \fBogg123\fR(1), \fBoggdec\fR(1), \fBflac\fR(1), \fBspeexenc\fR(1), \fBffmpeg2theora\fR(1), \fBkateenc\fR(1)

Modified: trunk/vorbis-tools/oggenc/oggenc.c
===================================================================
--- trunk/vorbis-tools/oggenc/oggenc.c	2008-10-12 20:06:55 UTC (rev 15394)
+++ trunk/vorbis-tools/oggenc/oggenc.c	2008-10-13 19:12:22 UTC (rev 15395)
@@ -69,6 +69,8 @@
     {"discard-comments", 0, 0, 0},
     {"utf8", 0,0,0},
     {"ignorelength", 0, 0, 0},
+    {"lyrics",1,0,'L'},
+    {"lyrics-language",1,0,'Y'},
     {NULL,0,0,0}
 };
 
@@ -84,10 +86,17 @@
 int main(int argc, char **argv)
 {
     /* Default values */
-    oe_options opt = {NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL,
-              0, NULL, 0, NULL, 0, NULL, 0, 1, 0, 0, 0,16,44100,2, 0, NULL,
-              DEFAULT_NAMEFMT_REMOVE, DEFAULT_NAMEFMT_REPLACE,
-              NULL, 0, -1,-1,-1,.3,-1,0, 0,0.f, 0, 0, 0, 0};
+    oe_options opt = {
+              NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
+              NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
+              1, 0, 0, 0,
+              16,44100,2, 0,
+              NULL, DEFAULT_NAMEFMT_REMOVE, DEFAULT_NAMEFMT_REPLACE,
+              NULL,
+              0, -1,-1,-1,
+              .3,-1,
+              0,0,0.f,
+              0, 0, 0, 0, 0};
 
     int i;
 
@@ -139,6 +148,7 @@
                 srand(time(NULL) ^ getpid());
         opt.serial = rand();
         opt.skeleton_serial = opt.serial + numfiles;
+        opt.kate_serial = opt.skeleton_serial + numfiles;
     }
 
     for(i = 0; i < numfiles; i++)
@@ -153,13 +163,14 @@
         int closeout = 0, closein = 0;
         char *artist=NULL, *album=NULL, *title=NULL, *track=NULL;
         char *date=NULL, *genre=NULL;
+        char *lyrics=NULL, *lyrics_language=NULL;
         input_format *format;
         int resampled = 0;
 
         /* Set various encoding defaults */
 
         enc_opts.serialno = opt.serial++;
-        enc_opts.skeleton_serialno = opt.skeleton_serial++;
+        enc_opts.kate_serialno = opt.kate_serial++;
         enc_opts.progress_update = update_statistics_full;
         enc_opts.start_encode = start_encode_full;
         enc_opts.end_encode = final_statistics;
@@ -173,6 +184,28 @@
         build_comments(&vc, &opt, i, &artist, &album, &title, &track,
                 &date, &genre);
 
+        if(opt.lyrics_count)
+        {
+            if(i >= opt.lyrics_count)
+            {
+                lyrics = NULL;
+            }
+            else
+                lyrics = opt.lyrics[i];
+        }
+
+        if(opt.lyrics_language_count)
+        {
+            if(i >= opt.lyrics_language_count)
+            {
+                if(!opt.quiet)
+                    fprintf(stderr, _("WARNING: Insufficient lyrics languages specified, defaulting to final lyrics language.\n"));
+                lyrics_language = opt.lyrics_language[opt.lyrics_language_count-1];
+            }
+            else
+                lyrics_language = opt.lyrics_language[i];
+        }
+
         if(!strcmp(infiles[i], "-"))
         {
             setbinmode(stdin);
@@ -277,15 +310,20 @@
                 end = strrchr(infiles[i], '.');
                 end = end?end:(start + strlen(infiles[i])+1);
 
-                extension = (opt.with_skeleton) ? ".oga" : ".ogg";
+                /* if adding Skeleton or Kate, we're not Vorbis I anymore */
+                extension = (opt.with_skeleton || opt.lyrics_count>0) ? ".oga" : ".ogg";
                 out_fn = malloc(end - start + 5);
                 strncpy(out_fn, start, end-start);
                 out_fn[end-start] = 0;
                 strcat(out_fn, extension);
             }
             else {
-                fprintf(stderr, _("WARNING: No filename, defaulting to \"default.ogg\"\n"));
-                out_fn = strdup("default.ogg");
+                /* if adding skeleton or kate, we're not Vorbis I anymore */
+                if (opt.with_skeleton || opt.lyrics_count>0)
+                    out_fn = strdup("default.oga");
+                else
+                    out_fn = strdup("default.ogg");
+                fprintf(stderr, _("WARNING: No filename, defaulting to \"%s\"\n"), out_fn);
             }
 
             /* Create any missing subdirectories, if possible */
@@ -343,6 +381,8 @@
         enc_opts.quality_set = opt.quality_set;
         enc_opts.advopt = opt.advopt;
         enc_opts.advopt_count = opt.advopt_count;
+        enc_opts.lyrics = lyrics;
+        enc_opts.lyrics_language = lyrics_language;
 
         if(opt.resamplefreq && opt.resamplefreq != enc_opts.rate) {
             int fromrate = enc_opts.rate;
@@ -477,7 +517,7 @@
     fprintf(stdout, _(
         " --discard-comments   Prevents comments in FLAC and Ogg FLAC files from\n"
         "                      being copied to the output Ogg Vorbis file.\n"
-        " --ignorelength       Ignore the datalength in wav headers. This will allow\n"
+        " --ignorelength       Ignore the datalength in Wave headers. This allows\n"
         "                      support for files > 4GB and STDIN data streams. \n"
         "\n"));
     fprintf(stdout, _(
@@ -511,27 +551,33 @@
         " -a, --artist         Name of artist\n"
         " -G, --genre          Genre of track\n"));
     fprintf(stdout, _(
+        " -L, --lyrics         Include lyrics from given file (.srt or .lrc format)\n"
+        " -Y, --lyrics-language  Sets the language for the lyrics\n"));
+    fprintf(stdout, _(
         "                      If multiple input files are given, then multiple\n"
-        "                      instances of the previous five arguments will be used,\n"
+        "                      instances of the previous eight arguments will be used,\n"
         "                      in the order they are given. If fewer titles are\n"
         "                      specified than files, OggEnc will print a warning, and\n"
         "                      reuse the final one for the remaining files. If fewer\n"
         "                      track numbers are given, the remaining files will be\n"
-        "                      unnumbered. For the others, the final tag will be reused\n"
-        "                      for all others without warning (so you can specify a date\n"
-        "                      once, for example, and have it used for all the files)\n"
+        "                      unnumbered. If fewer lyrics are given, the remaining\n"
+        "                      files will not have lyrics added. For the others, the\n"
+        "                      final tag will be reused for all others without warning\n"
+        "                      (so you can specify a date once, for example, and have\n"
+        "                      it used for all the files)\n"
         "\n"));
     fprintf(stdout, _(
         "INPUT FILES:\n"
-        " OggEnc input files must currently be 24, 16, or 8 bit PCM WAV, AIFF, or AIFF/C\n"
-        " files, 32 bit IEEE floating point WAV, and optionally FLAC or Ogg FLAC. Files\n"
+        " OggEnc input files must currently be 24, 16, or 8 bit PCM Wave, AIFF, or AIFF/C\n"
+        " files, 32 bit IEEE floating point Wave, and optionally FLAC or Ogg FLAC. Files\n"
                 "  may be mono or stereo (or more channels) and any sample rate.\n"
         " Alternatively, the --raw option may be used to use a raw PCM data file, which\n"
-        " must be 16 bit stereo little-endian PCM ('headerless wav'), unless additional\n"
+        " must be 16 bit stereo little-endian PCM ('headerless Wave'), unless additional\n"
         " parameters for raw mode are specified.\n"
         " You can specify taking the file from stdin by using - as the input filename.\n"
         " In this mode, output is to stdout unless an output filename is specified\n"
         " with -o\n"
+        " Lyrics files may be in SubRip (.srt) or LRC (.lrc) format\n"
         "\n"));
 }
 
@@ -643,7 +689,7 @@
     int ret;
     int option_index = 1;
 
-    while((ret = getopt_long(argc, argv, "A:a:b:B:c:C:d:G:hkl:m:M:n:N:o:P:q:QrR:s:t:VX:",
+    while((ret = getopt_long(argc, argv, "A:a:b:B:c:C:d:G:hklL:m:M:n:N:o:P:q:QrR:s:t:VX:Y:",
                     long_options, &option_index)) != -1)
     {
         switch(ret)
@@ -905,6 +951,26 @@
             case 'k':
                 opt->with_skeleton = 1;
                 break;
+            case 'L':
+#ifdef HAVE_KATE
+                opt->lyrics = realloc(opt->lyrics, (++opt->lyrics_count)*sizeof(char *));
+                opt->lyrics[opt->lyrics_count - 1] = strdup(optarg);
+#else
+                fprintf(stderr, _("WARNING: Kate support not compiled in; lyrics will not be included.\n"));
+#endif
+                break;
+            case 'Y':
+#ifdef HAVE_KATE
+                opt->lyrics_language = realloc(opt->lyrics_language, (++opt->lyrics_language_count)*sizeof(char *));
+                opt->lyrics_language[opt->lyrics_language_count - 1] = strdup(optarg);
+                if (strlen(opt->lyrics_language[opt->lyrics_language_count - 1]) > 15) {
+                  fprintf(stderr, _("WARNING: language can not be longer than 15 characters; truncated.\n"));
+                  opt->lyrics_language[opt->lyrics_language_count - 1][15] = 0;
+                }
+#else
+                fprintf(stderr, _("WARNING: Kate support not compiled in; lyrics will not be included.\n"));
+#endif
+                break;
             case '?':
                 fprintf(stderr, _("WARNING: Unknown option specified, ignoring->\n"));
                 break;



More information about the commits mailing list