gmyth/src/gmyth_file_local.c
author renatofilho
Tue Aug 07 16:00:49 2007 +0100 (2007-08-07)
branchtrunk
changeset 797 7563dc4ed8d5
parent 750 312d6bc514f3
permissions -rwxr-xr-x
[svn r803] copyright fixed
rosfran@513
     1
/**
rosfran@513
     2
 * GMyth Library
rosfran@513
     3
 *
rosfran@513
     4
 * @file_local gmyth/gmyth_file_local.c
rosfran@513
     5
 * 
rosfran@513
     6
 * @brief <p> GMythFileLocal deals with the file_local streaming media remote/local
rosfran@513
     7
 * transfering to the MythTV frontend.
rosfran@513
     8
 *
rosfran@513
     9
 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
rosfran@513
    10
 * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
rosfran@513
    11
 *
rosfran@701
    12
 * 
rosfran@701
    13
 * This program is free software; you can redistribute it and/or modify
rosfran@701
    14
 * it under the terms of the GNU Lesser General Public License as published by
rosfran@701
    15
 * the Free Software Foundation; either version 2 of the License, or
rosfran@701
    16
 * (at your option) any later version.
rosfran@701
    17
 *
rosfran@701
    18
 * This program is distributed in the hope that it will be useful,
rosfran@701
    19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rosfran@701
    20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
rosfran@701
    21
 * GNU General Public License for more details.
rosfran@701
    22
 *
rosfran@701
    23
 * You should have received a copy of the GNU Lesser General Public License
rosfran@701
    24
 * along with this program; if not, write to the Free Software
rosfran@701
    25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
rosfran@701
    26
 */
rosfran@698
    27
rosfran@513
    28
#ifdef HAVE_CONFIG_H
rosfran@513
    29
#include "config.h"
rosfran@513
    30
#endif
rosfran@513
    31
rosfran@513
    32
#include "gmyth_file_local.h"
rosfran@513
    33
#include "gmyth_recorder.h"
rosfran@513
    34
#include "gmyth_util.h"
rosfran@513
    35
#include "gmyth_socket.h"
rosfran@513
    36
#include "gmyth_stringlist.h"
rosfran@513
    37
#include "gmyth_debug.h"
rosfran@513
    38
#include "gmyth_uri.h"
rosfran@513
    39
#include "gmyth_marshal.h"
rosfran@513
    40
rosfran@513
    41
#include <unistd.h>
rosfran@513
    42
#include <glib.h>
rosfran@513
    43
rosfran@513
    44
#include <arpa/inet.h>
rosfran@513
    45
#include <sys/types.h>
rosfran@513
    46
#include <sys/socket.h>
rosfran@513
    47
#include <netdb.h>
rosfran@513
    48
#include <errno.h>
rosfran@513
    49
#include <stdlib.h>
rosfran@513
    50
#include <assert.h>
rosfran@513
    51
rosfran@513
    52
#define GMYTH_FILE_LOCAL_GET_PRIVATE(obj) \
rosfran@701
    53
	(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalPrivate))
rosfran@513
    54
renatofilho@754
    55
struct _GMythFileLocalPrivate {
rosfran@698
    56
renatofilho@754
    57
    gboolean        disposed;
rosfran@698
    58
renatofilho@754
    59
    GMutex         *mutex;
rosfran@698
    60
renatofilho@754
    61
    gint            fd;
rosfran@698
    62
renatofilho@754
    63
    GIOChannel     *file_io;
rosfran@513
    64
renatofilho@750
    65
};
rosfran@513
    66
renatofilho@754
    67
static void     gmyth_file_local_class_init(GMythFileLocalClass * klass);
renatofilho@754
    68
static void     gmyth_file_local_init(GMythFileLocal * object);
renatofilho@754
    69
static void     gmyth_file_local_dispose(GObject * object);
renatofilho@754
    70
static void     gmyth_file_local_finalize(GObject * object);
rosfran@513
    71
renatofilho@750
    72
static gboolean _control_acquire_context(GMythFileLocal * file_local,
renatofilho@754
    73
                                         gboolean do_wait);
rosfran@513
    74
renatofilho@750
    75
static gboolean _control_release_context(GMythFileLocal * file_local);
rosfran@513
    76
