gst-plugins-mythtv/src/gstmythtvsrc.c.new
author renatofilho
Wed Mar 21 21:35:20 2007 +0000 (2007-03-21)
branchtrunk
changeset 425 9638cccfa1fe
parent 10 00c73ffe40ad
permissions -rwxr-xr-x
[svn r430] inital seek imple
rosfran@10
     1
/* vim: set sw=2: -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2; c-indent-level: 2 -*- */
rosfran@10
     2
/* GStreamer MythTV Plug-in
rosfran@10
     3
 * Copyright (C) <2006> Rosfran Borges <rosfran.borges@indt.org.br>
rosfran@10
     4
 *
rosfran@10
     5
 * This library is free software; you can redistribute it and/or
rosfran@10
     6
 * modify it under the terms of the GNU Library General Public
rosfran@10
     7
 * License as published by the Free Software Foundation; either
rosfran@10
     8
 * version 2 of the License, or (at your option) any later version.
rosfran@10
     9
 *
rosfran@10
    10
 * This library is distributed in the hope that it will be useful,
rosfran@10
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rosfran@10
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
rosfran@10
    13
 * Library General Public License for more 
rosfran@10
    14
 */
rosfran@10
    15
rosfran@10
    16
#ifdef HAVE_CONFIG_H
rosfran@10
    17
#include "config.h"
rosfran@10
    18
#endif
rosfran@10
    19
rosfran@10
    20
#include "gstmythtvsrc.h"
rosfran@10
    21
#include "myth_file_transfer.h"
rosfran@10
    22
#include "myth_livetv.h"
rosfran@10
    23
rosfran@10
    24
#include <gmyth/gmyth_socket.h>
rosfran@10
    25
#include <gmyth/gmyth_tvchain.h>
rosfran@10
    26
rosfran@10
    27
#include <string.h>
rosfran@10
    28
#include <unistd.h>
rosfran@10
    29
rosfran@10
    30
GST_DEBUG_CATEGORY_STATIC (mythtvsrc_debug);
rosfran@10
    31
#define GST_CAT_DEFAULT mythtvsrc_debug
rosfran@10
    32
rosfran@10
    33
#define GST_MYTHTV_ID_NUM		1
rosfran@10
    34
rosfran@10
    35
#define MYTHTV_VERSION_DEFAULT		30
rosfran@10
    36
rosfran@10
    37
#define MYTHTV_TRANSFER_MAX_WAITS	100
rosfran@10
    38
rosfran@10
    39
#define MYTHTV_TRANSFER_MAX_BUFFER	( 32*1024  )
rosfran@10
    40
rosfran@10
    41
/* 4*1024 ??? */
rosfran@10
    42
#define MAX_READ_SIZE                   ( 16*1024 )
rosfran@10
    43
rosfran@10
    44
#define ENABLE_TIMING_POSITION		1
rosfran@10
    45
rosfran@10
    46
/* stablish a maximum iteration value to the IS_RECORDING message */
rosfran@10
    47
static guint wait_to_transfer = 0;
rosfran@10
    48
rosfran@10
    49
static const GstElementDetails gst_mythtv_src_details =
rosfran@10
    50
GST_ELEMENT_DETAILS ("MythTV client source",
rosfran@10
    51
    "Source/Network",
rosfran@10
    52
    "Control and receive data as a client over the network via raw socket connections using the MythTV protocol",
rosfran@10
    53
    "Rosfran Borges <rosfran.borges@indt.org.br>");
rosfran@10
    54
rosfran@10
    55
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
rosfran@10
    56
    GST_PAD_SRC,
rosfran@10
    57
    GST_PAD_ALWAYS,
rosfran@10
    58
    GST_STATIC_CAPS_ANY);
rosfran@10
    59
rosfran@10
    60
static GstTask *update_size_task = NULL;
rosfran@10
    61
rosfran@10
    62
static GStaticRecMutex update_size_mutex = G_STATIC_REC_MUTEX_INIT;
rosfran@10
    63
rosfran@10
    64
enum
rosfran@10
    65
{
rosfran@10
    66
  PROP_0,
rosfran@10
    67
  PROP_LOCATION,
rosfran@10
    68
  PROP_URI,
rosfran@10
    69
#ifndef GST_DISABLE_GST_DEBUG
rosfran@10
    70
  PROP_MYTHTV_DBG,
rosfran@10
    71
#endif
rosfran@10
    72
  PROP_MYTHTV_VERSION,
rosfran@10
    73
  PROP_MYTHTV_LIVE,
rosfran@10
    74
  PROP_MYTHTV_LIVEID,
rosfran@10
    75
  PROP_MYTHTV_LIVE_CHAINID
rosfran@10
    76
};
rosfran@10
    77
rosfran@10
    78
static void gst_mythtv_src_finalize (GObject * gobject);
rosfran@10
    79
rosfran@10
    80
static GstFlowReturn gst_mythtv_src_create (GstBaseSrc * psrc,
rosfran@10
    81
    guint64 offset, guint size, GstBuffer ** outbuf);
rosfran@10
    82
static gboolean gst_mythtv_src_start (GstBaseSrc * bsrc);
rosfran@10
    83
static gboolean gst_mythtv_src_stop (GstBaseSrc * bsrc);
rosfran@10
    84
static gboolean gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size);
rosfran@10
    85
static gboolean gst_mythtv_src_is_seekable( GstBaseSrc *base_src );
rosfran@10
    86
rosfran@10
    87
static void gst_mythtv_src_set_property (GObject * object, guint prop_id,
rosfran@10
    88
    const GValue * value, GParamSpec * pspec);
rosfran@10
    89
static void gst_mythtv_src_get_property (GObject * object, guint prop_id,
rosfran@10
    90
    GValue * value, GParamSpec * pspec);
rosfran@10
    91
rosfran@10
    92
static void
rosfran@10
    93
gst_mythtv_src_uri_handler_init (gpointer g_iface, gpointer iface_data);
rosfran@10
    94
rosfran@10
    95
static gboolean
rosfran@10
    96
gst_mythtv_src_handle_event (GstPad * pad, GstEvent * event);
rosfran@10
    97
rosfran@10
    98
  static void
rosfran@10
    99
_urihandler_init (GType type)
rosfran@10
   100
{
rosfran@10
   101
  static const GInterfaceInfo urihandler_info = {
rosfran@10
   102
    gst_mythtv_src_uri_handler_init,
rosfran@10
   103
    NULL,
rosfran@10
   104
    NULL
rosfran@10
   105
  };
rosfran@10
   106
rosfran@10
   107
  g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info);
rosfran@10
   108
rosfran@10
   109
  GST_DEBUG_CATEGORY_INIT (mythtvsrc_debug, "mythtvsrc", 0,
rosfran@10
   110
      "MythTV src");
rosfran@10
   111
}
rosfran@10
   112
rosfran@10
   113
GST_BOILERPLATE_FULL (GstMythtvSrc, gst_mythtv_src, GstBaseSrc,
rosfran@10
   114
    GST_TYPE_BASE_SRC, _urihandler_init);
rosfran@10
   115
rosfran@10
   116
  static void
rosfran@10
   117
