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 gst.app.AppSrc; 26 27 private import gobject.ObjectG; 28 private import gobject.Signals; 29 private import gst.app.c.functions; 30 public import gst.app.c.types; 31 private import gst.base.BaseSrc; 32 private import gstreamer.Buffer; 33 private import gstreamer.Caps; 34 private import gstreamer.Sample; 35 private import gstreamer.URIHandlerIF; 36 private import gstreamer.URIHandlerT; 37 private import std.algorithm; 38 39 40 /** 41 * The appsrc element can be used by applications to insert data into a 42 * GStreamer pipeline. Unlike most GStreamer elements, appsrc provides 43 * external API functions. 44 * 45 * appsrc can be used by linking with the libgstapp library to access the 46 * methods directly or by using the appsrc action signals. 47 * 48 * Before operating appsrc, the caps property must be set to fixed caps 49 * describing the format of the data that will be pushed with appsrc. An 50 * exception to this is when pushing buffers with unknown caps, in which case no 51 * caps should be set. This is typically true of file-like sources that push raw 52 * byte buffers. If you don't want to explicitly set the caps, you can use 53 * gst_app_src_push_sample. This method gets the caps associated with the 54 * sample and sets them on the appsrc replacing any previously set caps (if 55 * different from sample's caps). 56 * 57 * The main way of handing data to the appsrc element is by calling the 58 * gst_app_src_push_buffer() method or by emitting the push-buffer action signal. 59 * This will put the buffer onto a queue from which appsrc will read from in its 60 * streaming thread. It is important to note that data transport will not happen 61 * from the thread that performed the push-buffer call. 62 * 63 * The "max-bytes" property controls how much data can be queued in appsrc 64 * before appsrc considers the queue full. A filled internal queue will always 65 * signal the "enough-data" signal, which signals the application that it should 66 * stop pushing data into appsrc. The "block" property will cause appsrc to 67 * block the push-buffer method until free data becomes available again. 68 * 69 * When the internal queue is running out of data, the "need-data" signal is 70 * emitted, which signals the application that it should start pushing more data 71 * into appsrc. 72 * 73 * In addition to the "need-data" and "enough-data" signals, appsrc can emit the 74 * "seek-data" signal when the "stream-mode" property is set to "seekable" or 75 * "random-access". The signal argument will contain the new desired position in 76 * the stream expressed in the unit set with the "format" property. After 77 * receiving the seek-data signal, the application should push-buffers from the 78 * new position. 79 * 80 * These signals allow the application to operate the appsrc in two different 81 * ways: 82 * 83 * The push mode, in which the application repeatedly calls the push-buffer/push-sample 84 * method with a new buffer/sample. Optionally, the queue size in the appsrc 85 * can be controlled with the enough-data and need-data signals by respectively 86 * stopping/starting the push-buffer/push-sample calls. This is a typical 87 * mode of operation for the stream-type "stream" and "seekable". Use this 88 * mode when implementing various network protocols or hardware devices. 89 * 90 * The pull mode, in which the need-data signal triggers the next push-buffer call. 91 * This mode is typically used in the "random-access" stream-type. Use this 92 * mode for file access or other randomly accessable sources. In this mode, a 93 * buffer of exactly the amount of bytes given by the need-data signal should be 94 * pushed into appsrc. 95 * 96 * In all modes, the size property on appsrc should contain the total stream 97 * size in bytes. Setting this property is mandatory in the random-access mode. 98 * For the stream and seekable modes, setting this property is optional but 99 * recommended. 100 * 101 * When the application has finished pushing data into appsrc, it should call 102 * gst_app_src_end_of_stream() or emit the end-of-stream action signal. After 103 * this call, no more buffers can be pushed into appsrc until a flushing seek 104 * occurs or the state of the appsrc has gone through READY. 105 */ 106 public class AppSrc : BaseSrc, URIHandlerIF 107 { 108 /** the main Gtk struct */ 109 protected GstAppSrc* gstAppSrc; 110 111 /** Get the main Gtk struct */ 112 public GstAppSrc* getAppSrcStruct(bool transferOwnership = false) 113 { 114 if (transferOwnership) 115 ownedRef = false; 116 return gstAppSrc; 117 } 118 119 /** the main Gtk struct as a void* */ 120 protected override void* getStruct() 121 { 122 return cast(void*)gstAppSrc; 123 } 124 125 protected override void setStruct(GObject* obj) 126 { 127 gstAppSrc = cast(GstAppSrc*)obj; 128 super.setStruct(obj); 129 } 130 131 /** 132 * Sets our main struct and passes it to the parent class. 133 */ 134 public this (GstAppSrc* gstAppSrc, bool ownedRef = false) 135 { 136 this.gstAppSrc = gstAppSrc; 137 super(cast(GstBaseSrc*)gstAppSrc, ownedRef); 138 } 139 140 // add the URIHandler capabilities 141 mixin URIHandlerT!(GstAppSrc); 142 143 144 /** */ 145 public static GType getType() 146 { 147 return gst_app_src_get_type(); 148 } 149 150 /** 151 * Indicates to the appsrc element that the last buffer queued in the 152 * element is the last buffer of the stream. 153 * 154 * Returns: #GST_FLOW_OK when the EOS was successfuly queued. 155 * #GST_FLOW_FLUSHING when @appsrc is not PAUSED or PLAYING. 156 */ 157 public GstFlowReturn endOfStream() 158 { 159 return gst_app_src_end_of_stream(gstAppSrc); 160 } 161 162 /** 163 * Get the configured caps on @appsrc. 164 * 165 * Returns: the #GstCaps produced by the source. gst_caps_unref() after usage. 166 */ 167 public Caps getCaps() 168 { 169 auto p = gst_app_src_get_caps(gstAppSrc); 170 171 if(p is null) 172 { 173 return null; 174 } 175 176 return ObjectG.getDObject!(Caps)(cast(GstCaps*) p, true); 177 } 178 179 /** 180 * Get the number of currently queued bytes inside @appsrc. 181 * 182 * Returns: The number of currently queued bytes. 183 * 184 * Since: 1.2 185 */ 186 public ulong getCurrentLevelBytes() 187 { 188 return gst_app_src_get_current_level_bytes(gstAppSrc); 189 } 190 191 /** 192 * Get the duration of the stream in nanoseconds. A value of GST_CLOCK_TIME_NONE means that the duration is 193 * not known. 194 * 195 * Returns: the duration of the stream previously set with gst_app_src_set_duration(); 196 * 197 * Since: 1.10 198 */ 199 public GstClockTime getDuration() 200 { 201 return gst_app_src_get_duration(gstAppSrc); 202 } 203 204 /** 205 * Check if appsrc will emit the "new-preroll" and "new-buffer" signals. 206 * 207 * Returns: %TRUE if @appsrc is emitting the "new-preroll" and "new-buffer" 208 * signals. 209 */ 210 public bool getEmitSignals() 211 { 212 return gst_app_src_get_emit_signals(gstAppSrc) != 0; 213 } 214 215 /** 216 * Retrieve the min and max latencies in @min and @max respectively. 217 * 218 * Params: 219 * min = the min latency 220 * max = the min latency 221 */ 222 public void getLatency(ulong* min, ulong* max) 223 { 224 gst_app_src_get_latency(gstAppSrc, min, max); 225 } 226 227 /** 228 * Get the maximum amount of bytes that can be queued in @appsrc. 229 * 230 * Returns: The maximum amount of bytes that can be queued. 231 */ 232 public ulong getMaxBytes() 233 { 234 return gst_app_src_get_max_bytes(gstAppSrc); 235 } 236 237 /** 238 * Get the size of the stream in bytes. A value of -1 means that the size is 239 * not known. 240 * 241 * Returns: the size of the stream previously set with gst_app_src_set_size(); 242 */ 243 public long getSize() 244 { 245 return gst_app_src_get_size(gstAppSrc); 246 } 247 248 /** 249 * Get the stream type. Control the stream type of @appsrc 250 * with gst_app_src_set_stream_type(). 251 * 252 * Returns: the stream type. 253 */ 254 public GstAppStreamType getStreamType() 255 { 256 return gst_app_src_get_stream_type(gstAppSrc); 257 } 258 259 /** 260 * Adds a buffer to the queue of buffers that the appsrc element will 261 * push to its source pad. This function takes ownership of the buffer. 262 * 263 * When the block property is TRUE, this function can block until free 264 * space becomes available in the queue. 265 * 266 * Params: 267 * buffer = a #GstBuffer to push 268 * 269 * Returns: #GST_FLOW_OK when the buffer was successfuly queued. 270 * #GST_FLOW_FLUSHING when @appsrc is not PAUSED or PLAYING. 271 * #GST_FLOW_EOS when EOS occured. 272 */ 273 public GstFlowReturn pushBuffer(Buffer buffer) 274 { 275 return gst_app_src_push_buffer(gstAppSrc, (buffer is null) ? null : buffer.getBufferStruct()); 276 } 277 278 /** 279 * Extract a buffer from the provided sample and adds it to the queue of 280 * buffers that the appsrc element will push to its source pad. Any 281 * previous caps that were set on appsrc will be replaced by the caps 282 * associated with the sample if not equal. 283 * 284 * When the block property is TRUE, this function can block until free 285 * space becomes available in the queue. 286 * 287 * Params: 288 * sample = a #GstSample from which buffer and caps may be 289 * extracted 290 * 291 * Returns: #GST_FLOW_OK when the buffer was successfuly queued. 292 * #GST_FLOW_FLUSHING when @appsrc is not PAUSED or PLAYING. 293 * #GST_FLOW_EOS when EOS occured. 294 * 295 * Since: 1.6 296 */ 297 public GstFlowReturn pushSample(Sample sample) 298 { 299 return gst_app_src_push_sample(gstAppSrc, (sample is null) ? null : sample.getSampleStruct()); 300 } 301 302 /** 303 * Set callbacks which will be executed when data is needed, enough data has 304 * been collected or when a seek should be performed. 305 * This is an alternative to using the signals, it has lower overhead and is thus 306 * less expensive, but also less flexible. 307 * 308 * If callbacks are installed, no signals will be emitted for performance 309 * reasons. 310 * 311 * Params: 312 * callbacks = the callbacks 313 * userData = a user_data argument for the callbacks 314 * notify = a destroy notify function 315 */ 316 public void setCallbacks(GstAppSrcCallbacks* callbacks, void* userData, GDestroyNotify notify) 317 { 318 gst_app_src_set_callbacks(gstAppSrc, callbacks, userData, notify); 319 } 320 321 /** 322 * Set the duration of the stream in nanoseconds. A value of GST_CLOCK_TIME_NONE means that the duration is 323 * not known. 324 * 325 * Params: 326 * duration = the duration to set 327 * 328 * Since: 1.10 329 */ 330 public void setDuration(GstClockTime duration) 331 { 332 gst_app_src_set_duration(gstAppSrc, duration); 333 } 334 335 /** 336 * Make appsrc emit the "new-preroll" and "new-buffer" signals. This option is 337 * by default disabled because signal emission is expensive and unneeded when 338 * the application prefers to operate in pull mode. 339 * 340 * Params: 341 * emit = the new state 342 */ 343 public void setEmitSignals(bool emit) 344 { 345 gst_app_src_set_emit_signals(gstAppSrc, emit); 346 } 347 348 /** 349 * Configure the @min and @max latency in @src. If @min is set to -1, the 350 * default latency calculations for pseudo-live sources will be used. 351 * 352 * Params: 353 * min = the min latency 354 * max = the min latency 355 */ 356 public void setLatency(ulong min, ulong max) 357 { 358 gst_app_src_set_latency(gstAppSrc, min, max); 359 } 360 361 /** 362 * Set the maximum amount of bytes that can be queued in @appsrc. 363 * After the maximum amount of bytes are queued, @appsrc will emit the 364 * "enough-data" signal. 365 * 366 * Params: 367 * max = the maximum number of bytes to queue 368 */ 369 public void setMaxBytes(ulong max) 370 { 371 gst_app_src_set_max_bytes(gstAppSrc, max); 372 } 373 374 /** 375 * Set the size of the stream in bytes. A value of -1 means that the size is 376 * not known. 377 * 378 * Params: 379 * size = the size to set 380 */ 381 public void setSize(long size) 382 { 383 gst_app_src_set_size(gstAppSrc, size); 384 } 385 386 /** 387 * Set the stream type on @appsrc. For seekable streams, the "seek" signal must 388 * be connected to. 389 * 390 * A stream_type stream 391 * 392 * Params: 393 * type = the new state 394 */ 395 public void setStreamType(GstAppStreamType type) 396 { 397 gst_app_src_set_stream_type(gstAppSrc, type); 398 } 399 400 protected class OnEndOfStreamDelegateWrapper 401 { 402 GstFlowReturn delegate(AppSrc) dlg; 403 gulong handlerId; 404 405 this(GstFlowReturn delegate(AppSrc) dlg) 406 { 407 this.dlg = dlg; 408 onEndOfStreamListeners ~= this; 409 } 410 411 void remove(OnEndOfStreamDelegateWrapper source) 412 { 413 foreach(index, wrapper; onEndOfStreamListeners) 414 { 415 if (wrapper.handlerId == source.handlerId) 416 { 417 onEndOfStreamListeners[index] = null; 418 onEndOfStreamListeners = std.algorithm.remove(onEndOfStreamListeners, index); 419 break; 420 } 421 } 422 } 423 } 424 OnEndOfStreamDelegateWrapper[] onEndOfStreamListeners; 425 426 /** 427 * Notify @appsrc that no more buffer are available. 428 */ 429 gulong addOnEndOfStream(GstFlowReturn delegate(AppSrc) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 430 { 431 auto wrapper = new OnEndOfStreamDelegateWrapper(dlg); 432 wrapper.handlerId = Signals.connectData( 433 this, 434 "end-of-stream", 435 cast(GCallback)&callBackEndOfStream, 436 cast(void*)wrapper, 437 cast(GClosureNotify)&callBackEndOfStreamDestroy, 438 connectFlags); 439 return wrapper.handlerId; 440 } 441 442 extern(C) static GstFlowReturn callBackEndOfStream(GstAppSrc* appsrcStruct, OnEndOfStreamDelegateWrapper wrapper) 443 { 444 return wrapper.dlg(wrapper.outer); 445 } 446 447 extern(C) static void callBackEndOfStreamDestroy(OnEndOfStreamDelegateWrapper wrapper, GClosure* closure) 448 { 449 wrapper.remove(wrapper); 450 } 451 452 protected class OnEnoughDataDelegateWrapper 453 { 454 void delegate(AppSrc) dlg; 455 gulong handlerId; 456 457 this(void delegate(AppSrc) dlg) 458 { 459 this.dlg = dlg; 460 onEnoughDataListeners ~= this; 461 } 462 463 void remove(OnEnoughDataDelegateWrapper source) 464 { 465 foreach(index, wrapper; onEnoughDataListeners) 466 { 467 if (wrapper.handlerId == source.handlerId) 468 { 469 onEnoughDataListeners[index] = null; 470 onEnoughDataListeners = std.algorithm.remove(onEnoughDataListeners, index); 471 break; 472 } 473 } 474 } 475 } 476 OnEnoughDataDelegateWrapper[] onEnoughDataListeners; 477 478 /** 479 * Signal that the source has enough data. It is recommended that the 480 * application stops calling push-buffer until the need-data signal is 481 * emitted again to avoid excessive buffer queueing. 482 */ 483 gulong addOnEnoughData(void delegate(AppSrc) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 484 { 485 auto wrapper = new OnEnoughDataDelegateWrapper(dlg); 486 wrapper.handlerId = Signals.connectData( 487 this, 488 "enough-data", 489 cast(GCallback)&callBackEnoughData, 490 cast(void*)wrapper, 491 cast(GClosureNotify)&callBackEnoughDataDestroy, 492 connectFlags); 493 return wrapper.handlerId; 494 } 495 496 extern(C) static void callBackEnoughData(GstAppSrc* appsrcStruct, OnEnoughDataDelegateWrapper wrapper) 497 { 498 wrapper.dlg(wrapper.outer); 499 } 500 501 extern(C) static void callBackEnoughDataDestroy(OnEnoughDataDelegateWrapper wrapper, GClosure* closure) 502 { 503 wrapper.remove(wrapper); 504 } 505 506 protected class OnNeedDataDelegateWrapper 507 { 508 void delegate(uint, AppSrc) dlg; 509 gulong handlerId; 510 511 this(void delegate(uint, AppSrc) dlg) 512 { 513 this.dlg = dlg; 514 onNeedDataListeners ~= this; 515 } 516 517 void remove(OnNeedDataDelegateWrapper source) 518 { 519 foreach(index, wrapper; onNeedDataListeners) 520 { 521 if (wrapper.handlerId == source.handlerId) 522 { 523 onNeedDataListeners[index] = null; 524 onNeedDataListeners = std.algorithm.remove(onNeedDataListeners, index); 525 break; 526 } 527 } 528 } 529 } 530 OnNeedDataDelegateWrapper[] onNeedDataListeners; 531 532 /** 533 * Signal that the source needs more data. In the callback or from another 534 * thread you should call push-buffer or end-of-stream. 535 * 536 * @length is just a hint and when it is set to -1, any number of bytes can be 537 * pushed into @appsrc. 538 * 539 * You can call push-buffer multiple times until the enough-data signal is 540 * fired. 541 * 542 * Params: 543 * length = the amount of bytes needed. 544 */ 545 gulong addOnNeedData(void delegate(uint, AppSrc) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 546 { 547 auto wrapper = new OnNeedDataDelegateWrapper(dlg); 548 wrapper.handlerId = Signals.connectData( 549 this, 550 "need-data", 551 cast(GCallback)&callBackNeedData, 552 cast(void*)wrapper, 553 cast(GClosureNotify)&callBackNeedDataDestroy, 554 connectFlags); 555 return wrapper.handlerId; 556 } 557 558 extern(C) static void callBackNeedData(GstAppSrc* appsrcStruct, uint length, OnNeedDataDelegateWrapper wrapper) 559 { 560 wrapper.dlg(length, wrapper.outer); 561 } 562 563 extern(C) static void callBackNeedDataDestroy(OnNeedDataDelegateWrapper wrapper, GClosure* closure) 564 { 565 wrapper.remove(wrapper); 566 } 567 568 protected class OnPushBufferDelegateWrapper 569 { 570 GstFlowReturn delegate(Buffer, AppSrc) dlg; 571 gulong handlerId; 572 573 this(GstFlowReturn delegate(Buffer, AppSrc) dlg) 574 { 575 this.dlg = dlg; 576 onPushBufferListeners ~= this; 577 } 578 579 void remove(OnPushBufferDelegateWrapper source) 580 { 581 foreach(index, wrapper; onPushBufferListeners) 582 { 583 if (wrapper.handlerId == source.handlerId) 584 { 585 onPushBufferListeners[index] = null; 586 onPushBufferListeners = std.algorithm.remove(onPushBufferListeners, index); 587 break; 588 } 589 } 590 } 591 } 592 OnPushBufferDelegateWrapper[] onPushBufferListeners; 593 594 /** 595 * Adds a buffer to the queue of buffers that the appsrc element will 596 * push to its source pad. This function does not take ownership of the 597 * buffer so the buffer needs to be unreffed after calling this function. 598 * 599 * When the block property is TRUE, this function can block until free space 600 * becomes available in the queue. 601 * 602 * Params: 603 * buffer = a buffer to push 604 */ 605 gulong addOnPushBuffer(GstFlowReturn delegate(Buffer, AppSrc) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 606 { 607 auto wrapper = new OnPushBufferDelegateWrapper(dlg); 608 wrapper.handlerId = Signals.connectData( 609 this, 610 "push-buffer", 611 cast(GCallback)&callBackPushBuffer, 612 cast(void*)wrapper, 613 cast(GClosureNotify)&callBackPushBufferDestroy, 614 connectFlags); 615 return wrapper.handlerId; 616 } 617 618 extern(C) static GstFlowReturn callBackPushBuffer(GstAppSrc* appsrcStruct, GstBuffer* buffer, OnPushBufferDelegateWrapper wrapper) 619 { 620 return wrapper.dlg(ObjectG.getDObject!(Buffer)(buffer), wrapper.outer); 621 } 622 623 extern(C) static void callBackPushBufferDestroy(OnPushBufferDelegateWrapper wrapper, GClosure* closure) 624 { 625 wrapper.remove(wrapper); 626 } 627 628 protected class OnPushSampleDelegateWrapper 629 { 630 GstFlowReturn delegate(Sample, AppSrc) dlg; 631 gulong handlerId; 632 633 this(GstFlowReturn delegate(Sample, AppSrc) dlg) 634 { 635 this.dlg = dlg; 636 onPushSampleListeners ~= this; 637 } 638 639 void remove(OnPushSampleDelegateWrapper source) 640 { 641 foreach(index, wrapper; onPushSampleListeners) 642 { 643 if (wrapper.handlerId == source.handlerId) 644 { 645 onPushSampleListeners[index] = null; 646 onPushSampleListeners = std.algorithm.remove(onPushSampleListeners, index); 647 break; 648 } 649 } 650 } 651 } 652 OnPushSampleDelegateWrapper[] onPushSampleListeners; 653 654 /** 655 * Extract a buffer from the provided sample and adds the extracted buffer 656 * to the queue of buffers that the appsrc element will 657 * push to its source pad. This function set the appsrc caps based on the caps 658 * in the sample and reset the caps if they change. 659 * Only the caps and the buffer of the provided sample are used and not 660 * for example the segment in the sample. 661 * This function does not take ownership of the 662 * sample so the sample needs to be unreffed after calling this function. 663 * 664 * When the block property is TRUE, this function can block until free space 665 * becomes available in the queue. 666 * 667 * Params: 668 * sample = a sample from which extract buffer to push 669 * 670 * Since: 1.6 671 */ 672 gulong addOnPushSample(GstFlowReturn delegate(Sample, AppSrc) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 673 { 674 auto wrapper = new OnPushSampleDelegateWrapper(dlg); 675 wrapper.handlerId = Signals.connectData( 676 this, 677 "push-sample", 678 cast(GCallback)&callBackPushSample, 679 cast(void*)wrapper, 680 cast(GClosureNotify)&callBackPushSampleDestroy, 681 connectFlags); 682 return wrapper.handlerId; 683 } 684 685 extern(C) static GstFlowReturn callBackPushSample(GstAppSrc* appsrcStruct, GstSample* sample, OnPushSampleDelegateWrapper wrapper) 686 { 687 return wrapper.dlg(ObjectG.getDObject!(Sample)(sample), wrapper.outer); 688 } 689 690 extern(C) static void callBackPushSampleDestroy(OnPushSampleDelegateWrapper wrapper, GClosure* closure) 691 { 692 wrapper.remove(wrapper); 693 } 694 695 protected class OnSeekDataDelegateWrapper 696 { 697 bool delegate(ulong, AppSrc) dlg; 698 gulong handlerId; 699 700 this(bool delegate(ulong, AppSrc) dlg) 701 { 702 this.dlg = dlg; 703 onSeekDataListeners ~= this; 704 } 705 706 void remove(OnSeekDataDelegateWrapper source) 707 { 708 foreach(index, wrapper; onSeekDataListeners) 709 { 710 if (wrapper.handlerId == source.handlerId) 711 { 712 onSeekDataListeners[index] = null; 713 onSeekDataListeners = std.algorithm.remove(onSeekDataListeners, index); 714 break; 715 } 716 } 717 } 718 } 719 OnSeekDataDelegateWrapper[] onSeekDataListeners; 720 721 /** 722 * Seek to the given offset. The next push-buffer should produce buffers from 723 * the new @offset. 724 * This callback is only called for seekable stream types. 725 * 726 * Params: 727 * offset = the offset to seek to 728 * 729 * Returns: %TRUE if the seek succeeded. 730 */ 731 gulong addOnSeekData(bool delegate(ulong, AppSrc) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 732 { 733 auto wrapper = new OnSeekDataDelegateWrapper(dlg); 734 wrapper.handlerId = Signals.connectData( 735 this, 736 "seek-data", 737 cast(GCallback)&callBackSeekData, 738 cast(void*)wrapper, 739 cast(GClosureNotify)&callBackSeekDataDestroy, 740 connectFlags); 741 return wrapper.handlerId; 742 } 743 744 extern(C) static int callBackSeekData(GstAppSrc* appsrcStruct, ulong offset, OnSeekDataDelegateWrapper wrapper) 745 { 746 return wrapper.dlg(offset, wrapper.outer); 747 } 748 749 extern(C) static void callBackSeekDataDestroy(OnSeekDataDelegateWrapper wrapper, GClosure* closure) 750 { 751 wrapper.remove(wrapper); 752 } 753 754 /** 755 * Set the capabilities on the appsrc element. This function takes 756 * a copy of the caps structure. After calling this method, the source will 757 * only produce caps that match @caps. @caps must be fixed and the caps on the 758 * buffers must match the caps or left NULL. 759 * 760 * Params: 761 * caps = caps to set 762 */ 763 public void appSrcSetCaps(Caps caps) 764 { 765 gst_app_src_set_caps(gstAppSrc, (caps is null) ? null : caps.getCapsStruct()); 766 } 767 }