renatofilho@750
    77
G_DEFINE_TYPE(GMythFileLocal, gmyth_file_local, GMYTH_FILE_TYPE)
renatofilho@754
    78
    static void     gmyth_file_local_class_init(GMythFileLocalClass *
renatofilho@754
    79
                                                klass)
rosfran@513
    80
{
renatofilho@754
    81
    GObjectClass   *gobject_class;
renatofilho@754
    82
    GMythFileLocalClass *gtransfer_class;
rosfran@513
    83
renatofilho@754
    84
    gobject_class = (GObjectClass *) klass;
renatofilho@754
    85
    gtransfer_class = (GMythFileLocalClass *) gobject_class;
rosfran@513
    86
renatofilho@754
    87
    gobject_class->dispose = gmyth_file_local_dispose;
renatofilho@754
    88
    gobject_class->finalize = gmyth_file_local_finalize;
rosfran@698
    89
renatofilho@754
    90
    g_type_class_add_private(gobject_class, sizeof(GMythFileLocalPrivate));
rosfran@513
    91
rosfran@513
    92
}
rosfran@513
    93
rosfran@513
    94
static void
renatofilho@750
    95
gmyth_file_local_init(GMythFileLocal * file_local)
rosfran@698
    96
{
renatofilho@754
    97
    GMythFileLocalPrivate *priv;
rosfran@513
    98
renatofilho@754
    99
    g_return_if_fail(file_local != NULL);
rosfran@698
   100
renatofilho@754
   101
    priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
rosfran@698
   102
renatofilho@754
   103
    priv->mutex = g_mutex_new();
rosfran@513
   104
}
rosfran@513
   105
rosfran@513
   106
static void
renatofilho@750
   107
gmyth_file_local_dispose(GObject * object)
rosfran@698
   108
{
renatofilho@754
   109
    GMythFileLocalPrivate *priv;
renatofilho@754
   110
    GMythFileLocal *file_local = GMYTH_FILE_LOCAL(object);
rosfran@513
   111
renatofilho@754
   112
    g_return_if_fail(file_local != NULL);
rosfran@513
   113
renatofilho@754
   114
    priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
rosfran@513
   115
renatofilho@754
   116
    if (priv->disposed) {
renatofilho@754
   117
        /*
renatofilho@754
   118
         * If dispose did already run, return. 
renatofilho@754
   119
         */
renatofilho@754
   120
        return;
renatofilho@754
   121
    }
rosfran@698
   122
renatofilho@754
   123
    /*
renatofilho@754
   124
     * Make sure dispose does not run twice. 
renatofilho@754
   125
     */
renatofilho@754
   126
    priv->disposed = TRUE;
rosfran@698
   127
renatofilho@754
   128
    if (priv->mutex != NULL) {
renatofilho@754
   129
        g_mutex_free(priv->mutex);
renatofilho@754
   130
        priv->mutex = NULL;
renatofilho@754
   131
    }
rosfran@698
   132
renatofilho@754
   133
    if (priv->file_io != NULL) {
renatofilho@754
   134
        g_io_channel_unref(priv->file_io);
renatofilho@754
   135
        priv->file_io = NULL;
renatofilho@754
   136
    }
rosfran@513
   137
renatofilho@754
   138
    G_OBJECT_CLASS(gmyth_file_local_parent_class)->dispose(object);
rosfran@513
   139
}
rosfran@513
   140
rosfran@513
   141
static void
renatofilho@750
   142
gmyth_file_local_finalize(GObject * object)
rosfran@513
   143
{
renatofilho@754
   144
    g_signal_handlers_destroy(object);
rosfran@513
   145
renatofilho@754
   146
    G_OBJECT_CLASS(gmyth_file_local_parent_class)->finalize(object);
rosfran@513
   147
}
rosfran@513
   148
rosfran@513
   149
/** 
rosfran@513
   150
 * Creates a new instance of GMythFileLocal.
rosfran@513
   151
 * 
rosfran@513
   152
 * @param backend_info The BackendInfo instance, with all the MythTV network 
rosfran@513
   153
 * 										 configuration data.
rosfran@513
   154
 * 
rosfran@513
   155
 * @return a new instance of the File Transfer. 
rosfran@513
   156
 */
