gstevent.c 24 KB
Newer Older
1 2 3
/* GStreamer
 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
 *                    2000 Wim Taymans <wim.taymans@chello.be>
4
 *                    2005 Wim Taymans <wim@fluendo.com>
5
 *
6
 * gstevent.c: GstEvent subsystem
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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.
 */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
23

24 25
/**
 * SECTION:gstevent
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
26 27
 * @short_description: Structure describing events that are passed up and down
 *                     a pipeline
28 29
 * @see_also: #GstPad, #GstElement
 *
30 31
 * The event class provides factory methods to construct and functions query
 * (parse) events.
32
 *
33 34
 * Events are usually created with gst_event_new_*() which takes event-type
 * specific parameters as arguments.
35 36
 * To send an event application will usually use gst_element_send_event() and
 * elements will use gst_pad_send_event() or gst_pad_push_event().
37 38 39 40
 * The event should be unreffed with gst_event_unref() if it has not been sent.
 *
 * Events that have been received can be parsed with their respective 
 * gst_event_parse_*() functions.
41
 *
Wim Taymans's avatar
Wim Taymans committed
42 43 44 45
 * Events are passed between elements in parallel to the data stream. Some events
 * are serialized with buffers, others are not. Some events only travel downstream,
 * others only upstream. Some events can travel both upstream and downstream. 
 * 
46 47 48
 * The events are used to signal special conditions in the datastream such as
 * EOS (end of stream) or the start of a new stream-segment.
 * Events are also used to flush the pipeline of any pending data.
Wim Taymans's avatar
Wim Taymans committed
49
 *
50 51 52 53
 * Most of the event API is used inside plugins. Applications usually only 
 * construct and use seek events. 
 * To do that gst_event_new_seek() is used to create a seek event. It takes
 * the needed parameters to specity seeking time and mode.
Wim Taymans's avatar
Wim Taymans committed
54 55 56 57 58 59 60 61 62 63
 * <example>
 * <title>performing a seek on a pipeline</title>
 *   <programlisting>
 *   GstEvent *event;
 *   gboolean result;
 *   ...
 *   // construct a seek event to play the media from second 2 to 5, flush
 *   // the pipeline to decrease latency.
 *   event = gst_event_new_seek (1.0, 
 *      GST_FORMAT_TIME, 
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
64 65 66
 *      GST_SEEK_FLAG_FLUSH,
 *      GST_SEEK_TYPE_SET, 2 * GST_SECOND,
 *      GST_SEEK_TYPE_SET, 5 * GST_SECOND);
Wim Taymans's avatar
Wim Taymans committed
67 68 69 70 71 72 73
 *   ...
 *   result = gst_element_send_event (pipeline, event);
 *   if (!result)
 *     g_warning ("seek failed");
 *   ...
 *   </programlisting>
 * </example>
Wim Taymans's avatar
Wim Taymans committed
74
 *
75
 * Last reviewed on 2006-01-24 (0.10.2)
76
 */
Wim Taymans's avatar
Wim Taymans committed
77

78
#include <string.h>             /* memcpy */
79

80 81 82
#include "gst_private.h"

#include "gstinfo.h"
83
#include "gstevent.h"
Wim Taymans's avatar
Wim Taymans committed
84
#include "gstenumtypes.h"
85
#include "gstutils.h"
Benjamin Otte's avatar
Benjamin Otte committed
86

87 88 89 90
static void gst_event_init (GTypeInstance * instance, gpointer g_class);
static void gst_event_class_init (gpointer g_class, gpointer class_data);
static void gst_event_finalize (GstEvent * event);
static GstEvent *_gst_event_copy (GstEvent * event);
91 92 93 94

void
_gst_event_initialize (void)
{
95 96 97
  gst_event_get_type ();
}

98 99 100 101 102 103 104 105 106 107 108 109 110 111
typedef struct
{
  gint type;
  gchar *name;
  GQuark quark;
} GstEventQuarks;

