[easytag/wip/opus-support] Add support for writing Opus Tags



commit 98041266aa2cdb4a6b1cab387ad7356e41d922fb
Author: Abhinav <abhijangda hotmail com>
Date:   Sat Mar 29 21:32:58 2014 +0530

    Add support for writing Opus Tags

 src/et_core.c    |    5 +++
 src/ogg_header.h |    9 +++++-
 src/ogg_tag.h    |    3 +-
 src/vcedit.c     |   73 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 src/vcedit.h     |   10 ++++++-
 5 files changed, 89 insertions(+), 11 deletions(-)
---
diff --git a/src/et_core.c b/src/et_core.c
index 9154c7e..82885c5 100644
--- a/src/et_core.c
+++ b/src/et_core.c
@@ -4009,6 +4009,11 @@ gboolean ET_Save_File_Tag_To_HD (ET_File *ETFile)
             state = Wavpack_Tag_Write_File_Tag(ETFile);
             break;
 #endif
+#ifdef ENABLE_OPUS
+        case OPUS_TAG:
+            state = ogg_tag_write_file_tag (ETFile, &error);
+            break;
+#endif
         case UNKNOWN_TAG:
         default:
             Log_Print(LOG_ERROR,"Saving to HD: Undefined function for tag type '%d' (file %s).",
diff --git a/src/ogg_header.h b/src/ogg_header.h
index 0817a31..df916fe 100644
--- a/src/ogg_header.h
+++ b/src/ogg_header.h
@@ -52,7 +52,9 @@ GQuark et_ogg_error_quark (void);
  * @ET_OGG_ERROR_VORBIS: eof before end of Vorbis headers
  * @ET_OGG_ERROR_FAILED: corrupt or missing data
  * @ET_OGG_ERROR_OUTPUT: error writing stream to output
- *
+ * @ET_OGG_OPUS_HEADER_ERROR_FORMAT: Ogg Opus Tags does not starts with "OpusTags"
+ * @ET_OGG_OPUS_HEADER_ERROR_FAULT: not enough memory to store Ogg Opus Tags
+ * @ET_OGG_OPUS_HEADER_ERROR_BADHEADER: Ogg Opus Tags doesnot follow specifications
  * Errors that can occur when reading OGG files.
  */
 typedef enum
@@ -69,7 +71,10 @@ typedef enum
     ET_OGG_ERROR_EXTRA,
     ET_OGG_ERROR_VORBIS,
     ET_OGG_ERROR_FAILED,
-    ET_OGG_ERROR_OUTPUT
+    ET_OGG_ERROR_OUTPUT,
+    ET_OGG_OPUS_HEADER_ERROR_FORMAT,
+    ET_OGG_OPUS_HEADER_ERROR_FAULT,
+    ET_OGG_OPUS_HEADER_ERROR_BADHEADER
 } EtOGGError;
 
 /**************
diff --git a/src/ogg_tag.h b/src/ogg_tag.h
index e37eb77..f2137c1 100644
--- a/src/ogg_tag.h
+++ b/src/ogg_tag.h
@@ -36,5 +36,6 @@ gboolean ogg_tag_write_file_tag (ET_File *ETFile, GError **error);
 void
 et_add_file_tags_from_vorbis_comments (vorbis_comment *vc, File_Tag *FileTag,
                                        const gchar *filename_utf8);
-
+void
+et_add_vorbis_comments_from_file_tags (vorbis_comment *vc, File_Tag *FileTag);
 #endif /* __OGG_TAG_H__ */
diff --git a/src/vcedit.c b/src/vcedit.c
index b407257..5edd9f0 100644
--- a/src/vcedit.c
+++ b/src/vcedit.c
@@ -66,6 +66,11 @@ static void vcedit_clear_internals(vcedit_state *state)
         vorbis_info_clear(state->vi);
         free(state->vi);
     }
+    if (state->oi)
+    {
+        g_free (state->oi);
+    }
+
     g_object_unref (state->in);
     memset(state, 0, sizeof(*state));
 }
@@ -104,6 +109,12 @@ static int _commentheader_out(vcedit_state *state, ogg_packet *op)
         oggpack_write(&opb,0x03,8);
         _v_writestring(&opb,"vorbis", 6);
     }
+#ifdef ENABLE_OPUS
+    else if (state->oggtype == VCEDIT_IS_OPUS)
+    {        
+        _v_writestring(&opb,"OpusTags", 8);
+    }
+#endif
 
     /* vendor */
     oggpack_write(&opb,strlen(vendor),32);
@@ -351,16 +362,26 @@ vcedit_open(vcedit_state *state, GFile *file, GError **error)
     {
         state->oggtype = VCEDIT_IS_OGGVORBIS;
     }
-#ifdef ENABLE_SPEEX
     else
     {
+#ifdef ENABLE_SPEEX
         // Done after "Ogg test" to avoid to display an error message in function
         // speex_packet_to_header when the file is not Speex.
         state->si = malloc(sizeof(SpeexHeader));
         if((state->si = speex_packet_to_header((char*)(&header_main)->packet,(&header_main)->bytes)))
             state->oggtype = VCEDIT_IS_SPEEX;
-    }
 #endif
