[easytag/wip/opus-support: 9/9] Support for writing tags to Ogg Opus files



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

    Support for writing tags to Ogg Opus files
    
    https://bugzilla.gnome.org/show_bug.cgi?id=692389

 src/et_core.c |    5 +++
 src/ogg_tag.h |    3 +-
 src/vcedit.c  |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 src/vcedit.h  |   10 ++++++-
 4 files changed, 90 insertions(+), 9 deletions(-)
---
diff --git a/src/et_core.c b/src/et_core.c
index 1e67a78..242ffdc 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_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..8b3f2b2 100644
--- a/src/vcedit.c
+++ b/src/vcedit.c
@@ -66,6 +66,13 @@ static void vcedit_clear_internals(vcedit_state *state)
         vorbis_info_clear(state->vi);
         free(state->vi);
     }
+#ifdef ENABLE_OPUS
+    if (state->oi)
+    {
+        g_free (state->oi);
+    }
+#endif /* ENABLE_OPUS */
+
     g_object_unref (state->in);
     memset(state, 0, sizeof(*state));
 }
@@ -104,6 +111,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 +364,29 @@ 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 +407,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 +465,33 @@ 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_ERROR_HEADER,
+                                                 "Ogg Opus tags do not start with \"OpusTags\"");
+                                    goto err;
+                                    break;
+
+                                case OP_EFAULT:
+                                    g_set_error (error, ET_OGG_ERROR,
+                                                 ET_OGG_ERROR_HEADER,
+                                                 "Not enough memory to store Ogg Opus tags");
+                                    goto err;
+                                    break;
+
+                                case OP_EBADHEADER:
+                                    g_set_error (error, ET_OGG_ERROR,
+                                                 ET_OGG_ERROR_HEADER,
+                                                 "Ogg Opus tags do not follow the specification");
+                                    goto err;
+                                    break;
+                            }
                     }
                     i++;
                 }
@@ -530,7 +588,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 +676,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]