rosfran@698
   157
GMythFileLocal *
renatofilho@750
   158
gmyth_file_local_new(GMythBackendInfo * backend_info)
rosfran@513
   159
{
renatofilho@754
   160
    GMythFileLocal *file_local =
renatofilho@754
   161
        GMYTH_FILE_LOCAL(g_object_new(GMYTH_FILE_LOCAL_TYPE, NULL));
rosfran@513
   162
renatofilho@754
   163
    g_object_set(GMYTH_FILE(file_local), "backend-info", &backend_info,
renatofilho@754
   164
                 NULL);
rosfran@518
   165
renatofilho@754
   166
    return file_local;
rosfran@513
   167
}
rosfran@513
   168
rosfran@513
   169
/** 
rosfran@513
   170
 * Creates a new instance of GMythFileLocal.
rosfran@513
   171
 * 
rosfran@513
   172
 * @param uri_str The URI poiting to the MythTV backend server.
rosfran@513
   173
 * 
rosfran@518
   174
 * @return a new instance of the File Transfer.
rosfran@513
   175
 */
rosfran@698
   176
GMythFileLocal *
renatofilho@750
   177
gmyth_file_local_new_with_uri(const gchar * uri_str)
rosfran@513
   178
{
renatofilho@754
   179
    GMythFileLocal *file_local =
renatofilho@754
   180
        GMYTH_FILE_LOCAL(g_object_new(GMYTH_FILE_LOCAL_TYPE, NULL));
renatofilho@754
   181
    GMythURI       *uri = gmyth_uri_new_with_value(uri_str);
rosfran@698
   182
renatofilho@754
   183
    gmyth_debug("GMythURI path segment = %s", gmyth_uri_get_path(uri));
rosfran@698
   184
renatofilho@754
   185
    g_object_set(GMYTH_FILE(file_local),
renatofilho@754
   186
                 "backend-info", gmyth_backend_info_new_with_uri(uri_str),
renatofilho@754
   187
                 "filename", g_strdup(gmyth_uri_get_path(uri)), NULL);
rosfran@698
   188
renatofilho@754
   189
    g_object_unref(uri);
rosfran@698
   190
renatofilho@754
   191
    return file_local;
rosfran@513
   192
}
rosfran@513
   193
renatofilho@754
   194
gchar          *
renatofilho@750
   195
gmyth_file_local_get_file_name(GMythFileLocal * file_local)
rosfran@513
   196
{
renatofilho@754
   197
    return gmyth_file_get_file_name(GMYTH_FILE(file_local));
rosfran@518
   198
}
rosfran@518
   199
rosfran@518
   200
void
renatofilho@750
   201
gmyth_file_local_set_file_name(GMythFileLocal * file_local,
renatofilho@754
   202
                               const gchar * filename)
rosfran@518
   203
{
renatofilho@754
   204
    gmyth_file_set_file_name(GMYTH_FILE(file_local), filename);
rosfran@513
   205
}
rosfran@513
   206
rosfran@513
   207
/** 
rosfran@513
   208
 * Open a File in order to get a local file.
rosfran@513
   209
 * 
rosfran@513
   210
 * @param file_local The actual File Transfer instance. 
rosfran@513
   211
 * 
rosfran@513
   212
 * @return <code>true</code>, if the connection opening had been done successfully. 
rosfran@513
   213
 */
rosfran@513
   214
gboolean
renatofilho@750
   215
gmyth_file_local_open(GMythFileLocal * file_local)
rosfran@513
   216
{
renatofilho@754
   217
    gboolean        ret = TRUE;
renatofilho@754
   218
    GMythFileLocalPrivate *priv;
renatofilho@754
   219
    gchar          *file_name_uri = NULL;
rosfran@698
   220
renatofilho@754
   221
    g_return_val_if_fail(file_local != NULL, FALSE);
rosfran@513
   222
renatofilho@754
   223
    priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
renatofilho@754
   224
    file_name_uri = gmyth_file_local_get_file_name(file_local);
rosfran@518
   225
renatofilho@754
   226
    if (file_name_uri != NULL) {
renatofilho@754
   227
        priv->file_io =
renatofilho@754
   228
            g_io_channel_new_file(g_strdup(file_name_uri), "r+", NULL);
renatofilho@754
   229
        g_free(file_name_uri);
renatofilho@754
   230
    }
rosfran@518
   231
renatofilho@754
   232
    if (priv->file_io < 0)
renatofilho@754
   233
        ret = FALSE;
rosfran@513
   234
renatofilho@754
   235
    return ret;
rosfran@513
   236
}
rosfran@513
   237