gst_mythtv_src_base_init (gpointer g_class)
rosfran@10
   118
{
rosfran@10
   119
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
rosfran@10
   120
rosfran@10
   121
  gst_element_class_add_pad_template (element_class,
rosfran@10
   122
      gst_static_pad_template_get (&srctemplate));
rosfran@10
   123
rosfran@10
   124
  gst_element_class_set_details (element_class, &gst_mythtv_src_details);
rosfran@10
   125
}
rosfran@10
   126
rosfran@10
   127
  static void
rosfran@10
   128
gst_mythtv_src_class_init (GstMythtvSrcClass * klass)
rosfran@10
   129
{
rosfran@10
   130
  GObjectClass *gobject_class;
rosfran@10
   131
  GstBaseSrcClass *gstbasesrc_class;
rosfran@10
   132
rosfran@10
   133
  gobject_class = (GObjectClass *) klass;
rosfran@10
   134
  gstbasesrc_class = (GstBaseSrcClass *) klass;
rosfran@10
   135
rosfran@10
   136
  gobject_class->set_property = gst_mythtv_src_set_property;
rosfran@10
   137
  gobject_class->get_property = gst_mythtv_src_get_property;
rosfran@10
   138
  gobject_class->finalize = gst_mythtv_src_finalize;
rosfran@10
   139
rosfran@10
   140
  g_object_class_install_property
rosfran@10
   141
    (gobject_class, PROP_LOCATION,
rosfran@10
   142
     g_param_spec_string ("location", "Location",
rosfran@10
   143
       "The location. In the form:"
rosfran@10
   144
       "\n\t\t\tmyth://a.com/file.nuv"
rosfran@10
   145
       "\n\t\t\tmyth://a.com:23223/file.nuv "
rosfran@10
   146
       "\n\t\t\ta.com/file.nuv - default scheme 'myth'",
rosfran@10
   147
       "", G_PARAM_READWRITE));
rosfran@10
   148
rosfran@10
   149
  g_object_class_install_property
rosfran@10
   150
    (gobject_class, PROP_URI,
rosfran@10
   151
     g_param_spec_string ("uri", "Uri",
rosfran@10
   152
       "The location in form of a URI (deprecated; use location)",
rosfran@10
   153
       "", G_PARAM_READWRITE));
rosfran@10
   154
rosfran@10
   155
  g_object_class_install_property
rosfran@10
   156
    (gobject_class, PROP_MYTHTV_VERSION,
rosfran@10
   157
     g_param_spec_int ("mythtv-version", "mythtv-version",
rosfran@10
   158
       "Change Myth TV version",
rosfran@10
   159
       26, 30, 26, G_PARAM_READWRITE));
rosfran@10
   160
rosfran@10
   161
  g_object_class_install_property
rosfran@10
   162
    (gobject_class, PROP_MYTHTV_LIVEID,
rosfran@10
   163
     g_param_spec_int ("mythtv-live-id", "mythtv-live-id",
rosfran@10
   164
       "Change Myth TV version",
rosfran@10
   165
       0, 200, GST_MYTHTV_ID_NUM, G_PARAM_READWRITE));
rosfran@10
   166
rosfran@10
   167
  g_object_class_install_property
rosfran@10
   168
    (gobject_class, PROP_MYTHTV_LIVE_CHAINID,
rosfran@10
   169
     g_param_spec_string ("mythtv-live-chainid", "mythtv-live-chainid",
rosfran@10
   170
       "Sets the Myth TV chain ID (from TV Chain)",
rosfran@10
   171
       "", G_PARAM_READWRITE));
rosfran@10
   172
rosfran@10
   173
  g_object_class_install_property
rosfran@10
   174
    (gobject_class, PROP_MYTHTV_LIVE,
rosfran@10
   175
     g_param_spec_boolean ("mythtv-live", "mythtv-live",
rosfran@10
   176
       "Enable MythTV Live TV content streaming",
rosfran@10
   177
       FALSE, G_PARAM_READWRITE));
rosfran@10
   178
rosfran@10
   179
#ifndef GST_DISABLE_GST_DEBUG
rosfran@10
   180
  g_object_class_install_property
rosfran@10
   181
    (gobject_class, PROP_MYTHTV_DBG,
rosfran@10
   182
     g_param_spec_boolean ("mythtv-debug", "mythtv-debug",
rosfran@10
   183
       "Enable MythTV debug messages",
rosfran@10
   184
       FALSE, G_PARAM_READWRITE));
rosfran@10
   185
#endif
rosfran@10
   186
rosfran@10
   187
  gstbasesrc_class->start = gst_mythtv_src_start;
rosfran@10
   188
  gstbasesrc_class->stop = gst_mythtv_src_stop;
rosfran@10
   189
  gstbasesrc_class->get_size = gst_mythtv_src_get_size;
rosfran@10
   190
  gstbasesrc_class->is_seekable = gst_mythtv_src_is_seekable;
rosfran@10
   191
rosfran@10
   192
  gstbasesrc_class->create = gst_mythtv_src_create;
rosfran@10
   193
rosfran@10
   194
  GST_DEBUG_CATEGORY_INIT (mythtvsrc_debug, "mythtvsrc", 0,
rosfran@10
   195
      "MythTV Client Source");
rosfran@10
   196
}
rosfran@10
   197
rosfran@10
   198
  static void
rosfran@10
   199
gst_mythtv_src_init (GstMythtvSrc * this, GstMythtvSrcClass * g_class)
rosfran@10
   200
{
rosfran@10
   201
  this->file_transfer = NULL;
rosfran@10
   202
rosfran@10
   203
  this->unique_setup = FALSE;
rosfran@10
   204
rosfran@10
   205
  this->mythtv_version = MYTHTV_VERSION_DEFAULT;
rosfran@10
   206
rosfran@10
   207
  this->bytes_read = 0;
rosfran@10
   208
rosfran@10
   209
  this->content_size = -1;
rosfran@10
   210
  this->read_offset = 0;
rosfran@10
   211
rosfran@10
   212
  this->live_tv = FALSE;
rosfran@10
   213
rosfran@10
   214
  this->user_agent = g_strdup ("mythtvsrc");
rosfran@10
   215
  this->mythtv_caps = NULL;    
rosfran@10
   216
rosfran@10
   217
  gst_base_src_set_live ( GST_BASE_SRC( this ), TRUE );
rosfran@10
   218
rosfran@10
   219
  gst_pad_set_event_function (GST_BASE_SRC_PAD(GST_BASE_SRC(this)),
rosfran@10
   220
      GST_DEBUG_FUNCPTR (gst_mythtv_src_handle_event));
rosfran@10
   221
rosfran@10
   222
}
rosfran@10
   223
rosfran@10
   224
  static void
rosfran@10
   225