static GstEventQuarks event_quarks[] = {
  {GST_EVENT_UNKNOWN, "unknown", 0},
  {GST_EVENT_FLUSH_START, "flush-start", 0},
  {GST_EVENT_FLUSH_STOP, "flush-stop", 0},
  {GST_EVENT_EOS, "eos", 0},
  {GST_EVENT_NEWSEGMENT, "newsegment", 0},
  {GST_EVENT_TAG, "tag", 0},
112
  {GST_EVENT_BUFFERSIZE, "buffersize", 0},
113 114 115
  {GST_EVENT_QOS, "qos", 0},
  {GST_EVENT_SEEK, "seek", 0},
  {GST_EVENT_NAVIGATION, "navigation", 0},
116 117 118
  {GST_EVENT_CUSTOM_UPSTREAM, "custom-upstream", 0},
  {GST_EVENT_CUSTOM_DOWNSTREAM, "custom-downstream", 0},
  {GST_EVENT_CUSTOM_DOWNSTREAM_OOB, "custom-downstream-oob", 0},
119 120 121
  {GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
  {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},

122 123 124
  {0, NULL, 0}
};

Stefan Kost's avatar
Stefan Kost committed
125 126 127 128 129 130
/**
 * gst_event_type_get_name:
 * @type: the event type
 *
 * Get a printable name for the given event type. Do not modify or free.
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
131
 * Returns: a reference to the static name of the event.
Stefan Kost's avatar
Stefan Kost committed
132
 */
133 134 135 136 137 138 139 140 141 142 143 144
const gchar *
gst_event_type_get_name (GstEventType type)
{
  gint i;

  for (i = 0; event_quarks[i].name; i++) {
    if (type == event_quarks[i].type)
      return event_quarks[i].name;
  }
  return "unknown";
}

Stefan Kost's avatar
Stefan Kost committed
145 146 147 148 149 150 151 152
/**
 * gst_event_type_to_quark:
 * @type: the event type
 *
 * Get the unique quark for the given event type.
 *
 * Returns: the quark associated with the event type
 */
153 154 155 156 157 158 159 160 161 162 163 164
GQuark
gst_event_type_to_quark (GstEventType type)
{
  gint i;

  for (i = 0; event_quarks[i].name; i++) {
    if (type == event_quarks[i].type)
      return event_quarks[i].quark;
  }
  return 0;
}

165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
/**
 * gst_event_type_get_flags:
 * @type: a #GstEventType
 *
 * Gets the #GstEventTypeFlags associated with @type.
 *
 * Returns: a #GstEventTypeFlags.
 */
GstEventTypeFlags
gst_event_type_get_flags (GstEventType type)
{
  GstEventTypeFlags ret;

  ret = type & ((1 << GST_EVENT_TYPE_SHIFT) - 1);

  return ret;
}

183 184 185 186
GType
gst_event_get_type (void)
{
  static GType _gst_event_type;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
187
  int i;
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204

  if (G_UNLIKELY (_gst_event_type == 0)) {
    static const GTypeInfo event_info = {
      sizeof (GstEventClass),
      NULL,
      NULL,
      gst_event_class_init,
      NULL,
      NULL,
      sizeof (GstEvent),
      0,
      gst_event_init,
      NULL
    };

    _gst_event_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
        "GstEvent", &event_info, 0);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
205 206 207 208

    for (i = 0; event_quarks[i].name; i++) {
      event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name);
    }
209
  }
210

211
  return _gst_event_type;
212 213
}

214 215
static void
gst_event_class_init (gpointer g_class, gpointer class_data)
Wim Taymans's avatar
Wim Taymans committed
216
{
217
  GstEventClass *event_class = GST_EVENT_CLASS (g_class);
Wim Taymans's avatar
Wim Taymans committed
218

219 220 221 222 223
  event_class->mini_object_class.copy =
      (GstMiniObjectCopyFunction) _gst_event_copy;
  event_class->mini_object_class.finalize =
      (GstMiniObjectFinalizeFunction) gst_event_finalize;
}
Wim Taymans's avatar
Wim Taymans committed
224

225 226 227 228
static void
gst_event_init (GTypeInstance * instance, gpointer g_class)
{
  GstEvent *event;
229

230
  event = GST_EVENT (instance);
Wim Taymans's avatar
Wim Taymans committed
231

232
  GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
Wim Taymans's avatar
Wim Taymans committed
233 234
}

