gstcdparanoia.c 30.7 KB
Newer Older
1
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
Andy Wingo's avatar
Andy Wingo committed
2
/* GStreamer
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

21
/* #define GST_DEBUG_ENABLED */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
22 23 24 25 26 27 28 29 30 31 32 33 34

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
Wim Taymans's avatar
Wim Taymans committed
35

36
/* taken from linux/cdrom.h */
37 38 39
#define CD_MSF_OFFSET       150	/* MSF numbering offset of first frame */
#define CD_SECS              60	/* seconds per minute */
#define CD_FRAMES            75	/* frames per second */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
40 41 42 43 44 45

#include "gstcdparanoia.h"


static GstElementDetails cdparanoia_details = {
  "CD Audio (cdda) Source, Paranoia IV",
46
  "Source/File",
47
  "LGPL",
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
48 49 50 51 52 53
  "Read audio from CD in paranoid mode",
  VERSION,
  "Erik Walthinsen <omega@cse.ogi.edu>",
  "(C) 2000",
};

54
GST_PAD_TEMPLATE_FACTORY (cdparanoia_src_factory,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
55 56 57 58 59 60
  "src",
  GST_PAD_SRC,
  GST_PAD_ALWAYS,
  GST_CAPS_NEW (
    "cdparanoia_src",
    "audio/raw",
61 62 63 64 65 66 67 68 69
	"format", 	GST_PROPS_STRING ("int"),
	"law", 		GST_PROPS_INT (0),
	"endianness", 	GST_PROPS_INT (G_BYTE_ORDER),
	"signed", 	GST_PROPS_BOOLEAN (TRUE),
	"width", 	GST_PROPS_INT (16),
	"depth", 	GST_PROPS_INT (16),
	"rate", 	GST_PROPS_INT (44100),
	"channels", 	GST_PROPS_INT (2),
	"chunksize", 	GST_PROPS_INT (CD_FRAMESIZE_RAW)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
70 71 72 73 74
  )
);


/********** Define useful types for non-programmatic interfaces **********/
Wim Taymans's avatar
Wim Taymans committed
75
#define GST_TYPE_PARANOIA_MODE (gst_paranoia_mode_get_type())
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
76
static GType
Wim Taymans's avatar
Wim Taymans committed
77
gst_paranoia_mode_get_type (void)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
78 79 80
{
  static GType paranoia_mode_type = 0;
  static GEnumValue paranoia_modes[] = {
81 82 83
    { PARANOIA_MODE_DISABLE, "0",   "Disable paranoid checking"},
    { PARANOIA_MODE_OVERLAP, "4",   "cdda2wav-style overlap checking"},
    { PARANOIA_MODE_FULL,    "255", "Full paranoia"},
84
    {0, NULL, NULL},
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
85
  };
86

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
87 88 89 90 91 92
  if (!paranoia_mode_type) {
    paranoia_mode_type = g_enum_register_static ("GstParanoiaMode", paranoia_modes);
  }
  return paranoia_mode_type;
}

93 94 95 96 97 98
#define GST_TYPE_PARANOIA_ENDIAN (gst_paranoia_endian_get_type())
static GType
gst_paranoia_endian_get_type (void)
{
  static GType paranoia_endian_type = 0;
  static GEnumValue paranoia_endians[] = {
99 100 101
    { 0, "0", "treat drive as little endian"},
    { 1, "1", "treat drive as big endian"},
    { 0, NULL, NULL},
102 103 104 105 106 107 108
  };

  if (!paranoia_endian_type) {
    paranoia_endian_type = g_enum_register_static ("GstParanoiaEndian", paranoia_endians);
  }
  return paranoia_endian_type;
}
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
109 110 111

/********** Standard stuff for signals and arguments **********/
/* CDParanoia signals and args */
112 113
enum
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
114 115 116 117 118 119
  SMILIE_CHANGE,
  TRANSPORT_ERROR,
  UNCORRECTED_ERROR,
  LAST_SIGNAL
};

120 121
enum
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
122 123 124 125 126 127 128 129 130 131 132 133 134
  ARG_0,
  ARG_LOCATION,
  ARG_GENERIC_DEVICE,
  ARG_DEFAULT_SECTORS,
  ARG_SEARCH_OVERLAP,
  ARG_ENDIAN,
  ARG_READ_SPEED,
  ARG_TOC_OFFSET,
  ARG_TOC_BIAS,
  ARG_NEVER_SKIP,
  ARG_ABORT_ON_SKIP,
  ARG_PARANOIA_MODE,
  ARG_SMILIE,
135
  ARG_DISCID
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
136 137 138
};


139 140
static void 		cdparanoia_class_init 		(CDParanoiaClass *klass);
static void 		cdparanoia_init 		(CDParanoia *cdparanoia);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
141

142 143 144 145
static void 		cdparanoia_set_property 	(GObject *object, guint prop_id, 
							 const GValue *value, GParamSpec *pspec);
static void 		cdparanoia_get_property 	(GObject *object, guint prop_id,
							 GValue *value, GParamSpec *pspec);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
146

