gstmessage.c 26 KB
Newer Older
Wim Taymans's avatar
Wim Taymans committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* GStreamer
 * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
 *
 * gstmessage.c: GstMessage subsystem
 *
 * 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
21

22 23
/**
 * SECTION:gstmessage
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
24 25
 * @short_description: Lightweight objects to signal the application of
 *                     pipeline events
26 27
 * @see_also: #GstBus,#GstMiniObject
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
28
 * Messages are implemented as a subclass of #GstMiniObject with a generic
29 30 31 32
 * #GstStructure as the content. This allows for writing custom messages without
 * requiring an API change while allowing a wide range of different types
 * of messages.
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
33 34
 * Messages are posted by objects in the pipeline and are passed to the
 * application using the #GstBus.
35
 */
Wim Taymans's avatar
Wim Taymans committed
36 37 38 39

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

#include "gst_private.h"
40
#include "gsterror.h"
41
#include "gstenumtypes.h"
Wim Taymans's avatar
Wim Taymans committed
42 43
#include "gstinfo.h"
#include "gstmessage.h"
44
#include "gsttaglist.h"
45
#include "gstutils.h"
Wim Taymans's avatar
Wim Taymans committed
46 47


48 49 50 51
static void gst_message_init (GTypeInstance * instance, gpointer g_class);
static void gst_message_class_init (gpointer g_class, gpointer class_data);
static void gst_message_finalize (GstMessage * message);
static GstMessage *_gst_message_copy (GstMessage * message);
Wim Taymans's avatar
Wim Taymans committed
52 53 54 55