235
static void
236
gst_event_finalize (GstEvent * event)
237
{
238 239 240
  g_return_if_fail (event != NULL);
  g_return_if_fail (GST_IS_EVENT (event));

241
  GST_CAT_LOG (GST_CAT_EVENT, "freeing event %p type %s", event,
242
      GST_EVENT_TYPE_NAME (event));
Wim Taymans's avatar
Wim Taymans committed
243

244 245
  if (GST_EVENT_SRC (event)) {
    gst_object_unref (GST_EVENT_SRC (event));
246
    GST_EVENT_SRC (event) = NULL;
247
  }
Wim Taymans's avatar
Wim Taymans committed
248 249 250
  if (event->structure) {
    gst_structure_set_parent_refcount (event->structure, NULL);
    gst_structure_free (event->structure);
251
  }
252 253 254 255 256 257 258
}

static GstEvent *
_gst_event_copy (GstEvent * event)
{
  GstEvent *copy;

Wim Taymans's avatar
Wim Taymans committed
259
  copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
260

Wim Taymans's avatar
Wim Taymans committed
261 262
  GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event);
  GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
263

Wim Taymans's avatar
Wim Taymans committed
264 265 266 267 268 269 270
  if (GST_EVENT_SRC (event)) {
    GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event));
  }
  if (event->structure) {
    copy->structure = gst_structure_copy (event->structure);
    gst_structure_set_parent_refcount (copy->structure,
        &event->mini_object.refcount);
271 272
  }
  return copy;
273 274
}

Wim Taymans's avatar
Wim Taymans committed
275 276
static GstEvent *
gst_event_new (GstEventType type)
277
{
Wim Taymans's avatar
Wim Taymans committed
278
  GstEvent *event;
279

Wim Taymans's avatar
Wim Taymans committed
280
  event = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
281

282
  GST_CAT_DEBUG (GST_CAT_EVENT, "creating new event %p %s", event,
283
      gst_event_type_get_name (type));
284

Wim Taymans's avatar
Wim Taymans committed
285 286 287
  event->type = type;
  event->src = NULL;
  event->structure = NULL;
288

Wim Taymans's avatar
Wim Taymans committed
289
  return event;
290 291
}

292
/**
Wim Taymans's avatar
Wim Taymans committed
293
 * gst_event_new_custom:
294
 * @type: The type of the new event
Wim Taymans's avatar
Wim Taymans committed
295 296
 * @structure: The structure for the event. The event will take ownership of
 * the structure.
297
 *
Wim Taymans's avatar
Wim Taymans committed
298 299 300
 * Create a new custom-typed event. This can be used for anything not
 * handled by other event-specific functions to pass an event to another
 * element.
301
 *
Wim Taymans's avatar
Wim Taymans committed
302 303 304 305 306 307 308 309
 * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro,
 * assigning a free number and filling in the correct direction and
 * serialization flags.
 *
 * New custom events can also be created by subclassing the event type if
 * needed.
 *
 * Returns: The new custom event.
310
 */
311
GstEvent *
Wim Taymans's avatar
Wim Taymans committed
312
gst_event_new_custom (GstEventType type, GstStructure * structure)
313 314 315
{
  GstEvent *event;

Wim Taymans's avatar
Wim Taymans committed
316 317 318 319 320
  event = gst_event_new (type);
  if (structure) {
    gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
    event->structure = structure;
  }
321
  return event;
322 323
}

324
/**
Wim Taymans's avatar
Wim Taymans committed
325 326
 * gst_event_get_structure:
 * @event: The #GstEvent.
327
 *
Wim Taymans's avatar
Wim Taymans committed
328
 * Access the structure of the event.
329
 *
Wim Taymans's avatar
Wim Taymans committed
330 331 332 333 334
 * Returns: The structure of the event. The structure is still
 * owned by the event, which means that you should not free it and
 * that the pointer becomes invalid when you free the event.
 *
 * MT safe.
335
 */
Wim Taymans's avatar
Wim Taymans committed
336 337
const GstStructure *
gst_event_get_structure (GstEvent * event)
338
{
Wim Taymans's avatar
Wim Taymans committed
339
  g_return_val_if_fail (GST_IS_EVENT (event), NULL);
340

Wim Taymans's avatar
Wim Taymans committed
341
  return event->structure;
342
}
343