147 148 149 150 151 152 153 154 155 156 157
static GstBuffer*	cdparanoia_get 			(GstPad *pad);
static gboolean 	cdparanoia_event 		(GstPad *pad, GstEvent *event);
static const GstEventMask*
			cdparanoia_get_event_mask 	(GstPad *pad);
static const GstFormat*
			cdparanoia_get_formats 		(GstPad *pad);
static gboolean 	cdparanoia_convert 		(GstPad *pad,
				    			 GstFormat src_format,
				    			 gint64 src_value, 
							 GstFormat *dest_format, 
							 gint64 *dest_value);
Wim Taymans's avatar
Wim Taymans committed
158
static gboolean 	cdparanoia_query 		(GstPad *pad, GstQueryType type,
159
		     					 GstFormat *format, gint64 *value);
Wim Taymans's avatar
Wim Taymans committed
160
static const GstQueryType*
161
			cdparanoia_get_query_types 	(GstPad *pad);
Iain Holmes's avatar
Iain Holmes committed
162 163 164
static void cdparanoia_set_index (GstElement *element, GstIndex *index);
static GstIndex *cdparanoia_get_index (GstElement *element);
																	
165

166
static GstElementStateReturn cdparanoia_change_state (GstElement *element);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
167 168 169 170 171


static GstElementClass *parent_class = NULL;
static guint cdparanoia_signals[LAST_SIGNAL] = { 0 };

172
static GstFormat track_format;
173
static GstFormat sector_format;
174

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
175 176 177 178 179 180 181
GType
cdparanoia_get_type (void)
{
  static GType cdparanoia_type = 0;

  if (!cdparanoia_type) {
    static const GTypeInfo cdparanoia_info = {
182
      sizeof (CDParanoiaClass), NULL,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
183
      NULL,
184
      (GClassInitFunc) cdparanoia_class_init,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
185 186
      NULL,
      NULL,
187
      sizeof (CDParanoia),
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
188
      0,
189
      (GInstanceInitFunc) cdparanoia_init,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
190
    };
191

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
192
    cdparanoia_type = g_type_register_static (GST_TYPE_ELEMENT, "CDParanoia", &cdparanoia_info, 0);
193 194 195 196
    
    /* Register the track format */
    track_format = gst_format_register ("track", "CD track");
    sector_format = gst_format_register ("sector", "CD sector");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
197 198 199 200 201 202 203 204 205
  }
  return cdparanoia_type;
}

static void
cdparanoia_class_init (CDParanoiaClass *klass)
{
  GObjectClass *gobject_class;
  GstElementClass *gstelement_class;
206
  char *success = strerror_tr[0];
207

208
  success = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
209

210 211
  gobject_class = (GObjectClass *) klass;
  gstelement_class = (GstElementClass *) klass;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
212 213 214 215

  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);

  cdparanoia_signals[SMILIE_CHANGE] =
216 217 218
    g_signal_new ("smilie_change", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (CDParanoiaClass, smilie_change), NULL, NULL,
		  g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
219
  cdparanoia_signals[TRANSPORT_ERROR] =
220 221 222
    g_signal_new ("transport_error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (CDParanoiaClass, transport_error), NULL, NULL,
		  g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
223
  cdparanoia_signals[UNCORRECTED_ERROR] =
224 225 226 227 228 229 230 231 232 233 234 235 236
    g_signal_new ("uncorrected_error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (CDParanoiaClass, uncorrected_error), NULL, NULL,
		  g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);

  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATION, 
    g_param_spec_string ("location", "location", "location", 
	                 NULL, G_PARAM_READWRITE));	
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_GENERIC_DEVICE, 
    g_param_spec_string ("generic_device", "Generic device", "Use specified generic scsi device", 
	                 NULL, G_PARAM_READWRITE));
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEFAULT_SECTORS, 
    g_param_spec_int ("default_sectors", "Default sectors", 
	    	      "Force default number of sectors in read to n sectors", 
237
		      -1, 100, -1, G_PARAM_READWRITE));
238 239 240
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SEARCH_OVERLAP, 
    g_param_spec_int ("search_overlap", "Search overlap", 
	    	      "Force minimum overlap search during verification to n sectors", 
241
		       -1, 75, -1, G_PARAM_READWRITE));
242 243 244 245 246 247
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ENDIAN, 
    g_param_spec_enum ("endian", "Endian", "Force endian on drive", 
		       GST_TYPE_PARANOIA_ENDIAN, 0, G_PARAM_READWRITE));
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_READ_SPEED, 
    g_param_spec_int ("read_speed", "Read speed", "Read from device at specified speed", 
		      G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
248
  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_TOC_OFFSET,
249 250
    g_param_spec_int("toc_offset", "TOC offset", "Add <n> sectors to the values reported",
                     G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); 
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
251
  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_TOC_BIAS,
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
    g_param_spec_boolean("toc_bias", "TOC bias",
	    		 "Assume that the beginning offset of track 1 as reported in the TOC "
			 "will be addressed as LBA 0.  Necessary for some Toshiba drives to "
			 "get track boundaries",
                         TRUE,G_PARAM_READWRITE)); 
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NEVER_SKIP, 
    g_param_spec_int ("never_skip", "Never skip", 
	    	      "never accept any less than perfect data reconstruction (don't allow "
		      "'V's) but if [n] is given, skip after [n] retries without progress.", 
		      0, G_MAXINT, 0, G_PARAM_READWRITE));
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ABORT_ON_SKIP, 
    g_param_spec_boolean ("abort_on_skip", "Abort on skip", "Abort on imperfect reads/skips", 
		          TRUE, G_PARAM_READWRITE));
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PARANOIA_MODE, 
    g_param_spec_enum ("paranoia_mode", "Paranoia mode", "Type of checking to perform", 
		       GST_TYPE_PARANOIA_MODE, 0, G_PARAM_READWRITE));
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DISCID,
    g_param_spec_string ("discid", "discid", "The dics id",
			 NULL, G_PARAM_READABLE));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