gst_mythtv_src_finalize (GObject * gobject)
rosfran@10
   226
{
rosfran@10
   227
  GstMythtvSrc *this = GST_MYTHTV_SRC (gobject);
rosfran@10
   228
rosfran@10
   229
  g_free (this->user_agent);
rosfran@10
   230
rosfran@10
   231
  if (this->mythtv_caps) {
rosfran@10
   232
    gst_caps_unref (this->mythtv_caps);
rosfran@10
   233
    this->mythtv_caps = NULL;
rosfran@10
   234
  }
rosfran@10
   235
rosfran@10
   236
  if (this->file_transfer) {
rosfran@10
   237
    g_object_unref (this->file_transfer);
rosfran@10
   238
    this->file_transfer = NULL;
rosfran@10
   239
  }
rosfran@10
   240
rosfran@10
   241
  if (this->uri_name) {
rosfran@10
   242
    g_free (this->uri_name);
rosfran@10
   243
  }
rosfran@10
   244
rosfran@10
   245
  if (this->user_agent) {
rosfran@10
   246
    g_free (this->user_agent);
rosfran@10
   247
  }
rosfran@10
   248
rosfran@10
   249
  if ( update_size_task != NULL ) {
rosfran@10
   250
rosfran@10
   251
    if ( GST_TASK_STATE( update_size_task ) != GST_TASK_STOPPED )
rosfran@10
   252
    	gst_task_stop( update_size_task );
rosfran@10
   253
rosfran@10
   254
    gst_object_unref( update_size_task );
rosfran@10
   255
rosfran@10
   256
    update_size_task = NULL;
rosfran@10
   257
rosfran@10
   258
  }
rosfran@10
   259
rosfran@10
   260
  G_OBJECT_CLASS (parent_class)->finalize (gobject);
rosfran@10
   261
}
rosfran@10
   262
rosfran@10
   263
#if 0
rosfran@10
   264
  static guint
rosfran@10
   265
do_seek( GstMythtvSrc *src, guint64 offset, guint size, GstBuffer *outbuf )
rosfran@10
   266
{
rosfran@10
   267
  guint64 off_uint64 = myth_file_transfer_seek(src->file_transfer, offset, 1);
rosfran@10
   268
rosfran@10
   269
  g_print( "[%s] Call MythTV SEEK with offset %llu, got a new one %llu...\n", __FUNCTION__, 
rosfran@10
   270
      offset, off_uint64 );
rosfran@10
   271
rosfran@10
   272
  return off_uint64;
rosfran@10
   273
rosfran@10
   274
}
rosfran@10
   275
#endif
rosfran@10
   276
rosfran@10
   277
  static guint
rosfran@10
   278
do_read_request_response (GstMythtvSrc * src, guint64 offset, guint size, GstBuffer * outbuf)
rosfran@10
   279
{
rosfran@10
   280
  guint read = 0;
rosfran@10
   281
  guint sizetoread = size; //GST_BUFFER_SIZE (outbuf);
rosfran@10
   282
rosfran@10
   283
  g_print( "[%s] Reading %d bytes...\n", __FUNCTION__, sizetoread ); 
rosfran@10
   284
rosfran@10
   285
  /* Loop sending the request:
rosfran@10
   286
   * Retry whilst authentication fails and we supply it. */
rosfran@10
   287
rosfran@10
   288
  ssize_t len = 0;
rosfran@10
   289
rosfran@10
   290
  //GST_OBJECT_LOCK(src);
rosfran@10
   291
rosfran@10
   292
  while ( sizetoread > 0 ) {
rosfran@10
   293
rosfran@10
   294
    len = myth_file_transfer_read( src->file_transfer,
rosfran@10
   295
	GST_BUFFER_DATA (outbuf) + read, sizetoread, TRUE );
rosfran@10
   296
rosfran@10
   297
    if ( len > 0 ) {
rosfran@10
   298
      read += len;
rosfran@10
   299
      src->read_offset += read;
rosfran@10
   300
      sizetoread -= len;
rosfran@10
   301
    } else if ( len < 0 ) {
rosfran@10
   302
      goto done;
rosfran@10
   303
    }
rosfran@10
   304
    else if ( len == 0 ) {
rosfran@10
   305
      if ( src->live_tv == FALSE )
rosfran@10
   306
	goto done;
rosfran@10
   307
      else
rosfran@10
   308
	goto eos;
rosfran@10
   309
rosfran@10
   310
    }
rosfran@10
   311
rosfran@10
   312
    if ( len == sizetoread )
rosfran@10
   313
      break;
rosfran@10
   314
rosfran@10
   315
  }
rosfran@10
   316
rosfran@10
   317
  if ( read > 0 ) {
rosfran@10
   318
    src->bytes_read += read;
rosfran@10
   319
rosfran@10
   320
    GST_BUFFER_SIZE (outbuf) = read;
rosfran@10
   321
  } else if ( read <= 0 || len <= 0 ) {
rosfran@10
   322
    if ( src->live_tv == FALSE )
rosfran@10
   323
      goto eos;
rosfran@10
   324
    else
rosfran@10
   325
      goto done;
rosfran@10
   326
  }
rosfran@10
   327
  //GST_BUFFER_OFFSET (outbuf) = src->read_offset;
rosfran@10
   328
rosfran@10
   329
  g_print( "[%s]\tBYTES READ (actual) = %d, BYTES READ (cumulative) = %llu, "\
rosfran@10
   330
      "OFFSET = %llu, CONTENT SIZE = %llu.\n", __FUNCTION__, read, src->bytes_read, 
rosfran@10
   331
      src->read_offset, src->content_size );
rosfran@10
   332
rosfran@10
   333
  //GST_OBJECT_UNLOCK(src);
rosfran@10
   334
rosfran@10
   335
  if ( len < 0 ) {
rosfran@10
   336
    read = len;
rosfran@10
   337
    if ( src->live_tv == FALSE ) 
rosfran@10
   338
      goto eos;
rosfran@10
   339
    else
rosfran@10
   340
      goto done;
rosfran@10
   341
  }
rosfran@10
   342
rosfran@10
   343
  if ( src->bytes_read < src->content_size )
rosfran@10
   344
    goto done;
rosfran@10
   345
rosfran@10
   346
eos:
rosfran@10
   347
  //GST_OBJECT_UNLOCK(src);
rosfran@10
   348
rosfran@10
   349
  src->eos = TRUE;
rosfran@10
   350
done:
rosfran@10
   351
  //GST_OBJECT_UNLOCK(src);
rosfran@10
   352
rosfran@10
   353
  return read;
rosfran@10
   354
}
rosfran@10
   355
rosfran@10
   356
  static GstFlowReturn
rosfran@10
   357
gst_mythtv_src_create ( GstBaseSrc * psrc, guint64 offset, 
rosfran@10
   358
    guint size, GstBuffer **outbuf )
rosfran@10
   359
{
rosfran@10
   360
  GstMythtvSrc *src;
rosfran@10
   361
  GstFlowReturn ret = GST_FLOW_OK;
rosfran@10
   362
  guint read = 0;
rosfran@10
   363
rosfran@10
   364
  src = GST_MYTHTV_SRC (psrc);
rosfran@10
   365
rosfran@10
   366
  //src->do_start = FALSE;
rosfran@10
   367
  src->do_start = FALSE;
rosfran@10
   368
  gst_task_join ( update_size_task );
rosfran@10
   369
rosfran@10
   370
  g_print( "[%s]\tBUFFER OFFSET = %llu, BUFFER SIZE = %d.\n", __FUNCTION__, offset, 
rosfran@10
   371
      size );
rosfran@10
   372
rosfran@10
   373
  /* The caller should know the number of bytes and not read beyond EOS. */
rosfran@10
   374
  //if (G_UNLIKELY (src->eos))
rosfran@10
   375
  //  goto eos;
rosfran@10
   376
  //g_static_rec_mutex_lock( &update_size_mutex );
rosfran@10
   377
rosfran@10
   378
  /* Create the buffer. */
rosfran@10
   379
  ret = gst_pad_alloc_buffer ( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)),
