[easytag] Use GFile instead of stdio in vcedit.c, bug 700874



commit 94b6a68b51347d10e6a5c9a07dc035a3e3ce025c
Author: Abhinav <abhijangda hotmail com>
Date:   Thu May 23 23:13:59 2013 +0530

    Use GFile instead of stdio in vcedit.c, bug 700874

 src/ogg_header.c |   38 +++++---
 src/ogg_header.h |   41 ++++++++
 src/ogg_tag.c    |   92 ++++++++++--------
 src/vcedit.c     |  291 ++++++++++++++++++++++++++++++++++++++----------------
 src/vcedit.h     |   15 +---
 5 files changed, 327 insertions(+), 150 deletions(-)
---
diff --git a/src/ogg_header.c b/src/ogg_header.c
index 9d86a46..fed435a 100644
--- a/src/ogg_header.c
+++ b/src/ogg_header.c
@@ -18,7 +18,7 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#include <config.h> // For definition of ENABLE_OGG
+#include "config.h" /* For definition of ENABLE_OGG. */
 
 #ifdef ENABLE_OGG
 
@@ -46,6 +46,19 @@
  * Functions *
  *************/
 
+/*
+ * et_ogg_error_quark:
+ *
+ * To get EtOGGError domain.
+ *
+ * Returns: GQuark for EtOGGError domain
+ */
+GQuark
+et_ogg_error_quark (void)
+{
+    return g_quark_from_static_string ("et-ogg-error-quark");
+}
+
 gboolean Ogg_Header_Read_File_Info (gchar *filename, ET_File_Info *ETFileInfo)
 {
     FILE *file;
@@ -149,7 +162,6 @@ gboolean Ogg_Header_Read_File_Info (gchar *filename, ET_File_Info *ETFileInfo)
 
 gboolean Speex_Header_Read_File_Info (gchar *filename, ET_File_Info *ETFileInfo)
 {
-    FILE *file;
     vcedit_state *state;
     SpeexHeader  *si;
     gchar *encoder_version = NULL;
@@ -159,24 +171,22 @@ gboolean Speex_Header_Read_File_Info (gchar *filename, ET_File_Info *ETFileInfo)
     gdouble duration = 0;
     gulong filesize;
     gchar *filename_utf8;
+    GFile *gfile;
+    GError *error = NULL;
 
     g_return_val_if_fail (filename != NULL && ETFileInfo != NULL, FALSE);
 
     filename_utf8 = filename_to_display(filename);
 
-    if ( (file=fopen(filename,"rb"))==NULL ) // Warning : it is important to open the file in binary mode! 
(to get header information under Win32)
-    {
-        Log_Print(LOG_ERROR,_("Error while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno));
-        g_free(filename_utf8);
-        return FALSE;
-    }
-
-
     state = vcedit_new_state();    // Allocate memory for 'state'
-    if ( vcedit_open(state,file) < 0 )
+    gfile = g_file_new_for_path (filename);
+    if (!vcedit_open (state, gfile, &error))
     {
-        Log_Print(LOG_ERROR,_("Error: Failed to open file: '%s' as Vorbis 
(%s)."),filename_utf8,vcedit_error(state));
-        fclose(file);
+        Log_Print (LOG_ERROR,
+                   _("Error: Failed to open file: '%s' as Vorbis (%s)."),
+                   filename_utf8, error->message);
+        g_error_free (error);
+        g_object_unref (gfile);
         g_free(filename_utf8);
         vcedit_clear(state);
         return FALSE;
@@ -210,7 +220,7 @@ gboolean Speex_Header_Read_File_Info (gchar *filename, ET_File_Info *ETFileInfo)
         ETFileInfo->duration   = duration;
 
     vcedit_clear(state);
-    fclose(file);
+    g_object_unref (gfile);
     g_free(filename_utf8);
     return TRUE;
 }
diff --git a/src/ogg_header.h b/src/ogg_header.h
index 3662576..c35c36c 100644
--- a/src/ogg_header.h
+++ b/src/ogg_header.h
@@ -30,6 +30,47 @@
  * Declarations *
  ****************/
 
+/*
+ * Error domain and codes for errors while reading/writing OGG files
+ */
+GQuark et_ogg_error_quark (void);
+
+#define ET_OGG_ERROR et_ogg_error_quark ()
+
+/*
+ * EtOGGError:
+ * @ET_OGG_ERROR_EOS: reached end of logical bitstream
+ * @ET_OGG_ERROR_EOF: reached end of file
+ * @ET_OGG_ERROR_SN: page and state's serial number are unequal
+ * @ET_OGG_ERROR_TRUNC: input truncated or empty
+ * @ET_OGG_ERROR_NOTOGG: input is not ogg bitstream
+ * @ET_OGG_ERROR_PAGE: cannot read first page of ogg bitstream
+ * @ET_OGG_ERROR_HEADER: error reading initial header packet
+ * @ET_OGG_ERROR_INVALID: ogg bitstream doesnot contains Speex or Vorbis data
+ * @ET_OGG_ERROR_CORRUPT: corrupt secondary header
+ * @ET_OGG_ERROR_EXTRA: need to save extra headers
+ * @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
+ *
+ * Errors that can occur when reading OGG files.
+ */
+typedef enum
+{
+    ET_OGG_ERROR_EOS,
+    ET_OGG_ERROR_EOF,
+    ET_OGG_ERROR_SN,
+    ET_OGG_ERROR_TRUNC,
+    ET_OGG_ERROR_NOTOGG,
+    ET_OGG_ERROR_PAGE,
+    ET_OGG_ERROR_HEADER,
+    ET_OGG_ERROR_INVALID,
+    ET_OGG_ERROR_CORRUPT,
+    ET_OGG_ERROR_EXTRA,
+    ET_OGG_ERROR_VORBIS,
+    ET_OGG_ERROR_FAILED,
+    ET_OGG_ERROR_OUTPUT
+} EtOGGError;
 
 /**************
  * Prototypes *
diff --git a/src/ogg_tag.c b/src/ogg_tag.c
index d06cc1e..907d887 100644
--- a/src/ogg_tag.c
+++ b/src/ogg_tag.c
@@ -18,7 +18,7 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#include <config.h> // For definition of ENABLE_OGG
+#include "config.h" // For definition of ENABLE_OGG
 
 #ifdef ENABLE_OGG
 
@@ -105,7 +105,8 @@
 /**************
  * Prototypes *
  **************/
-static gboolean Ogg_Tag_Write_File (FILE *file_in, gchar *filename_in, vcedit_state *state);
+static gboolean Ogg_Tag_Write_File (GFile *file_in, gchar *filename_in,
+                                    vcedit_state *state, GError **error);
 
 static gboolean Ogg_Write_Delimetered_Tag (vorbis_comment *vc, const gchar *tag_name, gchar *values);
 static gboolean Ogg_Write_Tag (vorbis_comment *vc, const gchar *tag_name, gchar *value);
@@ -123,6 +124,8 @@ static void Ogg_Set_Tag (vorbis_comment *vc, const gchar *tag_name, gchar *value
 gboolean Ogg_Tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
 {
     FILE           *file;
+    GFile *gfile;
+    GError *error = NULL;
     vcedit_state   *state;
     vorbis_comment *vc;
     gchar          *string = NULL;
@@ -177,12 +180,18 @@ gboolean Ogg_Tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
     }
     }
 
+    fclose(file);
+
     state = vcedit_new_state();    // Allocate memory for 'state'
-    if ( vcedit_open(state,file) < 0 )
+    gfile = g_file_new_for_path (filename);
+
+    if (!vcedit_open (state, gfile, &error))
     {
-        Log_Print(LOG_ERROR,_("Error: Failed to open file: '%s' as Vorbis 
(%s)."),filename_utf8,vcedit_error(state));
-        ogg_error_msg = vcedit_error(state);
-        fclose(file);
+        Log_Print (LOG_ERROR,
+                   _("Error: Failed to open file: '%s' as Vorbis (%s)."),
+                   filename_utf8, error->message);
+        g_error_free (error);
+        g_object_unref (gfile);
         g_free(filename_utf8);
         vcedit_clear(state);
         return FALSE;
@@ -572,7 +581,7 @@ gboolean Ogg_Tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
     }
 
     vcedit_clear(state);
-    fclose(file);
+    g_object_unref (gfile);
     g_free(filename_utf8);
 
     return TRUE;
@@ -631,6 +640,8 @@ gboolean Ogg_Tag_Write_File_Tag (ET_File *ETFile)
     gchar          *string;
     GList          *list;
     Picture        *pic;
+    GFile *gfile_in;
+    GError *error = NULL;
 
     g_return_val_if_fail (ETFile != NULL && ETFile->FileTag != NULL, FALSE);
 
@@ -679,12 +690,17 @@ gboolean Ogg_Tag_Write_File_Tag (ET_File *ETFile)
     }
     }
 
+    fclose (file_in);
+
     state = vcedit_new_state();    // Allocate memory for 'state'
-    if ( vcedit_open(state,file_in) < 0 )
-    {
-        Log_Print(LOG_ERROR,_("Error: Failed to open file: '%s' as Vorbis 
(%s)."),filename_utf8,vcedit_error(state));
-        ogg_error_msg = vcedit_error(state);
-        fclose(file_in);
+    gfile_in = g_file_new_for_path (filename);
+    if (!vcedit_open (state, gfile_in, &error))
+    {
+        Log_Print (LOG_ERROR,
+                   _("Error: Failed to open file: '%s' as Vorbis (%s)."),
+                   filename_utf8, error->message);
+        g_object_unref (gfile_in);
+        g_error_free (error);
         vcedit_clear(state);
         return FALSE;
     }
@@ -818,12 +834,14 @@ gboolean Ogg_Tag_Write_File_Tag (ET_File *ETFile)
         list = list->next;
     }
 
-    /* Write tag, and close also 'file_in' in all cases */
-    if ( Ogg_Tag_Write_File(file_in,filename,state) == FALSE )
+    /* Write tag to 'gfile_in' in all cases */
+    if (Ogg_Tag_Write_File (gfile_in, filename, state, &error) == FALSE)
     {
-        ogg_error_msg = vcedit_error(state);
-        Log_Print(LOG_ERROR,_("Error: Failed to write comments to file '%s' 
(%s)."),filename_utf8,ogg_error_msg == NULL ? "" : ogg_error_msg);
-
+        Log_Print (LOG_ERROR,
+                   _("Error: Failed to write comments to file '%s' (%s)."),
+                   filename_utf8, error->message);
+        g_error_free (error);
+        g_object_unref (gfile_in);
         vcedit_clear(state);
         return FALSE;
     }else
@@ -834,6 +852,7 @@ gboolean Ogg_Tag_Write_File_Tag (ET_File *ETFile)
         vcedit_clear(state);
     }
 
+    g_object_unref (gfile_in);
     return TRUE;
 }
 
@@ -843,44 +862,37 @@ gboolean Ogg_Tag_Write_File_Tag (ET_File *ETFile)
  * Write tag information to a new temporary file, and rename it the the initial name.
  */
 static gboolean
-Ogg_Tag_Write_File (FILE *file_in, gchar *filename_in, vcedit_state *state)
+Ogg_Tag_Write_File (GFile *file_in, gchar *filename_in, vcedit_state *state,
+                    GError **error)
 {
     gchar *filename_out;
-    gint   file_mkstemp;
-    FILE  *file_out;
+    GFile  *file_out;
+    GFileIOStream *iostream;
     gboolean return_code = TRUE;
 
+    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
     filename_out = g_strdup_printf("%s.XXXXXX",filename_in);
-    
-    // Function mkstemp() opens also the file!
-    if ((file_mkstemp = mkstemp(filename_out)) < 0)
+    file_out = g_file_new_tmp (filename_out, &iostream, error);
+    if (!file_out)
     {
-        fclose(file_in);
-        close(file_mkstemp);
-        g_free(filename_out);
-        return FALSE;
-    }
-    close(file_mkstemp);
-    
-    if ( (file_out=fopen(filename_out,"wb")) == NULL )
-    {
-        fclose(file_in);
-        remove(filename_out);
         g_free(filename_out);
         return FALSE;
     }
+
+    g_object_unref (iostream);
     
-    if (vcedit_write(state,file_out) < 0)
+    if (vcedit_write (state, file_out, error) < 0)
     {
-        fclose(file_in);
-        fclose(file_out);
-        remove(filename_out);
+        g_assert (error == NULL || *error != NULL);
+        g_file_delete (file_out, NULL, error);
+        g_object_unref (file_out);
         g_free(filename_out);
         return FALSE;
     }
-    fclose(file_in);
-    fclose(file_out);
+
+    g_assert (error == NULL || *error == NULL);
+    g_object_unref (file_out);
 
     // Some platforms fail to rename a file if the new name already
     // exists, so we need to remove, then rename...
diff --git a/src/vcedit.c b/src/vcedit.c
index e687db4..5162b5f 100644
--- a/src/vcedit.c
+++ b/src/vcedit.c
@@ -9,10 +9,10 @@
  * last modified: $Id: vcedit.c,v 1.23 2003/09/03 07:58:05 calc Exp $
  */
 
-#include <config.h> // For definition of ENABLE_OGG
+#include "config.h" /* For definition of ENABLE_OGG. */
 
 #ifdef ENABLE_OGG
-
+#include <gtk/gtk.h>
 #include <glib/gi18n-lib.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -22,14 +22,10 @@
 #include <vorbis/codec.h>
 
 #include "vcedit.h"
-
+#include "ogg_header.h"
 
 #define CHUNKSIZE 4096
 
-static int vcedit_open_callbacks(vcedit_state *state, void *in,
-                                 vcedit_read_func read_func,
-                                 vcedit_write_func write_func);
-
 vcedit_state *vcedit_new_state(void)
 {
     vcedit_state *state = malloc(sizeof(vcedit_state));
@@ -39,11 +35,6 @@ vcedit_state *vcedit_new_state(void)
     return state;
 }
 
-char *vcedit_error(vcedit_state *state)
-{
-    return state->lasterror;
-}
-
 vorbis_comment *vcedit_comments(vcedit_state *state)
 {
     return state->vc;
@@ -51,7 +42,6 @@ vorbis_comment *vcedit_comments(vcedit_state *state)
 
 static void vcedit_clear_internals(vcedit_state *state)
 {
-    char *tmp;
     if(state->vc)
     {
         vorbis_comment_clear(state->vc);
@@ -77,10 +67,8 @@ static void vcedit_clear_internals(vcedit_state *state)
         vorbis_info_clear(state->vi);
         free(state->vi);
     }
-
-    tmp = state->lasterror;
+    g_object_unref (state->in);
     memset(state, 0, sizeof(*state));
-    state->lasterror = tmp;
 }
 
 void vcedit_clear(vcedit_state *state)
@@ -170,11 +158,14 @@ static int _blocksize(vcedit_state *s, ogg_packet *p)
 }
 
 static gboolean
-_fetch_next_packet (vcedit_state *s, ogg_packet *p, ogg_page *page)
+_fetch_next_packet (vcedit_state *s, ogg_packet *p, ogg_page *page,
+                    GError **error)
 {
     int result;
     char *buffer;
-    int bytes;
+    gssize bytes;
+
+    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
     result = ogg_stream_packetout(s->os, p);
 
@@ -183,26 +174,45 @@ _fetch_next_packet (vcedit_state *s, ogg_packet *p, ogg_page *page)
     else
     {
         if(s->eosin)
+        {
+            g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_EOS,
+                         "Page reached end of logical bitstream");
+            g_assert (error == NULL || *error != NULL);
             return FALSE;
+        }
         while(ogg_sync_pageout(s->oy, page) <= 0)
         {
             buffer = ogg_sync_buffer(s->oy, CHUNKSIZE);
-            bytes = s->read(buffer,1, CHUNKSIZE, s->in);
+            bytes = g_input_stream_read (G_INPUT_STREAM (s->in), buffer,
+                                         CHUNKSIZE, NULL, error);
             ogg_sync_wrote(s->oy, bytes);
             if(bytes == 0)
+            {
+                g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_EOF,
+                             "Reached end of file");
+                g_assert (error == NULL || *error != NULL);
                 return FALSE;
+            }
+            else if (bytes == -1)
+            {
+                g_assert (error == NULL || *error != NULL);
+                return FALSE;
+            }
         }
         if(ogg_page_eos(page))
             s->eosin = 1;
         else if(ogg_page_serialno(page) != s->serial)
         {
+            g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_SN,
+                         "Page serial number and state serial number doesn't match");
             s->eosin = 1;
             s->extrapage = 1;
+            g_assert (error == NULL || *error != NULL);
             return FALSE;
         }
-
+        g_assert (error == NULL || *error == NULL);
         ogg_stream_pagein(s->os, page);
-        return _fetch_next_packet(s, p, page);
+        return _fetch_next_packet(s, p, page, error);
     }
 }
 
@@ -250,19 +260,12 @@ err_out:
     return(1);
 }
 
-int vcedit_open(vcedit_state *state, FILE *in)
+gboolean
+vcedit_open(vcedit_state *state, GFile *file, GError **error)
 {
-    return vcedit_open_callbacks(state, (void *)in,
-            (vcedit_read_func)fread, (vcedit_write_func)fwrite);
-}
-
-static int
-vcedit_open_callbacks(vcedit_state *state, void *in,
-                      vcedit_read_func read_func, vcedit_write_func write_func)
-{
-
     char *buffer;
-    int bytes,i;
+    gssize bytes;
+    int i;
     int chunks = 0;
     int headerpackets = 0;
     oggpack_buffer opb;
@@ -271,10 +274,18 @@ vcedit_open_callbacks(vcedit_state *state, void *in,
     ogg_packet  header_comments;
     ogg_packet  header_codebooks;
     ogg_page    og;
+    GFileInputStream *istream;
+
+    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+    istream = g_file_read (file, NULL, error);
+    if (!istream)
+    {
+        g_assert (error == NULL || *error != NULL);
+        return FALSE;
+    }
 
-    state->in = in;
-    state->read = read_func;
-    state->write = write_func;
+    state->in = g_data_input_stream_new (G_INPUT_STREAM (istream));
 
     state->oy = malloc(sizeof(ogg_sync_state));
     ogg_sync_init(state->oy);
@@ -282,7 +293,12 @@ vcedit_open_callbacks(vcedit_state *state, void *in,
     while(1)
     {
         buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
-        bytes = state->read(buffer, 1, CHUNKSIZE, state->in);
+        bytes = g_input_stream_read (G_INPUT_STREAM (state->in), buffer,
+                                     CHUNKSIZE, NULL, error);
+        if (bytes == -1)
+        {
+            goto err;
+        }
 
         ogg_sync_wrote(state->oy, bytes);
 
@@ -292,9 +308,11 @@ vcedit_open_callbacks(vcedit_state *state, void *in,
         if(chunks++ >= 10) /* Bail if we don't find data in the first 40 kB */
         {
             if(bytes<CHUNKSIZE)
-                state->lasterror = _("Input truncated or empty.");
+                g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_TRUNC,
+                             "Input truncated or empty");
             else
-                state->lasterror = _("Input is not an Ogg bitstream.");
+                g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_NOTOGG,
+                             "Input is not an OGG bitstream");
             goto err;
         }
     }
@@ -312,13 +330,15 @@ vcedit_open_callbacks(vcedit_state *state, void *in,
 
     if(ogg_stream_pagein(state->os, &og) < 0)
     {
-        state->lasterror = _("Error reading first page of Ogg bitstream.");
+        g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_PAGE,
+                     "Error reading first page of OGG bitstream");
         goto err;
     }
 
     if(ogg_stream_packetout(state->os, &header_main) != 1)
     {
-        state->lasterror = _("Error reading initial header packet.");
+        g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_HEADER,
+                     "Error reading initial header packet");
         goto err;
     }
 
@@ -345,7 +365,8 @@ vcedit_open_callbacks(vcedit_state *state, void *in,
 
     if (state->oggtype == VCEDIT_IS_UNKNOWN)
     {
-        state->lasterror = _("Ogg bitstream contains neither Speex or Vorbis data.");
+        g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_INVALID,
+                     "OGG bitstream contains neither Speex nor Vorbis data");
         goto err;
     }
 
@@ -378,7 +399,8 @@ vcedit_open_callbacks(vcedit_state *state, void *in,
                     if(result == 0) break;
                     if(result == -1)
                     {
-                        state->lasterror = _("Corrupt secondary header.");
+                        g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_CORRUPT,
+                                     "Corrupt secondary header");
                         goto err;
                     }
                     switch (state->oggtype)
@@ -407,8 +429,9 @@ vcedit_open_callbacks(vcedit_state *state, void *in,
                                     oggpack_readinit(&opb,header->packet,header->bytes);
                                     _speex_unpack_comment(state->vc,&opb);
                                     break;
-                                default:
-                                    state->lasterror = _("Need to save extra headers"); /* FIXME. */
+                                default: /* FIXME. */
+                                    g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_EXTRA,
+                                                 "Need to save extra headers");
                                     goto err;
                                     break;
                             }
@@ -419,10 +442,17 @@ vcedit_open_callbacks(vcedit_state *state, void *in,
         }
 
         buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
-        bytes = state->read(buffer, 1, CHUNKSIZE, state->in);
+        bytes = g_input_stream_read (G_INPUT_STREAM (state->in), buffer,
+                                     CHUNKSIZE, NULL, error);
+        if (bytes == -1)
+        {
+            goto err;
+        }
+
         if(bytes == 0 && i < 2)
         {
-            state->lasterror = _("EOF before end of Vorbis headers.");
+            g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_VORBIS,
+                         "EOF before end of Vorbis headers");
             goto err;
         }
         ogg_sync_wrote(state->oy, bytes);
@@ -433,14 +463,20 @@ vcedit_open_callbacks(vcedit_state *state, void *in,
     strcpy(state->vendor, state->vc->vendor);
 
     /* Headers are done! */
-    return 0;
+    g_assert (error == NULL || *error == NULL);
+
+    g_object_unref (istream);
+    return TRUE;
 
 err:
+    g_assert (error == NULL || *error != NULL);
+    g_object_unref (istream);
     vcedit_clear_internals(state);
-    return -1;
+    return FALSE;
 }
 
-int vcedit_write(vcedit_state *state, void *out)
+gboolean
+vcedit_write(vcedit_state *state, GFile *file, GError **error)
 {
     ogg_stream_state streamout;
     ogg_packet header_main;
@@ -454,6 +490,21 @@ int vcedit_write(vcedit_state *state, void *out)
     char *buffer;
     int bytes;
     int needflush=0, needout=0;
+    GFileOutputStream *ostream;
+    GDataOutputStream *dostream;
+
+    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+    ostream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE,
+                              NULL, error);
+
+    if (!ostream)
+    {
+        g_assert (error == NULL || *error != NULL);
+        return FALSE;
+    }
+
+    dostream = g_data_output_stream_new (G_OUTPUT_STREAM (ostream));
 
     state->eosin = 0;
     state->extrapage = 0;
@@ -482,38 +533,62 @@ int vcedit_write(vcedit_state *state, void *out)
 
     while((result = ogg_stream_flush(&streamout, &ogout)))
     {
-        if(state->write(ogout.header,1,ogout.header_len, out) !=
-                (size_t) ogout.header_len)
+        if (g_output_stream_write (G_OUTPUT_STREAM (dostream), ogout.header,
+                                   ogout.header_len, NULL, error)
+            != (gssize) ogout.header_len)
+        {
+            g_assert (error == NULL || *error != NULL);
             goto cleanup;
-        if(state->write(ogout.body,1,ogout.body_len, out) !=
-                (size_t) ogout.body_len)
+        }
+
+        if (g_output_stream_write (G_OUTPUT_STREAM (dostream), ogout.body,
+                                   ogout.body_len, NULL, error)
+            != (gssize) ogout.body_len)
+        {
+            g_assert (error == NULL || *error != NULL);
             goto cleanup;
+        }
     }
 
-    while(_fetch_next_packet(state, &op, &ogin))
+    while (_fetch_next_packet (state, &op, &ogin, error))
     {
         if(needflush)
         {
-            if(ogg_stream_flush(&streamout, &ogout))
+            if (g_output_stream_write (G_OUTPUT_STREAM (dostream), ogout.header,
+                                       ogout.header_len, NULL, error)
+                != (gssize) ogout.header_len)
             {
-                if(state->write(ogout.header,1,ogout.header_len,
-                            out) != (size_t) ogout.header_len)
-                    goto cleanup;
-                if(state->write(ogout.body,1,ogout.body_len,
-                            out) != (size_t) ogout.body_len)
-                    goto cleanup;
+                g_assert (error == NULL || *error != NULL);
+                goto cleanup;
+            }
+
+            if (g_output_stream_write (G_OUTPUT_STREAM (dostream), ogout.body,
+                                       ogout.body_len, NULL, error)
+                != (gssize) ogout.body_len)
+            {
+                g_assert (error == NULL || *error != NULL);
+                goto cleanup;
             }
         }
         else if(needout)
         {
             if(ogg_stream_pageout(&streamout, &ogout))
             {
-                if(state->write(ogout.header,1,ogout.header_len,
-                            out) != (size_t) ogout.header_len)
+                if (g_output_stream_write (G_OUTPUT_STREAM (dostream), ogout.header,
+                                           ogout.header_len, NULL, error)
+                    != (gssize) ogout.header_len)
+                {
+                    g_assert (error == NULL || *error != NULL);
                     goto cleanup;
-                if(state->write(ogout.body,1,ogout.body_len,
-                            out) != (size_t) ogout.body_len)
+                }
+
+                if (g_output_stream_write (G_OUTPUT_STREAM (dostream), ogout.body,
+                                           ogout.body_len, NULL, error)
+                    != (gssize) ogout.body_len)
+                {
+                    g_assert (error == NULL || *error != NULL);
                     goto cleanup;
+                }
             }
         }
 
@@ -555,25 +630,48 @@ int vcedit_write(vcedit_state *state, void *out)
         }
     }
 
+    if (error == NULL || *error != NULL)
+    {
+        goto cleanup;
+    }
+
     streamout.e_o_s = 1;
     while(ogg_stream_flush(&streamout, &ogout))
     {
-        if(state->write(ogout.header,1,ogout.header_len,
-                    out) != (size_t) ogout.header_len)
+        if (g_output_stream_write (G_OUTPUT_STREAM (dostream), ogout.header,
+                                   ogout.header_len, NULL, error)
+            != (gssize) ogout.header_len)
+        {
+            g_assert (error == NULL || *error != NULL);
             goto cleanup;
-        if(state->write(ogout.body,1,ogout.body_len,
-                    out) != (size_t) ogout.body_len)
+        }
+
+        if (g_output_stream_write (G_OUTPUT_STREAM (dostream), ogout.body,
+                                   ogout.body_len, NULL, error)
+            != (gssize) ogout.body_len)
+        {
+            g_assert (error == NULL || *error != NULL);
             goto cleanup;
+        }
     }
 
     if (state->extrapage)
     {
-        if(state->write(ogin.header,1,ogin.header_len,
-                        out) != (size_t) ogin.header_len)
+        if (g_output_stream_write (G_OUTPUT_STREAM (dostream), ogout.header,
+                                   ogout.header_len, NULL, error)
+            != (gssize) ogout.header_len)
+        {
+            g_assert (error == NULL || *error != NULL);
             goto cleanup;
-        if (state->write(ogin.body,1,ogin.body_len, out) !=
-                (size_t) ogin.body_len)
+        }
+
+        if (g_output_stream_write (G_OUTPUT_STREAM (dostream), ogout.body,
+                                   ogout.body_len, NULL, error)
+            != (gssize) ogout.body_len)
+        {
+            g_assert (error == NULL || *error != NULL);
             goto cleanup;
+        }
     }
 
     state->eosin=0; /* clear it, because not all paths to here do */
@@ -587,23 +685,43 @@ int vcedit_write(vcedit_state *state, void *out)
             if(result==0)
                 break;
             if(result<0)
-                state->lasterror = _("Corrupt or missing data, continuing…");
+            {
+                g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_FAILED,
+                             "Corrupt or missing data, continuing…");
+                goto cleanup;
+            }
             else
             {
                 /* Don't bother going through the rest, we can just
                  * write the page out now */
-                if(state->write(ogout.header,1,ogout.header_len,
-                        out) != (size_t) ogout.header_len) {
+                if (g_output_stream_write (G_OUTPUT_STREAM (dostream), ogout.header,
+                                           ogout.header_len, NULL, error)
+                    != (gssize) ogout.header_len)
+                {
+                    g_assert (error == NULL || *error != NULL);
                     goto cleanup;
                 }
-                if(state->write(ogout.body,1,ogout.body_len, out) !=
-                        (size_t) ogout.body_len) {
+
+                if (g_output_stream_write (G_OUTPUT_STREAM (dostream), ogout.body,
+                                           ogout.body_len, NULL, error)
+                    != (gssize) ogout.body_len)
+                {
+                    g_assert (error == NULL || *error != NULL);
                     goto cleanup;
                 }
             }
         }
         buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
-        bytes = state->read(buffer,1, CHUNKSIZE, state->in);
+
+        bytes = g_input_stream_read (G_INPUT_STREAM (state->in), buffer,
+                                     CHUNKSIZE, NULL, error);
+
+        if (bytes == -1)
+        {
+            g_assert (error == NULL || *error != NULL);
+            goto cleanup;
+        }
+
         ogg_sync_wrote(state->oy, bytes);
         if(bytes == 0)
         {
@@ -621,14 +739,19 @@ cleanup:
     free(state->bookbuf);
     state->mainbuf = state->bookbuf = NULL;
 
-    if(!state->eosin)
+    if (!state->eosin)
     {
-        state->lasterror =
-            _("Error writing stream to output. "
-            "Output stream may be corrupted or truncated.");
-        return -1;
+        g_set_error (error, ET_OGG_ERROR, ET_OGG_ERROR_OUTPUT,
+                     "Error writing stream to output. Output stream may be corrupted or truncated");
     }
 
+    g_object_unref (ostream);
+    g_object_unref (dostream);
+
+    if (error == NULL || *error != NULL)
+        return FALSE;
+
+    g_assert (error == NULL || *error == NULL);
     return 0;
 }
 
diff --git a/src/vcedit.h b/src/vcedit.h
index 3a9e5f9..15321dd 100644
--- a/src/vcedit.h
+++ b/src/vcedit.h
@@ -28,9 +28,6 @@ extern "C" {
 #define VCEDIT_IS_SPEEX     1
 #define VCEDIT_IS_OGGVORBIS 2
 
-typedef size_t (*vcedit_read_func)(void *, size_t, size_t, void *);
-typedef size_t (*vcedit_write_func)(const void *, size_t, size_t, void *);
-
 typedef struct {
     ogg_sync_state      *oy;
     ogg_stream_state    *os;
@@ -42,16 +39,12 @@ typedef struct {
     SpeexHeader         *si;
 #endif
 
-    vcedit_read_func read;
-    vcedit_write_func write;
-
-    void        *in;
+    GDataInputStream    *in;
     long        serial;
     unsigned char   *mainbuf;
     unsigned char   *bookbuf;
     int     mainlen;
     int     booklen;
-    char   *lasterror;
     char   *vendor;
     int prevW;
     int extrapage;
@@ -61,13 +54,11 @@ typedef struct {
 extern vcedit_state    *vcedit_new_state(void);
 extern void             vcedit_clear(vcedit_state *state);
 extern vorbis_comment  *vcedit_comments(vcedit_state *state);
-extern int              vcedit_open(vcedit_state *state, FILE *in);
-extern int              vcedit_write(vcedit_state *state, void *out);
-extern char            *vcedit_error(vcedit_state *state);
+extern int              vcedit_open(vcedit_state *state, GFile *in, GError **error);
+extern int              vcedit_write(vcedit_state *state, GFile *file, GError **error);
 
 #ifdef __cplusplus
 }
 #endif 
 
 #endif /* __VCEDIT_H */
-


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