271 272 273 274 275

  gobject_class->set_property = cdparanoia_set_property;
  gobject_class->get_property = cdparanoia_get_property;

  gstelement_class->change_state = cdparanoia_change_state;
Iain Holmes's avatar
Iain Holmes committed
276 277
	gstelement_class->set_index = cdparanoia_set_index;
	gstelement_class->get_index = cdparanoia_get_index;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
278 279 280 281 282
}

static void
cdparanoia_init (CDParanoia *cdparanoia)
{
283 284
  cdparanoia->srcpad =
    gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (cdparanoia_src_factory), "src");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
285
  gst_pad_set_get_function (cdparanoia->srcpad, cdparanoia_get);
286 287 288 289
  gst_pad_set_event_function (cdparanoia->srcpad, cdparanoia_event);
  gst_pad_set_event_mask_function (cdparanoia->srcpad, cdparanoia_get_event_mask);
  gst_pad_set_convert_function (cdparanoia->srcpad, cdparanoia_convert);
  gst_pad_set_query_function (cdparanoia->srcpad, cdparanoia_query);
290
  gst_pad_set_query_type_function (cdparanoia->srcpad, cdparanoia_get_query_types);
291 292
  gst_pad_set_formats_function (cdparanoia->srcpad, cdparanoia_get_formats);

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
293 294
  gst_element_add_pad (GST_ELEMENT (cdparanoia), cdparanoia->srcpad);

295
  cdparanoia->device = g_strdup ("/dev/cdrom");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
296 297 298
  cdparanoia->generic_device = NULL;
  cdparanoia->default_sectors = -1;
  cdparanoia->search_overlap = -1;
299
  cdparanoia->endian = 0;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
300 301 302 303 304 305 306
  cdparanoia->read_speed = -1;
  cdparanoia->toc_offset = 0;
  cdparanoia->toc_bias = FALSE;
  cdparanoia->never_skip = FALSE;
  cdparanoia->paranoia_mode = 2;
  cdparanoia->abort_on_skip = FALSE;

307
  cdparanoia->total_seconds = 0;
308
  cdparanoia->discont_pending = FALSE;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
}


static void
cdparanoia_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
  CDParanoia *src;

  /* it's not null if we got it, but it might not be ours */
  g_return_if_fail (GST_IS_CDPARANOIA (object));

  src = CDPARANOIA (object);

  switch (prop_id) {
    case ARG_LOCATION:
324 325
      if (src->device)
	g_free (src->device);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
326
      /* clear the filename if we get a NULL (is that possible?) */
327 328
      if (!g_ascii_strcasecmp (g_value_get_string (value), ""))
	src->device = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
329 330
      /* otherwise set the new filename */
      else
331
	src->device = g_strdup (g_value_get_string (value));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
332 333 334
      break;
    case ARG_GENERIC_DEVICE:

335 336
      if (src->generic_device)
	g_free (src->generic_device);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
337
      /* reset the device if we get a NULL (is that possible?) */
338 339
      if (!g_ascii_strcasecmp (g_value_get_string (value), ""))
	src->generic_device = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
340 341
      /* otherwise set the new filename */
      else
342
	src->generic_device = g_strdup (g_value_get_string (value));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
343 344 345 346 347 348 349 350
      break;
    case ARG_DEFAULT_SECTORS:
      src->default_sectors = g_value_get_int (value);
      break;
    case ARG_SEARCH_OVERLAP:
      src->search_overlap = g_value_get_int (value);
      break;
    case ARG_ENDIAN:
351
      src->endian = g_value_get_enum (value);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
352 353 354 355 356 357 358 359 360 361 362
      break;
    case ARG_READ_SPEED:
      src->read_speed = g_value_get_int (value);
      break;
    case ARG_TOC_OFFSET:
      src->toc_offset = g_value_get_int (value);
      break;
    case ARG_TOC_BIAS:
      src->toc_bias = g_value_get_boolean (value);
      break;
    case ARG_NEVER_SKIP:
363
      src->never_skip = g_value_get_int (value);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
364 365 366 367 368
      break;
    case ARG_ABORT_ON_SKIP:
      src->abort_on_skip = g_value_get_boolean (value);
      break;
    case ARG_PARANOIA_MODE:
Wim Taymans's avatar
Wim Taymans committed
369
      src->paranoia_mode = g_value_get_enum (value);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
      break;
    default:
      break;
  }

}

