[easytag/wip/dsf-support: 3/8] Read DSF header information
- From: David King <davidk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [easytag/wip/dsf-support: 3/8] Read DSF header information
- Date: Thu, 20 Nov 2014 23:07:28 +0000 (UTC)
commit 0db1a474f71ccae24f63f7fe4fa2d246a158bbe8
Author: David King <amigadave amigadave com>
Date: Sun Nov 9 00:01:55 2014 +0000
Read DSF header information
https://bugzilla.gnome.org/show_bug.cgi?id=708368
Makefile.am | 2 +
po/POTFILES.in | 1 +
src/et_core.c | 10 ++
src/et_core.h | 1 +
src/tags/dsf_header.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++++
src/tags/dsf_header.h | 32 ++++++
6 files changed, 298 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 4c1a261..0fc9d46 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -70,6 +70,7 @@ easytag_SOURCES = \
src/tags/libapetag/info_mac.c \
src/tags/libapetag/info_mpc.c \
src/tags/ape_tag.c \
+ src/tags/dsf_header.c \
src/tags/flac_header.c \
src/tags/flac_tag.c \
src/tags/gio_wrapper.cc \
@@ -122,6 +123,7 @@ easytag_headers = \
src/tags/libapetag/info_mac.h \
src/tags/libapetag/info_mpc.h \
src/tags/ape_tag.h \
+ src/tags/dsf_header.h \
src/tags/flac_header.h \
src/tags/flac_tag.h \
src/tags/gio_wrapper.h \
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 195bbf3..4c67fb6 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -36,6 +36,7 @@ src/setting.c
src/status_bar.c
src/tag_area.c
src/tags/ape_tag.c
+src/tags/dsf_header.c
src/tags/flac_header.c
src/tags/flac_tag.c
src/tags/id3_tag.c
diff --git a/src/et_core.c b/src/et_core.c
index a07b0f9..fabf16f 100644
--- a/src/et_core.c
+++ b/src/et_core.c
@@ -32,6 +32,7 @@
#include <errno.h>
#include "application_window.h"
+#include "dsf_header.h"
#include "easytag.h"
#include "et_core.h"
#include "mpeg_header.h"
@@ -110,6 +111,7 @@ const ET_File_Description ETFileDescription[] =
{ MP4_FILE, ".m4p", MP4_TAG}, /* Implemented by Michael Ihde. */
{ MP4_FILE, ".m4v", MP4_TAG},
#endif
+ { DSF_FILE, ".dsf", UNKNOWN_TAG },
#ifdef ENABLE_WAVPACK
{ WAVPACK_FILE, ".wv", WAVPACK_TAG}, /* Implemented by Maarten Maathuis. */
#endif
@@ -659,6 +661,9 @@ GList *ET_Add_File_To_File_List (gchar *filename)
success = et_mp4_header_read_file_info (file, ETFileInfo, &error);
break;
#endif
+ case DSF_FILE:
+ success = et_dsf_header_read_file_info (file, ETFileInfo, &error);
+ break;
#ifdef ENABLE_OPUS
case OPUS_FILE:
success = et_opus_read_file_info (file, ETFileInfo, &error);
@@ -2957,6 +2962,11 @@ ET_Display_File_Data_To_UI (ET_File *ETFile)
et_mp4_file_header_fields_free (fields);
break;
#endif
+ case DSF_FILE:
+ fields = et_dsf_header_display_file_info_to_ui (ETFile);
+ et_application_window_file_area_set_header_fields (window, fields);
+ et_dsf_file_header_fields_free (fields);
+ break;
#ifdef ENABLE_WAVPACK
case WAVPACK_FILE:
fields = et_wavpack_header_display_file_info_to_ui (ETFile);
diff --git a/src/et_core.h b/src/et_core.h
index 3feaecb..785a9aa 100644
--- a/src/et_core.h
+++ b/src/et_core.h
@@ -50,6 +50,7 @@ typedef enum
OFR_FILE, // OptimFROG (lossless) : .ofr .ofs
WAVPACK_FILE, // Wavpack (lossless) : .wv
OPUS_FILE, /* Ogg Opus File: .opus */
+ DSF_FILE, /* DSD codec in DSF container: .dsf */
UNKNOWN_FILE
} ET_File_Type;
diff --git a/src/tags/dsf_header.c b/src/tags/dsf_header.c
new file mode 100644
index 0000000..d9f1340
--- /dev/null
+++ b/src/tags/dsf_header.c
@@ -0,0 +1,252 @@
+/* EasyTAG - Tag editor for audio files.
+ * Copyright (C) 2014 David King <amigadave amigadave 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"
+
+#include <glib/gi18n.h>
+
+#include "dsf_header.h"
+
+#include "easytag.h"
+#include "et_core.h"
+#include "misc.h"
+
+#define DSF_HEADER_LENGTH 80
+#define DSF_HEADER_MAGIC "DSD "
+#define DSF_HEADER_FORMAT_MAGIC "fmt "
+
+/* Read the little-endian 32-bit integer from the next 4 characters. */
+static guint32
+guint32_from_byte (guchar *str)
+{
+ gsize i;
+ guint32 result = 0;
+
+ for (i = 4; i > 0; i--)
+ {
+ result = (result << 8) + str[i - 1];
+ }
+
+ return result;
+}
+
+/* Read the little-endian 64-bit integer from the next 8 characters. */
+static guint64
+guint64_from_byte (guchar *str)
+{
+ gsize i;
+ guint64 result = 0;
+
+ for (i = 8; i > 0; i--)
+ {
+ result = (result << 8) + str[i - 1];
+ }
+
+ return result;
+}
+
+gboolean
+et_dsf_header_read_file_info (GFile *file,
+ ET_File_Info *ETFileInfo,
+ GError **error)
+{
+ GFileInputStream *file_istream;
+ GInputStream *istream;
+ guchar header[DSF_HEADER_LENGTH];
+ gsize bytes_read;
+ GFileInfo *info;
+ guint64 file_size_header;
+ goffset file_size;
+ guint32 bps;
+ guint64 n_samples;
+
+ g_return_val_if_fail (file != NULL && ETFileInfo != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ file_istream = g_file_read (file, NULL, error);
+
+ if (file_istream == NULL)
+ {
+ return FALSE;
+ }
+
+ istream = G_INPUT_STREAM (file_istream);
+
+ /* Read the complete header from the file. */
+ if (!g_input_stream_read_all (istream, &header, DSF_HEADER_LENGTH,
+ &bytes_read, NULL, error))
+ {
+ g_debug ("Only %" G_GSIZE_FORMAT " bytes out of %d "
+ "bytes were read", bytes_read, DSF_HEADER_LENGTH);
+ goto err;
+ }
+
+ info = g_file_input_stream_query_info (file_istream,
+ G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ NULL, error);
+ g_object_unref (file_istream);
+
+ if (info == NULL)
+ {
+ goto err;
+ }
+
+ file_size = g_file_info_get_size (info);
+ g_object_unref (info);
+
+ if (memcmp (&header, DSF_HEADER_MAGIC, 4) != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s",
+ _("Not a DSF file"));
+ goto err;
+ }
+
+ if (memcmp (&header[28], DSF_HEADER_FORMAT_MAGIC, 4) != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s",
+ _("Not a DSF file"));
+ goto err;
+ }
+
+ /* 12 (8 bytes) total file size. */
+ file_size_header = guint64_from_byte (&header[12]);
+
+ if (file_size_header != file_size)
+ {
+ g_debug ("DSF file is %" G_GUINT64_FORMAT
+ " bytes, but the file size stored in the header is %"
+ G_GOFFSET_FORMAT " bytes", file_size, file_size_header);
+ }
+
+ ETFileInfo->size = file_size;
+
+ /* 44 (4 bytes) format ID, normally 0. */
+ ETFileInfo->version = guint32_from_byte (&header[44]);
+
+ /* 48 (4 bytes) channel type, normally 1-7. */
+ ETFileInfo->mode = guint32_from_byte (&header[52]);
+
+ /* 52 (4 bytes) number of channels. */
+
+ /* 56 (4 bytes) sampling frequency, 2822400 or 5644800 Hz. */
+ ETFileInfo->samplerate = guint32_from_byte (&header[56]);
+
+ /* 60 (4 bytes) bits per sample, 1 or 8. */
+ bps = guint32_from_byte (&header[60]);
+
+ /* 64 (8 bytes) sample count (per channel). */
+ n_samples = guint64_from_byte (&header[64]);
+
+ /* 72 (4 bytes) block size per channel, 4096. */
+
+ /* 76 (4 bytes) zero padded. */
+
+ ETFileInfo->duration = n_samples / ETFileInfo->samplerate;
+ ETFileInfo->bitrate = bps * (n_samples / ETFileInfo->duration / 1000);
+
+ return TRUE;
+
+err:
+ g_object_unref (file_istream);
+ return FALSE;
+}
+
+EtFileHeaderFields *
+et_dsf_header_display_file_info_to_ui (const ET_File *ETFile)
+{
+ EtFileHeaderFields *fields;
+ ET_File_Info *info;
+ gchar *time = NULL;
+ gchar *time1 = NULL;
+ gchar *size = NULL;
+ gchar *size1 = NULL;
+
+ info = ETFile->ETFileInfo;
+ fields = g_slice_new (EtFileHeaderFields);
+
+ fields->description = _("DSF File");
+
+ /* Encoder version */
+ fields->version_label = _("Encoder:");
+ fields->version = g_strdup_printf ("%d", info->version);
+
+ /* Bitrate */
+ fields->bitrate = g_strdup_printf (_("%d kb/s"), info->bitrate);
+
+ /* Samplerate */
+ fields->samplerate = g_strdup_printf (_("%d Hz"), info->samplerate);
+
+ /* Mode */
+ fields->mode_label = _("Channels:");
+
+ switch (info->mode)
+ {
+ case 1:
+ fields->mode = g_strdup (_("Mono"));
+ break;
+ case 2:
+ fields->mode = g_strdup (_("Stereo"));
+ break;
+ case 3:
+ fields->mode = g_strdup_printf ("%d", info->mode);
+ break;
+ case 4:
+ fields->mode = g_strdup (_("Quadrophonic"));
+ break;
+ case 5:
+ case 6:
+ fields->mode = g_strdup_printf ("%d", info->mode + 1);
+ break;
+ case 7:
+ fields->mode = g_strdup (_("5.1"));
+ break;
+ default:
+ fields->mode = g_strdup (_("Unknown"));
+ break;
+ }
+
+ /* Size */
+ size = g_format_size (info->size);
+ size1 = g_format_size (ETCore->ETFileDisplayedList_TotalSize);
+ fields->size = g_strdup_printf ("%s (%s)", size, size1);
+ g_free (size);
+ g_free (size1);
+
+ /* Duration */
+ time = Convert_Duration (info->duration);
+ time1 = Convert_Duration (ETCore->ETFileDisplayedList_TotalDuration);
+ fields->duration = g_strdup_printf ("%s (%s)", time, time1);
+ g_free (time);
+ g_free (time1);
+
+ return fields;
+}
+
+void
+et_dsf_file_header_fields_free (EtFileHeaderFields *fields)
+{
+ g_return_if_fail (fields != NULL);
+
+ g_free (fields->version);
+ g_free (fields->bitrate);
+ g_free (fields->samplerate);
+ g_free (fields->mode);
+ g_free (fields->size);
+ g_free (fields->duration);
+ g_slice_free (EtFileHeaderFields, fields);
+}
diff --git a/src/tags/dsf_header.h b/src/tags/dsf_header.h
new file mode 100644
index 0000000..2d2b891
--- /dev/null
+++ b/src/tags/dsf_header.h
@@ -0,0 +1,32 @@
+/* EasyTAG - Tag editor for audio files
+ * Copyright (C) 2014 David King <amigadave amigadave 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_DSF_HEADER_H_
+#define ET_DSF_HEADER_H_
+
+#include "et_core.h"
+
+G_BEGIN_DECLS
+
+gboolean et_dsf_header_read_file_info (GFile *file, ET_File_Info *ETFileInfo, GError **error);
+EtFileHeaderFields * et_dsf_header_display_file_info_to_ui (const ET_File *ETFile);
+void et_dsf_file_header_fields_free (EtFileHeaderFields *fields);
+
+G_END_DECLS
+
+#endif /* ET_DSF_HEADER_H_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]