Wim Taymans's avatar
Wim Taymans committed
344
/**
Wim Taymans's avatar
Wim Taymans committed
345 346 347 348 349 350 351
 * gst_event_new_flush_start:
 *
 * Allocate a new flush start event. The flush start event can be send
 * upstream and downstream and travels out-of-bounds with the dataflow.
 * It marks pads as being in a WRONG_STATE to process more data.
 *
 * Elements unlock and blocking functions and exit their streaming functions
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
352
 * as fast as possible.
Wim Taymans's avatar
Wim Taymans committed
353
 *
Wim Taymans's avatar
Wim Taymans committed
354 355
 * This event is typically generated after a seek to minimize the latency
 * after the seek.
Wim Taymans's avatar
Wim Taymans committed
356
 *
Wim Taymans's avatar
Wim Taymans committed
357
 * Returns: A new flush start event.
Wim Taymans's avatar
Wim Taymans committed
358
 */
359
GstEvent *
Wim Taymans's avatar
Wim Taymans committed
360
gst_event_new_flush_start (void)
361
{
Wim Taymans's avatar
Wim Taymans committed
362
  return gst_event_new (GST_EVENT_FLUSH_START);
363 364
}

365
/**
Wim Taymans's avatar
Wim Taymans committed
366 367 368 369 370 371
 * gst_event_new_flush_stop:
 *
 * Allocate a new flush stop event. The flush start event can be send
 * upstream and downstream and travels out-of-bounds with the dataflow.
 * It is typically send after sending a FLUSH_START event to make the
 * pads accept data again.
372
 *
Wim Taymans's avatar
Wim Taymans committed
373 374
 * Elements can process this event synchronized with the dataflow since
 * the preceeding FLUSH_START event stopped the dataflow.
375
 *
Wim Taymans's avatar
Wim Taymans committed
376 377 378 379
 * This event is typically generated to complete a seek and to resume
 * dataflow.
 *
 * Returns: A new flush stop event.
380
 */
381
GstEvent *
Wim Taymans's avatar
Wim Taymans committed
382
gst_event_new_flush_stop (void)
383
{
Wim Taymans's avatar
Wim Taymans committed
384
  return gst_event_new (GST_EVENT_FLUSH_STOP);
385 386
}

Wim Taymans's avatar
Wim Taymans committed
387
/**
Wim Taymans's avatar
Wim Taymans committed
388
 * gst_event_new_eos:
Wim Taymans's avatar
Wim Taymans committed
389
 *
Wim Taymans's avatar
Wim Taymans committed
390 391 392 393
 * Create a new EOS event. The eos event can only travel downstream
 * synchronized with the buffer flow. Elements that receive the EOS
 * event on a pad can return UNEXPECTED as a GstFlowReturn when data
 * after the EOS event arrives.
Wim Taymans's avatar
Wim Taymans committed
394
 *
Jan Schmidt's avatar
Jan Schmidt committed
395 396 397
 * The EOS event will travel down to the sink elements in the pipeline
 * which will then post the GST_MESSAGE_EOS on the bus after they have
 * finished playing any buffered data.
Wim Taymans's avatar
Wim Taymans committed
398 399 400 401 402
 *
 * When all sinks have posted an EOS message, the EOS message is
 * forwarded to the application.
 *
 * Returns: The new EOS event.
Wim Taymans's avatar
Wim Taymans committed
403
 */
Wim Taymans's avatar
Wim Taymans committed
404 405
GstEvent *
gst_event_new_eos (void)
406
{
Wim Taymans's avatar
Wim Taymans committed
407
  return gst_event_new (GST_EVENT_EOS);
408 409
}