rosfran@10
   380
      //      GST_BUFFER_OFFSET_NONE, GST_BASE_SRC (psrc)->blocksize,
rosfran@10
   381
      offset, size,
rosfran@10
   382
      src->mythtv_caps ? src->mythtv_caps :
rosfran@10
   383
      GST_PAD_CAPS (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc))), outbuf );
rosfran@10
   384
rosfran@10
   385
  //if (G_UNLIKELY (ret == GST_FLOW_UNEXPECTED))
rosfran@10
   386
  //  goto eos;
rosfran@10
   387
rosfran@10
   388
  if (G_UNLIKELY (ret != GST_FLOW_OK))
rosfran@10
   389
    goto eos;
rosfran@10
   390
rosfran@10
   391
  if (G_UNLIKELY (ret == GST_FLOW_ERROR))
rosfran@10
   392
    goto read_error;
rosfran@10
   393
rosfran@10
   394
  read = do_read_request_response ( src, offset, size, *outbuf );
rosfran@10
   395
rosfran@10
   396
  //g_static_rec_mutex_unlock( &update_size_mutex );
rosfran@10
   397
rosfran@10
   398
  src->do_start = TRUE;
rosfran@10
   399
  gst_task_start ( update_size_task );
rosfran@10
   400
rosfran@10
   401
#if 0
rosfran@10
   402
  g_static_rec_mutex_lock( &update_size_mutex );
rosfran@10
   403
  src->do_start = FALSE;  
rosfran@10
   404
  g_static_rec_mutex_unlock( &update_size_mutex );
rosfran@10
   405
  GST_TASK_SIGNAL( update_size_task );
rosfran@10
   406
#endif
rosfran@10
   407
rosfran@10
   408
  //g_static_rec_mutex_unlock( &update_size_mutex );
rosfran@10
   409
rosfran@10
   410
#if 0
rosfran@10
   411
#if ENABLE_TIMING_POSITION == 1
rosfran@10
   412
  guint64 size_tmp = 0;
rosfran@10
   413
  if (src->live_tv == TRUE) {
rosfran@10
   414
    //g_usleep( 1000 );
rosfran@10
   415
get_file_pos:
rosfran@10
   416
    //g_usleep( 100 );
rosfran@10
   417
    size_tmp = myth_file_transfer_get_file_position( src->file_transfer );
rosfran@10
   418
    if ( size_tmp > ( src->content_size + MYTHTV_TRANSFER_MAX_BUFFER ) )
rosfran@10
   419
      src->content_size = size_tmp;
rosfran@10
   420
    else
rosfran@10
   421
      goto get_file_pos;
rosfran@10
   422
    g_print( "\t[%s]\tGET_POSITION: file_position = %llu\n", 
rosfran@10
   423
	__FUNCTION__, size_tmp);
rosfran@10
   424
rosfran@10
   425
  }
rosfran@10
   426
#endif
rosfran@10
   427
#endif
rosfran@10
   428
rosfran@10
   429
  //if (G_UNLIKELY (read < 0))
rosfran@10
   430
  //  goto read_error;
rosfran@10
   431
rosfran@10
   432
  if (G_UNLIKELY(src->eos))
rosfran@10
   433
    goto eos;
rosfran@10
   434
  else
rosfran@10
   435
    goto done;
rosfran@10
   436
rosfran@10
   437
done:
rosfran@10
   438
  return ret;
rosfran@10
   439
eos:
rosfran@10
   440
#if 0
rosfran@10
   441
#if ENABLE_TIMING_POSITION == 1
rosfran@10
   442
  if ( src->live_tv == TRUE ) {
rosfran@10
   443
    //g_usleep( 1000 );
rosfran@10
   444
    guint64 size_tmp = 0;
rosfran@10
   445
get_file_pos_eos:
rosfran@10
   446
    //g_usleep( 100 );
rosfran@10
   447
    size_tmp = myth_file_transfer_get_file_position( src->file_transfer );
rosfran@10
   448
    if ( size_tmp > ( src->content_size + MYTHTV_TRANSFER_MAX_BUFFER ) )
rosfran@10
   449
      src->content_size = size_tmp;
rosfran@10
   450
    else
rosfran@10
   451
      goto get_file_pos_eos;
rosfran@10
   452
    g_print( "\t[%s]\tGET_POSITION: file_position = %llu\n", 
rosfran@10
   453
	__FUNCTION__, size_tmp);
rosfran@10
   454
    goto done;
rosfran@10
   455
  } else 
rosfran@10
   456
#endif
rosfran@10
   457
#endif
rosfran@10
   458
  {
rosfran@10
   459
    GST_DEBUG_OBJECT (src, "EOS reached");
rosfran@10
   460
    return GST_FLOW_UNEXPECTED;
rosfran@10
   461
  }
rosfran@10
   462
  /* ERRORS */
rosfran@10
   463
read_error:
rosfran@10
   464
  {
rosfran@10
   465
    GST_ELEMENT_ERROR (src, RESOURCE, READ,
rosfran@10
   466
	(NULL), ("Could not read any bytes (%i, %s)", read,
rosfran@10
   467
	  src->uri_name));
rosfran@10
   468
    return GST_FLOW_ERROR;
rosfran@10
   469
  }
rosfran@10
   470
  #if 0
rosfran@10
   471
need_pause:
rosfran@10
   472
  {
rosfran@10
   473
    const gchar *reason = gst_flow_get_name (ret);
rosfran@10
   474
rosfran@10
   475
    GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
rosfran@10
   476
    return GST_FLOW_UNEXPECTED;
rosfran@10
   477
  }
rosfran@10
   478
  #endif
rosfran@10
   479
rosfran@10
   480
}
rosfran@10
   481
rosfran@10
   482
#if 0
rosfran@10
   483
/* The following two charset mangling functions were copied from gnomevfssrc.
rosfran@10
   484
 * Preserve them under the unverified assumption that they do something vaguely
rosfran@10
   485
 * worthwhile.
rosfran@10
   486
 */
rosfran@10
   487
  static char *
rosfran@10
   488
unicodify (const char *str, int len, ...)
rosfran@10
   489
{
rosfran@10
   490
  char *ret = NULL, *cset;
rosfran@10
   491
  va_list args;
rosfran@10
   492
  gsize bytes_read, bytes_written;
rosfran@10
   493
rosfran@10
   494
  if (g_utf8_validate (str, len, NULL))
rosfran@10
   495
    return g_strndup (str, len >= 0 ? len : strlen (str));
rosfran@10
   496
rosfran@10
   497
  va_start (args, len);
rosfran@10
   498
  while ((cset = va_arg (args, char *)) != NULL)
rosfran@10
   499
  {
rosfran@10
   500
    if (!strcmp (cset, "locale"))
rosfran@10
   501
      ret = g_locale_to_utf8 (str, len, &bytes_read, &bytes_written, NULL);
rosfran@10
   502
    else
rosfran@10
   503
      ret = g_convert (str, len, "UTF-8", cset,
rosfran@10
   504
	  &bytes_read, &bytes_written, NULL);
rosfran@10
   505
    if (ret)
rosfran@10
   506
      break;
rosfran@10
   507
  }
rosfran@10
   508
  va_end (args);
rosfran@10
   509
rosfran@10
   510
  return ret;
rosfran@10
   511
}
rosfran@10
   512