+#ifdef ENABLE_OPUS
+        if (state->oggtype == VCEDIT_IS_UNKNOWN)
+        {
+            state->oi = g_malloc (sizeof (OpusHead));
+            if (opus_head_parse (state->oi,
+                                 (unsigned char*)(&header_main)->packet,
+                                 (&header_main)->bytes) == 0)
+                state->oggtype = VCEDIT_IS_OPUS;
+        }
+#endif
+    }
 
     if (state->oggtype == VCEDIT_IS_UNKNOWN)
     {
@@ -381,6 +402,11 @@ vcedit_open(vcedit_state *state, GFile *file, GError **error)
             headerpackets = 2 + state->si->extra_headers;
             break;
 #endif
+#ifdef ENABLE_OPUS
+        case VCEDIT_IS_OPUS:
+            header = &header_comments;
+            headerpackets = 2;
+#endif
     }
     i = 1;
     while(i<headerpackets)
@@ -434,6 +460,30 @@ vcedit_open(vcedit_state *state, GFile *file, GError **error)
                                     goto err;
                                     break;
                             }
+                            break;
+                        case VCEDIT_IS_OPUS:
+                            switch (opus_tags_parse ((OpusTags *)state->vc,
+                                                 header->packet,
+                                                 header->bytes))
+                            {
+                                case OP_ENOTFORMAT:
+                                    g_set_error (error, ET_OGG_ERROR,
+                                                 ET_OGG_OPUS_HEADER_ERROR_FORMAT,
+                                                 "Ogg Opus Tags does not starts with \"OpusTags\"");
+                                    goto err;
+
+                                case OP_EFAULT:
+                                    g_set_error (error, ET_OGG_ERROR,
+                                                 ET_OGG_OPUS_HEADER_ERROR_FAULT,
+                                                 "Not enough memory to store Ogg Opus Tags");
+                                    goto err;
+
+                                case OP_EBADHEADER:
+                                    g_set_error (error, ET_OGG_ERROR,
+                                                 ET_OGG_OPUS_HEADER_ERROR_BADHEADER,
+                                                 "Ogg Opus Tags doesnot follow specifications");
+                                    goto err;
+                            }
                     }
                     i++;
                 }
@@ -530,7 +580,7 @@ vcedit_write(vcedit_state *state, GFile *file, GError **error)
     ogg_stream_packetin(&streamout, &header_main);
     ogg_stream_packetin(&streamout, &header_comments);
 
-    if (state->oggtype != VCEDIT_IS_SPEEX)
+    if (state->oggtype == VCEDIT_IS_OGGVORBIS)
         ogg_stream_packetin(&streamout, &header_codebooks);
 
     while((result = ogg_stream_flush(&streamout, &ogout)))
@@ -618,11 +668,20 @@ vcedit_write(vcedit_state *state, GFile *file, GError **error)
 
         needflush=needout=0;
 
-        if (state->oggtype == VCEDIT_IS_OGGVORBIS)
+        if (state->oggtype == VCEDIT_IS_OGGVORBIS ||
+            state->oggtype == VCEDIT_IS_OPUS)
         {
-            int size;
-            size = _blocksize(state, &op);
-            granpos += size;
+            if (state->oggtype == VCEDIT_IS_OGGVORBIS)
+            {
+                int size;
+                size = _blocksize(state, &op);
+                granpos += size;
+            }
+            else
+            {
+                granpos += opus_packet_get_samples_per_frame (op.packet,
+                                                              48000);
+            }
 
             if(op.granulepos == -1)
             {
diff --git a/src/vcedit.h b/src/vcedit.h
index e14d050..3c25eb8 100644
--- a/src/vcedit.h
+++ b/src/vcedit.h
@@ -19,6 +19,11 @@ extern "C" {
 #include <ogg/ogg.h>
 #include <vorbis/codec.h>
 
+#ifdef ENABLE_OPUS
+#include <opus/opus.h>
+#include <opus/opusfile.h>
+#endif
+
 #ifdef ENABLE_SPEEX
 #include <speex/speex.h>
 #include <speex/speex_header.h>
@@ -27,6 +32,7 @@ extern "C" {
 #define VCEDIT_IS_UNKNOWN   0
 #define VCEDIT_IS_SPEEX     1
 #define VCEDIT_IS_OGGVORBIS 2
+#define VCEDIT_IS_OPUS      3
 
 typedef struct {
     ogg_sync_state      *oy;
@@ -38,7 +44,9 @@ typedef struct {
 #ifdef ENABLE_SPEEX
     SpeexHeader         *si;
 #endif
-
+#ifdef ENABLE_OPUS
+    OpusHead            *oi;
+#endif
     GFileInputStream    *in;
     long        serial;
     unsigned char   *mainbuf;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]