gstclock.c 15.9 KB
Newer Older
1 2 3
/* GStreamer
 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
 *                    2000 Wim Taymans <wtay@chello.be>
4
 *                    2004 Wim Taymans <wim@fluendo.com>
5 6
 *
 * gstclock.c: Clock subsystem for maintaining time sync
Wim Taymans's avatar
Wim Taymans committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * 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.
 */

24
#include <time.h>
25 26

#include "gst_private.h"
27

28
#include "gstclock.h"
29
#include "gstinfo.h"
30
#include "gstmemchunk.h"
31
#include "gstatomic_impl.h"
Wim Taymans's avatar
Wim Taymans committed
32

Wim Taymans's avatar
Wim Taymans committed
33
#ifndef GST_DISABLE_TRACE
Wim Taymans's avatar
Wim Taymans committed
34
/* #define GST_WITH_ALLOC_TRACE */
Wim Taymans's avatar
Wim Taymans committed
35 36 37
#include "gsttrace.h"
static GstAllocTrace *_gst_clock_entry_trace;
#endif
Wim Taymans's avatar
Wim Taymans committed
38

39
#define DEFAULT_EVENT_DIFF	(GST_SECOND)
40 41
#define DEFAULT_MAX_DIFF	(2 * GST_SECOND)

42 43
enum
{
44 45
  ARG_0,
  ARG_STATS,
46 47
  ARG_MAX_DIFF,
  ARG_EVENT_DIFF
48 49
};

50 51 52 53 54
static GstMemChunk *_gst_clock_entries_chunk;

static void gst_clock_class_init (GstClockClass * klass);
static void gst_clock_init (GstClock * clock);
static void gst_clock_dispose (GObject * object);
Wim Taymans's avatar
Wim Taymans committed
55

56 57 58 59 60
static void gst_clock_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_clock_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);
static void gst_clock_update_stats (GstClock * clock);
61

62

63
static GstObjectClass *parent_class = NULL;
64

65 66
/* static guint gst_clock_signals[LAST_SIGNAL] = { 0 }; */

Wim Taymans's avatar
Wim Taymans committed
67
static GstClockID
68 69
gst_clock_entry_new (GstClock * clock, GstClockTime time,
    GstClockTime interval, GstClockEntryType type)
70 71
{
  GstClockEntry *entry;
72

73
  entry = gst_mem_chunk_alloc (_gst_clock_entries_chunk);
Wim Taymans's avatar
Wim Taymans committed
74
#ifndef GST_DISABLE_TRACE
Wim Taymans's avatar
Wim Taymans committed
75
  gst_alloc_trace_new (_gst_clock_entry_trace, entry);
Wim Taymans's avatar
Wim Taymans committed
76
#endif
77
  GST_CAT_DEBUG (GST_CAT_CLOCK, "created entry %p", entry);
78

79
  gst_atomic_int_init (&entry->refcount, 1);
80 81
  entry->clock = clock;
  entry->time = time;
82
  entry->interval = interval;
83
  entry->type = type;
84
  entry->status = GST_CLOCK_BUSY;
85

86 87
  return (GstClockID) entry;
}
88

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
/**
 * gst_clock_id_ref:
 * @id: The clockid to ref
 *
 * Increase the refcount of the given clockid.
 *
 * Returns: The same #GstClockID with increased refcount.
 *
 * MT safe.
 */
GstClockID
gst_clock_id_ref (GstClockID id)
{
  g_return_val_if_fail (id != NULL, NULL);

  gst_atomic_int_inc (&((GstClockEntry *) id)->refcount);

  return id;
}

static void
_gst_clock_id_free (GstClockID id)
{
  g_return_if_fail (id != NULL);

  GST_CAT_DEBUG (GST_CAT_CLOCK, "freed entry %p", id);

#ifndef GST_DISABLE_TRACE
  gst_alloc_trace_free (_gst_clock_entry_trace, id);
#endif
  gst_mem_chunk_free (_gst_clock_entries_chunk, id);
}