rosfran@10
   513
  static char *
rosfran@10
   514
gst_mythtv_src_unicodify (const char *str)
rosfran@10
   515
{
rosfran@10
   516
  return unicodify (str, -1, "locale", "ISO-8859-1", NULL);
rosfran@10
   517
}
rosfran@10
   518
#endif
rosfran@10
   519
rosfran@10
   520
void
rosfran@10
   521
update_size_func( void *mythtv_data ) 
rosfran@10
   522
{
rosfran@10
   523
  GstMythtvSrc *src;
rosfran@10
   524
rosfran@10
   525
  g_return_if_fail( mythtv_data != NULL );
rosfran@10
   526
rosfran@10
   527
  src = GST_MYTHTV_SRC ( mythtv_data );
rosfran@10
   528
  if ( src->do_start ) {
rosfran@10
   529
 #if ENABLE_TIMING_POSITION == 1
rosfran@10
   530
  guint64 size_tmp = 0;
rosfran@10
   531
  if (src->live_tv == TRUE) {
rosfran@10
   532
get_file_pos:
rosfran@10
   533
    //g_usleep( 50 );
rosfran@10
   534
    size_tmp = myth_file_transfer_get_file_position( src->file_transfer );
rosfran@10
   535
    if ( size_tmp > ( src->content_size + MYTHTV_TRANSFER_MAX_BUFFER ) )
rosfran@10
   536
      src->content_size = size_tmp;
rosfran@10
   537
    else
rosfran@10
   538
      goto get_file_pos;
rosfran@10
   539
    g_print( "\t[%s]\tGET_POSITION: file_position = %llu\n",
rosfran@10
   540
	__FUNCTION__, size_tmp );
rosfran@10
   541
  }
rosfran@10
   542
#endif
rosfran@10
   543
}
rosfran@10
   544
  gst_task_pause( update_size_task );
rosfran@10
   545
 // src->do_start = FALSE;
rosfran@10
   546
  //GST_TASK_SIGNAL( update_size_task );
rosfran@10
   547
rosfran@10
   548
}
rosfran@10
   549
rosfran@10
   550
/* create a socket for connecting to remote server */
rosfran@10
   551
  static gboolean
rosfran@10
   552