410
/**
411
 * gst_event_new_new_segment:
412
 * @update: is this segment an update to a previous one
Wim Taymans's avatar
Wim Taymans committed
413 414
 * @rate: a new rate for playback
 * @format: The format of the segment values
415 416 417
 * @start: the start value of the segment
 * @stop: the stop value of the segment
 * @position: stream position
Wim Taymans's avatar
Wim Taymans committed
418 419 420 421
 *
 * Allocate a new newsegment event with the given format/values tripplets.
 *
 * The newsegment event marks the range of buffers to be processed. All
422 423 424
 * data not within the segment range is not to be processed. This can be
 * used intelligently by plugins to use more efficient methods of skipping
 * unneeded packets.
425
 *
426
 * The stream time of the segment is used to convert the buffer timestamps
427
 * into the stream time again, this is usually done in sinks to report the
428
 * current stream_time. @stream_time cannot be -1.
429
 *
430 431
 * @start cannot be -1, @stop can be -1. If there
 * is a valid @stop given, it must be greater or equal than @start.
432
 *
Wim Taymans's avatar
Wim Taymans committed
433 434
 * After a newsegment event, the buffer stream time is calculated with:
 *
435
 *   stream_time + (TIMESTAMP(buf) - start) * ABS (rate)
Wim Taymans's avatar
Wim Taymans committed
436 437
 *
 * Returns: A new newsegment event.
438
 */
439
GstEvent *
440
gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
441
    gint64 start, gint64 stop, gint64 position)
442
{
443 444
  g_return_val_if_fail (rate != 0.0, NULL);

445 446
  if (format == GST_FORMAT_TIME) {
    GST_CAT_INFO (GST_CAT_EVENT,
447
        "creating newsegment update %d, rate %lf, format GST_FORMAT_TIME, "
448
        "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
449 450 451
        ", position %" GST_TIME_FORMAT,
        update, rate, GST_TIME_ARGS (start),
        GST_TIME_ARGS (stop), GST_TIME_ARGS (position));
452 453
  } else {
    GST_CAT_INFO (GST_CAT_EVENT,
454
        "creating newsegment update %d, rate %lf, format %d, "
455 456
        "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
        G_GINT64_FORMAT, update, rate, format, start, stop, position);
457
  }
458 459 460 461
  g_return_val_if_fail (position != -1, NULL);
  g_return_val_if_fail (start != -1, NULL);
  if (stop != -1)
    g_return_val_if_fail (start <= stop, NULL);
462

Wim Taymans's avatar
Wim Taymans committed
463
  return gst_event_new_custom (GST_EVENT_NEWSEGMENT,
464 465 466
      gst_structure_new ("GstEventNewsegment",
          "update", G_TYPE_BOOLEAN, update,
          "rate", G_TYPE_DOUBLE, rate,
Wim Taymans's avatar
Wim Taymans committed
467
          "format", GST_TYPE_FORMAT, format,
468 469 470
          "start", G_TYPE_INT64, start,
          "stop", G_TYPE_INT64, stop,
          "position", G_TYPE_INT64, position, NULL));
Wim Taymans's avatar
Wim Taymans committed
471
}
472

Wim Taymans's avatar
Wim Taymans committed
473
/**
474
 * gst_event_parse_new_segment:
Wim Taymans's avatar
Wim Taymans committed
475
 * @event: The event to query
476
 * @update: A pointer to the update flag of the segment
Wim Taymans's avatar
Wim Taymans committed
477 478
 * @rate: A pointer to the rate of the segment
 * @format: A pointer to the format of the newsegment values
479 480 481
 * @start: A pointer to store the start value in
 * @stop: A pointer to store the stop value in
 * @position: A pointer to store the stream time in
Wim Taymans's avatar
Wim Taymans committed
482
 *
483
 * Get the format, start, stop and position in the newsegment event.
Wim Taymans's avatar
Wim Taymans committed
484 485
 */
void
486
gst_event_parse_new_segment (GstEvent * event, gboolean * update,
487 488
    gdouble * rate, GstFormat * format, gint64 * start,
    gint64 * stop, gint64 * position)
Wim Taymans's avatar
Wim Taymans committed
489 490
{
  const GstStructure *structure;
491

Wim Taymans's avatar
Wim Taymans committed
492 493 494 495
  g_return_if_fail (GST_IS_EVENT (event));
  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);

  structure = gst_event_get_structure (event);
496 497 498
  if (update)
    *update =
        g_value_get_boolean (gst_structure_get_value (structure, "update"));
Wim Taymans's avatar
Wim Taymans committed
499 500 501 502
  if (rate)
    *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
  if (format)
    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
