[easytag/wip/opus-support] Support reading tags from Opus Ogg File



commit 82bf6b5082321b5c03a57b4a41680607c6670df5
Author: Abhinav <abhijangda hotmail com>
Date:   Mon Mar 24 23:45:51 2014 +0530

    Support reading tags from Opus Ogg File

 Makefile.am       |    2 +
 configure.ac      |   21 +++++-
 src/easytag.c     |   18 ++++
 src/et_core.c     |   40 +++++++++
 src/et_core.h     |    5 +
 src/misc.c        |    2 +-
 src/ogg_tag.c     |  247 ++++++++++++++++++++++++++++-------------------------
 src/ogg_tag.h     |    5 +-
 src/opus_header.c |  238 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/opus_header.h |   77 +++++++++++++++++
 src/opus_tag.c    |   88 +++++++++++++++++++
 src/opus_tag.h    |   35 ++++++++
 12 files changed, 659 insertions(+), 119 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 0260c1c..d513cb0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -59,6 +59,8 @@ easytag_SOURCES = \
        src/musepack_header.c \
        src/ogg_header.c \
        src/ogg_tag.c \
+       src/opus_header.c \
+       src/opus_tag.c \
        src/picture.c \
        src/prefs.c \
        src/scan.c \
diff --git a/configure.ac b/configure.ac
index fbe1111..4495ce9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -115,6 +115,9 @@ AC_ARG_ENABLE([id3v23],
 AC_ARG_ENABLE([ogg],
               [AS_HELP_STRING([--disable-ogg], [Disable support for Ogg Vorbis files (default=auto)])])
 
+AC_ARG_ENABLE([opus],
+              [AS_HELP_STRING([--disable-opus], [Disable support for Opus Vorbis files (default=auto)])])
+
 AC_ARG_ENABLE([speex],
               [AS_HELP_STRING([--disable-speex], [Disable support for Ogg Speex files (default=auto)])])
 
@@ -176,6 +179,21 @@ AS_IF([test "x$have_ogg" != "xno"],
              [AC_MSG_ERROR([OGG Vorbis support requested but required dependencies ($OGG_DEPS) not 
found])])])
 
 dnl ################################################
+dnl # Opus libraries
+dnl ################################################
+
+OPUS_DEPS="opus >= 1.0 opusfile"
+AS_IF([test "x$enable_opus" != "xno"],
+      [PKG_CHECK_EXISTS([$OPUS_DEPS], [have_opus=yes], [have_opus=no])],
+      [have_opus=no])
+
+AS_IF([test "x$have_opus" != "xno"],
+      [AC_DEFINE([ENABLE_OPUS], [], [Define for Opus Vorbis support])],
+      [OPUS_DEPS=""
+       AS_IF([test "x$enable_opus" = "xyes"],
+             [AC_MSG_ERROR([OPUS support requested but required dependencies ($OPUS_DEPS) not found])])])
+
+dnl ################################################
 dnl # libSpeex library
 dnl ################################################
 dnl check for system libspeex