/**
 * gst_clock_id_unref:
 * @id: The clockid to unref
 *
 * Unref the given clockid. When the refcount reaches 0 the
 * #GstClockID will be freed.
 *
 * MT safe.
 */
void
gst_clock_id_unref (GstClockID id)
{
  gint zero;

  g_return_if_fail (id != NULL);

  zero = gst_atomic_int_dec_and_test (&((GstClockEntry *) id)->refcount);
  /* if we ended up with the refcount at zero, free the id */
  if (zero) {
    _gst_clock_id_free (id);
  }
}

145 146 147 148 149 150
/**
 * gst_clock_new_single_shot_id
 * @clock: The clockid to get a single shot notification from
 * @time: the requested time
 *
 * Get an ID from the given clock to trigger a single shot 
151 152
 * notification at the requested time. The single shot id should be
 * unreffed after usage.
153 154
 *
 * Returns: An id that can be used to request the time notification.
155 156
 *
 * MT safe.
157 158
 */
GstClockID
159
gst_clock_new_single_shot_id (GstClock * clock, GstClockTime time)
160
{
161 162
  g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);

163 164
  return gst_clock_entry_new (clock,
      time, GST_CLOCK_TIME_NONE, GST_CLOCK_ENTRY_SINGLE);
165 166 167
}

/**
Wim Taymans's avatar
Wim Taymans committed
168
 * gst_clock_new_periodic_id
169 170 171 172 173 174
 * @clock: The clockid to get a periodic notification id from
 * @start_time: the requested start time
 * @interval: the requested interval
 *
 * Get an ID from the given clock to trigger a periodic notification.
 * The periodeic notifications will be start at time start_time and
175 176
 * will then be fired with the given interval. The id should be unreffed
 * after usage.
177 178
 *
 * Returns: An id that can be used to request the time notification.
179 180
 *
 * MT safe.
181 182
 */
GstClockID
183 184
gst_clock_new_periodic_id (GstClock * clock, GstClockTime start_time,
    GstClockTime interval)
185
{
186
  g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
187
  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (start_time), NULL);
188 189
  g_return_val_if_fail (interval != 0, NULL);

190 191
  return gst_clock_entry_new (clock,
      start_time, interval, GST_CLOCK_ENTRY_PERIODIC);
192 193
}

194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
/**
 * gst_clock_id_compare_func
 * @id1: A clockid
 * @id2: A clockid to compare with
 *
 * Compares the two GstClockID instances. This function can be used
 * as a GCompareFunc when sorting ids.
 *
 * Returns: negative value if a < b; zero if a = b; positive value if a > b
 *
 * MT safe.
 */
gint
gst_clock_id_compare_func (gconstpointer id1, gconstpointer id2)
{
  GstClockEntry *entry1, *entry2;

  entry1 = (GstClockEntry *) id1;
  entry2 = (GstClockEntry *) id2;

  if (GST_CLOCK_ENTRY_TIME (entry1) > GST_CLOCK_ENTRY_TIME (entry2)) {
    return 1;
  }
  if (GST_CLOCK_ENTRY_TIME (entry1) < GST_CLOCK_ENTRY_TIME (entry2)) {
    return -1;
  }

  return entry1 - entry2;
}

224 225 226 227 228 229
/**
 * gst_clock_id_get_time
 * @id: The clockid to query
 *
 * Get the time of the clock ID
 *
230 231 232
 * Returns: the time of the given clock id.
 *
 * MT safe.
233 234 235 236 237 238
 */
GstClockTime
gst_clock_id_get_time (GstClockID id)
{
  g_return_val_if_fail (id != NULL, GST_CLOCK_TIME_NONE);

239
  return GST_CLOCK_ENTRY_TIME ((GstClockEntry *) id);
240 241 242 243 244 245 246 247 248
}