rosfran@513
   238
/** 
rosfran@513
   239
 * Closes a remote File Transfer connection.
rosfran@513
   240
 * 
rosfran@513
   241
 * @param file_local The actual File Transfer instance. 
rosfran@513
   242
 */
rosfran@513
   243
void
renatofilho@750
   244
gmyth_file_local_close(GMythFileLocal * file_local)
rosfran@513
   245
{
renatofilho@754
   246
    g_return_if_fail(file_local != NULL);
rosfran@513
   247
}
rosfran@513
   248
rosfran@513
   249
/** 
rosfran@513
   250
 * Acquire access to a local file read/write pointer.
rosfran@513
   251
 * 
rosfran@513
   252
 * @param transfer The actual File Local instance.
rosfran@513
   253
 * @param do_wait Waits or not on a GCond, when trying to read from the remote socket.
rosfran@513
   254
 * 
rosfran@513
   255
 * @return <code>true</code>, if the acquire had been got. 
rosfran@513
   256
 */
renatofilho@754
   257
static          gboolean
renatofilho@750
   258
_control_acquire_context(GMythFileLocal * file_local, gboolean do_wait)
rosfran@513
   259
{
renatofilho@754
   260
    gboolean        ret = TRUE;
renatofilho@754
   261
    GMythFileLocalPrivate *priv;
rosfran@513
   262
renatofilho@754
   263
    g_return_val_if_fail(file_local != NULL, FALSE);
renatofilho@754
   264
    priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
rosfran@513
   265
renatofilho@754
   266
    g_mutex_lock(priv->mutex);
renatofilho@754
   267
    return ret;
rosfran@513
   268
}
rosfran@513
   269
rosfran@513
   270
/** 
rosfran@513
   271
 * Release access to a local file read/write pointer.
rosfran@513
   272
 * 
rosfran@513
   273
 * @param transfer The actual File Transfer instance.
rosfran@513
   274
 * 
rosfran@513
   275
 * @return <code>true</code>, if the local file read/write permissions had been releaseds. 
rosfran@513
   276
 */
renatofilho@754
   277
static          gboolean
renatofilho@750
   278
_control_release_context(GMythFileLocal * file_local)
rosfran@513
   279
{
renatofilho@754
   280
    gboolean        ret = TRUE;
renatofilho@754
   281
    GMythFileLocalPrivate *priv;
rosfran@513
   282
renatofilho@754
   283
    g_return_val_if_fail(file_local != NULL, FALSE);
renatofilho@754
   284
    priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
rosfran@698
   285
renatofilho@754
   286
    g_mutex_unlock(priv->mutex);
rosfran@698
   287
renatofilho@754
   288
    return ret;
rosfran@513
   289
}
rosfran@513
   290
rosfran@513
   291
/** 
rosfran@513
   292
 * Reads a block from a remote file.
rosfran@513
   293
 * 
rosfran@513
   294
 * @param transfer The actual File Transfer instance.
rosfran@513
   295
 * @param data A GByteArray instance, where all the binary data representing 
rosfran@513
   296
 *                       the remote file will be stored.
rosfran@513
   297
 * @param size The block size, in bytes, to be requested from a remote file.
rosfran@513
   298
 * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only 
rosfran@513
   299
 *                                           gets the actual size
rosfran@513
   300
 * 
rosfran@513
   301
 * @return The actual block size (in bytes) returned by REQUEST_BLOCK message,
rosfran@513
   302
 *              or the error code. 
rosfran@513
   303
 */
rosfran@698
   304
GMythFileReadResult
renatofilho@750
   305
gmyth_file_local_read(GMythFileLocal * file_local, GByteArray * data,
renatofilho@754
   306
                      gint size, gboolean read_unlimited)
