[easytag] Support reading tags from Ogg Opus files
- From: David King <davidk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [easytag] Support reading tags from Ogg Opus files
- Date: Wed, 2 Apr 2014 17:00:55 +0000 (UTC)
commit c636cd01eca6cdc4d741050790ac00354014d7a4
Author: Abhinav <abhijangda hotmail com>
Date: Mon Mar 24 23:45:51 2014 +0530
Support reading tags from Ogg Opus files
https://bugzilla.gnome.org/show_bug.cgi?id=692389
Makefile.am | 5 +
README | 3 +-
configure.ac | 21 ++++-
po/POTFILES.in | 1 +
src/easytag.c | 18 ++++
src/et_core.c | 48 ++++++++++-
src/et_core.h | 5 +
src/ogg_tag.c | 247 ++++++++++++++++++++++++++++-------------------------
src/ogg_tag.h | 5 +-
src/opus_header.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/opus_header.h | 65 ++++++++++++++
src/opus_tag.c | 96 ++++++++++++++++++++
src/opus_tag.h | 31 +++++++
13 files changed, 675 insertions(+), 120 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 0260c1c..42529cf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,6 +5,7 @@ DISTCHECK_CONFIGURE_FLAGS = \
--enable-flac \
--enable-id3v23 \
--enable-ogg \
+ --enable-opus \
--enable-man \
--enable-mp3 \
--enable-mp4 \
@@ -59,6 +60,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 \
@@ -98,6 +101,8 @@ easytag_headers = \
src/musepack_header.h \
src/ogg_header.h \
src/ogg_tag.h \
+ src/opus_header.h \
+ src/opus_tag.h \
src/picture.h \
src/prefs.h \
src/scan.h \
diff --git a/README b/README
index df9af68..0e16fe7 100644
--- a/README
+++ b/README
@@ -57,8 +57,9 @@ Installation
* GLib version greater than 2.30.0 (http://www.gtk.org)
* GTK+ version greater than 2.24.0 (http://www.gtk.org)
* id3lib version greater than 3.7.12 (http://id3lib.sourceforge.net) (Recommended: id3lib-3.8.3)
-* libogg and libvorbis (http://www.vorbis.com) (if not deactivated by './configure --disable-ogg')
* flac (http://flac.sourceforge.net) (if not deactivated by './configure --disable-flac')
+* libogg and libvorbis (http://www.vorbis.com) (if not deactivated by './configure --disable-ogg')
+* opus and opusfile (http://www.opus-codec.org/) (if not deactivated by './configure --disable-opus')
* taglib (http://taglib.github.com/) (if not deactivated by './configure --disable-mp4')
* wavpack (http://www.wavpack.com/) (if not deactivated by './configure --disable-wavpack')
* yelp-tools (https://git.gnome.org/browse/yelp-tools)
diff --git a/configure.ac b/configure.ac
index daf0cf9..4d1a635 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 Ogg Opus 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 Ogg 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/po/POTFILES.in b/po/POTFILES.in
index 2270e4d..9af196d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -22,6 +22,7 @@ src/mpeg_header.c
src/musepack_header.c
src/ogg_header.c
src/ogg_tag.c
+src/opus_header.c
src/picture.c
src/prefs.c
src/scan.c
diff --git a/src/easytag.c b/src/easytag.c
index 7612a55..9d8aebd 100644
--- a/src/easytag.c
+++ b/src/easytag.c
@@ -4070,6 +4070,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..bc834d5 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"
@@ -463,6 +467,8 @@ GList *ET_Add_File_To_File_List (gchar *filename)
if (!filename)
return ETCore->ETFileList;
+ file = g_file_new_for_path (filename);
+
/* Primary Key for this file */
ETFileKey = ET_File_Key_New();
@@ -525,6 +531,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 (file, 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 +590,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 (file, 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);
@@ -592,7 +619,6 @@ GList *ET_Add_File_To_File_List (gchar *filename)
/* Store the modification time of the file to check if the file was changed
* before saving */
- file = g_file_new_for_path (filename);
fileinfo = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED,
G_FILE_QUERY_INFO_NONE, NULL, NULL);
g_object_unref (file);
@@ -2652,6 +2678,9 @@ void ET_Display_File_Data_To_UI (ET_File *ETFile)
gchar *cur_filename;
gchar *cur_filename_utf8;
gchar *msg;
+#ifdef ENABLE_OPUS
+ GFile *file;
+#endif
g_return_if_fail (ETFile != NULL &&
((GList *)ETFile->FileNameCur)->data != NULL);
@@ -2707,6 +2736,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 +2804,14 @@ 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"));
+ file = g_file_new_for_path (cur_filename);
+ et_opus_header_display_file_info_to_ui (file, ETFile->ETFileInfo);
+ g_object_unref (file);
+ break;
+#endif
case UNKNOWN_FILE:
default:
gtk_frame_set_label(GTK_FRAME(FileFrame),_("File"));
@@ -3268,6 +3311,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 9d3fa11..d5e67fe 100644
--- a/src/et_core.h
+++ b/src/et_core.h
@@ -107,6 +107,7 @@ typedef enum
SPEEX_FILE, // Speech audio files : .spx
OFR_FILE, // OptimFROG (lossless) : .ofr .ofs
WAVPACK_FILE, // Wavpack (lossless) : .wv
+ OPUS_FILE, /* Ogg Opus File: .opus */
UNKNOWN_FILE
} ET_File_Type;
@@ -122,6 +123,7 @@ typedef enum
FLAC_TAG,
MP4_TAG,
WAVPACK_TAG,
+ OPUS_TAG,
UNKNOWN_TAG
} ET_Tag_Type;
@@ -228,6 +230,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/ogg_tag.c b/src/ogg_tag.c
index f544fda..df2ee7f 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,
+ const 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..e37eb77 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,
+ const 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..61bbfc8
--- /dev/null
+++ b/src/opus_header.c
@@ -0,0 +1,250 @@
+/* EasyTAG - tag editor for audio 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 <errno.h>
+
+#include "easytag.h"
+#include "opus_header.h"
+#include "et_core.h"
+#include "charset.h"
+#include "log.h"
+#include "misc.h"
+
+/*
+ * et_opus_error_quark:
+ *
+ * To get EtOpusError domain.
+ *
+ * Returns: GQuark for EtOpusError domain
+ */
+GQuark
+et_opus_error_quark (void)
+{
+ return g_quark_from_static_string ("et-opus-error-quark");
+}
+
+/*
+ * et_opus_open_file:
+ * @filename: Filepath to open
+ * @error: GError or %NULL
+ *
+ * Opens an Opus file.
+ *
+ * Returns: a OggOpusFile on success or %NULL on error.
+ */
+OggOpusFile *
+et_opus_open_file (GFile *gfile, GError **error)
+{
+ OggOpusFile *file;
+ gchar *path;
+ int error_val;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ g_return_val_if_fail (gfile != NULL, NULL);
+
+ path = g_file_get_path (gfile);
+ file = op_open_file (path, &error_val);
+ g_free (path);
+
+ 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 () did not");
+ 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,
+ "Corrupted 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:
+ * @file: file to read info from
+ * @ETFileInfo: ET_File_Info to put information into
+ * @error: a GError or %NULL
+ *
+ * Read header information of an Opus file.
+ *
+ * Returns: %TRUE if successful otherwise %FALSE
+ */
+gboolean
+et_opus_read_file_info (GFile *gfile, ET_File_Info *ETFileInfo,
+ GError **error)
+{
+ OggOpusFile *file;
+ const OpusHead* head;
+ GFileInfo *info;
+
+ g_return_val_if_fail (gfile != NULL && ETFileInfo != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ file = et_opus_open_file (gfile, error);
+ if (!file)
+ {
+ g_assert (error == NULL || *error != NULL);
+ return FALSE;
+ }
+
+ info = g_file_query_info (gfile, G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ G_FILE_QUERY_INFO_NONE, NULL, NULL);
+
+ 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;
+
+ if (info)
+ {
+ ETFileInfo->size = g_file_info_get_size (info);
+ g_object_unref (info);
+ }
+ else
+ {
+ ETFileInfo->size = 0;
+ }
+
+ 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: file to display info of
+ * @ETFileInfo: ET_File_Info to display information
+ *
+ * Display header info from ET_File_Info.
+ *
+ * Returns: %TRUE if successful, otherwise %FALSE
+ */
+gboolean
+et_opus_header_display_file_info_to_ui (GFile *file,
+ 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..8feb0f6
--- /dev/null
+++ b/src/opus_header.h
@@ -0,0 +1,65 @@
+/* EasyTAG - tag editor for audio 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 ET_OPUS_HEADER_H_
+#define ET_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,
+} EtOpusError;
+
+gboolean et_opus_read_file_info (GFile *gfile, ET_File_Info *ETFileInfo, GError **error);
+OggOpusFile * et_opus_open_file (GFile *gfile, GError **error);
+gboolean et_opus_header_display_file_info_to_ui (GFile *gfile, ET_File_Info *ETFileInfo);
+
+#endif /* ET_OPUS_HEADER_H_ */
diff --git a/src/opus_tag.c b/src/opus_tag.c
new file mode 100644
index 0000000..c28addf
--- /dev/null
+++ b/src/opus_tag.c
@@ -0,0 +1,96 @@
+/* EasyTAG - tag editor for audio 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: file from which to read tags
+ * @FileTag: File_Tag to read tag into
+ * @error: a GError or %NULL
+ *
+ * Read file tags and store into File_Tag.
+ *
+ * Returns: %TRUE if successful otherwise %FALSE
+ */
+gboolean
+et_opus_tag_read_file_tag (GFile *gfile, File_Tag *FileTag,
+ GError **error)
+{
+ OggOpusFile *file;
+ const OpusTags *tags;
+ GFileInfo *info;
+
+ g_return_val_if_fail (gfile != NULL && FileTag != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ file = et_opus_open_file (gfile, error);
+
+ if (!file)
+ {
+ g_assert (error == NULL || *error != NULL);
+ return FALSE;
+ }
+
+ tags = op_tags (file, 0);
+ info = g_file_query_info (gfile, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ G_FILE_QUERY_INFO_NONE, NULL, error);
+
+ if (!info)
+ {
+ op_free (file);
+ g_assert (error == NULL || *error != NULL);
+ return FALSE;
+ }
+
+ /* The cast is safe according to the opusfile documentation. */
+ et_add_file_tags_from_vorbis_comments ((vorbis_comment *)tags, FileTag,
+ g_file_info_get_display_name (info));
+ g_object_unref (info);
+ op_free (file);
+
+ 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..e012727
--- /dev/null
+++ b/src/opus_tag.h
@@ -0,0 +1,31 @@
+/* EasyTAG - tag editor for audio 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 ET_OPUS_TAG_H_
+#define ET_OPUS_TAG_H_
+
+#include <glib.h>
+#include "et_core.h"
+
+G_BEGIN_DECLS
+
+gboolean et_opus_tag_read_file_tag (GFile *file, File_Tag *FileTag, GError **error);
+
+G_END_DECLS
+
+#endif /* ET_OPUS_TAG_H_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]