/**
 * gst_clock_id_wait
 * @id: The clockid to wait on
 * @jitter: A pointer that will contain the jitter
 *
 * Perform a blocking wait on the given ID. The jitter arg can be
249
 * NULL.
250 251
 *
 * Returns: the result of the blocking wait.
252 253
 *
 * MT safe.
254 255
 */
GstClockReturn
256
gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter)
257 258
{
  GstClockEntry *entry;
259
  GstClock *clock;
260
  GstClockReturn res;
261
  GstClockTime requested;
Wim Taymans's avatar
Wim Taymans committed
262
  GstClockClass *cclass;
263

264
  g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
265

266 267
  entry = (GstClockEntry *) id;
  requested = GST_CLOCK_ENTRY_TIME (entry);
268

269 270 271 272 273
  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
    goto invalid_time;

  if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
    goto unscheduled;
274

275
  clock = GST_CLOCK_ENTRY_CLOCK (entry);
Wim Taymans's avatar
Wim Taymans committed
276
  cclass = GST_CLOCK_GET_CLASS (clock);
277

278
  if (G_LIKELY (cclass->wait)) {
279

280 281 282
    GST_CAT_DEBUG (GST_CAT_CLOCK, "waiting on clock entry %p", id);
    res = cclass->wait (clock, entry);
    GST_CAT_DEBUG (GST_CAT_CLOCK, "done waiting entry %p", id);
283

284
    if (jitter) {
285 286
      GstClockTime now = gst_clock_get_time (clock);

287 288
      *jitter = now - requested;
    }
289 290 291
    if (entry->type == GST_CLOCK_ENTRY_PERIODIC) {
      entry->time += entry->interval;
    }
292 293 294 295

    if (clock->stats) {
      gst_clock_update_stats (clock);
    }
296 297
  } else {
    res = GST_CLOCK_UNSUPPORTED;
298 299
  }
  return res;
300 301 302 303 304 305 306 307 308 309 310 311

  /* ERRORS */
invalid_time:
  {
    GST_CAT_DEBUG (GST_CAT_CLOCK, "invalid time requested, returning _BADTIME");
    return GST_CLOCK_BADTIME;
  }
unscheduled:
  {
    GST_CAT_DEBUG (GST_CAT_CLOCK, "entry was unscheduled return _UNSCHEDULED");
    return GST_CLOCK_UNSCHEDULED;
  }
312 313 314
}

/**
Wim Taymans's avatar
Wim Taymans committed
315 316
 * gst_clock_id_wait_async:
 * @id: a #GstClockID to wait on
317 318 319
 * @func: The callback function 
 * @user_data: User data passed in the calback
 *
Wim Taymans's avatar
Wim Taymans committed
320
 * Register a callback on the given clockid with the given
321 322 323 324
 * function and user_data. When passing an id with an invalid
 * time to this function, the callback will be called immediatly
 * with  a time set to GST_CLOCK_TIME_NONE. The callback will
 * be called when the time of the id has been reached.
325
 *
326
 * Returns: the result of the non blocking wait.
327 328
 *
 * MT safe.
329 330 331
 */
GstClockReturn
gst_clock_id_wait_async (GstClockID id,
332
    GstClockCallback func, gpointer user_data)
333 334 335
{
  GstClockEntry *entry;
  GstClock *clock;
336
  GstClockReturn res;
Wim Taymans's avatar
Wim Taymans committed
337
  GstClockClass *cclass;
338
  GstClockTime requested;
339

340
  g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
341
  g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR);
342 343

  entry = (GstClockEntry *) id;
344 345
  requested = GST_CLOCK_ENTRY_TIME (entry);
  clock = GST_CLOCK_ENTRY_CLOCK (entry);
346

347 348 349 350 351
  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
    goto invalid_time;

  if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
    goto unscheduled;
352