gst_mythtv_src_start ( GstBaseSrc * bsrc )
rosfran@10
   553
{
rosfran@10
   554
  GstMythtvSrc *src = GST_MYTHTV_SRC (bsrc);
rosfran@10
   555
rosfran@10
   556
  GString *chain_id_local = NULL;
rosfran@10
   557
rosfran@10
   558
  gboolean ret = TRUE;
rosfran@10
   559
#if 0
rosfran@10
   560
  if (src->live_tv == TRUE && src->file_transfer != NULL) {
rosfran@10
   561
    guint64 size_tmp = myth_file_transfer_get_file_position( src->file_transfer );
rosfran@10
   562
    if (size_tmp > src->content_size)
rosfran@10
   563
      src->content_size = size_tmp;
rosfran@10
   564
    g_print( "\t[%s]\tGET_POSITION: file_position = %llu\n", 
rosfran@10
   565
	__FUNCTION__, size_tmp);
rosfran@10
   566
  }
rosfran@10
   567
#endif
rosfran@10
   568
  if (src->unique_setup == FALSE) {
rosfran@10
   569
    src->unique_setup = TRUE;
rosfran@10
   570
  } else {
rosfran@10
   571
    goto done;
rosfran@10
   572
  }
rosfran@10
   573
rosfran@10
   574
  //GST_OBJECT_LOCK(src);
rosfran@10
   575
rosfran@10
   576
  if ( src->live_tv ) {
rosfran@10
   577
    src->spawn_livetv = myth_livetv_new( );
rosfran@10
   578
    if ( myth_livetv_setup( src->spawn_livetv ) == FALSE ) {
rosfran@10
   579
    	ret = FALSE;
rosfran@10
   580
    	goto init_failed;
rosfran@10
   581
    }
rosfran@10
   582
    /* set up the uri variable */
rosfran@10
   583
    src->uri_name = g_strdup( src->spawn_livetv->proginfo->pathname->str );
rosfran@10
   584
    chain_id_local = gmyth_tvchain_get_id( src->spawn_livetv->tvchain );
rosfran@10
   585
    if ( chain_id_local != NULL ) {
rosfran@10
   586
      src->live_chain_id = g_strdup( chain_id_local->str );
rosfran@10
   587
      g_print( "\t[%s]\tLocal chain ID = %s.\n", __FUNCTION__, src->live_chain_id );
rosfran@10
   588
    }
rosfran@10
   589
    src->live_tv_id = src->spawn_livetv->remote_encoder->recorder_num;
rosfran@10
   590
    g_print ( "[%s] LiveTV id = %d, URI path = %s.\n", __FUNCTION__, src->live_tv_id, src->uri_name );
rosfran@10
   591
  }
rosfran@10
   592
rosfran@10
   593
  src->file_transfer = myth_file_transfer_new( src->live_tv_id, 
rosfran@10
   594
      g_string_new( src->uri_name ), -1, src->mythtv_version );
rosfran@10
   595
rosfran@10
   596
  if ( src->file_transfer == NULL ) {
rosfran@10
   597
    //GST_OBJECT_UNLOCK(src);
rosfran@10
   598
rosfran@10
   599
    goto init_failed;
rosfran@10
   600
  }
rosfran@10
   601
rosfran@10
   602
  if ( src->live_tv ) {
rosfran@10
   603
    g_print ( "[%s] GST MYTHTVSRC: live_chain_id = %s\n", __FUNCTION__, src->live_chain_id );
rosfran@10
   604
    /* sets the MythSocket to the FileTransfer */
rosfran@10
   605
    //ret = myth_file_transfer_livetv_setup( &(src->file_transfer), src->spawn_livetv->remote_encoder->myth_socket );
rosfran@10
   606
  }
rosfran@10
   607
  /* sets the Playback monitor connection */
rosfran@10
   608
  ret = myth_file_transfer_playback_setup( &(src->file_transfer), src->live_tv );
rosfran@10
   609
rosfran@10
   610
  if ( src->live_tv == TRUE && ret == TRUE ) {
rosfran@10
   611
    /* loop finished, set the max tries variable to zero again... */
rosfran@10
   612
    wait_to_transfer = 0;
rosfran@10
   613
rosfran@10
   614
    while ( wait_to_transfer++ < MYTHTV_TRANSFER_MAX_WAITS && ( myth_file_transfer_is_recording( src->file_transfer ) == FALSE 
rosfran@10
   615
	  /*|| ( myth_file_transfer_get_file_position( src->file_transfer ) < ( src->content_size + 327680 ) )*/ ) )
rosfran@10
   616
      g_usleep( 100 );
rosfran@10
   617
  }
rosfran@10
   618
rosfran@10
   619
  /* sets the FileTransfer instance connection (video/audio download) */
rosfran@10
   620
  ret = myth_file_transfer_setup( &(src->file_transfer), src->live_tv );
rosfran@10
   621
rosfran@10
   622
  if ( ret == FALSE ) {
rosfran@10
   623
    //GST_OBJECT_UNLOCK(src);
rosfran@10
   624
#ifndef GST_DISABLE_GST_DEBUG  
rosfran@10
   625
    if ( src->mythtv_msgs_dbg )
rosfran@10
   626
      g_printerr( "MythTV FileTransfer request failed when setting up socket connection!\n" );  	  
rosfran@10
   627
#endif
rosfran@10
   628
    goto begin_req_failed;
rosfran@10
   629
  }
rosfran@10
   630
rosfran@10
   631
  src->content_size = src->file_transfer->filesize;
rosfran@10
   632
rosfran@10
   633
  //GST_OBJECT_UNLOCK(src);
rosfran@10
   634
rosfran@10
   635
  update_size_task = gst_task_create( update_size_func, src );
rosfran@10
   636
rosfran@10
   637
  gst_task_set_lock( update_size_task, &update_size_mutex );
rosfran@10
   638
rosfran@10
   639
  g_print( "[%s] Update Size task = %s\n", __FUNCTION__, gst_task_start( update_size_task ) && 
rosfran@10
   640
  		GST_TASK_STATE( update_size_task ) == GST_TASK_STARTED ? "OK !" : "ERROR!!!" );
rosfran@10
   641
rosfran@10
   642
  src->do_start = TRUE;
rosfran@10
   643
rosfran@10
   644
#if 0
rosfran@10
   645
  const char *str_value;
rosfran@10
   646
  gint gint_value;
rosfran@10
   647
rosfran@10
   648
  str_value = ne_get_response_header (src->request, "myth-metaint");
rosfran@10
   649
  if (str_value) {
rosfran@10
   650
    if ( sscanf (str_value, "%d", &gint_value) == 1 ) {
rosfran@10
   651
      if (src->myth_caps) {
rosfran@10
   652
	gst_caps_unref (src->myth_caps);
rosfran@10
   653
	src->myth_caps = NULL;
rosfran@10
   654
      }
rosfran@10
   655
      src->myth_metaint = gint_value;
rosfran@10
   656
#endif
rosfran@10
   657
      //src->mythtv_caps = gst_caps_new_simple ("application/x-gst_ff-nuv", NULL);
rosfran@10
   658
      //   }
rosfran@10
   659
      // }
rosfran@10
   660
done:
rosfran@10
   661
      return TRUE;
rosfran@10
   662
rosfran@10
   663
      /* ERRORS */
rosfran@10
   664
init_failed:
rosfran@10
   665
      {
rosfran@10
   666
      	if (src->spawn_livetv != NULL )
rosfran@10
   667
	  g_object_unref( src->spawn_livetv );
rosfran@10
   668
rosfran@10
   669
	GST_ELEMENT_ERROR (src, LIBRARY, INIT,
rosfran@10
   670
	    (NULL), ("Could not initialize MythTV library (%i, %s)", ret, src->uri_name));
rosfran@10
   671
	return FALSE;
rosfran@10
   672
      }
rosfran@10
   673
begin_req_failed:
rosfran@10
   674
      {
rosfran@10
   675
	GST_ELEMENT_ERROR (src, LIBRARY, INIT,
rosfran@10
   676
	    (NULL), ("Could not begin request sent to MythTV server (%i, %s)", ret, src->uri_name));
rosfran@10
   677
	return FALSE;
rosfran@10
   678
      }
rosfran@10
   679
}
rosfran@10
   680
rosfran@10
   681
#if 0
rosfran@10
   682
static gboolean
rosfran@10
   683
gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size)
rosfran@10
   684
{
rosfran@10
   685
  GstMythtvSrc *src;
rosfran@10
   686
  gboolean ret = FALSE;
rosfran@10
   687
rosfran@10
   688
  src = GST_MYTHTV_SRC (bsrc);
rosfran@10
   689
rosfran@10
   690
  g_static_rec_mutex_lock( &update_size_mutex );
rosfran@10
   691
  src->do_start = FALSE;  
rosfran@10
   692
  g_static_rec_mutex_unlock( &update_size_mutex );
rosfran@10
   693
  GST_TASK_SIGNAL( update_size_task );
rosfran@10
   694
 
rosfran@10
   695
rosfran@10
   696
  while (1) {
rosfran@10
   697
rosfran@10
   698
    g_static_rec_mutex_lock( &update_size_mutex );
rosfran@10
   699
    if ( !src->do_start ) {
rosfran@10
   700
rosfran@10
   701
      g_print( "[%s] GET SIZE: do_start? == %s\n", __FUNCTION__, src->do_start ? "YES" : "NO" );
rosfran@10
   702
rosfran@10
   703
      GST_TASK_WAIT( update_size_task );
rosfran@10
   704
    } else {
rosfran@10
   705
      if (src->content_size <= 0) {
rosfran@10
   706
	g_static_rec_mutex_unlock( &update_size_mutex );
rosfran@10
   707
	goto done;
rosfran@10
   708
      }
rosfran@10
   709
rosfran@10
   710
      *size = src->content_size;
rosfran@10
   711
      src->do_start = FALSE;
rosfran@10
   712
rosfran@10
   713
      g_static_rec_mutex_unlock( &update_size_mutex );
rosfran@10
   714
rosfran@10
   715
      break;
rosfran@10
   716
    }
rosfran@10
   717
    g_static_rec_mutex_unlock( &update_size_mutex );
rosfran@10
   718
rosfran@10
   719
  } // while (1) 
rosfran@10
   720
rosfran@10
   721
done:
rosfran@10
   722
  return ret;
rosfran@10
   723
rosfran@10
   724
}
rosfran@10
   725
#endif
rosfran@10
   726
rosfran@10
   727
static gboolean
rosfran@10
   728
gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size)
rosfran@10
   729
{
rosfran@10
   730
  GstMythtvSrc *src;
rosfran@10
   731
  gboolean ret = TRUE;
rosfran@10
   732
rosfran@10
   733
  src = GST_MYTHTV_SRC (bsrc);
rosfran@10
   734
rosfran@10
   735
  if (src->content_size <= 0)
rosfran@10
   736
    ret= FALSE;
rosfran@10
   737
rosfran@10
   738
  *size = src->content_size;
rosfran@10
   739
rosfran@10
   740
  return ret;
rosfran@10
   741
rosfran@10
   742
}
rosfran@10
   743
/* close the socket and associated resources
rosfran@10
   744
 * used both to recover from errors and go to NULL state */
rosfran@10
   745
  static gboolean
rosfran@10
   746
gst_mythtv_src_stop (GstBaseSrc * bsrc)
rosfran@10
   747
{
rosfran@10
   748
  GstMythtvSrc *src;
rosfran@10
   749
rosfran@10
   750
  src = GST_MYTHTV_SRC (bsrc);
rosfran@10
   751
rosfran@10
   752
  if (src->uri_name) {
rosfran@10
   753
    g_free (src->uri_name);
rosfran@10
   754
    src->uri_name = NULL;
rosfran@10
   755
  }
rosfran@10
   756
rosfran@10
   757
  if (src->mythtv_caps) {
rosfran@10
   758
    gst_caps_unref (src->mythtv_caps);
rosfran@10
   759
    src->mythtv_caps = NULL;
rosfran@10
   760
  }
rosfran@10
   761
rosfran@10
   762
  src->eos = FALSE;
rosfran@10
   763
rosfran@10
   764
  return TRUE;
rosfran@10
   765
}
rosfran@10
   766
rosfran@10
   767
  static gboolean
rosfran@10
   768