503 504 505 506 507 508 509
  if (start)
    *start = g_value_get_int64 (gst_structure_get_value (structure, "start"));
  if (stop)
    *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
  if (position)
    *position =
        g_value_get_int64 (gst_structure_get_value (structure, "position"));
Wim Taymans's avatar
Wim Taymans committed
510
}
511

512 513 514 515 516
/**
 * gst_event_new_tag:
 * @taglist: metadata list
 *
 * Generates a metadata tag event from the given @taglist.
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
517
 *
518 519
 * Returns: a new #GstEvent
 */
Wim Taymans's avatar
Wim Taymans committed
520 521 522 523 524 525
GstEvent *
gst_event_new_tag (GstTagList * taglist)
{
  g_return_val_if_fail (taglist != NULL, NULL);

  return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
526 527
}

528 529 530 531 532 533 534
/**
 * gst_event_parse_tag:
 * @event: a tag event
 * @taglist: pointer to metadata list
 *
 * Parses a tag @event and stores the results in the given @taglist location.
 */
Wim Taymans's avatar
Wim Taymans committed
535 536 537 538 539 540 541 542 543 544
void
gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
{
  g_return_if_fail (GST_IS_EVENT (event));
  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);

  if (taglist)
    *taglist = (GstTagList *) event->structure;
}

545 546
/* buffersize event */
/**
547
 * gst_event_new_buffer_size:
Stefan Kost's avatar
Stefan Kost committed
548 549 550 551
 * @format: buffer format
 * @minsize: minimum buffer size
 * @maxsize: maximum buffer size
 * @async: thread behavior
552 553 554 555 556 557 558 559 560
 *
 * Create a new buffersize event. The event is sent downstream and notifies
 * elements that they should provide a buffer of the specified dimensions.
 *
 * When the async flag is set, a thread boundary is prefered.
 *
 * Returns: a new #GstEvent
 */
GstEvent *
561
gst_event_new_buffer_size (GstFormat format, gint64 minsize,
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
    gint64 maxsize, gboolean async)
{
  GST_CAT_INFO (GST_CAT_EVENT,
      "creating buffersize format %d, minsize %" G_GINT64_FORMAT
      ", maxsize %" G_GINT64_FORMAT ", async %d", format,
      minsize, maxsize, async);

  return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
      gst_structure_new ("GstEventBufferSize",
          "format", GST_TYPE_FORMAT, format,
          "minsize", G_TYPE_INT64, minsize,
          "maxsize", G_TYPE_INT64, maxsize,
          "async", G_TYPE_BOOLEAN, async, NULL));
}

Stefan Kost's avatar
Stefan Kost committed
577
/**
578
 * gst_event_parse_buffer_size:
Stefan Kost's avatar
Stefan Kost committed
579 580 581 582 583 584 585 586
 * @event: The event to query
 * @format: A pointer to store the format in
 * @minsize: A pointer to store the minsize in
 * @maxsize: A pointer to store the maxsize in
 * @async: A pointer to store the async-flag in
 *
 * Get the format, minsize, maxsize and async-flag in the buffersize event.
 */
587
void
588
gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
    gint64 * minsize, gint64 * maxsize, gboolean * async)
{
  const GstStructure *structure;

  g_return_if_fail (GST_IS_EVENT (event));
  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);

  structure = gst_event_get_structure (event);
  if (format)
    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
  if (minsize)
    *minsize =
        g_value_get_int64 (gst_structure_get_value (structure, "minsize"));
  if (maxsize)
    *maxsize =
        g_value_get_int64 (gst_structure_get_value (structure, "maxsize"));
  if (async)
    *async = g_value_get_boolean (gst_structure_get_value (structure, "async"));
}