Wim Taymans's avatar
Wim Taymans committed
353 354 355 356 357 358 359
  cclass = GST_CLOCK_GET_CLASS (clock);

  if (cclass->wait_async) {
    entry->func = func;
    entry->user_data = user_data;

    res = cclass->wait_async (clock, entry);
360 361
  } else {
    res = GST_CLOCK_UNSUPPORTED;
362 363 364
  }
  return res;

365 366 367 368 369 370 371 372 373 374 375 376
  /* ERRORS */
invalid_time:
  {
    (func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
    GST_CAT_DEBUG (GST_CAT_CLOCK, "invalid time requested, returning _BADTIME");
    return GST_CLOCK_BADTIME;
  }
unscheduled:
  {
    GST_CAT_DEBUG (GST_CAT_CLOCK, "entry was unscheduled return _UNSCHEDULED");
    return GST_CLOCK_UNSCHEDULED;
  }
377 378
}

379
/**
Wim Taymans's avatar
Wim Taymans committed
380 381
 * gst_clock_id_unschedule:
 * @id: The id to unschedule
382
 *
383 384 385 386 387 388
 * Cancel an outstanding request with the given ID. This can either
 * be an outstanding async notification or a pending sync notification.
 * After this call, the @id cannot be used anymore to receive sync or
 * async notifications, you need to create a new GstClockID.
 *
 * MT safe.
389 390 391 392 393 394
 */
void
gst_clock_id_unschedule (GstClockID id)
{
  GstClockEntry *entry;
  GstClock *clock;
Wim Taymans's avatar
Wim Taymans committed
395
  GstClockClass *cclass;
396

397 398 399 400
  g_return_if_fail (id != NULL);

  entry = (GstClockEntry *) id;
  clock = entry->clock;
401

Wim Taymans's avatar
Wim Taymans committed
402 403 404 405
  cclass = GST_CLOCK_GET_CLASS (clock);

  if (cclass->unschedule)
    cclass->unschedule (clock, entry);
406 407
}

408 409 410 411

/**
 * GstClock abstract base class implementation
 */
412 413
GType
gst_clock_get_type (void)
Wim Taymans's avatar
Wim Taymans committed
414
{
415 416 417 418
  static GType clock_type = 0;

  if (!clock_type) {
    static const GTypeInfo clock_info = {
419
      sizeof (GstClockClass),
420 421 422 423 424
      NULL,
      NULL,
      (GClassInitFunc) gst_clock_class_init,
      NULL,
      NULL,
425
      sizeof (GstClock),
426
      0,
427 428 429
      (GInstanceInitFunc) gst_clock_init,
      NULL
    };
430

431
    clock_type = g_type_register_static (GST_TYPE_OBJECT, "GstClock",
432
        &clock_info, G_TYPE_FLAG_ABSTRACT);
433 434 435
  }
  return clock_type;
}
436

437
static void
438
gst_clock_class_init (GstClockClass * klass)
439 440 441
{
  GObjectClass *gobject_class;
  GstObjectClass *gstobject_class;
442

443 444
  gobject_class = (GObjectClass *) klass;
  gstobject_class = (GstObjectClass *) klass;
445

446
  parent_class = g_type_class_ref (GST_TYPE_OBJECT);
447

Wim Taymans's avatar
Wim Taymans committed
448 449 450
  if (!g_thread_supported ())
    g_thread_init (NULL);

451
  _gst_clock_entries_chunk = gst_mem_chunk_new ("GstClockEntries",
452
      sizeof (GstClockEntry), sizeof (GstClockEntry) * 32, G_ALLOC_AND_FREE);
453

Wim Taymans's avatar
Wim Taymans committed
454
#ifndef GST_DISABLE_TRACE
455 456
  _gst_clock_entry_trace =
      gst_alloc_trace_register (GST_CLOCK_ENTRY_TRACE_NAME);
Wim Taymans's avatar
Wim Taymans committed
457
#endif
458

459
  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_clock_dispose);
460 461 462 463
  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_clock_set_property);
  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_clock_get_property);

  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STATS,