rosfran@513
   307
{
renatofilho@754
   308
    gsize           bytes_read = 0;
renatofilho@754
   309
    gint64          total_read = 0;
renatofilho@754
   310
    GMythFileReadResult retval = GMYTH_FILE_READ_OK;
renatofilho@754
   311
    GMythFileLocalPrivate *priv;
rosfran@513
   312
renatofilho@754
   313
    GError         *error = NULL;
rosfran@513
   314
renatofilho@754
   315
    GIOCondition    io_cond;
renatofilho@754
   316
    GIOStatus       io_status = G_IO_STATUS_NORMAL;
rosfran@513
   317
renatofilho@754
   318
    g_return_val_if_fail(file_local != NULL, FALSE);
renatofilho@754
   319
    g_return_val_if_fail(data != NULL, GMYTH_FILE_READ_ERROR);
rosfran@513
   320
renatofilho@754
   321
    priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
rosfran@513
   322
renatofilho@754
   323
    io_status = g_io_channel_set_encoding(priv->file_io, NULL, &error);
renatofilho@754
   324
    if (io_status == G_IO_STATUS_NORMAL)
renatofilho@754
   325
        gmyth_debug("Setting encoding to binary file data stream.\n");
rosfran@513
   326
renatofilho@754
   327
    io_cond = g_io_channel_get_buffer_condition(priv->file_io);
rosfran@513
   328
renatofilho@754
   329
    _control_acquire_context(file_local, TRUE);
rosfran@513
   330
renatofilho@754
   331
    if (size > 0) {
renatofilho@754
   332
        gchar          *data_buffer = g_new0(gchar, size);
rosfran@698
   333
renatofilho@754
   334
        io_status = g_io_channel_read_chars(priv->file_io,
renatofilho@754
   335
                                            data_buffer, (gsize) size,
renatofilho@754
   336
                                            &bytes_read, &error);
rosfran@513
   337
renatofilho@754
   338
        if (io_status != G_IO_STATUS_NORMAL) {
renatofilho@754
   339
            gmyth_debug("Error on io_channel");
renatofilho@754
   340
            g_free(data_buffer);
renatofilho@754
   341
            retval = GMYTH_FILE_READ_ERROR;
renatofilho@754
   342
            goto error;
renatofilho@754
   343
        }
rosfran@513
   344
renatofilho@754
   345
        /*
renatofilho@754
   346
         * append new data to the increasing byte array 
renatofilho@754
   347
         */
renatofilho@754
   348
        data =
renatofilho@754
   349
            g_byte_array_append(data, (const guint8 *) data_buffer,
renatofilho@754
   350
                                bytes_read);
renatofilho@754
   351
        total_read += bytes_read;
rosfran@698
   352
renatofilho@754
   353
        if (!read_unlimited
renatofilho@754
   354
            && (gmyth_file_local_get_filesize(file_local) > 0)
renatofilho@754
   355
            && (gmyth_file_local_get_offset(file_local) ==
renatofilho@754
   356
                gmyth_file_local_get_filesize(file_local))) {
renatofilho@754
   357
            retval = GMYTH_FILE_READ_EOF;
renatofilho@754
   358
            goto error;
renatofilho@754
   359
        }
rosfran@698
   360
renatofilho@754
   361
        g_free(data_buffer);
renatofilho@754
   362
    } else {
renatofilho@754
   363
        retval = GMYTH_FILE_READ_ERROR;
renatofilho@754
   364
    }
rosfran@513
   365
renatofilho@754
   366
  error:
renatofilho@754
   367
    _control_release_context(file_local);
rosfran@513
   368
renatofilho@754
   369
    if (error != NULL) {
renatofilho@754
   370
        gmyth_debug("Cleaning-up ERROR: [msg = %s, code = %d]\n",
renatofilho@754
   371
                    error->message, error->code);
renatofilho@754
   372
        g_error_free(error);
renatofilho@754
   373
    }
rosfran@698
   374
renatofilho@754
   375
    if (total_read > 0)
renatofilho@754
   376
        gmyth_file_local_set_offset(file_local,
renatofilho@754
   377
                                    (gmyth_file_local_get_offset
renatofilho@754
   378
                                     (file_local) + total_read));
rosfran@513
   379
renatofilho@754
   380
    return retval;
rosfran@513
   381
}
rosfran@513
   382
rosfran@529
   383