609
/**
Wim Taymans's avatar
Wim Taymans committed
610 611 612 613 614 615 616 617 618 619 620 621 622
 * gst_event_new_qos:
 * @proportion: the proportion of the qos message
 * @diff: The time difference of the last Clock sync
 * @timestamp: The timestamp of the buffer
 *
 * Allocate a new qos event with the given values.
 * The QOS event is generated in an element that wants an upstream
 * element to either reduce or increase its rate because of
 * high/low CPU load.
 *
 * proportion is the requested adjustment in datarate, 1.0 is the normal
 * datarate, 0.75 means increase datarate by 75%, 1.5 is 150%. Negative
 * values request a slow down, so -0.75 means a decrease by 75%.
623
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
624
 * diff is the difference against the clock in stream time of the last
Wim Taymans's avatar
Wim Taymans committed
625
 * buffer that caused the element to generate the QOS event.
626
 *
Wim Taymans's avatar
Wim Taymans committed
627 628 629 630
 * timestamp is the timestamp of the last buffer that cause the element
 * to generate the QOS event.
 *
 * Returns: A new QOS event.
631
 */
632
GstEvent *
Wim Taymans's avatar
Wim Taymans committed
633 634
gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
    GstClockTime timestamp)
635
{
636 637 638 639 640
  GST_CAT_INFO (GST_CAT_EVENT,
      "creating qos proportion %lf, diff %" GST_TIME_FORMAT
      ", timestamp %" GST_TIME_FORMAT, proportion,
      GST_TIME_ARGS (diff), GST_TIME_ARGS (timestamp));

Wim Taymans's avatar
Wim Taymans committed
641 642 643 644 645 646
  return gst_event_new_custom (GST_EVENT_QOS,
      gst_structure_new ("GstEventQOS",
          "proportion", G_TYPE_DOUBLE, proportion,
          "diff", G_TYPE_INT64, diff,
          "timestamp", G_TYPE_UINT64, timestamp, NULL));
}
647

Wim Taymans's avatar
Wim Taymans committed
648 649 650 651 652 653 654 655 656 657 658 659 660 661
/**
 * gst_event_parse_qos:
 * @event: The event to query
 * @proportion: A pointer to store the proportion in
 * @diff: A pointer to store the diff in
 * @timestamp: A pointer to store the timestamp in
 *
 * Get the proportion, diff and timestamp in the qos event.
 */
void
gst_event_parse_qos (GstEvent * event, gdouble * proportion,
    GstClockTimeDiff * diff, GstClockTime * timestamp)
{
  const GstStructure *structure;
662

Wim Taymans's avatar
Wim Taymans committed
663 664 665 666 667 668 669 670 671 672 673 674
  g_return_if_fail (GST_IS_EVENT (event));
  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);

  structure = gst_event_get_structure (event);
  if (proportion)
    *proportion =
        g_value_get_double (gst_structure_get_value (structure, "proportion"));
  if (diff)
    *diff = g_value_get_int64 (gst_structure_get_value (structure, "diff"));
  if (timestamp)
    *timestamp =
        g_value_get_uint64 (gst_structure_get_value (structure, "timestamp"));
675
}
676 677

/**
Wim Taymans's avatar
Wim Taymans committed
678 679 680
 * gst_event_new_seek:
 * @rate: The new playback rate
 * @format: The format of the seek values
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
681
 * @flags: The optional seek flags
Wim Taymans's avatar
Wim Taymans committed
682 683 684 685 686 687 688
 * @cur_type: The type and flags for the new current position
 * @cur: The value of the new current position
 * @stop_type: The type and flags for the new stop position
 * @stop: The value of the new stop position
 *
 * Allocate a new seek event with the given parameters.
 *
689
 * The seek event configures playback of the pipeline from
Wim Taymans's avatar
Wim Taymans committed
690
 * @cur to @stop at the speed given in @rate, also called a segment.
Wim Taymans's avatar
Wim Taymans committed
691
 * The @cur and @stop values are expressed in format @format.
692
 *
Wim Taymans's avatar
Wim Taymans committed
693 694 695
 * A @rate of 1.0 means normal playback rate, 2.0 means double speed.
 * Negatives values means backwards playback. A value of 0.0 for the
 * rate is not allowed.
696
 *
Wim Taymans's avatar
Wim Taymans committed
697
 * @cur_type and @stop_type specify how to adjust the current and stop
Wim Taymans's avatar
Wim Taymans committed
698 699 700
 * time, relative or absolute. A type of #GST_SEEK_TYPE_NONE means that
 * the position should not be updated. The currently configured playback
 * segment can be queried with #GST_QUERY_SEGMENT.
Wim Taymans's avatar
Wim Taymans committed
701
 *
702 703 704 705 706 707
 * Note that updating the @cur position will actually move the current
 * playback pointer to that new position. It is not possible to seek 
 * relative to the current playing position, to do this, pause the pipeline,
 * get the current position and perform a GST_SEEK_TYPE_SET to the desired
 * position.
 *
Wim Taymans's avatar
Wim Taymans committed
708
 * Returns: A new seek event.
709 710
 */