464
      g_param_spec_boolean ("stats", "Stats", "Enable clock stats",
465
          FALSE, G_PARAM_READWRITE));
Wim Taymans's avatar
Wim Taymans committed
466 467
}

468
static void
469
gst_clock_init (GstClock * clock)
Wim Taymans's avatar
Wim Taymans committed
470
{
471
  clock->adjust = 0;
472 473
  clock->last_time = 0;
  clock->entries = NULL;
474
  clock->entries_changed = g_cond_new ();
475 476
  clock->flags = 0;
  clock->stats = FALSE;
Wim Taymans's avatar
Wim Taymans committed
477 478
}

Wim Taymans's avatar
Wim Taymans committed
479
static void
480
gst_clock_dispose (GObject * object)
Wim Taymans's avatar
Wim Taymans committed
481 482 483
{
  GstClock *clock = GST_CLOCK (object);

484
  g_cond_free (clock->entries_changed);
Wim Taymans's avatar
Wim Taymans committed
485 486 487 488

  G_OBJECT_CLASS (parent_class)->dispose (object);
}

Wim Taymans's avatar
Wim Taymans committed
489
/**
490 491 492
 * gst_clock_set_resolution
 * @clock: The clock set the resolution on
 * @resolution: The resolution to set
Wim Taymans's avatar
Wim Taymans committed
493
 *
494 495 496
 * Set the accuracy of the clock.
 *
 * Returns: the new resolution of the clock.
Wim Taymans's avatar
Wim Taymans committed
497
 */
498
guint64
499
gst_clock_set_resolution (GstClock * clock, guint64 resolution)
Wim Taymans's avatar
Wim Taymans committed
500
{
Wim Taymans's avatar
Wim Taymans committed
501 502
  GstClockClass *cclass;

Wim Taymans's avatar
Wim Taymans committed
503 504
  g_return_val_if_fail (GST_IS_CLOCK (clock), G_GINT64_CONSTANT (0));
  g_return_val_if_fail (resolution != 0, G_GINT64_CONSTANT (0));
505

Wim Taymans's avatar
Wim Taymans committed
506 507 508
  cclass = GST_CLOCK_GET_CLASS (clock);

  if (cclass->change_resolution)
509
    clock->resolution =
510
        cclass->change_resolution (clock, clock->resolution, resolution);
511

512 513
  return clock->resolution;
}
514

515 516 517 518 519 520 521
/**
 * gst_clock_get_resolution
 * @clock: The clock get the resolution of
 *
 * Get the accuracy of the clock.
 *
 * Returns: the resolution of the clock in microseconds.
522 523
 *
 * MT safe.
524 525
 */
guint64
526
gst_clock_get_resolution (GstClock * clock)
527
{
Wim Taymans's avatar
Wim Taymans committed
528 529
  GstClockClass *cclass;

Wim Taymans's avatar
Wim Taymans committed
530
  g_return_val_if_fail (GST_IS_CLOCK (clock), G_GINT64_CONSTANT (0));
531

Wim Taymans's avatar
Wim Taymans committed
532 533 534 535
  cclass = GST_CLOCK_GET_CLASS (clock);

  if (cclass->get_resolution)
    return cclass->get_resolution (clock);
536

Wim Taymans's avatar
Wim Taymans committed
537
  return G_GINT64_CONSTANT (1);
Wim Taymans's avatar
Wim Taymans committed
538 539
}

Wim Taymans's avatar
Wim Taymans committed
540
/**
541 542 543
 * gst_clock_adjust_unlocked
 * @clock: a #GstClock to use
 * @internal: a clock time
Wim Taymans's avatar
Wim Taymans committed
544
 *
545 546 547
 * Converts the given @internal clock time to the real time, adjusting
 * and making sure that the returned time is increasing.
 * This function should be called with the clock lock held.
Wim Taymans's avatar
Wim Taymans committed
548
 *
549
 * Returns: the converted time of the clock.
550
 *
551
 * MT safe.
552
 */