@@ -284,7 +302,7 @@ AS_IF([test "x$have_wavpack" != "xno"],
 
 dnl Check the pkg-config dependencies
 GIO_DEPS="gio-2.0 >= 2.32.0" dnl For g_file_new_tmp()
-PKG_CHECK_MODULES([EASYTAG], [$GIO_DEPS $GTK_DEPS $OGG_DEPS $SPEEX_DEPS $FLAC_DEPS $ID3TAG_DEPS $TAGLIB_DEPS 
$WAVPACK_DEPS])
+PKG_CHECK_MODULES([EASYTAG], [$GIO_DEPS $GTK_DEPS $OPUS_DEPS $OGG_DEPS $SPEEX_DEPS $FLAC_DEPS $ID3TAG_DEPS 
$TAGLIB_DEPS $WAVPACK_DEPS])
 
 dnl Check for winsock
 AC_SEARCH_LIBS([gethostbyname], [nsl socket], [],
@@ -363,6 +381,7 @@ echo MP3 file support ........: $have_mp3
 echo ID3v2.3 tags support ....: $have_id3lib $ID3LIB_VERSION
 echo Ogg Vorbis file support .: $have_ogg
 echo Ogg Speex file support ..: $have_speex
+echo Opus file support .......: $have_opus
 echo FLAC file support .......: $have_flac
 echo MP4 file support ........: $have_taglib
 echo WavPack support .........: $have_wavpack
diff --git a/src/easytag.c b/src/easytag.c
index 25b7814..19884ab 100644
--- a/src/easytag.c
+++ b/src/easytag.c
@@ -4071,6 +4071,24 @@ void Tag_Area_Display_Controls (ET_File *ETFile)
             break;
 #endif
 
+#ifdef ENABLE_OPUS
+        case OPUS_TAG:
+            gtk_widget_show(GTK_WIDGET(DiscNumberLabel));
+            gtk_widget_show(GTK_WIDGET(DiscNumberEntry));
+            gtk_widget_show(GTK_WIDGET(ComposerLabel));
+            gtk_widget_show(GTK_WIDGET(ComposerEntry));
+            gtk_widget_show(GTK_WIDGET(OrigArtistLabel));
+            gtk_widget_show(GTK_WIDGET(OrigArtistEntry));
+            gtk_widget_show(GTK_WIDGET(CopyrightLabel));
+            gtk_widget_show(GTK_WIDGET(CopyrightEntry));
+            gtk_widget_show(GTK_WIDGET(URLLabel));
+            gtk_widget_show(GTK_WIDGET(URLEntry));
+            gtk_widget_show(GTK_WIDGET(EncodedByLabel));
+            gtk_widget_show(GTK_WIDGET(EncodedByEntry));
+            et_tag_notebook_show_images_tab (TagNoteBook);
+            break;
+#endif
+
 #ifdef ENABLE_FLAC
         case FLAC_TAG:
             gtk_widget_show(GTK_WIDGET(DiscNumberLabel));
diff --git a/src/et_core.c b/src/et_core.c
index 4dbb1db..c71f81d 100644
--- a/src/et_core.c
+++ b/src/et_core.c
@@ -58,6 +58,10 @@
 #   include "wavpack_header.h"
 #   include "wavpack_tag.h"
 #endif
+#ifdef ENABLE_OPUS
+#   include "opus_tag.h"
+#   include "opus_header.h"
+#endif
 #include "bar.h"
 #include "browser.h"
 #include "log.h"
@@ -525,6 +529,17 @@ GList *ET_Add_File_To_File_List (gchar *filename)
             Wavpack_Tag_Read_File_Tag(filename, FileTag);
         break;
 #endif
+#ifdef ENABLE_OPUS
+        case OPUS_TAG:
+            if (!et_opus_tag_read_file_tag (filename, FileTag, &error))
+            {
+                Log_Print (LOG_ERROR,
+                           _("Error reading tag from opus file (%s)"),
+                           error->message);
+                g_clear_error (&error);
+            }
+            break;
+#endif
         case UNKNOWN_TAG:
         default:
             Log_Print(LOG_ERROR,"FileTag: Undefined tag type (%d) for file 
%s",ETFileDescription->TagType,filename_utf8);
@@ -573,6 +588,16 @@ GList *ET_Add_File_To_File_List (gchar *filename)
             Mp4_Header_Read_File_Info(filename,ETFileInfo);
             break;
 #endif
+#ifdef ENABLE_OPUS
+        case OPUS_FILE:
+            if (!et_opus_read_file_info (filename, ETFileInfo, &error))
+            {
+                Log_Print (LOG_ERROR, _("Error while querying information for file: '%s' (%s)"),
+                           filename_utf8, error->message);
+                g_error_free (error);
+            }
+            break;
+#endif
         case UNKNOWN_FILE:
         default:
             Log_Print(LOG_ERROR,"ETFileInfo: Undefined file type (%d) for file 
%s",ETFileDescription->FileType,filename_utf8);
@@ -2707,6 +2732,12 @@ void ET_Display_File_Data_To_UI (ET_File *ETFile)
             ET_Display_File_Tag_To_UI(ETFile);
             break;
 #endif
+#ifdef ENABLE_OPUS
+        case OPUS_TAG:
+            gtk_frame_set_label(GTK_FRAME(TagFrame),_("Opus Tag"));
+            ET_Display_File_Tag_To_UI(ETFile);
+            break;
+#endif
         case UNKNOWN_TAG:
         default:
             gtk_frame_set_label(GTK_FRAME(TagFrame),_("Tag"));
@@ -2769,6 +2800,12 @@ void ET_Display_File_Data_To_UI (ET_File *ETFile)
             Wavpack_Header_Display_File_Info_To_UI(cur_filename,ETFile->ETFileInfo);
             break;
 #endif
+#ifdef ENABLE_OPUS
+        case OPUS_FILE:
+            gtk_frame_set_label(GTK_FRAME(FileFrame),_("Opus File"));
+            et_opus_header_display_file_info_to_ui (cur_filename, ETFile->ETFileInfo);
+            break;
+#endif
         case UNKNOWN_FILE:
         default:
             gtk_frame_set_label(GTK_FRAME(FileFrame),_("File"));
@@ -3268,6 +3305,9 @@ void ET_Save_File_Data_From_UI (ET_File *ETFile)
 #ifdef ENABLE_WAVPACK
         case WAVPACK_TAG:
 #endif
+#ifdef ENABLE_OPUS
+        case OPUS_TAG:
+#endif
         case APE_TAG:
             ET_Save_File_Tag_From_UI(FileTag);
             ET_Copy_File_Tag_Item_Other_Field(ETFile,FileTag);
diff --git a/src/et_core.h b/src/et_core.h
index c9dc610..7fb5b59 100644
--- a/src/et_core.h
+++ b/src/et_core.h
@@ -110,6 +110,7 @@ typedef enum
     SPEEX_FILE,      // Speech audio files        : .spx
     OFR_FILE,        // OptimFROG (lossless)      : .ofr .ofs
     WAVPACK_FILE,    // Wavpack (lossless)        : .wv
+    OPUS_FILE,       // Opus File                 : .opus
     UNKNOWN_FILE
 } ET_File_Type;
 
@@ -125,6 +126,7 @@ typedef enum
     FLAC_TAG,
     MP4_TAG,
     WAVPACK_TAG,
+    OPUS_TAG,
     UNKNOWN_TAG
 } ET_Tag_Type;
 
@@ -231,6 +233,9 @@ static const ET_File_Description ETFileDescription[] =
     {MP3_FILE,     ".mp3",  ID3_TAG},
     {MP2_FILE,     ".mp2",  ID3_TAG},
 #endif
+#ifdef ENABLE_OPUS
+    {OPUS_FILE,    ".opus", OPUS_TAG},
+#endif
 #ifdef ENABLE_OGG
     {OGG_FILE,     ".ogg",  OGG_TAG},
     {OGG_FILE,     ".oga",  OGG_TAG},
diff --git a/src/misc.c b/src/misc.c
index 721b081..7a6e2ae 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1913,7 +1913,7 @@ void Open_Search_File_Window (void)
                                          N_("Original Artist"),
                                          N_("Copyright"),
                                          N_("URL"),
-                                         N_("Encoded By")
+                                         N_("Endffcoded By")
                                        };
 
 
diff --git a/src/ogg_tag.c b/src/ogg_tag.c
index f544fda..7c400f2 100644
--- a/src/ogg_tag.c
+++ b/src/ogg_tag.c
@@ -176,124 +176,23 @@ read_guint32_from_byte (guchar *str, gsize start)
 }
 
 /*
- * Read tag data into an Ogg Vorbis file.
- * Note:
- *  - if field is found but contains no info (strlen(str)==0), we don't read it
+ * et_add_file_tags_from_vorbis_comments:
+ * @vc: the byte string
+ * @FileTag: position to start with
+ * @filename_utf8: display filename
+ *
+ * Reads vorbis comments and copies them to file tag.
  */