void
_gst_message_initialize (void)
{
56 57
  gpointer ptr;

Wim Taymans's avatar
Wim Taymans committed
58 59
  GST_CAT_INFO (GST_CAT_GST_INIT, "init messages");

60
  gst_message_get_type ();
Wim Taymans's avatar
Wim Taymans committed
61

62 63 64 65 66
  /* the GstMiniObject types need to be class_ref'd once before it can be
   * done from multiple threads;
   * see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
  ptr = g_type_class_ref (GST_TYPE_MESSAGE);
  g_type_class_unref (ptr);
Wim Taymans's avatar
Wim Taymans committed
67 68
}

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
typedef struct
{
  gint type;
  gchar *name;
  GQuark quark;
} GstMessageQuarks;

static GstMessageQuarks message_quarks[] = {
  {GST_MESSAGE_UNKNOWN, "unknown", 0},
  {GST_MESSAGE_EOS, "eos", 0},
  {GST_MESSAGE_ERROR, "error", 0},
  {GST_MESSAGE_WARNING, "warning", 0},
  {GST_MESSAGE_INFO, "info", 0},
  {GST_MESSAGE_TAG, "tag", 0},
  {GST_MESSAGE_BUFFERING, "buffering", 0},
  {GST_MESSAGE_STATE_CHANGED, "state-changed", 0},
85
  {GST_MESSAGE_STATE_DIRTY, "state-dirty", 0},
86
  {GST_MESSAGE_STEP_DONE, "step-done", 0},
Wim Taymans's avatar
Wim Taymans committed
87 88
  {GST_MESSAGE_CLOCK_PROVIDE, "clock-provide", 0},
  {GST_MESSAGE_CLOCK_LOST, "clock-lost", 0},
89 90 91 92
  {GST_MESSAGE_NEW_CLOCK, "new-clock", 0},
  {GST_MESSAGE_STRUCTURE_CHANGE, "structure-change", 0},
  {GST_MESSAGE_STREAM_STATUS, "stream-status", 0},
  {GST_MESSAGE_APPLICATION, "application", 0},
Wim Taymans's avatar
Wim Taymans committed
93
  {GST_MESSAGE_ELEMENT, "element", 0},
94 95
  {GST_MESSAGE_SEGMENT_START, "segment-start", 0},
  {GST_MESSAGE_SEGMENT_DONE, "segment-done", 0},
96
  {GST_MESSAGE_DURATION, "duration", 0},
97 98 99
  {0, NULL, 0}
};

Stefan Kost's avatar
Stefan Kost committed
100 101 102 103 104 105
/**
 * gst_message_type_get_name:
 * @type: the message type
 *
 * Get a printable name for the given message type. Do not modify or free.
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
106
 * Returns: a reference to the static name of the message.
Stefan Kost's avatar
Stefan Kost committed
107
 */
108 109 110 111 112 113 114 115 116 117 118 119
const gchar *
gst_message_type_get_name (GstMessageType type)
{
  gint i;

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

Stefan Kost's avatar
Stefan Kost committed
120 121 122 123 124 125 126 127
/**
 * gst_message_type_to_quark:
 * @type: the message type
 *
 * Get the unique quark for the given message type.
 *
 * Returns: the quark associated with the message type
 */
128 129 130 131 132 133 134 135 136 137 138 139
GQuark
gst_message_type_to_quark (GstMessageType type)
{
  gint i;

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

140 141
GType
gst_message_get_type (void)
Wim Taymans's avatar
Wim Taymans committed
142
{
143 144 145
  static GType _gst_message_type;

  if (G_UNLIKELY (_gst_message_type == 0)) {
146
    gint i;
147 148 149 150 151 152 153 154 155 156 157 158
    static const GTypeInfo message_info = {
      sizeof (GstMessageClass),
      NULL,
      NULL,
      gst_message_class_init,
      NULL,
      NULL,
      sizeof (GstMessage),
      0,
      gst_message_init,
      NULL
    };
Wim Taymans's avatar
Wim Taymans committed
159

160 161
    _gst_message_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
        "GstMessage", &message_info, 0);
162 163 164 165 166

    for (i = 0; message_quarks[i].name; i++) {
      message_quarks[i].quark =
          g_quark_from_static_string (message_quarks[i].name);
    }
167 168 169
  }
  return _gst_message_type;
}
Wim Taymans's avatar
Wim Taymans committed
170

171 172 173 174
static void
gst_message_class_init (gpointer g_class, gpointer class_data)
{
  GstMessageClass *message_class = GST_MESSAGE_CLASS (g_class);
Wim Taymans's avatar
Wim Taymans committed
175

176 177 178 179 180
  message_class->mini_object_class.copy =
      (GstMiniObjectCopyFunction) _gst_message_copy;
  message_class->mini_object_class.finalize =
      (GstMiniObjectFinalizeFunction) gst_message_finalize;
}
Wim Taymans's avatar
Wim Taymans committed
181

182 183 184 185 186
static void
gst_message_init (GTypeInstance * instance, gpointer g_class)
{
  GstMessage *message = GST_MESSAGE (instance);

187
  GST_CAT_LOG (GST_CAT_MESSAGE, "new message %p", message);
Wim Taymans's avatar
Wim Taymans committed
188
  GST_MESSAGE_TIMESTAMP (message) = GST_CLOCK_TIME_NONE;
Wim Taymans's avatar
Wim Taymans committed
189 190 191
}

static void
192
gst_message_finalize (GstMessage * message)
Wim Taymans's avatar
Wim Taymans committed
193
{
194
  g_return_if_fail (message != NULL);
Wim Taymans's avatar
Wim Taymans committed
195

196
  GST_CAT_LOG (GST_CAT_MESSAGE, "finalize message %p", message);
197

Wim Taymans's avatar
Wim Taymans committed
198
  if (GST_MESSAGE_SRC (message)) {
199
    gst_object_unref (GST_MESSAGE_SRC (message));
Wim Taymans's avatar
Wim Taymans committed
200
    GST_MESSAGE_SRC (message) = NULL;
Wim Taymans's avatar
Wim Taymans committed
201 202 203 204 205 206 207 208
  }

  if (message->lock) {
    GST_MESSAGE_LOCK (message);
    GST_MESSAGE_SIGNAL (message);
    GST_MESSAGE_UNLOCK (message);
  }

209 210
  if (message->structure) {
    gst_structure_set_parent_refcount (message->structure, NULL);
Wim Taymans's avatar
Wim Taymans committed
211
    gst_structure_free (message->structure);
212
  }
Wim Taymans's avatar
Wim Taymans committed
213 214
}

215 216
static GstMessage *
_gst_message_copy (GstMessage * message)
Wim Taymans's avatar
Wim Taymans committed
217
{
218 219
  GstMessage *copy;

220
  GST_CAT_LOG (GST_CAT_MESSAGE, "copy message %p", message);
221 222 223

  copy = (GstMessage *) gst_mini_object_new (GST_TYPE_MESSAGE);

Wim Taymans's avatar
Wim Taymans committed
224
  /* FIXME, need to copy relevant data from the miniobject. */
225 226
  //memcpy (copy, message, sizeof (GstMessage));

Wim Taymans's avatar
Wim Taymans committed
227 228 229 230
  GST_MESSAGE_GET_LOCK (copy) = GST_MESSAGE_GET_LOCK (message);
  GST_MESSAGE_COND (copy) = GST_MESSAGE_COND (message);
  GST_MESSAGE_TYPE (copy) = GST_MESSAGE_TYPE (message);
  GST_MESSAGE_TIMESTAMP (copy) = GST_MESSAGE_TIMESTAMP (message);
231 232

  if (GST_MESSAGE_SRC (message)) {
233
    GST_MESSAGE_SRC (copy) = gst_object_ref (GST_MESSAGE_SRC (message));
234 235 236 237 238 239 240 241 242
  }

  if (message->structure) {
    copy->structure = gst_structure_copy (message->structure);
    gst_structure_set_parent_refcount (copy->structure,
        &message->mini_object.refcount);
  }

  return copy;
Wim Taymans's avatar
Wim Taymans committed
243 244
}

Wim Taymans's avatar
Wim Taymans committed
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
/**
 * gst_message_new_custom:
 * @type: The #GstMessageType to distinguish messages
 * @src: The object originating the message.
 * @structure: The structure for the message. The message will take ownership of
 * the structure.
 *
 * Create a new custom-typed message. This can be used for anything not
 * handled by other message-specific functions to pass a message to the
 * app. The structure field can be NULL.
 *
 * Returns: The new message.
 *
 * MT safe.
 */
GstMessage *
gst_message_new_custom (GstMessageType type, GstObject * src,
    GstStructure * structure)
Wim Taymans's avatar
Wim Taymans committed
263 264 265
{
  GstMessage *message;

266
  message = (GstMessage *) gst_mini_object_new (GST_TYPE_MESSAGE);
Wim Taymans's avatar
Wim Taymans committed
267

268 269
  GST_CAT_LOG (GST_CAT_MESSAGE, "source %s: creating new message %p %s",
      (src ? GST_OBJECT_NAME (src) : "NULL"), message,
270
      gst_message_type_get_name (type));
Wim Taymans's avatar
Wim Taymans committed
271

272
  message->type = type;
273 274 275 276 277

  if (src)
    gst_object_ref (src);
  message->src = src;

Wim Taymans's avatar
Wim Taymans committed
278 279 280 281 282
  if (structure) {
    gst_structure_set_parent_refcount (structure,
        &message->mini_object.refcount);
  }
  message->structure = structure;
Wim Taymans's avatar
Wim Taymans committed
283 284 285 286 287 288

  return message;
}

/**
 * gst_message_new_eos:
Stefan Kost's avatar
Stefan Kost committed
289
 * @src: The object originating the message.
Wim Taymans's avatar
Wim Taymans committed
290
 *
291 292 293
 * Create a new eos message. This message is generated and posted in
 * the sink elements of a GstBin. The bin will only forward the EOS
 * message to the application if all sinks have posted an EOS message.
Wim Taymans's avatar
Wim Taymans committed
294 295 296 297 298 299 300 301 302 303
 *
 * Returns: The new eos message.
 *
 * MT safe.
 */
GstMessage *
gst_message_new_eos (GstObject * src)
{
  GstMessage *message;

Wim Taymans's avatar
Wim Taymans committed
304
  message = gst_message_new_custom (GST_MESSAGE_EOS, src, NULL);
Wim Taymans's avatar
Wim Taymans committed
305 306 307 308 309 310 311 312 313 314

  return message;
}

/**
 * gst_message_new_error:
 * @src: The object originating the message.
 * @error: The GError for this message.
 * @debug: A debugging string for something or other.
 *
315
 * Create a new error message. The message will copy @error and
316
 * @debug. This message is posted by element when a fatal event
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
317
 * occured. The pipeline will probably (partially) stop.
Wim Taymans's avatar
Wim Taymans committed
318 319 320 321 322 323 324 325 326 327
 *
 * Returns: The new error message.
 *
 * MT safe.
 */
GstMessage *
gst_message_new_error (GstObject * src, GError * error, gchar * debug)
{
  GstMessage *message;

Wim Taymans's avatar
Wim Taymans committed
328 329 330
  message = gst_message_new_custom (GST_MESSAGE_ERROR, src,
      gst_structure_new ("GstMessageError", "gerror", GST_TYPE_G_ERROR, error,
          "debug", G_TYPE_STRING, debug, NULL));
Wim Taymans's avatar
Wim Taymans committed
331 332 333 334 335 336 337 338 339 340

  return message;
}

/**
 * gst_message_new_warning:
 * @src: The object originating the message.
 * @error: The GError for this message.
 * @debug: A debugging string for something or other.
 *
341
 * Create a new warning message. The message will make copies of @error and
Wim Taymans's avatar
Wim Taymans committed
342 343 344 345 346 347 348 349 350 351 352
 * @debug.
 *
 * Returns: The new warning message.
 *
 * MT safe.
 */
GstMessage *
gst_message_new_warning (GstObject * src, GError * error, gchar * debug)
{
  GstMessage *message;

Wim Taymans's avatar
Wim Taymans committed
353 354 355
  message = gst_message_new_custom (GST_MESSAGE_WARNING, src,
      gst_structure_new ("GstMessageWarning", "gerror", GST_TYPE_G_ERROR, error,
          "debug", G_TYPE_STRING, debug, NULL));
Wim Taymans's avatar
Wim Taymans committed
356 357 358 359 360 361 362 363 364 365

  return message;
}

/**
 * gst_message_new_tag:
 * @src: The object originating the message.
 * @tag_list: The tag list for the message.
 *
 * Create a new tag message. The message will take ownership of the tag list.
366
 * The message is posted by elements that discovered a new taglist.
Wim Taymans's avatar
Wim Taymans committed
367 368 369 370 371 372 373 374 375 376
 *
 * Returns: The new tag message.
 *
 * MT safe.
 */
GstMessage *
gst_message_new_tag (GstObject * src, GstTagList * tag_list)
{
  GstMessage *message;

377 378
  g_return_val_if_fail (GST_IS_STRUCTURE (tag_list), NULL);

Wim Taymans's avatar
Wim Taymans committed
379 380
  message =
      gst_message_new_custom (GST_MESSAGE_TAG, src, (GstStructure *) tag_list);
Wim Taymans's avatar
Wim Taymans committed
381 382 383 384 385

  return message;
}

/**
Stefan Kost's avatar
Stefan Kost committed
386
 * gst_message_new_state_changed:
387 388 389 390
 * @src: the object originating the message
 * @oldstate: the previous state
 * @newstate: the new (current) state
 * @pending: the pending (target) state
Wim Taymans's avatar
Wim Taymans committed
391
 *
392 393
 * Create a state change message. This message is posted whenever an element
 * changed its state.
Wim Taymans's avatar
Wim Taymans committed
394 395 396 397 398 399
 *
 * Returns: The new state change message.
 *
 * MT safe.
 */
GstMessage *
400
gst_message_new_state_changed (GstObject * src,
401
    GstState oldstate, GstState newstate, GstState pending)
Wim Taymans's avatar
Wim Taymans committed
402 403 404
{
  GstMessage *message;

Wim Taymans's avatar
Wim Taymans committed
405 406
  message = gst_message_new_custom (GST_MESSAGE_STATE_CHANGED, src,
      gst_structure_new ("GstMessageState",
407 408
          "old-state", GST_TYPE_STATE, (gint) oldstate,
          "new-state", GST_TYPE_STATE, (gint) newstate,
Wim Taymans's avatar
Wim Taymans committed
409 410 411 412 413
          "pending-state", GST_TYPE_STATE, (gint) pending, NULL));

  return message;
}

414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
/**
 * gst_message_new_state_dirty:
 * @src: the object originating the message
 *
 * Create a state dirty message. This message is posted whenever an element
 * changed its state asynchronously and is used internally to update the
 * states of container objects.
 *
 * Returns: The new state dirty message.
 *
 * MT safe.
 */
GstMessage *
gst_message_new_state_dirty (GstObject * src)
{
  GstMessage *message;

  message = gst_message_new_custom (GST_MESSAGE_STATE_DIRTY, src, NULL);

  return message;
}

Wim Taymans's avatar
Wim Taymans committed
436 437 438
/**
 * gst_message_new_clock_provide:
 * @src: The object originating the message.
439
 * @clock: The clock it provides
Wim Taymans's avatar
Wim Taymans committed
440 441
 * @ready: TRUE if the sender can provide a clock
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
442
 * Create a clock provide message. This message is posted whenever an
Wim Taymans's avatar
Wim Taymans committed
443 444 445
 * element is ready to provide a clock or lost its ability to provide
 * a clock (maybe because it paused or became EOS).
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
446
 * This message is mainly used internally to manage the clock
Wim Taymans's avatar
Wim Taymans committed
447 448 449 450 451 452 453
 * selection.
 *
 * Returns: The new provide clock message.
 *
 * MT safe.
 */
GstMessage *
454 455
gst_message_new_clock_provide (GstObject * src, GstClock * clock,
    gboolean ready)
Wim Taymans's avatar
Wim Taymans committed
456 457 458 459 460
{
  GstMessage *message;

  message = gst_message_new_custom (GST_MESSAGE_CLOCK_PROVIDE, src,
      gst_structure_new ("GstMessageClockProvide",
461
          "clock", GST_TYPE_CLOCK, clock,
Wim Taymans's avatar
Wim Taymans committed
462
          "ready", G_TYPE_BOOLEAN, ready, NULL));
463

Wim Taymans's avatar
Wim Taymans committed
464 465 466
  return message;
}

467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
/**
 * gst_message_new_clock_lost:
 * @src: The object originating the message.
 * @clock: the clock that was lost
 *
 * Create a clock lost message. This message is posted whenever the
 * clock is not valid anymore.
 *
 * If this message is posted by the pipeline, the pipeline will
 * select a new clock again when it goes to PLAYING. It might therefore
 * be needed to set the pipeline to PAUSED and PLAYING again.
 *
 * Returns: The new clock lost message.
 *
 * MT safe.
 */
GstMessage *
gst_message_new_clock_lost (GstObject * src, GstClock * clock)
{
  GstMessage *message;

  message = gst_message_new_custom (GST_MESSAGE_CLOCK_LOST, src,
      gst_structure_new ("GstMessageClockLost",
          "clock", GST_TYPE_CLOCK, clock, NULL));

  return message;
}

Wim Taymans's avatar
Wim Taymans committed
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
/**
 * gst_message_new_new_clock:
 * @src: The object originating the message.
 * @clock: the new selected clock
 *
 * Create a new clock message. This message is posted whenever the
 * pipeline selectes a new clock for the pipeline.
 *
 * Returns: The new new clock message.
 *
 * MT safe.
 */
GstMessage *
gst_message_new_new_clock (GstObject * src, GstClock * clock)
{
  GstMessage *message;

  message = gst_message_new_custom (GST_MESSAGE_NEW_CLOCK, src,
      gst_structure_new ("GstMessageNewClock",
          "clock", GST_TYPE_CLOCK, clock, NULL));
Wim Taymans's avatar
Wim Taymans committed
515 516 517 518 519

  return message;
}

/**
520 521
 * gst_message_new_segment_start:
 * @src: The object originating the message.
522 523
 * @format: The format of the position being played
 * @position: The position of the segment being played
524 525 526 527 528 529 530 531 532 533 534
 *
 * Create a new segment message. This message is posted by elements that
 * start playback of a segment as a result of a segment seek. This message
 * is not received by the application but is used for maintenance reasons in
 * container elements.
 *
 * Returns: The new segment start message.
 *
 * MT safe.
 */
GstMessage *
535 536
gst_message_new_segment_start (GstObject * src, GstFormat format,
    gint64 position)
537 538 539
{
  GstMessage *message;

Wim Taymans's avatar
Wim Taymans committed
540
  message = gst_message_new_custom (GST_MESSAGE_SEGMENT_START, src,
541 542 543
      gst_structure_new ("GstMessageSegmentStart",
          "format", GST_TYPE_FORMAT, format,
          "position", G_TYPE_INT64, position, NULL));
544 545 546 547 548 549 550

  return message;
}

/**
 * gst_message_new_segment_done:
 * @src: The object originating the message.
551 552
 * @format: The format of the position being done
 * @position: The position of the segment being done
553 554 555 556 557 558 559 560 561 562 563
 *
 * Create a new segment done message. This message is posted by elements that
 * finish playback of a segment as a result of a segment seek. This message
 * is received by the application after all elements that posted a segment_start
 * have posted the segment_done.
 *
 * Returns: The new segment done message.
 *
 * MT safe.
 */
GstMessage *
564 565
gst_message_new_segment_done (GstObject * src, GstFormat format,
    gint64 position)
566 567 568
{
  GstMessage *message;

Wim Taymans's avatar
Wim Taymans committed
569
  message = gst_message_new_custom (GST_MESSAGE_SEGMENT_DONE, src,
570 571 572
      gst_structure_new ("GstMessageSegmentDone",
          "format", GST_TYPE_FORMAT, format,
          "position", G_TYPE_INT64, position, NULL));
573 574 575 576

  return message;
}

577 578 579 580 581 582 583 584 585
/**
 * gst_message_new_application:
 * @src: The object originating the message.
 * @structure: The structure for the message. The message will take ownership of
 * the structure.
 *
 * Create a new application-typed message. GStreamer will never create these
 * messages; they are a gift from us to you. Enjoy.
 *
Stefan Kost's avatar
Stefan Kost committed
586 587
 * Returns: The new application message.
 *
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
 * MT safe.
 */
GstMessage *
gst_message_new_application (GstObject * src, GstStructure * structure)
{
  return gst_message_new_custom (GST_MESSAGE_APPLICATION, src, structure);
}

/**
 * gst_message_new_element:
 * @src: The object originating the message.
 * @structure: The structure for the message. The message will take ownership of
 * the structure.
 *
 * Create a new element-specific message. This is meant as a generic way of
 * allowing one-way communication from an element to an application, for example
 * "the firewire cable was unplugged". The format of the message should be
 * documented in the element's documentation. The structure field can be NULL.
 *
Stefan Kost's avatar
Stefan Kost committed
607 608
 * Returns: The new element message.
 *
609 610 611 612 613 614 615 616
 * MT safe.
 */
GstMessage *
gst_message_new_element (GstObject * src, GstStructure * structure)
{
  return gst_message_new_custom (GST_MESSAGE_ELEMENT, src, structure);
}

617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
/**
 * gst_message_new_duration:
 * @src: The object originating the message.
 * @format: The format of the duration
 * @duration: The new duration 
 *
 * Create a new duration message. This message is posted by elements that
 * know the duration of a stream in a specific format. This message
 * is received by bins and is used to calculate the total duration of a
 * pipeline.
 *
 * Returns: The new duration message.
 *
 * MT safe.
 */
GstMessage *
gst_message_new_duration (GstObject * src, GstFormat format, gint64 duration)
{
  GstMessage *message;

  message = gst_message_new_custom (GST_MESSAGE_DURATION, src,
      gst_structure_new ("GstMessageDuration",
          "format", GST_TYPE_FORMAT, format,
          "duration", G_TYPE_INT64, duration, NULL));

  return message;
}

Wim Taymans's avatar
Wim Taymans committed
645 646 647 648 649 650
/**
 * gst_message_get_structure:
 * @message: The #GstMessage.
 *
 * Access the structure of the message.
 *
651
 * Returns: The structure of the message. The structure is still
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
652
 * owned by the message, which means that you should not free it and
653
 * that the pointer becomes invalid when you free the message.
Wim Taymans's avatar
Wim Taymans committed
654 655 656 657 658 659 660
 *
 * MT safe.
 */
const GstStructure *
gst_message_get_structure (GstMessage * message)
{
  g_return_val_if_fail (GST_IS_MESSAGE (message), NULL);
661

Wim Taymans's avatar
Wim Taymans committed
662 663 664 665 666 667
  return message->structure;
}

/**
 * gst_message_parse_tag:
 * @message: A valid #GstMessage of type GST_MESSAGE_TAG.
Stefan Kost's avatar
Stefan Kost committed
668
 * @tag_list: Return location for the tag-list.
Wim Taymans's avatar
Wim Taymans committed
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
 *
 * Extracts the tag list from the GstMessage. The tag list returned in the
 * output argument is a copy; the caller must free it when done.
 *
 * MT safe.
 */
void
gst_message_parse_tag (GstMessage * message, GstTagList ** tag_list)
{
  g_return_if_fail (GST_IS_MESSAGE (message));
  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG);

  *tag_list = (GstTagList *) gst_structure_copy (message->structure);
}

/**
685
 * gst_message_parse_state_changed:
686 687 688 689
 * @message: a valid #GstMessage of type GST_MESSAGE_STATE_CHANGED
 * @oldstate: the previous state
 * @newstate: the new (current) state
 * @pending: the pending (target) state
Wim Taymans's avatar
Wim Taymans committed
690 691 692 693 694 695
 *
 * Extracts the old and new states from the GstMessage.
 *
 * MT safe.
 */
void
696
gst_message_parse_state_changed (GstMessage * message,
697
    GstState * oldstate, GstState * newstate, GstState * pending)
Wim Taymans's avatar
Wim Taymans committed
698 699 700 701
{
  g_return_if_fail (GST_IS_MESSAGE (message));
  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STATE_CHANGED);

702
  if (oldstate)
703
    gst_structure_get_enum (message->structure, "old-state",
704 705
        GST_TYPE_STATE, (gint *) oldstate);
  if (newstate)
706
    gst_structure_get_enum (message->structure, "new-state",
707
        GST_TYPE_STATE, (gint *) newstate);
708 709 710
  if (pending)
    gst_structure_get_enum (message->structure, "pending-state",
        GST_TYPE_STATE, (gint *) pending);
Wim Taymans's avatar
Wim Taymans committed
711 712
}