static void
cdparanoia_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
  CDParanoia *src;

  g_return_if_fail (GST_IS_CDPARANOIA (object));

  src = CDPARANOIA (object);

  switch (prop_id) {
    case ARG_LOCATION:
      g_value_set_string (value, src->device);
      break;
    case ARG_GENERIC_DEVICE:
      g_value_set_string (value, src->generic_device);
      break;
    case ARG_DEFAULT_SECTORS:
      g_value_set_int (value, src->default_sectors);
      break;
    case ARG_SEARCH_OVERLAP:
      g_value_set_int (value, src->search_overlap);
      break;
    case ARG_ENDIAN:
400
      g_value_set_enum (value, src->endian);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
401 402 403 404 405 406 407 408 409 410 411
      break;
    case ARG_READ_SPEED:
      g_value_set_int (value, src->read_speed);
      break;
    case ARG_TOC_OFFSET:
      g_value_set_int (value, src->toc_offset);
      break;
    case ARG_TOC_BIAS:
      g_value_set_boolean (value, src->toc_bias);
      break;
    case ARG_NEVER_SKIP:
412
      g_value_set_int (value, src->never_skip);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
413 414 415 416 417
      break;
    case ARG_ABORT_ON_SKIP:
      g_value_set_boolean (value, src->abort_on_skip);
      break;
    case ARG_PARANOIA_MODE:
Wim Taymans's avatar
Wim Taymans committed
418
      g_value_set_enum (value, src->paranoia_mode);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
419
      break;
420
    case ARG_DISCID:
421
      g_value_set_string (value, src->discid);
422
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
423 424 425 426 427 428
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

429 430 431
static void
cdparanoia_callback (long inpos, int function)
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
432 433
}