gint64
renatofilho@750
   384
gmyth_file_local_seek(GMythFileLocal * file_local, gint64 pos,
renatofilho@754
   385
                      GSeekType whence)
rosfran@529
   386
{
renatofilho@754
   387
    GMythFileLocalPrivate *priv;
rosfran@698
   388
renatofilho@754
   389
    GError         *error;
rosfran@698
   390
renatofilho@754
   391
    GIOStatus       io_status = G_IO_STATUS_NORMAL;
rosfran@698
   392
renatofilho@754
   393
    g_return_val_if_fail(file_local != NULL, -1);
rosfran@698
   394
renatofilho@754
   395
    priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
rosfran@698
   396
renatofilho@754
   397
    io_status =
renatofilho@754
   398
        g_io_channel_seek_position(priv->file_io, pos, whence, &error);
rosfran@698
   399
renatofilho@754
   400
    if (io_status == G_IO_STATUS_ERROR)
renatofilho@754
   401
        pos = -1;
rosfran@698
   402
renatofilho@754
   403
    return pos;
rosfran@698
   404
rosfran@529
   405
}
rosfran@529
   406
rosfran@513
   407
/** 
rosfran@513
   408
 * Gets the actual file_local size of the binary content.
rosfran@513
   409
 * 
rosfran@513
   410
 * @param file_local The actual File Transfer instance.
rosfran@513
   411
 * 
rosfran@513
   412
 * @return The actual file_local size in bytes. 
rosfran@513
   413
 */
rosfran@513
   414
guint64
renatofilho@750
   415
gmyth_file_local_get_filesize(GMythFileLocal * file_local)
rosfran@513
   416
{
renatofilho@754
   417
    g_return_val_if_fail(file_local != NULL, 0);
rosfran@513
   418
renatofilho@754
   419
    return gmyth_file_get_filesize(GMYTH_FILE(file_local));
rosfran@513
   420
}
rosfran@513
   421
rosfran@513
   422
/** 
rosfran@513
   423
 * Sets the actual file_local size.
rosfran@513
   424
 * 
rosfran@513
   425
 * @param file_local The actual File Transfer instance.
rosfran@513
   426
 * @param filesize The actual File Transfer size, in bytes.
rosfran@513
   427
 */
rosfran@513
   428
void
renatofilho@754
   429
gmyth_file_local_set_filesize(GMythFileLocal * file_local,
renatofilho@754
   430
                              guint64 filesize)
rosfran@513
   431
{
renatofilho@754
   432
    g_return_if_fail(file_local != NULL);
rosfran@513
   433
renatofilho@754
   434
    gmyth_file_set_filesize(GMYTH_FILE(file_local), filesize);
rosfran@513
   435
}
rosfran@513
   436
rosfran@513
   437
/** 
rosfran@513
   438
 * Gets the actual file offset of the binary content.
rosfran@513
   439
 * 
rosfran@513
   440
 * @param file_local The actual File Transfer instance.
rosfran@513
   441
 * 
rosfran@518
   442
 * @return The actual file offset in bytes.
rosfran@513
   443
 */
rosfran@513
   444
gint64
renatofilho@750
   445
gmyth_file_local_get_offset(GMythFileLocal * file_local)
rosfran@513
   446
{
renatofilho@754
   447
    g_return_val_if_fail(file_local != NULL, 0);
rosfran@513
   448
renatofilho@754
   449
    return gmyth_file_get_offset(GMYTH_FILE(file_local));
rosfran@513
   450
}
rosfran@513
   451
rosfran@513
   452
/** 
rosfran@513
   453
 * Sets the actual file offset.
rosfran@513
   454
 * 
rosfran@513
   455
 * @param file_local The actual File Local instance.
rosfran@513
   456
 * @param offset The actual File Local offset, in bytes.
rosfran@513
   457
 */
rosfran@513
   458
void
renatofilho@750
   459
gmyth_file_local_set_offset(GMythFileLocal * file_local, gint64 offset)
rosfran@513
   460
{
renatofilho@754
   461
    g_return_if_fail(file_local != NULL);
rosfran@513
   462
renatofilho@754
   463
    gmyth_file_set_offset(GMYTH_FILE(file_local), offset);
rosfran@513
   464
}