Wim Taymans's avatar
Wim Taymans committed
713 714 715
/**
 * gst_message_parse_clock_provide:
 * @message: A valid #GstMessage of type GST_MESSAGE_CLOCK_PROVIDE.
716 717
 * @clock: A pointer to  hold a clock object.
 * @ready: A pointer to hold the ready flag.
Wim Taymans's avatar
Wim Taymans committed
718
 *
719 720
 * Extracts the clock and ready flag from the GstMessage.
 * The clock object returned remains valid until the message is freed.
Wim Taymans's avatar
Wim Taymans committed
721 722 723 724
 *
 * MT safe.
 */
void
725 726
gst_message_parse_clock_provide (GstMessage * message, GstClock ** clock,
    gboolean * ready)
Wim Taymans's avatar
Wim Taymans committed
727
{
728 729
  const GValue *clock_gvalue;

Wim Taymans's avatar
Wim Taymans committed
730 731 732
  g_return_if_fail (GST_IS_MESSAGE (message));
  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_CLOCK_PROVIDE);

733 734 735 736
  clock_gvalue = gst_structure_get_value (message->structure, "clock");
  g_return_if_fail (clock_gvalue != NULL);
  g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);

Wim Taymans's avatar
Wim Taymans committed
737 738
  if (ready)
    gst_structure_get_boolean (message->structure, "ready", ready);
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
  if (clock)
    *clock = (GstClock *) g_value_get_object (clock_gvalue);
}