GstEvent *
Wim Taymans's avatar
Wim Taymans committed
711 712
gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
    GstSeekType cur_type, gint64 cur, GstSeekType stop_type, gint64 stop)
713
{
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
  if (format == GST_FORMAT_TIME) {
    GST_CAT_INFO (GST_CAT_EVENT,
        "creating seek rate %lf, format TIME, flags %d, "
        "cur_type %d, cur %" GST_TIME_FORMAT ", "
        "stop_type %d, stop %" GST_TIME_FORMAT,
        rate, flags, cur_type, GST_TIME_ARGS (cur),
        stop_type, GST_TIME_ARGS (stop));
  } else {
    GST_CAT_INFO (GST_CAT_EVENT,
        "creating seek rate %lf, format %d, flags %d, "
        "cur_type %d, cur %" G_GINT64_FORMAT ", "
        "stop_type %d, stop %" G_GINT64_FORMAT,
        rate, format, flags, cur_type, cur, stop_type, stop);
  }

Wim Taymans's avatar
Wim Taymans committed
729 730 731 732 733 734 735 736 737
  return gst_event_new_custom (GST_EVENT_SEEK,
      gst_structure_new ("GstEventSeek", "rate", G_TYPE_DOUBLE, rate,
          "format", GST_TYPE_FORMAT, format,
          "flags", GST_TYPE_SEEK_FLAGS, flags,
          "cur_type", GST_TYPE_SEEK_TYPE, cur_type,
          "cur", G_TYPE_INT64, cur,
          "stop_type", GST_TYPE_SEEK_TYPE, stop_type,
          "stop", G_TYPE_INT64, stop, NULL));
}
738

739 740 741 742 743 744 745 746 747 748 749 750 751
/**
 * gst_event_parse_seek:
 * @event: a seek event
 * @rate: result location for the rate
 * @format: result location for the stream format
 * @flags:  result location for the #GstSeekFlags
 * @cur_type: result location for the #GstSeekType of the current position
 * @cur: result location for the current postion expressed in @format
 * @stop_type:  result location for the #GstSeekType of the stop position
 * @stop: result location for the stop postion expressed in @format
 *
 * Parses a seek @event and stores the results in the given result locations.
 */
Wim Taymans's avatar
Wim Taymans committed
752 753 754 755 756 757 758
void
gst_event_parse_seek (GstEvent * event, gdouble * rate, GstFormat * format,
    GstSeekFlags * flags,
    GstSeekType * cur_type, gint64 * cur,
    GstSeekType * stop_type, gint64 * stop)
{
  const GstStructure *structure;
759

Wim Taymans's avatar
Wim Taymans committed
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
  g_return_if_fail (GST_IS_EVENT (event));
  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);

  structure = gst_event_get_structure (event);
  if (rate)
    *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
  if (format)
    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
  if (flags)
    *flags = g_value_get_flags (gst_structure_get_value (structure, "flags"));
  if (cur_type)
    *cur_type =
        g_value_get_enum (gst_structure_get_value (structure, "cur_type"));
  if (cur)
    *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
  if (stop_type)
    *stop_type =
        g_value_get_enum (gst_structure_get_value (structure, "stop_type"));
  if (stop)
    *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
}

782 783 784 785 786 787 788 789
/**
 * gst_event_new_navigation:
 * @structure: description of the event
 *
 * Create a new navigation event from the given description.
 *
 * Returns: a new #GstEvent
 */
Wim Taymans's avatar
Wim Taymans committed
790 791 792 793 794 795
GstEvent *
gst_event_new_navigation (GstStructure * structure)
{
  g_return_val_if_fail (structure != NULL, NULL);

  return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);
796
}