434
static GstBuffer *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
435 436 437 438 439 440 441
cdparanoia_get (GstPad *pad)
{
  CDParanoia *src;
  GstBuffer *buf;

  src = CDPARANOIA (gst_pad_get_parent (pad));

442
  g_return_val_if_fail (GST_FLAG_IS_SET (src, CDPARANOIA_OPEN), NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
443

444 445
  /* stop things apropriatly */
  if (src->cur_sector > src->segment_end_sector) {
446
    GST_DEBUG (0, "setting EOS");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
447

Wim Taymans's avatar
Wim Taymans committed
448
    buf = GST_BUFFER (gst_event_new (GST_EVENT_EOS));
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
    gst_element_set_eos (GST_ELEMENT (src));
  }
  else {
    gint16 *cdda_buf;
    gint64 timestamp;
    GstFormat format;

    /* read a sector */
    cdda_buf = paranoia_read (src->p, cdparanoia_callback);

    /* convert the sequence sector number to a timestamp */
    format = GST_FORMAT_TIME;
    timestamp = 0LL;
    gst_pad_convert (src->srcpad, sector_format, src->seq, 
		    &format, &timestamp);

465 466
    /* have to copy the buffer for now since we don't own it... */
    /* FIXME must ask monty about allowing ownership transfer */
Wim Taymans's avatar
Wim Taymans committed
467
    buf = gst_buffer_new_and_alloc (CD_FRAMESIZE_RAW);
Wim Taymans's avatar
Wim Taymans committed
468
    memcpy (GST_BUFFER_DATA (buf), cdda_buf, CD_FRAMESIZE_RAW);
469 470 471 472
    GST_BUFFER_TIMESTAMP (buf) = timestamp;
  
    /* update current sector */
    src->cur_sector++;
Wim Taymans's avatar
Wim Taymans committed
473
    src->seq++;
Wim Taymans's avatar
Wim Taymans committed
474
  }
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
475 476 477 478 479

  /* we're done, push the buffer off now */
  return buf;
}

480 481 482 483 484 485
/* need some stuff to get a discid (cdparanoia doesn't do cddb but lets
 * not stop other ppl doing it ;-) */
typedef int byte;

typedef struct
{
486 487 488 489 490
  byte m;
  byte s;
  byte f;
}
toc_msf;
491 492 493

/* cdparanoia provides the toc in lba format dang we need it in msf so
 * we have to convert it */
494 495
static inline void
lba_to_msf (const gint lba, byte *m, byte *s, byte *f)
496
{
497 498 499 500 501 502 503 504 505 506
  gint lba2 = lba;

  lba2 += CD_MSF_OFFSET;
  lba2 &= 0xffffff;
  *m = lba2 / (CD_SECS * CD_FRAMES);
  lba2 %= (CD_SECS * CD_FRAMES);
  *s = lba2 / CD_FRAMES;
  *f = lba2 % CD_FRAMES;
  *f += (*m) * 60 * 75;
  *f += (*s) * 75;
507 508
}

509
static void
Wim Taymans's avatar
Wim Taymans committed
510
lba_toc_to_msf_toc (TOC *lba_toc, toc_msf *msf_toc, gint tracks)
511
{
512 513 514 515
  gint i;

  for (i = 0; i <= tracks; i++)
    lba_to_msf (lba_toc[i].dwStartSector, &msf_toc[i].m, &msf_toc[i].s, &msf_toc[i].f);
516 517 518
}

/* the cddb hash function */
Wim Taymans's avatar
Wim Taymans committed
519
static guint
520
cddb_sum (gint n)
521
{
522 523 524 525 526 527 528 529
  guint ret;

  ret = 0;
  while (n > 0) {
    ret += (n % 10);
    n /= 10;
  }
  return ret;
530 531
}

532 533
static void
cddb_discid (gchar *discid, toc_msf *toc, gint tracks)
534
{
535
  guint i = 0, t = 0, n = 0;
536

537 538 539 540 541 542 543
  while (i < tracks) {
    n = n + cddb_sum ((toc[i].m * 60) + toc[i].s);
    i++;
  }
  t = ((toc[tracks].m * 60) + toc[tracks].s) - ((toc[0].m * 60)
						+ toc[0].s);
  sprintf (discid, "%08x", ((n % 0xff) << 24 | t << 8 | tracks));
544 545 546
}

/* get all the cddb info at once */
547 548
static void
get_cddb_info (TOC *toc, gint tracks, gchar *discid, gint64 *offsets, gint64 *total_seconds)
549
{
550 551 552
  toc_msf msf_toc[MAXTRK];
  gint i;
  gint64 *p = offsets;
553

554 555
  lba_toc_to_msf_toc (toc, &msf_toc[0], tracks);
  cddb_discid (discid, &msf_toc[0], tracks);
556

557 558 559 560 561
  for (i = 0; i < tracks; i++) {
    *p++ = msf_toc[i].f;
  }

  *total_seconds = msf_toc[tracks].f / 75;
562 563 564

}

Iain Holmes's avatar
Iain Holmes committed
565 566 567 568 569 570 571 572 573 574
static void
add_index_associations (CDParanoia *src)
{
	int i;

	for (i = 0; i < src->d->tracks; i++) {
		gint64 sector;

		sector = cdda_track_firstsector (src->d, i + 1);
		gst_index_add_association (src->index, src->index_id,
David I. Lehn's avatar
David I. Lehn committed
575
															 GST_ASSOCIATION_FLAG_KEY_UNIT,
Iain Holmes's avatar
Iain Holmes committed
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
															 track_format, i,
															 sector_format, sector,
															 GST_FORMAT_TIME, (gint64) (((CD_FRAMESIZE_RAW >> 2) * sector * GST_SECOND) / 44100),
															 GST_FORMAT_BYTES, (gint64) (sector << 2),
															 GST_FORMAT_UNITS, (gint64) ((CD_FRAMESIZE_RAW >> 2) * sector),
															 NULL);
#if 0
		g_print ("Added association for track %d\n", i + 1);
		g_print ("Sector: %lld\n", sector);
		g_print ("Time: %lld\n", (gint64) (((CD_FRAMESIZE_RAW >> 2) * sector * GST_SECOND) / 44100));
		g_print ("Bytes: %lld\n", (gint64) (sector << 2));
		g_print ("Units: %lld\n", (gint64) ((CD_FRAMESIZE_RAW >> 2) * sector));
		g_print ("-----------\n");
#endif
	}
}
			
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
593 594 595 596 597 598 599 600 601
/* open the file, necessary to go to RUNNING state */
static gboolean
cdparanoia_open (CDParanoia *src)
{
  gint i;
  gint paranoia_mode;

  g_return_val_if_fail (!GST_FLAG_IS_SET (src, CDPARANOIA_OPEN), FALSE);

602
  GST_DEBUG_ENTER ("(\"%s\",...)", gst_element_get_name (GST_ELEMENT (src)));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
603

604
  /* find the device */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
605 606 607 608 609 610 611 612 613 614
  if (src->generic_device != NULL) {
    src->d = cdda_identify_scsi (src->generic_device, src->device, FALSE, NULL);
  } else {
    if (src->device != NULL) {
      src->d = cdda_identify (src->device, FALSE, NULL);
    } else {
      src->d = cdda_identify ("/dev/cdrom", FALSE, NULL);
    }
  }

615
  /* fail if the device couldn't be found */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
616
  if (src->d == NULL) {
617
    GST_DEBUG (0, "couldn't open device");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
618 619 620
    return FALSE;
  }

621
  /* set verbosity mode */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
622 623
  cdda_verbose_set (src->d, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);

624
  /* set various other parameters */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
625
  if (src->default_sectors != -1) {
626 627
    src->d->nsectors = src->default_sectors;
    src->d->bigbuff = src->default_sectors * CD_FRAMESIZE_RAW;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
628 629
  }

630
  /* open the disc */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
631
  if (cdda_open (src->d)) {
632
    GST_DEBUG (0, "couldn't open disc");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
633 634 635 636 637
    cdda_close (src->d);
    src->d = NULL;
    return FALSE;
  }

638 639
  /* I don't like this here i would prefer it under get_cddb_info but for somereason
   * when leaving the function it clobbers the allocated mem and all is lost bugger
640
   */
641

642
  get_cddb_info (&src->d->disc_toc[0], src->d->tracks, src->discid,
643
		 src->offsets, &src->total_seconds);
Wim Taymans's avatar
Wim Taymans committed
644 645 646 647

  g_object_freeze_notify (G_OBJECT (src));
  g_object_notify (G_OBJECT (src), "discid");
  g_object_thaw_notify (G_OBJECT (src));
648

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
649 650 651
  if (src->toc_bias) {
    src->toc_offset -= cdda_track_firstsector (src->d, 1);
  }
652
  for (i = 0; i < src->d->tracks + 1; i++) {
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
653 654 655 656 657 658 659
    src->d->disc_toc[i].dwStartSector += src->toc_offset;
  }

  if (src->read_speed != -1) {
    cdda_speed_set (src->d, src->read_speed);
  }

660 661 662
  /* save thse ones */
  src->first_sector = cdda_disc_firstsector (src->d);
  src->last_sector  = cdda_disc_lastsector (src->d);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
663

664 665 666
  /* this is the default segment we will play */
  src->segment_start_sector = src->first_sector;
  src->segment_end_sector   = src->last_sector;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
667

668
  /* create the paranoia struct and set it up */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
669 670
  src->p = paranoia_init (src->d);
  if (src->p == NULL) {
671
    GST_DEBUG (0, "couldn't create paranoia struct");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
672 673 674
    return FALSE;
  }

675
  paranoia_mode = src->paranoia_mode;
676 677
  if (src->never_skip)
    paranoia_mode |= PARANOIA_MODE_NEVERSKIP;
Iain Holmes's avatar
Iain Holmes committed
678
	
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
679 680 681 682 683 684
  paranoia_modeset (src->p, paranoia_mode);

  if (src->search_overlap != -1) {
    paranoia_overlapset (src->p, src->search_overlap);
  }

685
  src->cur_sector = src->first_sector;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
686
  paranoia_seek (src->p, src->cur_sector, SEEK_SET);
687
  GST_DEBUG (0, "successfully seek'd to beginning of disk");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
688 689 690

  GST_FLAG_SET (src, CDPARANOIA_OPEN);

Iain Holmes's avatar
Iain Holmes committed
691 692 693 694
	if (src->index && GST_INDEX_IS_WRITABLE (src->index)) {
		add_index_associations (src);
	}
	
695
  GST_DEBUG_LEAVE ("");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
696 697 698 699 700 701 702 703 704 705

  return TRUE;
}

/* close the file */
static void
cdparanoia_close (CDParanoia *src)
{
  g_return_if_fail (GST_FLAG_IS_SET (src, CDPARANOIA_OPEN));

706
  /* kill the paranoia state */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
707 708
  paranoia_free (src->p);
  src->p = NULL;
709 710

  src->total_seconds = 0LL;
711
  /* close the disc */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
712 713 714 715 716 717 718 719 720
  cdda_close (src->d);
  src->d = NULL;

  GST_FLAG_UNSET (src, CDPARANOIA_OPEN);
}

static GstElementStateReturn
cdparanoia_change_state (GstElement *element)
{
Wim Taymans's avatar
Wim Taymans committed
721 722
  CDParanoia *cdparanoia;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
723 724
  g_return_val_if_fail (GST_IS_CDPARANOIA (element), GST_STATE_FAILURE);

Wim Taymans's avatar
Wim Taymans committed
725 726 727
  cdparanoia = CDPARANOIA (element);

  switch (GST_STATE_TRANSITION (element)) {
Iain Holmes's avatar
Iain Holmes committed
728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
	case GST_STATE_NULL_TO_READY:
		break;
	case GST_STATE_READY_TO_PAUSED:
		if (!cdparanoia_open (CDPARANOIA (element))) {
			g_warning ("cdparanoia: failed opening cd");
			return GST_STATE_FAILURE;
		}
		cdparanoia->seq = 0;
		break;
	case GST_STATE_PAUSED_TO_PLAYING:
		break;
	case GST_STATE_PLAYING_TO_PAUSED:
		break;
	case GST_STATE_PAUSED_TO_READY:
		cdparanoia_close (CDPARANOIA (element));
		break;
	case GST_STATE_READY_TO_NULL:
		break;
	default:
		break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
748
  }
Iain Holmes's avatar
Iain Holmes committed
749
	
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
750 751 752 753 754 755 756
  /* if we haven't failed already, give the parent class a chance too ;-) */
  if (GST_ELEMENT_CLASS (parent_class)->change_state)
    return GST_ELEMENT_CLASS (parent_class)->change_state (element);

  return GST_STATE_SUCCESS;
}

757 758 759
static const GstEventMask *
cdparanoia_get_event_mask (GstPad *pad)
{
760
  static const GstEventMask masks[] = {
761 762 763 764 765 766 767 768
    {GST_EVENT_SEEK,         GST_SEEK_METHOD_SET | 
	                     GST_SEEK_METHOD_CUR | 
	                     GST_SEEK_METHOD_END | 
		             GST_SEEK_FLAG_FLUSH },
    {GST_EVENT_SEEK_SEGMENT, GST_SEEK_METHOD_SET | 
	                     GST_SEEK_METHOD_CUR | 
	                     GST_SEEK_METHOD_END | 
		             GST_SEEK_FLAG_FLUSH },
769 770
    {0,}
  };
771

772
  return masks;
773 774 775
}

static gboolean
776
cdparanoia_event (GstPad *pad, GstEvent *event)
777
{
778
  CDParanoia *src;
779
  gboolean res = TRUE;
780 781 782

  src = CDPARANOIA (gst_pad_get_parent (pad));

Iain Holmes's avatar
Iain Holmes committed
783 784
  if (!GST_FLAG_IS_SET (src, CDPARANOIA_OPEN)) {
		g_print ("Not open\n");
785
    goto error;
Iain Holmes's avatar
Iain Holmes committed
786
	}
787

788 789
  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEEK:
790 791 792 793 794 795 796 797 798 799 800 801 802 803
    case GST_EVENT_SEEK_SEGMENT:
    {
      gint64 offset, endoffset;
      gint format;
      gint64 seg_start_sector = -1, seg_end_sector = -1;
	    
      format    = GST_EVENT_SEEK_FORMAT (event);
      offset    = GST_EVENT_SEEK_OFFSET (event);
      endoffset = GST_EVENT_SEEK_ENDOFFSET (event);

      /* we can only seek on sectors, so we convert the requested
       * offsets to sectors first */
      if (offset != -1) {
        res &= gst_pad_convert (src->srcpad, format, offset, 
Iain Holmes's avatar
Iain Holmes committed
804
																&sector_format, &seg_start_sector);
805 806 807
      }
      if (endoffset != -1) {
        res &= gst_pad_convert (src->srcpad, format, endoffset, 
Iain Holmes's avatar
Iain Holmes committed
808
																&sector_format, &seg_end_sector);
809 810 811
      }
      
      if (!res) {
Iain Holmes's avatar
Iain Holmes committed
812 813
				GST_DEBUG (0, "could not convert offsets to sectors");
				goto error;
814
      }
815
      
816
      switch (GST_EVENT_SEEK_METHOD (event)) {
Iain Holmes's avatar
Iain Holmes committed
817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
			case GST_SEEK_METHOD_SET:
				/* values are set for regular seek set */
				break;
			case GST_SEEK_METHOD_CUR:
				if (seg_start_sector != -1) {
					seg_start_sector += src->cur_sector;
				}
				if (seg_end_sector != -1) {
					seg_end_sector += src->cur_sector;
				}
				break;
			case GST_SEEK_METHOD_END:
				if (seg_start_sector != -1) {
					seg_start_sector = src->last_sector - seg_start_sector;
				}
				if (seg_end_sector != -1) {
					seg_end_sector = src->last_sector - seg_end_sector;
				}
				break;
			default:
				goto error;
838
      }
839 840 841
      /* do we need to update the start sector? */
      if (seg_start_sector != -1) {
        seg_start_sector = CLAMP (seg_start_sector, 
Iain Holmes's avatar
Iain Holmes committed
842 843
																	src->first_sector, src->last_sector);
				
844
        if (paranoia_seek (src->p, seg_start_sector, SEEK_SET) > -1) {
Iain Holmes's avatar
Iain Holmes committed
845 846 847 848 849 850 851 852
					GST_DEBUG (0, "seeked to %lld", seg_start_sector);
					
					src->segment_start_sector = seg_start_sector;;
					src->cur_sector = src->segment_start_sector;
				}
				else {
					goto error;
				}
853
      }
854 855
      if (seg_end_sector != -1) {
        seg_end_sector = CLAMP (seg_end_sector, 
Iain Holmes's avatar
Iain Holmes committed
856
																src->first_sector, src->last_sector);
857
        src->segment_end_sector = seg_end_sector;;
858
      }
859
      GST_DEBUG (GST_CAT_PLUGIN_INFO, "configured for %d -> %d sectors\n", 
Iain Holmes's avatar
Iain Holmes committed
860 861
								 src->segment_start_sector, 
								 src->segment_end_sector);
862
      break;
863
    }
Iain Holmes's avatar
Iain Holmes committed
864 865
	default:
		goto error;
866
  }
Iain Holmes's avatar
Iain Holmes committed
867
	
868
  if (FALSE) {
Iain Holmes's avatar
Iain Holmes committed
869
	error:
870 871
    res = FALSE;
  }
872
  gst_event_unref (event);
Iain Holmes's avatar
Iain Holmes committed
873
	
874
  return res;
875 876 877 878 879
}