/**
 * gst_message_parse_clock_lost:
 * @message: A valid #GstMessage of type GST_MESSAGE_CLOCK_LOST.
 * @clock: A pointer to hold the lost clock
 *
 * Extracts the lost clock from the GstMessage.
 * The clock object returned remains valid until the message is freed.
 *
 * MT safe.
 */
void
gst_message_parse_clock_lost (GstMessage * message, GstClock ** clock)
{
  const GValue *clock_gvalue;

  g_return_if_fail (GST_IS_MESSAGE (message));
  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEW_CLOCK);

  clock_gvalue = gst_structure_get_value (message->structure, "clock");
  g_return_if_fail (clock_gvalue != NULL);
  g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);

  if (clock)
    *clock = (GstClock *) g_value_get_object (clock_gvalue);
Wim Taymans's avatar
Wim Taymans committed
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
}

/**
 * gst_message_parse_new_clock:
 * @message: A valid #GstMessage of type GST_MESSAGE_NEW_CLOCK.
 * @clock: A pointer to hold the selected new clock
 *
 * Extracts the new clock from the GstMessage.
 * The clock object returned remains valid until the message is freed.
 *
 * MT safe.
 */
void
gst_message_parse_new_clock (GstMessage * message, GstClock ** clock)
{
  const GValue *clock_gvalue;

  g_return_if_fail (GST_IS_MESSAGE (message));
  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEW_CLOCK);

  clock_gvalue = gst_structure_get_value (message->structure, "clock");
  g_return_if_fail (clock_gvalue != NULL);
  g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);

  if (clock)
    *clock = (GstClock *) g_value_get_object (clock_gvalue);
}