gst_mythtv_src_handle_event (GstPad * pad, GstEvent * event)
rosfran@10
   769
{
rosfran@10
   770
  GstMythtvSrc *src = GST_MYTHTV_SRC (GST_PAD_PARENT (pad));
rosfran@10
   771
rosfran@10
   772
  switch (GST_EVENT_TYPE (event)) {
rosfran@10
   773
    case GST_EVENT_FLUSH_START:
rosfran@10
   774
      src->eos = FALSE;
rosfran@10
   775
      break;
rosfran@10
   776
      //return TRUE;
rosfran@10
   777
#if 0
rosfran@10
   778
case GST_EVENT_FLUSH_STOP:
rosfran@10
   779
      src->do_start = TRUE;
rosfran@10
   780
      src->eos = FALSE;
rosfran@10
   781
      gst_element_set_state (GST_ELEMENT(src), GST_STATE_NULL);
rosfran@10
   782
      //gst_element_set_locked_state (GST_ELEMENT(src), TRUE);
rosfran@10
   783
      break;
rosfran@10
   784
#endif
rosfran@10
   785
    case GST_EVENT_SEEK:  	  
rosfran@10
   786
      {
rosfran@10
   787
	gdouble rate;
rosfran@10
   788
	//gboolean update = TRUE;
rosfran@10
   789
	GstFormat format;
rosfran@10
   790
	GstSeekType cur_type, stop_type;
rosfran@10
   791
	GstSeekFlags flags;
rosfran@10
   792
	gint64 cur = 0, stop = 0;
rosfran@10
   793
	gst_event_parse_seek ( event, &rate, &format,
rosfran@10
   794
	    &flags, &cur_type, &cur,
rosfran@10
   795
	    &stop_type, &stop );
rosfran@10
   796
rosfran@10
   797
	g_print( "[%s] Got EVENT_SEEK.\n", __FUNCTION__ );
rosfran@10
   798
	if ( !( flags & GST_SEEK_FLAG_FLUSH ) ) {
rosfran@10
   799
	  g_print( "[%s] Could get the FLAG_FLUSH message.\n", __FUNCTION__ );
rosfran@10
   800
	}
rosfran@10
   801
	//gboolean ret = gst_event_parse_new_segment ( event,
rosfran@10
   802
	//    &update, &rate, &format, &start, &stop,
rosfran@10
   803
	//    &position );
rosfran@10
   804
	//GstFlowReturn flow_ret = gst_mythtv_src_create (GST_BASE_SRC( GST_PAD_PARENT( psrc ) ), 
rosfran@10
   805
	//			cur, stop - cur + 1, GstBuffer)
rosfran@10
   806
rosfran@10
   807
      } 
rosfran@10
   808
    default:
rosfran@10
   809
      return gst_pad_event_default (pad, event);
rosfran@10
   810
  }
rosfran@10
   811
rosfran@10
   812
  return gst_pad_event_default (pad, event);
rosfran@10
   813
}
rosfran@10
   814
rosfran@10
   815
  static gboolean
rosfran@10
   816
gst_mythtv_src_is_seekable( GstBaseSrc *base_src )
rosfran@10
   817
{
rosfran@10
   818
  return TRUE;
rosfran@10
   819
}
rosfran@10
   820
rosfran@10
   821
  static void
rosfran@10
   822
gst_mythtv_src_set_property (GObject * object, guint prop_id,
rosfran@10
   823
    const GValue * value, GParamSpec * pspec)
rosfran@10
   824
{
rosfran@10
   825
  GstMythtvSrc *mythtvsrc = GST_MYTHTV_SRC (object);
rosfran@10
   826
rosfran@10
   827
  GST_OBJECT_LOCK (mythtvsrc);
rosfran@10
   828
  switch (prop_id) {
rosfran@10
   829
    case PROP_URI:
rosfran@10
   830
    case PROP_LOCATION:
rosfran@10
   831
      {
rosfran@10
   832
	if (!g_value_get_string (value)) {
rosfran@10
   833
	  GST_WARNING ("location property cannot be NULL");
rosfran@10
   834
	  goto done;
rosfran@10
   835
	}
rosfran@10
   836
rosfran@10
   837
	if (mythtvsrc->uri_name != NULL) {
rosfran@10
   838
	  g_free (mythtvsrc->uri_name);
rosfran@10
   839
	  mythtvsrc->uri_name = NULL;
rosfran@10
   840
	}
rosfran@10
   841
	mythtvsrc->uri_name = g_value_dup_string (value);
rosfran@10
   842
rosfran@10
   843
	break;
rosfran@10
   844
      }
rosfran@10
   845
#ifndef GST_DISABLE_GST_DEBUG
rosfran@10
   846
    case PROP_MYTHTV_DBG:
rosfran@10
   847
      {
rosfran@10
   848
	mythtvsrc->mythtv_msgs_dbg = g_value_get_boolean (value);
rosfran@10
   849
	break;
rosfran@10
   850
      }
rosfran@10
   851
#endif
rosfran@10
   852
    case PROP_MYTHTV_VERSION:
rosfran@10
   853
      {
rosfran@10
   854
	mythtvsrc->mythtv_version = g_value_get_int (value);
rosfran@10
   855
	break;
rosfran@10
   856
      }
rosfran@10
   857
    case PROP_MYTHTV_LIVEID:
rosfran@10
   858
      {
rosfran@10
   859
	mythtvsrc->live_tv_id = g_value_get_int (value);
rosfran@10
   860
	break;
rosfran@10
   861
      }
rosfran@10
   862
    case PROP_MYTHTV_LIVE:
rosfran@10
   863
      {
rosfran@10
   864
	mythtvsrc->live_tv = g_value_get_boolean (value);
rosfran@10
   865
	break;
rosfran@10
   866
      }
rosfran@10
   867
    case PROP_MYTHTV_LIVE_CHAINID:
rosfran@10
   868
      {
rosfran@10
   869
	if (!g_value_get_string (value)) {
rosfran@10
   870
	  GST_WARNING ("MythTV Live chainid property cannot be NULL");
rosfran@10
   871
	  goto done;
rosfran@10
   872
	}
rosfran@10
   873
rosfran@10
   874
	if (mythtvsrc->live_chain_id != NULL) {
rosfran@10
   875
	  g_free (mythtvsrc->live_chain_id);
rosfran@10
   876
	  mythtvsrc->live_chain_id = NULL;
rosfran@10
   877
	}
rosfran@10
   878
	mythtvsrc->live_chain_id = g_value_dup_string (value);
rosfran@10
   879
rosfran@10
   880
	break;
rosfran@10
   881
      }
rosfran@10
   882
rosfran@10
   883
    default:
rosfran@10
   884
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
rosfran@10
   885
      break;
rosfran@10
   886
  }
rosfran@10
   887
  GST_OBJECT_UNLOCK (mythtvsrc);
rosfran@10
   888
done:
rosfran@10
   889
  return;
rosfran@10
   890
}
rosfran@10
   891
rosfran@10
   892
  static void
rosfran@10
   893
gst_mythtv_src_get_property (GObject * object, guint prop_id,
rosfran@10
   894
    GValue * value, GParamSpec * pspec)