static const GstFormat *
cdparanoia_get_formats (GstPad *pad)
{
880 881
  static GstFormat formats[] = {
    GST_FORMAT_TIME,
882
    GST_FORMAT_BYTES,
883
    GST_FORMAT_UNITS,
884 885
    0,			/* filled later */
    0,			/* filled later */
886 887 888
    0
  };

889 890
  formats[3] = track_format;
  formats[4] = sector_format;
891

892
  return formats;
893 894 895 896
}

static gboolean
cdparanoia_convert (GstPad *pad,
897 898
		    GstFormat src_format, gint64 src_value, 
		    GstFormat *dest_format, gint64 *dest_value)
899
{
900
  CDParanoia *src;
901

902
  src = CDPARANOIA (gst_pad_get_parent (pad));
903

Iain Holmes's avatar
Iain Holmes committed
904
  if (!GST_FLAG_IS_SET (src, CDPARANOIA_OPEN)) {
905
    return FALSE;
Iain Holmes's avatar
Iain Holmes committed
906
	}
907

908
  switch (src_format) {
Iain Holmes's avatar
Iain Holmes committed
909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957
	case GST_FORMAT_TIME:
		switch (*dest_format) {
		case GST_FORMAT_BYTES:
			src_value <<= 2;	/* 4 bytes per sample */
		case GST_FORMAT_UNITS:
			*dest_value = src_value * 44100 / GST_SECOND;
			break;
		default:
			if (*dest_format == track_format || *dest_format == sector_format) {
				gint sector = (src_value * 44100) / ((CD_FRAMESIZE_RAW >> 2) * GST_SECOND);
				
				if (*dest_format == sector_format) {
					*dest_value = sector;
				}
				else {
					*dest_value = cdda_sector_gettrack (src->d, sector) - 1;
				}
			}
			else 
				return FALSE;
			break;
		}
		break;
	case GST_FORMAT_BYTES:
		src_value >>= 2;
	case GST_FORMAT_UNITS:
		switch (*dest_format) {
		case GST_FORMAT_BYTES:
			*dest_value = src_value * 4;
			break;
		case GST_FORMAT_TIME:
			*dest_value = src_value * GST_SECOND / 44100;
			break;
		default:
			if (*dest_format == track_format || *dest_format == sector_format) {
				gint sector = src_value / (CD_FRAMESIZE_RAW >> 2);
				
				if (*dest_format == track_format) {
					*dest_value = cdda_sector_gettrack (src->d, sector) - 1;
				}
				else {
					*dest_value = sector;
				}
			}
			else 
				return FALSE;
			break;
		}
		break;
958
	default:
Iain Holmes's avatar
Iain Holmes committed
959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004
	{
		gint sector;
		
		if (src_format == track_format) {
			/* some sanity checks */
			if (src_value < 0 || src_value > src->d->tracks)
				return FALSE;
			
			sector = cdda_track_firstsector (src->d, src_value + 1);
		}
		else if (src_format == sector_format) {
			sector = src_value;
		}
		else {
			return FALSE;
		}
		
		switch (*dest_format) {
		case GST_FORMAT_TIME:
			*dest_value = ((CD_FRAMESIZE_RAW >> 2) * sector * GST_SECOND) / 44100;
			break;
		case GST_FORMAT_BYTES:
			sector <<= 2;
		case GST_FORMAT_UNITS:
			*dest_value = (CD_FRAMESIZE_RAW >> 2) * sector;
			break;
		default:
			if (*dest_format == sector_format) {
				*dest_value = sector;
			}
			else if (*dest_format == track_format) {
				/* if we go past the last sector, make sure to report the last track */
				if (sector > src->last_sector)
					*dest_value = cdda_sector_gettrack (src->d, src->last_sector);
				else 
					*dest_value = cdda_sector_gettrack (src->d, sector) - 1;
			}
			else {
				return FALSE;
			}
			break;
		}
		break;
	}
	}
	
1005
  return TRUE;
1006 1007
}