Wim Taymans's avatar
Wim Taymans committed
795 796 797
/**
 * gst_message_parse_error:
 * @message: A valid #GstMessage of type GST_MESSAGE_ERROR.
Stefan Kost's avatar
Stefan Kost committed
798 799
 * @gerror: Location for the GError
 * @debug: Location for the debug message
Wim Taymans's avatar
Wim Taymans committed
800
 *
Wim Taymans's avatar
Wim Taymans committed
801
 * Extracts the GError and debug string from the GstMessage. The values returned
Wim Taymans's avatar
Wim Taymans committed
802 803 804 805 806 807 808 809
 * in the output arguments are copies; the caller must free them when done.
 *
 * MT safe.
 */
void
gst_message_parse_error (GstMessage * message, GError ** gerror, gchar ** debug)
{
  const GValue *error_gvalue;
810
  GError *error_val;
Wim Taymans's avatar
Wim Taymans committed
811 812 813 814 815 816

  g_return_if_fail (GST_IS_MESSAGE (message));
  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR);

  error_gvalue = gst_structure_get_value (message->structure, "gerror");
  g_return_if_fail (error_gvalue != NULL);
817
  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
Wim Taymans's avatar
Wim Taymans committed
818

819
  error_val = (GError *) g_value_get_boxed (error_gvalue);