rosfran@10
   895
{
rosfran@10
   896
  GstMythtvSrc *mythtvsrc = GST_MYTHTV_SRC (object);
rosfran@10
   897
rosfran@10
   898
  GST_OBJECT_LOCK (mythtvsrc);
rosfran@10
   899
  switch (prop_id) {
rosfran@10
   900
    case PROP_URI:
rosfran@10
   901
    case PROP_LOCATION:
rosfran@10
   902
      {
rosfran@10
   903
	gchar *str = g_strdup( "" );
rosfran@10
   904
rosfran@10
   905
	if ( mythtvsrc->uri_name == NULL ) {
rosfran@10
   906
	  g_free (mythtvsrc->uri_name);
rosfran@10
   907
	  mythtvsrc->uri_name = NULL;
rosfran@10
   908
	} else {
rosfran@10
   909
	  str = g_strdup( mythtvsrc->uri_name );
rosfran@10
   910
	}
rosfran@10
   911
	g_value_set_string ( value, str );
rosfran@10
   912
	break;
rosfran@10
   913
      }
rosfran@10
   914
#ifndef GST_DISABLE_GST_DEBUG
rosfran@10
   915
    case PROP_MYTHTV_DBG:
rosfran@10
   916
      g_value_set_boolean ( value, mythtvsrc->mythtv_msgs_dbg );
rosfran@10
   917
      break;
rosfran@10
   918
#endif
rosfran@10
   919
    case PROP_MYTHTV_VERSION:
rosfran@10
   920
      {
rosfran@10
   921
	g_value_set_int ( value, mythtvsrc->mythtv_version );
rosfran@10
   922
	break;
rosfran@10
   923
      }
rosfran@10
   924
    case PROP_MYTHTV_LIVEID:
rosfran@10
   925
      {
rosfran@10
   926
	g_value_set_int ( value, mythtvsrc->live_tv_id );
rosfran@10
   927
	break;
rosfran@10
   928
      }
rosfran@10
   929
    case PROP_MYTHTV_LIVE:
rosfran@10
   930
      g_value_set_boolean ( value, mythtvsrc->live_tv );
rosfran@10
   931
      break;
rosfran@10
   932
    case PROP_MYTHTV_LIVE_CHAINID:
rosfran@10
   933
      {
rosfran@10
   934
	gchar *str = g_strdup( "" );
rosfran@10
   935
rosfran@10
   936
	if ( mythtvsrc->live_chain_id == NULL ) {
rosfran@10
   937
	  g_free (mythtvsrc->live_chain_id);
rosfran@10
   938
	  mythtvsrc->live_chain_id = NULL;
rosfran@10
   939
	} else {
rosfran@10
   940
	  str = g_strdup( mythtvsrc->live_chain_id );
rosfran@10
   941
	}
rosfran@10
   942
	g_value_set_string ( value, str );
rosfran@10
   943
	break;
rosfran@10
   944
      }
rosfran@10
   945
    default:
rosfran@10
   946
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
rosfran@10
   947
      break;
rosfran@10
   948
  }
rosfran@10
   949
  GST_OBJECT_UNLOCK (mythtvsrc);
rosfran@10
   950
}
rosfran@10
   951
rosfran@10
   952
/* entry point to initialize the plug-in
rosfran@10
   953
 * initialize the plug-in itself
rosfran@10
   954
 * register the element factories and pad templates
rosfran@10
   955
 * register the features
rosfran@10
   956
 */
rosfran@10
   957
  static gboolean
rosfran@10
   958
plugin_init (GstPlugin * plugin)
rosfran@10
   959
{
rosfran@10
   960
  return gst_element_register (plugin, "mythtvsrc", GST_RANK_NONE,
rosfran@10
   961
      GST_TYPE_MYTHTV_SRC);
rosfran@10
   962
}
rosfran@10
   963
rosfran@10
   964
/* this is the structure that gst-register looks for
rosfran@10
   965
 * so keep the name plugin_desc, or you cannot get your plug-in registered */
rosfran@10
   966
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
rosfran@10
   967
    GST_VERSION_MINOR,
rosfran@10
   968
    "mythtv",
rosfran@10
   969
    "lib MythTV src",
rosfran@10
   970
    plugin_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/")
rosfran@10
   971
rosfran@10
   972
rosfran@10
   973
/*** GSTURIHANDLER INTERFACE *************************************************/
rosfran@10
   974
  static guint 
rosfran@10
   975
gst_mythtv_src_uri_get_type (void)
rosfran@10
   976
{
rosfran@10
   977
  return GST_URI_SRC;
rosfran@10
   978
}
rosfran@10
   979
rosfran@10
   980
  static gchar **
rosfran@10
   981
gst_mythtv_src_uri_get_protocols (void)
rosfran@10
   982
{
rosfran@10
   983
  static gchar *protocols[] = { "myth", "myths", NULL };
rosfran@10
   984
rosfran@10
   985
  return protocols;
rosfran@10
   986
}
rosfran@10
   987
rosfran@10
   988
  static const gchar *
rosfran@10
   989
gst_mythtv_src_uri_get_uri (GstURIHandler * handler)
rosfran@10
   990
{
rosfran@10
   991
  GstMythtvSrc *src = GST_MYTHTV_SRC (handler);
rosfran@10
   992
rosfran@10
   993
  return src->uri_name;
rosfran@10
   994
}
rosfran@10
   995
rosfran@10
   996
  static gboolean
rosfran@10
   997
gst_mythtv_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
rosfran@10
   998
{
rosfran@10
   999
  GstMythtvSrc *src = GST_MYTHTV_SRC (handler);
rosfran@10
  1000
rosfran@10
  1001
  gchar *protocol;
rosfran@10
  1002
rosfran@10
  1003
  protocol = gst_uri_get_protocol (uri);
rosfran@10
  1004
  if ((strcmp (protocol, "myth") != 0) && (strcmp (protocol, "myths") != 0)) {
rosfran@10
  1005
    g_free (protocol);
rosfran@10
  1006
    return FALSE;
rosfran@10
  1007
  }
rosfran@10
  1008
  g_free (protocol);
rosfran@10
  1009
  g_object_set (src, "location", uri, NULL);
rosfran@10
  1010
rosfran@10
  1011
  return TRUE;
rosfran@10
  1012
}
rosfran@10
  1013
rosfran@10
  1014
  static void
rosfran@10
  1015
gst_mythtv_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
rosfran@10
  1016
{
rosfran@10
  1017
  GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
rosfran@10
  1018
rosfran@10
  1019
  iface->get_type = gst_mythtv_src_uri_get_type;
rosfran@10
  1020
  iface->get_protocols = gst_mythtv_src_uri_get_protocols;
rosfran@10
  1021
  iface->get_uri = gst_mythtv_src_uri_get_uri;
rosfran@10
  1022
  iface->set_uri = gst_mythtv_src_uri_set_uri;
rosfran@10
  1023
}
rosfran@10
  1024
rosfran@10
  1025
  void
rosfran@10
  1026
size_header_handler (void *userdata, const char *value)
rosfran@10
  1027
{
rosfran@10
  1028
  GstMythtvSrc *src = GST_MYTHTV_SRC (userdata);
rosfran@10
  1029
rosfran@10
  1030
  //src->content_size = g_ascii_strtoull (value, NULL, 10);
rosfran@10
  1031
rosfran@10
  1032
  GST_DEBUG_OBJECT (src, "content size = %lld bytes", src->content_size);
rosfran@10
  1033
}