Wim Taymans's avatar
Wim Taymans committed
1008
static const GstQueryType*
1009 1010
cdparanoia_get_query_types (GstPad *pad)
{
Wim Taymans's avatar
Wim Taymans committed
1011 1012 1013 1014 1015
  static const GstQueryType src_query_types[] = {
    GST_QUERY_TOTAL,
    GST_QUERY_POSITION,
    GST_QUERY_START,
    GST_QUERY_SEGMENT_END,
1016 1017 1018 1019 1020
    0
  };
  return src_query_types;
}

1021
static gboolean
Wim Taymans's avatar
Wim Taymans committed
1022
cdparanoia_query (GstPad *pad, GstQueryType type,
1023 1024 1025 1026 1027 1028 1029
		  GstFormat *format, gint64 *value)
{
  gboolean res = TRUE;
  CDParanoia *src;

  src = CDPARANOIA (gst_pad_get_parent (pad));

Iain Holmes's avatar
Iain Holmes committed
1030
  if (!GST_FLAG_IS_SET (src, CDPARANOIA_OPEN)) {
1031
    return FALSE;
Iain Holmes's avatar
Iain Holmes committed
1032
	}
1033 1034

  switch (type) {
Wim Taymans's avatar
Wim Taymans committed
1035
    case GST_QUERY_TOTAL:
1036 1037 1038 1039 1040
      /* we take the last sector + 1 so that we also have the full
       * size of that last sector */
      res = gst_pad_convert (src->srcpad, 
		             sector_format, src->last_sector + 1,
		             format, value);
1041
      break;
Wim Taymans's avatar
Wim Taymans committed
1042
    case GST_QUERY_POSITION:
1043 1044 1045 1046
      /* bring our current sector to the requested format */
      res = gst_pad_convert (src->srcpad, 
		             sector_format, src->cur_sector,
		             format, value);