553 554
GstClockTime
gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal)
555
{
556
  GstClockTime ret;
557

558 559 560 561 562 563
  ret = internal + clock->adjust;
  /* make sure the time is increasing, else return last_time */
  if ((gint64) ret < (gint64) clock->last_time) {
    ret = clock->last_time;
  } else {
    clock->last_time = ret;
564
  }
565
  return ret;
566 567
}

Wim Taymans's avatar
Wim Taymans committed
568 569
/**
 * gst_clock_get_time
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
570
 * @clock: a #GstClock to query
Wim Taymans's avatar
Wim Taymans committed
571
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
572
 * Gets the current time of the given clock. The time is always
Wim Taymans's avatar
Wim Taymans committed
573
 * monotonically increasing.
574
 *
575 576 577 578
 * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when
 * giving wrong input.
 *
 * MT safe.
Wim Taymans's avatar
Wim Taymans committed
579
 */
580
GstClockTime
581
gst_clock_get_time (GstClock * clock)
582
{
583
  GstClockTime ret;
584
  GstClockClass *cclass;
585

586
  g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
587

588
  cclass = GST_CLOCK_GET_CLASS (clock);
Wim Taymans's avatar
Wim Taymans committed
589

590
  if (cclass->get_internal_time) {
591
    ret = cclass->get_internal_time (clock);
592
  } else {
593
    ret = G_GINT64_CONSTANT (0);
594
  }
595 596
  GST_CAT_DEBUG (GST_CAT_CLOCK, "internal time %" GST_TIME_FORMAT,
      GST_TIME_ARGS (ret));
597

598 599 600
  GST_LOCK (clock);
  ret = gst_clock_adjust_unlocked (clock, ret);
  GST_UNLOCK (clock);
601

602 603
  GST_CAT_DEBUG (GST_CAT_CLOCK, "adjusted time %" GST_TIME_FORMAT,
      GST_TIME_ARGS (ret));
604

605
  return ret;
606 607
}

Wim Taymans's avatar
Wim Taymans committed
608
/**
609 610 611
 * gst_clock_set_time_adjust
 * @clock: a #GstClock to adjust
 * @adjust: the adjust value
Wim Taymans's avatar
Wim Taymans committed
612
 *
613 614 615 616 617
 * Adjusts the current time of the clock with the adjust value.
 * A positive value moves the clock forwards and a backwards value
 * moves it backwards. Note that _get_time() always returns 
 * increasing values so when you move the clock backwards, _get_time()
 * will report the previous value until the clock catches up.
Wim Taymans's avatar
Wim Taymans committed
618
 *
619
 * MT safe.
Wim Taymans's avatar
Wim Taymans committed
620
 */
621 622
void
gst_clock_set_time_adjust (GstClock * clock, GstClockTime adjust)
623
{
624
  g_return_if_fail (GST_IS_CLOCK (clock));
625

626
  GST_LOCK (clock);
627
  clock->adjust = adjust;
628 629 630 631
  GST_UNLOCK (clock);
}

static void
632
gst_clock_update_stats (GstClock * clock)
633
{
634 635
}

636
static void
637 638
gst_clock_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
639
{
640
  GstClock *clock;
641

642 643 644 645 646
  clock = GST_CLOCK (object);

  switch (prop_id) {
    case ARG_STATS:
      clock->stats = g_value_get_boolean (value);
647
      g_object_notify (object, "stats");
648 649 650 651
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
652
  }
Wim Taymans's avatar
Wim Taymans committed
653
}
654

655
static void
656 657
gst_clock_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
658
{
659
  GstClock *clock;
660

661 662 663 664 665 666 667 668 669
  clock = GST_CLOCK (object);

  switch (prop_id) {
    case ARG_STATS:
      g_value_set_boolean (value, clock->stats);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
670
  }
671
}