820 821 822 823
  if (error_val)
    *gerror = g_error_copy (error_val);
  else
    *gerror = NULL;
Wim Taymans's avatar
Wim Taymans committed
824 825 826 827 828 829
  *debug = g_strdup (gst_structure_get_string (message->structure, "debug"));
}

/**
 * gst_message_parse_warning:
 * @message: A valid #GstMessage of type GST_MESSAGE_WARNING.
Stefan Kost's avatar
Stefan Kost committed
830 831
 * @gerror: Location for the GError
 * @debug: Location for the debug message
Wim Taymans's avatar
Wim Taymans committed
832
 *
Wim Taymans's avatar
Wim Taymans committed
833
 * Extracts the GError and debug string from the GstMessage. The values returned
Wim Taymans's avatar
Wim Taymans committed
834 835 836 837 838 839 840 841 842
 * in the output arguments are copies; the caller must free them when done.
 *
 * MT safe.
 */
void
gst_message_parse_warning (GstMessage * message, GError ** gerror,
    gchar ** debug)
{
  const GValue *error_gvalue;
843
  GError *error_val;
Wim Taymans's avatar
Wim Taymans committed
844 845 846 847 848 849

  g_return_if_fail (GST_IS_MESSAGE (message));
  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING);

  error_gvalue = gst_structure_get_value (message->structure, "gerror");
  g_return_if_fail (error_gvalue != NULL);
