1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gstreamer.Clock; 26 27 private import gobject.ObjectG; 28 private import gobject.Signals; 29 private import gstreamer.ObjectGst; 30 private import gstreamer.c.functions; 31 public import gstreamer.c.types; 32 public import gstreamerc.gstreamertypes; 33 private import std.algorithm; 34 35 36 /** 37 * GStreamer uses a global clock to synchronize the plugins in a pipeline. 38 * Different clock implementations are possible by implementing this abstract 39 * base class or, more conveniently, by subclassing #GstSystemClock. 40 * 41 * The #GstClock returns a monotonically increasing time with the method 42 * gst_clock_get_time(). Its accuracy and base time depend on the specific 43 * clock implementation but time is always expressed in nanoseconds. Since the 44 * baseline of the clock is undefined, the clock time returned is not 45 * meaningful in itself, what matters are the deltas between two clock times. 46 * The time returned by a clock is called the absolute time. 47 * 48 * The pipeline uses the clock to calculate the running time. Usually all 49 * renderers synchronize to the global clock using the buffer timestamps, the 50 * newsegment events and the element's base time, see #GstPipeline. 51 * 52 * A clock implementation can support periodic and single shot clock 53 * notifications both synchronous and asynchronous. 54 * 55 * One first needs to create a #GstClockID for the periodic or single shot 56 * notification using gst_clock_new_single_shot_id() or 57 * gst_clock_new_periodic_id(). 58 * 59 * To perform a blocking wait for the specific time of the #GstClockID use the 60 * gst_clock_id_wait(). To receive a callback when the specific time is reached 61 * in the clock use gst_clock_id_wait_async(). Both these calls can be 62 * interrupted with the gst_clock_id_unschedule() call. If the blocking wait is 63 * unscheduled a return value of #GST_CLOCK_UNSCHEDULED is returned. 64 * 65 * Periodic callbacks scheduled async will be repeatedly called automatically 66 * until it is unscheduled. To schedule a sync periodic callback, 67 * gst_clock_id_wait() should be called repeatedly. 68 * 69 * The async callbacks can happen from any thread, either provided by the core 70 * or from a streaming thread. The application should be prepared for this. 71 * 72 * A #GstClockID that has been unscheduled cannot be used again for any wait 73 * operation, a new #GstClockID should be created and the old unscheduled one 74 * should be destroyed with gst_clock_id_unref(). 75 * 76 * It is possible to perform a blocking wait on the same #GstClockID from 77 * multiple threads. However, registering the same #GstClockID for multiple 78 * async notifications is not possible, the callback will only be called for 79 * the thread registering the entry last. 80 * 81 * None of the wait operations unref the #GstClockID, the owner is responsible 82 * for unreffing the ids itself. This holds for both periodic and single shot 83 * notifications. The reason being that the owner of the #GstClockID has to 84 * keep a handle to the #GstClockID to unblock the wait on FLUSHING events or 85 * state changes and if the entry would be unreffed automatically, the handle 86 * might become invalid without any notification. 87 * 88 * These clock operations do not operate on the running time, so the callbacks 89 * will also occur when not in PLAYING state as if the clock just keeps on 90 * running. Some clocks however do not progress when the element that provided 91 * the clock is not PLAYING. 92 * 93 * When a clock has the #GST_CLOCK_FLAG_CAN_SET_MASTER flag set, it can be 94 * slaved to another #GstClock with the gst_clock_set_master(). The clock will 95 * then automatically be synchronized to this master clock by repeatedly 96 * sampling the master clock and the slave clock and recalibrating the slave 97 * clock with gst_clock_set_calibration(). This feature is mostly useful for 98 * plugins that have an internal clock but must operate with another clock 99 * selected by the #GstPipeline. They can track the offset and rate difference 100 * of their internal clock relative to the master clock by using the 101 * gst_clock_get_calibration() function. 102 * 103 * The master/slave synchronisation can be tuned with the #GstClock:timeout, 104 * #GstClock:window-size and #GstClock:window-threshold properties. 105 * The #GstClock:timeout property defines the interval to sample the master 106 * clock and run the calibration functions. #GstClock:window-size defines the 107 * number of samples to use when calibrating and #GstClock:window-threshold 108 * defines the minimum number of samples before the calibration is performed. 109 */ 110 public class Clock : ObjectGst 111 { 112 /** the main Gtk struct */ 113 protected GstClock* gstClock; 114 115 /** Get the main Gtk struct */ 116 public GstClock* getClockStruct(bool transferOwnership = false) 117 { 118 if (transferOwnership) 119 ownedRef = false; 120 return gstClock; 121 } 122 123 /** the main Gtk struct as a void* */ 124 protected override void* getStruct() 125 { 126 return cast(void*)gstClock; 127 } 128 129 protected override void setStruct(GObject* obj) 130 { 131 gstClock = cast(GstClock*)obj; 132 super.setStruct(obj); 133 } 134 135 /** 136 * Sets our main struct and passes it to the parent class. 137 */ 138 public this (GstClock* gstClock, bool ownedRef = false) 139 { 140 this.gstClock = gstClock; 141 super(cast(GstObject*)gstClock, ownedRef); 142 } 143 144 145 /** */ 146 public static GType getType() 147 { 148 return gst_clock_get_type(); 149 } 150 151 /** 152 * Compares the two #GstClockID instances. This function can be used 153 * as a GCompareFunc when sorting ids. 154 * 155 * Params: 156 * id1 = A #GstClockID 157 * id2 = A #GstClockID to compare with 158 * 159 * Returns: negative value if a < b; zero if a = b; positive value if a > b 160 * 161 * MT safe. 162 */ 163 public static int idCompareFunc(void* id1, void* id2) 164 { 165 return gst_clock_id_compare_func(id1, id2); 166 } 167 168 /** 169 * Get the time of the clock ID 170 * 171 * Params: 172 * id = The #GstClockID to query 173 * 174 * Returns: the time of the given clock id. 175 * 176 * MT safe. 177 */ 178 public static GstClockTime idGetTime(GstClockID id) 179 { 180 return gst_clock_id_get_time(id); 181 } 182 183 /** 184 * Increase the refcount of given @id. 185 * 186 * Params: 187 * id = The #GstClockID to ref 188 * 189 * Returns: The same #GstClockID with increased refcount. 190 * 191 * MT safe. 192 */ 193 public static GstClockID idRef(GstClockID id) 194 { 195 return gst_clock_id_ref(id); 196 } 197 198 /** 199 * Unref given @id. When the refcount reaches 0 the 200 * #GstClockID will be freed. 201 * 202 * MT safe. 203 * 204 * Params: 205 * id = The #GstClockID to unref 206 */ 207 public static void idUnref(GstClockID id) 208 { 209 gst_clock_id_unref(id); 210 } 211 212 /** 213 * Cancel an outstanding request with @id. This can either 214 * be an outstanding async notification or a pending sync notification. 215 * After this call, @id cannot be used anymore to receive sync or 216 * async notifications, you need to create a new #GstClockID. 217 * 218 * MT safe. 219 * 220 * Params: 221 * id = The id to unschedule 222 */ 223 public static void idUnschedule(GstClockID id) 224 { 225 gst_clock_id_unschedule(id); 226 } 227 228 /** 229 * Perform a blocking wait on @id. 230 * @id should have been created with gst_clock_new_single_shot_id() 231 * or gst_clock_new_periodic_id() and should not have been unscheduled 232 * with a call to gst_clock_id_unschedule(). 233 * 234 * If the @jitter argument is not %NULL and this function returns #GST_CLOCK_OK 235 * or #GST_CLOCK_EARLY, it will contain the difference 236 * against the clock and the time of @id when this method was 237 * called. 238 * Positive values indicate how late @id was relative to the clock 239 * (in which case this function will return #GST_CLOCK_EARLY). 240 * Negative values indicate how much time was spent waiting on the clock 241 * before this function returned. 242 * 243 * Params: 244 * id = The #GstClockID to wait on 245 * jitter = a pointer that will contain the jitter, 246 * can be %NULL. 247 * 248 * Returns: the result of the blocking wait. #GST_CLOCK_EARLY will be returned 249 * if the current clock time is past the time of @id, #GST_CLOCK_OK if 250 * @id was scheduled in time. #GST_CLOCK_UNSCHEDULED if @id was 251 * unscheduled with gst_clock_id_unschedule(). 252 * 253 * MT safe. 254 */ 255 public static GstClockReturn idWait(GstClockID id, out GstClockTimeDiff jitter) 256 { 257 return gst_clock_id_wait(id, &jitter); 258 } 259 260 /** 261 * Register a callback on the given #GstClockID @id with the given 262 * function and user_data. When passing a #GstClockID with an invalid 263 * time to this function, the callback will be called immediately 264 * with a time set to GST_CLOCK_TIME_NONE. The callback will 265 * be called when the time of @id has been reached. 266 * 267 * The callback @func can be invoked from any thread, either provided by the 268 * core or from a streaming thread. The application should be prepared for this. 269 * 270 * Params: 271 * id = a #GstClockID to wait on 272 * func = The callback function 273 * userData = User data passed in the callback 274 * destroyData = #GDestroyNotify for user_data 275 * 276 * Returns: the result of the non blocking wait. 277 * 278 * MT safe. 279 */ 280 public static GstClockReturn idWaitAsync(GstClockID id, GstClockCallback func, void* userData, GDestroyNotify destroyData) 281 { 282 return gst_clock_id_wait_async(id, func, userData, destroyData); 283 } 284 285 /** 286 * The time @master of the master clock and the time @slave of the slave 287 * clock are added to the list of observations. If enough observations 288 * are available, a linear regression algorithm is run on the 289 * observations and @clock is recalibrated. 290 * 291 * If this functions returns %TRUE, @r_squared will contain the 292 * correlation coefficient of the interpolation. A value of 1.0 293 * means a perfect regression was performed. This value can 294 * be used to control the sampling frequency of the master and slave 295 * clocks. 296 * 297 * Params: 298 * slave = a time on the slave 299 * master = a time on the master 300 * rSquared = a pointer to hold the result 301 * 302 * Returns: %TRUE if enough observations were added to run the 303 * regression algorithm. 304 * 305 * MT safe. 306 */ 307 public bool addObservation(GstClockTime slave, GstClockTime master, out double rSquared) 308 { 309 return gst_clock_add_observation(gstClock, slave, master, &rSquared) != 0; 310 } 311 312 /** 313 * Add a clock observation to the internal slaving algorithm the same as 314 * gst_clock_add_observation(), and return the result of the master clock 315 * estimation, without updating the internal calibration. 316 * 317 * The caller can then take the results and call gst_clock_set_calibration() 318 * with the values, or some modified version of them. 319 * 320 * Params: 321 * slave = a time on the slave 322 * master = a time on the master 323 * rSquared = a pointer to hold the result 324 * internal = a location to store the internal time 325 * external = a location to store the external time 326 * rateNum = a location to store the rate numerator 327 * rateDenom = a location to store the rate denominator 328 * 329 * Since: 1.6 330 */ 331 public bool addObservationUnapplied(GstClockTime slave, GstClockTime master, out double rSquared, out GstClockTime internal, out GstClockTime external, out GstClockTime rateNum, out GstClockTime rateDenom) 332 { 333 return gst_clock_add_observation_unapplied(gstClock, slave, master, &rSquared, &internal, &external, &rateNum, &rateDenom) != 0; 334 } 335 336 /** 337 * Converts the given @internal clock time to the external time, adjusting for the 338 * rate and reference time set with gst_clock_set_calibration() and making sure 339 * that the returned time is increasing. This function should be called with the 340 * clock's OBJECT_LOCK held and is mainly used by clock subclasses. 341 * 342 * This function is the reverse of gst_clock_unadjust_unlocked(). 343 * 344 * Params: 345 * internal = a clock time 346 * 347 * Returns: the converted time of the clock. 348 */ 349 public GstClockTime adjustUnlocked(GstClockTime internal) 350 { 351 return gst_clock_adjust_unlocked(gstClock, internal); 352 } 353 354 /** 355 * Converts the given @internal_target clock time to the external time, 356 * using the passed calibration parameters. This function performs the 357 * same calculation as gst_clock_adjust_unlocked() when called using the 358 * current calibration parameters, but doesn't ensure a monotonically 359 * increasing result as gst_clock_adjust_unlocked() does. 360 * 361 * Note: The @clock parameter is unused and can be NULL 362 * 363 * Params: 364 * internalTarget = a clock time 365 * cinternal = a reference internal time 366 * cexternal = a reference external time 367 * cnum = the numerator of the rate of the clock relative to its 368 * internal time 369 * cdenom = the denominator of the rate of the clock 370 * 371 * Returns: the converted time of the clock. 372 * 373 * Since: 1.6 374 */ 375 public GstClockTime adjustWithCalibration(GstClockTime internalTarget, GstClockTime cinternal, GstClockTime cexternal, GstClockTime cnum, GstClockTime cdenom) 376 { 377 return gst_clock_adjust_with_calibration(gstClock, internalTarget, cinternal, cexternal, cnum, cdenom); 378 } 379 380 /** 381 * Gets the internal rate and reference time of @clock. See 382 * gst_clock_set_calibration() for more information. 383 * 384 * @internal, @external, @rate_num, and @rate_denom can be left %NULL if the 385 * caller is not interested in the values. 386 * 387 * MT safe. 388 * 389 * Params: 390 * internal = a location to store the internal time 391 * external = a location to store the external time 392 * rateNum = a location to store the rate numerator 393 * rateDenom = a location to store the rate denominator 394 */ 395 public void getCalibration(out GstClockTime internal, out GstClockTime external, out GstClockTime rateNum, out GstClockTime rateDenom) 396 { 397 gst_clock_get_calibration(gstClock, &internal, &external, &rateNum, &rateDenom); 398 } 399 400 /** 401 * Gets the current internal time of the given clock. The time is returned 402 * unadjusted for the offset and the rate. 403 * 404 * Returns: the internal time of the clock. Or GST_CLOCK_TIME_NONE when 405 * given invalid input. 406 * 407 * MT safe. 408 */ 409 public GstClockTime getInternalTime() 410 { 411 return gst_clock_get_internal_time(gstClock); 412 } 413 414 /** 415 * Get the master clock that @clock is slaved to or %NULL when the clock is 416 * not slaved to any master clock. 417 * 418 * Returns: a master #GstClock or %NULL 419 * when this clock is not slaved to a master clock. Unref after 420 * usage. 421 * 422 * MT safe. 423 */ 424 public Clock getMaster() 425 { 426 auto p = gst_clock_get_master(gstClock); 427 428 if(p is null) 429 { 430 return null; 431 } 432 433 return ObjectG.getDObject!(Clock)(cast(GstClock*) p, true); 434 } 435 436 /** 437 * Get the accuracy of the clock. The accuracy of the clock is the granularity 438 * of the values returned by gst_clock_get_time(). 439 * 440 * Returns: the resolution of the clock in units of #GstClockTime. 441 * 442 * MT safe. 443 */ 444 public GstClockTime getResolution() 445 { 446 return gst_clock_get_resolution(gstClock); 447 } 448 449 /** 450 * Gets the current time of the given clock. The time is always 451 * monotonically increasing and adjusted according to the current 452 * offset and rate. 453 * 454 * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when 455 * given invalid input. 456 * 457 * MT safe. 458 */ 459 public GstClockTime getTime() 460 { 461 return gst_clock_get_time(gstClock); 462 } 463 464 /** 465 * Get the amount of time that master and slave clocks are sampled. 466 * 467 * Returns: the interval between samples. 468 */ 469 public GstClockTime getTimeout() 470 { 471 return gst_clock_get_timeout(gstClock); 472 } 473 474 /** 475 * Checks if the clock is currently synced. 476 * 477 * This returns if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC is not set on the clock. 478 * 479 * Returns: %TRUE if the clock is currently synced 480 * 481 * Since: 1.6 482 */ 483 public bool isSynced() 484 { 485 return gst_clock_is_synced(gstClock) != 0; 486 } 487 488 /** 489 * Get an ID from @clock to trigger a periodic notification. 490 * The periodic notifications will start at time @start_time and 491 * will then be fired with the given @interval. @id should be unreffed 492 * after usage. 493 * 494 * Free-function: gst_clock_id_unref 495 * 496 * Params: 497 * startTime = the requested start time 498 * interval = the requested interval 499 * 500 * Returns: a #GstClockID that can be used to request the 501 * time notification. 502 * 503 * MT safe. 504 */ 505 public GstClockID newPeriodicId(GstClockTime startTime, GstClockTime interval) 506 { 507 return gst_clock_new_periodic_id(gstClock, startTime, interval); 508 } 509 510 /** 511 * Get a #GstClockID from @clock to trigger a single shot 512 * notification at the requested time. The single shot id should be 513 * unreffed after usage. 514 * 515 * Free-function: gst_clock_id_unref 516 * 517 * Params: 518 * time = the requested time 519 * 520 * Returns: a #GstClockID that can be used to request the 521 * time notification. 522 * 523 * MT safe. 524 */ 525 public GstClockID newSingleShotId(GstClockTime time) 526 { 527 return gst_clock_new_single_shot_id(gstClock, time); 528 } 529 530 /** 531 * Reinitializes the provided periodic @id to the provided start time and 532 * interval. Does not modify the reference count. 533 * 534 * Params: 535 * id = a #GstClockID 536 * startTime = the requested start time 537 * interval = the requested interval 538 * 539 * Returns: %TRUE if the GstClockID could be reinitialized to the provided 540 * @time, else %FALSE. 541 */ 542 public bool periodicIdReinit(GstClockID id, GstClockTime startTime, GstClockTime interval) 543 { 544 return gst_clock_periodic_id_reinit(gstClock, id, startTime, interval) != 0; 545 } 546 547 /** 548 * Adjusts the rate and time of @clock. A rate of 1/1 is the normal speed of 549 * the clock. Values bigger than 1/1 make the clock go faster. 550 * 551 * @internal and @external are calibration parameters that arrange that 552 * gst_clock_get_time() should have been @external at internal time @internal. 553 * This internal time should not be in the future; that is, it should be less 554 * than the value of gst_clock_get_internal_time() when this function is called. 555 * 556 * Subsequent calls to gst_clock_get_time() will return clock times computed as 557 * follows: 558 * 559 * |[ 560 * time = (internal_time - internal) * rate_num / rate_denom + external 561 * ]| 562 * 563 * This formula is implemented in gst_clock_adjust_unlocked(). Of course, it 564 * tries to do the integer arithmetic as precisely as possible. 565 * 566 * Note that gst_clock_get_time() always returns increasing values so when you 567 * move the clock backwards, gst_clock_get_time() will report the previous value 568 * until the clock catches up. 569 * 570 * MT safe. 571 * 572 * Params: 573 * internal = a reference internal time 574 * external = a reference external time 575 * rateNum = the numerator of the rate of the clock relative to its 576 * internal time 577 * rateDenom = the denominator of the rate of the clock 578 */ 579 public void setCalibration(GstClockTime internal, GstClockTime external, GstClockTime rateNum, GstClockTime rateDenom) 580 { 581 gst_clock_set_calibration(gstClock, internal, external, rateNum, rateDenom); 582 } 583 584 /** 585 * Set @master as the master clock for @clock. @clock will be automatically 586 * calibrated so that gst_clock_get_time() reports the same time as the 587 * master clock. 588 * 589 * A clock provider that slaves its clock to a master can get the current 590 * calibration values with gst_clock_get_calibration(). 591 * 592 * @master can be %NULL in which case @clock will not be slaved anymore. It will 593 * however keep reporting its time adjusted with the last configured rate 594 * and time offsets. 595 * 596 * Params: 597 * master = a master #GstClock 598 * 599 * Returns: %TRUE if the clock is capable of being slaved to a master clock. 600 * Trying to set a master on a clock without the 601 * #GST_CLOCK_FLAG_CAN_SET_MASTER flag will make this function return %FALSE. 602 * 603 * MT safe. 604 */ 605 public bool setMaster(Clock master) 606 { 607 return gst_clock_set_master(gstClock, (master is null) ? null : master.getClockStruct()) != 0; 608 } 609 610 /** 611 * Set the accuracy of the clock. Some clocks have the possibility to operate 612 * with different accuracy at the expense of more resource usage. There is 613 * normally no need to change the default resolution of a clock. The resolution 614 * of a clock can only be changed if the clock has the 615 * #GST_CLOCK_FLAG_CAN_SET_RESOLUTION flag set. 616 * 617 * Params: 618 * resolution = The resolution to set 619 * 620 * Returns: the new resolution of the clock. 621 */ 622 public GstClockTime setResolution(GstClockTime resolution) 623 { 624 return gst_clock_set_resolution(gstClock, resolution); 625 } 626 627 /** 628 * Sets @clock to synced and emits the GstClock::synced signal, and wakes up any 629 * thread waiting in gst_clock_wait_for_sync(). 630 * 631 * This function must only be called if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC 632 * is set on the clock, and is intended to be called by subclasses only. 633 * 634 * Params: 635 * synced = if the clock is synced 636 * 637 * Since: 1.6 638 */ 639 public void setSynced(bool synced) 640 { 641 gst_clock_set_synced(gstClock, synced); 642 } 643 644 /** 645 * Set the amount of time, in nanoseconds, to sample master and slave 646 * clocks 647 * 648 * Params: 649 * timeout = a timeout 650 */ 651 public void setTimeout(GstClockTime timeout) 652 { 653 gst_clock_set_timeout(gstClock, timeout); 654 } 655 656 /** 657 * Reinitializes the provided single shot @id to the provided time. Does not 658 * modify the reference count. 659 * 660 * Params: 661 * id = a #GstClockID 662 * time = The requested time. 663 * 664 * Returns: %TRUE if the GstClockID could be reinitialized to the provided 665 * @time, else %FALSE. 666 */ 667 public bool singleShotIdReinit(GstClockID id, GstClockTime time) 668 { 669 return gst_clock_single_shot_id_reinit(gstClock, id, time) != 0; 670 } 671 672 /** 673 * Converts the given @external clock time to the internal time of @clock, 674 * using the rate and reference time set with gst_clock_set_calibration(). 675 * This function should be called with the clock's OBJECT_LOCK held and 676 * is mainly used by clock subclasses. 677 * 678 * This function is the reverse of gst_clock_adjust_unlocked(). 679 * 680 * Params: 681 * external = an external clock time 682 * 683 * Returns: the internal time of the clock corresponding to @external. 684 */ 685 public GstClockTime unadjustUnlocked(GstClockTime external) 686 { 687 return gst_clock_unadjust_unlocked(gstClock, external); 688 } 689 690 /** 691 * Converts the given @external_target clock time to the internal time, 692 * using the passed calibration parameters. This function performs the 693 * same calculation as gst_clock_unadjust_unlocked() when called using the 694 * current calibration parameters. 695 * 696 * Note: The @clock parameter is unused and can be NULL 697 * 698 * Params: 699 * externalTarget = a clock time 700 * cinternal = a reference internal time 701 * cexternal = a reference external time 702 * cnum = the numerator of the rate of the clock relative to its 703 * internal time 704 * cdenom = the denominator of the rate of the clock 705 * 706 * Returns: the converted time of the clock. 707 * 708 * Since: 1.8 709 */ 710 public GstClockTime unadjustWithCalibration(GstClockTime externalTarget, GstClockTime cinternal, GstClockTime cexternal, GstClockTime cnum, GstClockTime cdenom) 711 { 712 return gst_clock_unadjust_with_calibration(gstClock, externalTarget, cinternal, cexternal, cnum, cdenom); 713 } 714 715 /** 716 * Waits until @clock is synced for reporting the current time. If @timeout 717 * is %GST_CLOCK_TIME_NONE it will wait forever, otherwise it will time out 718 * after @timeout nanoseconds. 719 * 720 * For asynchronous waiting, the GstClock::synced signal can be used. 721 * 722 * This returns immediately with TRUE if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC 723 * is not set on the clock, or if the clock is already synced. 724 * 725 * Params: 726 * timeout = timeout for waiting or %GST_CLOCK_TIME_NONE 727 * 728 * Returns: %TRUE if waiting was successful, or %FALSE on timeout 729 * 730 * Since: 1.6 731 */ 732 public bool waitForSync(GstClockTime timeout) 733 { 734 return gst_clock_wait_for_sync(gstClock, timeout) != 0; 735 } 736 737 protected class OnSyncedDelegateWrapper 738 { 739 void delegate(bool, Clock) dlg; 740 gulong handlerId; 741 742 this(void delegate(bool, Clock) dlg) 743 { 744 this.dlg = dlg; 745 onSyncedListeners ~= this; 746 } 747 748 void remove(OnSyncedDelegateWrapper source) 749 { 750 foreach(index, wrapper; onSyncedListeners) 751 { 752 if (wrapper.handlerId == source.handlerId) 753 { 754 onSyncedListeners[index] = null; 755 onSyncedListeners = std.algorithm.remove(onSyncedListeners, index); 756 break; 757 } 758 } 759 } 760 } 761 OnSyncedDelegateWrapper[] onSyncedListeners; 762 763 /** 764 * Signaled on clocks with GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC set once 765 * the clock is synchronized, or when it completely lost synchronization. 766 * This signal will not be emitted on clocks without the flag. 767 * 768 * This signal will be emitted from an arbitrary thread, most likely not 769 * the application's main thread. 770 * 771 * Params: 772 * synced = if the clock is synced now 773 * 774 * Since: 1.6 775 */ 776 gulong addOnSynced(void delegate(bool, Clock) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 777 { 778 auto wrapper = new OnSyncedDelegateWrapper(dlg); 779 wrapper.handlerId = Signals.connectData( 780 this, 781 "synced", 782 cast(GCallback)&callBackSynced, 783 cast(void*)wrapper, 784 cast(GClosureNotify)&callBackSyncedDestroy, 785 connectFlags); 786 return wrapper.handlerId; 787 } 788 789 extern(C) static void callBackSynced(GstClock* clockStruct, bool synced, OnSyncedDelegateWrapper wrapper) 790 { 791 wrapper.dlg(synced, wrapper.outer); 792 } 793 794 extern(C) static void callBackSyncedDestroy(OnSyncedDelegateWrapper wrapper, GClosure* closure) 795 { 796 wrapper.remove(wrapper); 797 } 798 }