-gboolean
-ogg_tag_read_file_tag (gchar *filename, File_Tag *FileTag, GError **error)
-{
-    GFile *file;
-    GFileInputStream *istream;
-    vcedit_state   *state;
-    vorbis_comment *vc;
-    gchar          *string = NULL;
-    gchar          *string1 = NULL;
-    gchar          *string2 = NULL;
-    gchar *filename_utf8;
-    guint           field_num, i;
-    Picture        *prev_pic = NULL;
-
-    g_return_val_if_fail (filename != NULL && FileTag != NULL, FALSE);
-    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-    file = g_file_new_for_path (filename);
-    istream = g_file_read (file, NULL, error);
-
-    if (!istream)
-    {
-        g_object_unref (file);
-        g_assert (error == NULL || *error != NULL);
-        return FALSE;
-    }
-
-    filename_utf8 = filename_to_display (filename);
-
-    {
-    // Skip the id3v2 tag
-    guchar tmp_id3[4];
-    gulong id3v2size;
-
-    // Check if there is an ID3v2 tag...
-    if (!g_seekable_seek (G_SEEKABLE (istream), 0L, G_SEEK_SET, NULL, error))
-    {
-        goto err;
-    }
-
-    if (g_input_stream_read (G_INPUT_STREAM (istream), tmp_id3, 4, NULL,
-                             error) == 4)
-    {
-        // Calculate ID3v2 length
-        if (tmp_id3[0] == 'I' && tmp_id3[1] == 'D' && tmp_id3[2] == '3' && tmp_id3[3] < 0xFF)
-        {
-            // id3v2 tag skipeer $49 44 33 yy yy xx zz zz zz zz [zz size]
-            /* Size is 6-9 position */
-            if (!g_seekable_seek (G_SEEKABLE (istream), 2, G_SEEK_CUR,
-                                  NULL, error))
-            {
-                goto err;
-            }
-
-            if (g_input_stream_read (G_INPUT_STREAM (istream), tmp_id3, 4,
-                                     NULL, error) == 4)
-            {
-                id3v2size = 10 + ( (long)(tmp_id3[3])        | ((long)(tmp_id3[2]) << 7)
-                                | ((long)(tmp_id3[1]) << 14) | ((long)(tmp_id3[0]) << 21) );
-
-                if (!g_seekable_seek (G_SEEKABLE (istream), id3v2size,
-                                      G_SEEK_SET, NULL, error))
-                {
-                    goto err;
-                }
-
-                Log_Print(LOG_ERROR,_("Warning: The Ogg Vorbis file '%s' contains an ID3v2 
tag."),filename_utf8);
-            }
-            else if (!g_seekable_seek (G_SEEKABLE (istream), 0L, G_SEEK_SET,
-                                       NULL, error))
-            {
-                goto err;
-            }
-
-        }
-        else if (!g_seekable_seek (G_SEEKABLE (istream), 0L, G_SEEK_SET,
-                                   NULL, error))
-        {
-            goto err;
-        }
-
-    }
-    else if (!g_seekable_seek (G_SEEKABLE (istream), 0L, G_SEEK_SET,
-                               NULL, error))
-    {
-        goto err;
-    }
 
-    }
-
-    g_assert (error == NULL || *error == NULL);
-
-    g_object_unref (istream);
-
-    state = vcedit_new_state();    // Allocate memory for 'state'
-
-    if (!vcedit_open (state, file, error))
-    {
-        g_assert (error == NULL || *error != NULL);
-        g_object_unref (file);
-        vcedit_clear(state);
-        g_free (filename_utf8);
-        return FALSE;
-    }
-
-    g_assert (error == NULL || *error == NULL);
-
-    /* Get data from tag */
-    vc = vcedit_comments(state);
-    /*{
-        gint i; 
-        for (i=0;i<vc->comments;i++) 
-            g_print("%s -> Ogg vc:'%s'\n",g_path_get_basename(filename),vc->user_comments[i]);
-    }*/
+void
+et_add_file_tags_from_vorbis_comments (vorbis_comment *vc, File_Tag *FileTag,
+                                       gchar *filename_utf8)
+{
+    gchar *string = NULL;
+    gchar *string1 = NULL;
+    gchar *string2 = NULL;
+    guint field_num, i;
+    Picture *prev_pic = NULL;
 
     /*********
      * Title *
@@ -743,7 +642,123 @@ ogg_tag_read_file_tag (gchar *filename, File_Tag *FileTag, GError **error)
                                            Try_To_Validate_Utf8_String(vc->user_comments[i]));
         }
     }
+}
+
+/*
+ * Read tag data into an Ogg Vorbis file.
+ * Note:
+ *  - if field is found but contains no info (strlen(str)==0), we don't read it
+ */
+gboolean
+ogg_tag_read_file_tag (gchar *filename, File_Tag *FileTag, GError **error)
+{
+    GFile *file;
+    GFileInputStream *istream;
+    vcedit_state   *state;
+    gchar *filename_utf8;
+
+    g_return_val_if_fail (filename != NULL && FileTag != NULL, FALSE);
+    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+    file = g_file_new_for_path (filename);
+    istream = g_file_read (file, NULL, error);
+
+    if (!istream)
+    {
+        g_object_unref (file);
+        g_assert (error == NULL || *error != NULL);
+        return FALSE;
+    }
+
+    filename_utf8 = filename_to_display (filename);
+
+    {
+    // Skip the id3v2 tag
+    guchar tmp_id3[4];
+    gulong id3v2size;
+
+    // Check if there is an ID3v2 tag...
+    if (!g_seekable_seek (G_SEEKABLE (istream), 0L, G_SEEK_SET, NULL, error))
+    {
+        goto err;
+    }
+
+    if (g_input_stream_read (G_INPUT_STREAM (istream), tmp_id3, 4, NULL,
+                             error) == 4)
+    {
+        // Calculate ID3v2 length
+        if (tmp_id3[0] == 'I' && tmp_id3[1] == 'D' && tmp_id3[2] == '3' && tmp_id3[3] < 0xFF)
+        {
+            // id3v2 tag skipeer $49 44 33 yy yy xx zz zz zz zz [zz size]
+            /* Size is 6-9 position */
+            if (!g_seekable_seek (G_SEEKABLE (istream), 2, G_SEEK_CUR,
+                                  NULL, error))
+            {
+                goto err;
+            }
+
+            if (g_input_stream_read (G_INPUT_STREAM (istream), tmp_id3, 4,
+                                     NULL, error) == 4)
+            {
+                id3v2size = 10 + ( (long)(tmp_id3[3])        | ((long)(tmp_id3[2]) << 7)
+                                | ((long)(tmp_id3[1]) << 14) | ((long)(tmp_id3[0]) << 21) );
+
+                if (!g_seekable_seek (G_SEEKABLE (istream), id3v2size,
+                                      G_SEEK_SET, NULL, error))
+                {
+                    goto err;
+                }
+
+                Log_Print(LOG_ERROR,_("Warning: The Ogg Vorbis file '%s' contains an ID3v2 
tag."),filename_utf8);
+            }
+            else if (!g_seekable_seek (G_SEEKABLE (istream), 0L, G_SEEK_SET,
+                                       NULL, error))
+            {
+                goto err;
+            }
+
+        }
+        else if (!g_seekable_seek (G_SEEKABLE (istream), 0L, G_SEEK_SET,
+                                   NULL, error))
+        {
+            goto err;
+        }
+
+    }
+    else if (!g_seekable_seek (G_SEEKABLE (istream), 0L, G_SEEK_SET,
+                               NULL, error))
+    {
+        goto err;
+    }
+
+    }
+
+    g_assert (error == NULL || *error == NULL);
+
+    g_object_unref (istream);
+
+    state = vcedit_new_state();    // Allocate memory for 'state'
+
+    if (!vcedit_open (state, file, error))
+    {
+        g_assert (error == NULL || *error != NULL);
+        g_object_unref (file);
+        vcedit_clear(state);
+        g_free (filename_utf8);
+        return FALSE;
+    }
+
+    g_assert (error == NULL || *error == NULL);
+
+    /* Get data from tag */
+    /*{
+        gint i; 
+        for (i=0;i<vc->comments;i++) 
+            g_print("%s -> Ogg vc:'%s'\n",g_path_get_basename(filename),vc->user_comments[i]);
+    }*/
 
+    et_add_file_tags_from_vorbis_comments (vcedit_comments(state), FileTag,
+                                           filename_utf8);
     vcedit_clear(state);
     g_object_unref (file);
     g_free(filename_utf8);
diff --git a/src/ogg_tag.h b/src/ogg_tag.h
index 620731d..6d62fbe 100644
--- a/src/ogg_tag.h
+++ b/src/ogg_tag.h
@@ -24,6 +24,7 @@
 
 
 #include <glib.h>
+#include "vcedit.h"
 #include "et_core.h"
 
 /**************
@@ -32,6 +33,8 @@
 gboolean ogg_tag_read_file_tag (gchar *filename, File_Tag *FileTag,
                                 GError **error);
 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,
+                                       gchar *filename_utf8);
 
 #endif /* __OGG_TAG_H__ */
diff --git a/src/opus_header.c b/src/opus_header.c
new file mode 100644
index 0000000..e85d6ee
--- /dev/null
+++ b/src/opus_header.c
@@ -0,0 +1,238 @@
+/* opus_header.c - 20014/03/25 */
+/*
+ *  EasyTAG - Tag editor for many file types
+ *  Copyright (C) 2014 Abhinav Jangda (abhijangda hotmail com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h> // For definition of ENABLE_OPUS
+
+#ifdef ENABLE_OPUS
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <errno.h>
+
+#include "easytag.h"
+#include "opus_header.h"
+#include "et_core.h"
+#include "charset.h"
+#include "log.h"
+#include "misc.h"
+
+/*************
+ * Functions *
+ *************/
+
+/*
+ * et_ogg_error_quark:
+ *
+ * To get EtOGGError domain.
+ *
+ * Returns: GQuark for EtOGGError domain
+ */
+GQuark
+et_opus_error_quark (void)
+{
+    return g_quark_from_static_string ("et-opus-error-quark");
+}
+
+/*
+ * et_op_open_file:
+ * @filename: Filepath to open
+ * @error: GError or NULL
+ *
+ * Opens an opus file with path as filename.
+ *
+ * Returns: a OggOpusFile on success or NULL on error.
+ */
+OggOpusFile *
+et_op_open_file (const gchar *filename, GError **error)
+{
+    OggOpusFile *file;
+    int error_val;
+
+    g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+    g_return_val_if_fail (filename != NULL, NULL);
+
+    file = op_open_file (filename, &error_val);
+    if (!file)
+    {
+        /* Got error while opening opus file */
+        switch (error_val)
+        {
+            case OP_EREAD:
+                g_set_error (error, ET_OPUS_ERROR, ET_OPUS_ERROR_READ,
+                             "Error reading file");
+                g_assert (error == NULL || *error != NULL);
+                return NULL;
+
+            case OP_EFAULT:
+                g_set_error (error, ET_OPUS_ERROR, ET_OPUS_ERROR_FAULT,
+                             "Memory allocation failure or internal library error");
+                g_assert (error == NULL || *error != NULL);
+                return NULL;
+
+            case OP_EIMPL:
+                g_set_error (error, ET_OPUS_ERROR, ET_OPUS_ERROR_IMPL,
+                             "Stream used an unimplemented feature");
+                g_assert (error == NULL || *error != NULL);
+                return NULL;
+
+            case OP_EINVAL:
+                g_set_error (error, ET_OPUS_ERROR, ET_OPUS_ERROR_INVAL,
+                             "seek () succeeded on this source but tell () didn't");
+                g_assert (error == NULL || *error != NULL);
+                return NULL;
+
+            case OP_ENOTFORMAT:
+                g_set_error (error, ET_OPUS_ERROR, ET_OPUS_ERROR_NOTFORMAT,
+                             "No logical stream found in a link");
+                g_assert (error == NULL || *error != NULL);
+                return NULL;
+
+            case OP_EBADHEADER:
+                g_set_error (error, ET_OPUS_ERROR, ET_OPUS_ERROR_BADHEADER,
+                             "Corrputed header packet");
+                g_assert (error == NULL || *error != NULL);
+                return NULL;
+
+            case OP_EVERSION:
+                g_set_error (error, ET_OPUS_ERROR, ET_OPUS_ERROR_VERSION,
+                             "ID header contained an unrecognized version number");
+                g_assert (error == NULL || *error != NULL);
+                return NULL;
+
+            case OP_EBADLINK:
+                g_set_error (error, ET_OPUS_ERROR, ET_OPUS_ERROR_BADLINK,
+                             "Corrupted link found");
+                g_assert (error == NULL || *error != NULL);
+                return NULL;
+
+            case OP_EBADTIMESTAMP:
+                g_set_error (error, ET_OPUS_ERROR, ET_OPUS_ERROR_BADTIMESTAMP,
+                             "First/last timestamp in a link failed checks");
+                g_assert (error == NULL || *error != NULL);
+                return NULL;
+        }
+    }
+
+    return file;
+}
+
+/*
+ * et_opus_read_file_info:
+ * @filename: Filepath to read info of
+ * @ETFileInfo: ET_File_Info to put information into
+ * @error: GError or NULL
+ *
+ * Read header information of an Opus file.
+ *
+ * Returns: TRUE if sucessfull otherwise FALSE
+ */
+gboolean
+et_opus_read_file_info (const gchar *filename, ET_File_Info *ETFileInfo,
+                        GError **error)
+{
+    OggOpusFile *file;
+    const OpusHead* head;
+
+    g_return_val_if_fail (filename != NULL && ETFileInfo != NULL, FALSE);
+    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+    file = et_op_open_file (filename, error);
+    if (!file)
+    {
+        g_assert (error == NULL || *error != NULL);
+        return FALSE;
+    }
+
+    head = op_head (file, -1);
+    ETFileInfo->version    = head->version;
+    ETFileInfo->bitrate    = op_bitrate (file, -1);
+    ETFileInfo->samplerate = head->input_sample_rate;
+    ETFileInfo->mode       = head->channel_count;
+    ETFileInfo->size       = et_get_file_size (filename);
+    ETFileInfo->duration   = op_pcm_total (file, -1);
+    op_free (file);
+
+    g_assert (error == NULL || *error == NULL);
+    return TRUE;
+}
+
+/*
+ * et_opus_header_display_file_info_to_ui:
+ * @filename: Filename to display info of
+ * @ETFileInfo: ET_File_Info to display information
+ *
+ * Display header info from ET_File_Info.
+ *
+ * Returns: TRUE if successfull otherwise FALSE
+ */
+gboolean
+et_opus_header_display_file_info_to_ui (gchar *filename,
+                                        ET_File_Info *ETFileInfo)
+{
+    gchar *text;
+    gchar *time = NULL;
+    gchar *time1 = NULL;
+    gchar *size = NULL;
+    gchar *size1 = NULL;
+
+    /* Encoder version */
+    gtk_label_set_text(GTK_LABEL(VersionLabel),_("Encoder:"));
+    text = g_strdup_printf("%d",ETFileInfo->version);
+    gtk_label_set_text(GTK_LABEL(VersionValueLabel),text);
+    g_free(text);
+
+    /* Bitrate */
+    text = g_strdup_printf(_("%d kb/s"),ETFileInfo->bitrate);
+    gtk_label_set_text(GTK_LABEL(BitrateValueLabel),text);
+    g_free(text);
+
+    /* Samplerate */
+    text = g_strdup_printf(_("%d Hz"),ETFileInfo->samplerate);
+    gtk_label_set_text(GTK_LABEL(SampleRateValueLabel),text);
+    g_free(text);
+
+    /* Mode */
+    gtk_label_set_text(GTK_LABEL(ModeLabel),_("Channels:"));
+    text = g_strdup_printf("%d",ETFileInfo->mode);
+    gtk_label_set_text(GTK_LABEL(ModeValueLabel),text);
+    g_free(text);
+
+    /* Size */
+    size  = g_format_size (ETFileInfo->size);
+    size1 = g_format_size (ETCore->ETFileDisplayedList_TotalSize);
+    text  = g_strdup_printf("%s (%s)",size,size1);
+    gtk_label_set_text(GTK_LABEL(SizeValueLabel),text);
+    g_free(size);
+    g_free(size1);
+    g_free(text);
+
+    /* Duration */
+    time  = Convert_Duration(ETFileInfo->duration);
+    time1 = Convert_Duration(ETCore->ETFileDisplayedList_TotalDuration);
+    text  = g_strdup_printf("%s (%s)",time,time1);
+    gtk_label_set_text(GTK_LABEL(DurationValueLabel),text);
+    g_free(time);
+    g_free(time1);
+    g_free(text);
+
+    return TRUE;
+}
+
+#endif /* ENABLE_OPUS */
diff --git a/src/opus_header.h b/src/opus_header.h
new file mode 100644
index 0000000..87b5781
--- /dev/null
+++ b/src/opus_header.h
@@ -0,0 +1,77 @@
+/* opus_header.h - 20014/03/25 */
+/*
+ *  EasyTAG - Tag editor for many file types
+ *  Copyright (C) 2014 Abhinav Jangda (abhijangda hotmail com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __OPUS_HEADER_H__
+#define __OPUS_HEADER_H__
+
+#include <glib.h>
+#include <opus/opusfile.h>
+
+#include "et_core.h"
+
+/*
+ * Error domain and codes for errors while reading/writing Opus files
+ */
+GQuark et_opus_error_quark (void);
+
+#define ET_OPUS_ERROR et_opus_error_quark ()
+
+/*
+ * EtOPUSError:
+ * @ET_OPUS_ERROR_READ: Error reading file
+ * @ET_OPUS_ERROR_FAULT: Memory allocation failure or internal library error
+ * @ET_OPUS_ERROR_IMPL: Stream used an unimplemented feature
+ * @ET_OPUS_ERROR_INVAL: seek () succeeded on this source but tell () didn't
+ * @ET_OPUS_ERROR_NOTFORMAT: No logical stream found in a link
+ * @ET_OPUS_ERROR_BADHEADER: Corrputed header packet
+ * @ET_OPUS_ERROR_VERSION: ID header contained an unrecognized version number
+ * @ET_OPUS_ERROR_BADLINK: Corrupted link found
+ * @ET_OPUS_ERROR_BADTIMESTAMP: First/last timestamp in a link failed checks
+ *
+ * Errors that can occur when reading OPUS files.
+ */
+typedef enum
+{
+    ET_OPUS_ERROR_READ,
+    ET_OPUS_ERROR_FAULT,
+    ET_OPUS_ERROR_IMPL,
+    ET_OPUS_ERROR_INVAL,
+    ET_OPUS_ERROR_NOTFORMAT,
+    ET_OPUS_ERROR_BADHEADER,
+    ET_OPUS_ERROR_VERSION,
+    ET_OPUS_ERROR_BADLINK,
+    ET_OPUS_ERROR_BADTIMESTAMP,
+} EtOggError;
+
+/**************
+ * Prototypes *
+ **************/
+
+gboolean
+et_opus_read_file_info (const gchar *filename,
+                        ET_File_Info *ETFileInfo,
+                        GError **error);
+OggOpusFile *
+et_op_open_file (const gchar *filename, GError **error);
+gboolean
+et_opus_header_display_file_info_to_ui (gchar *filename,
+                                        ET_File_Info *ETFileInfo);
+
+#endif /* __OPUS_HEADER_H__ */
diff --git a/src/opus_tag.c b/src/opus_tag.c
new file mode 100644
index 0000000..2be35d5
--- /dev/null
+++ b/src/opus_tag.c
@@ -0,0 +1,88 @@
+/* opus_tag.c - 2014/03/25 */
+/*
+ *  EasyTAG - Tag editor for MP3 and Ogg Vorbis files
+ *  Copyright (C) 2014 Abhinav Jangda (abhijangda hotmail com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h" // For definition of ENABLE_OPUS
+
+#ifdef ENABLE_OPUS
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <opus/opus.h>
+#include <vorbis/codec.h>
+
+#include "easytag.h"
+#include "opus_tag.h"
+#include "opus_header.h"
+#include "ogg_tag.h"
+#include "et_core.h"
+#include "log.h"
+#include "misc.h"
+#include "picture.h"
+#include "setting.h"
+#include "charset.h"
+
+#define MULTIFIELD_SEPARATOR " - "
+
+/*
+ * et_opus_tag_read_file_tag:
+ * @filename: Filename to read tags of
+ * @FileTag: File_Tag to read tag into
+ * @error: GError or NULL
+ *
+ * Read file tags and store int File_Tag.
+ *
+ * Returns: TRUE if successfull otherwise FALSE
+ */
+gboolean
+et_opus_tag_read_file_tag (gchar *filename, File_Tag *FileTag,
+                           GError **error)
+{
+    OggOpusFile *file;
+    const OpusTags *tags;
+    gchar *filename_utf8;
+
+    g_return_val_if_fail (filename != NULL && FileTag != NULL, FALSE);
+    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+    file = et_op_open_file (filename, error);
+    if (!file)
+    {
+        g_assert (error == NULL || *error != NULL);
+        return FALSE;
+    }
+
+    tags = op_tags (file, 0);
+    filename_utf8 = filename_to_display (filename);
+
+    et_add_file_tags_from_vorbis_comments ((vorbis_comment *)tags, FileTag,
+                                           filename_utf8);
+    op_free (file);
+    g_free(filename_utf8);
+
+    g_assert (error == NULL || *error == NULL);
+    return TRUE;
+}
+
+#endif
diff --git a/src/opus_tag.h b/src/opus_tag.h
new file mode 100644
index 0000000..1a49c4f
--- /dev/null
+++ b/src/opus_tag.h
@@ -0,0 +1,35 @@
+/* opus_tag.h - 2014/04/25 */
+/*
+ *  EasyTAG - Tag editor for MP3 and Ogg Vorbis files
+ *  Copyright (C) 2014 Abhinav Jangda (abhijangda hotmail com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __OPUS_TAG_H__
+#define __OPUS_TAG_H__
+
+#include <glib.h>
+#include "et_core.h"
+
+/**************
+ * Prototypes *
+ **************/
+
+gboolean
+et_opus_tag_read_file_tag (gchar *filename, File_Tag *FileTag,
+                           GError **error);
+
+#endif /* __OPUS_TAG_H__ */


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