850
  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
Wim Taymans's avatar
Wim Taymans committed
851

852
  error_val = (GError *) g_value_get_boxed (error_gvalue);
853 854 855 856 857
  if (error_val)
    *gerror = g_error_copy (error_val);
  else
    *gerror = NULL;

Wim Taymans's avatar
Wim Taymans committed
858 859
  *debug = g_strdup (gst_structure_get_string (message->structure, "debug"));
}
860 861 862 863

/**
 * gst_message_parse_segment_start:
 * @message: A valid #GstMessage of type GST_MESSAGE_SEGMENT_START.
864 865
 * @format: Result location for the format
 * @position: Result location for the position
866
 *
867
 * Extracts the position and format from the segment start message.
868 869 870 871
 *
 * MT safe.
 */
void
872 873
gst_message_parse_segment_start (GstMessage * message, GstFormat * format,
    gint64 * position)
874
{
875
  const GstStructure *structure;
876 877 878 879

  g_return_if_fail (GST_IS_MESSAGE (message));
  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_SEGMENT_START);

880 881 882 883 884 885
  structure = gst_message_get_structure (message);
  if (format)
    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
  if (position)
    *position =
        g_value_get_int64 (gst_structure_get_value (structure, "position"));
886 887 888 889 890
}

/**
 * gst_message_parse_segment_done:
 * @message: A valid #GstMessage of type GST_MESSAGE_SEGMENT_DONE.
891 892
 * @format: Result location for the format
 * @position: Result location for the position
893
 *
894
 * Extracts the position and format from the segment start message.
895 896 897 898
 *
 * MT safe.
 */
void
899 900
gst_message_parse_segment_done (GstMessage * message, GstFormat * format,
    gint64 * position)
901
{
902
  const GstStructure *structure;
903 904 905 906

  g_return_if_fail (GST_IS_MESSAGE (message));
  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_SEGMENT_DONE);

907 908 909 910 911 912 913
  structure = gst_message_get_structure (message);
  if (format)
    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
  if (position)
    *position =
        g_value_get_int64 (gst_structure_get_value (structure, "position"));
}
914

915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939
/**
 * gst_message_parse_duration:
 * @message: A valid #GstMessage of type GST_MESSAGE_DURATION.
 * @format: Result location for the format
 * @duration: Result location for the duration
 *
 * Extracts the duration and format from the duration message.
 *
 * MT safe.
 */
void
gst_message_parse_duration (GstMessage * message, GstFormat * format,
    gint64 * duration)
{
  const GstStructure *structure;

  g_return_if_fail (GST_IS_MESSAGE (message));
  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DURATION);

  structure = gst_message_get_structure (message);
  if (format)
    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
  if (duration)
    *duration =
        g_value_get_int64 (gst_structure_get_value (structure, "duration"));
940
}