gnomemm r1501 - in gstreamermm/trunk: . examples/element_link examples/media_player_gtkmm examples/ogg_player examples/ogg_player_gtkmm gstreamer/src tests tools/m4



Author: murrayc
Date: Sat May 17 20:34:30 2008
New Revision: 1501
URL: http://svn.gnome.org/viewvc/gnomemm?rev=1501&view=rev

Log:
2008-05-17  Murray Cumming  <murrayc murrayc com>

* gstreamer/src/structure.ccg:
* gstreamer/src/structure.hg: Use _CLASS_BOXEDTYPE() instead of the 
custom _CLASS_BOXEDTYPE_NCOPY() macro, so we can just use this by 
copying it instead of having strange ownership rules.
Add operator bool() to check for invalid instances.

* gstreamer/src/caps.ccg:
* gstreamer/src/caps.hg: create(), append_structure(), 
merge_structure(): Take a const Structure& instead of taking ownership.
get_structure(): Return by value.
Remove set_simple_valist() because it does not seem useful.

* gstreamer/src/event.ccg:
* gstreamer/src/event.hg: get_structure():
* gstreamer/src/message.ccg:
* gstreamer/src/message.hg: get_structure():
* gstreamer/src/query.ccg:
* gstreamer/src/query.hg: get_structure(): Return by copy.

* examples/element_link/element_link.cc:
* examples/media_player_gtkmm/player_window.cc:
* examples/ogg_player/main.cc:
* examples/ogg_player_gtkmm/main.cc:
* examples/ogg_player_gtkmm/player_window.cc:
* tests/test-caps-structures.cc (main):
* tests/test-event-wrap.cc (main):
* tests/test-message-wrap.cc (main):
* tests/test-query-wrap.cc (main): Adapted to the changed API.

Removed:
   gstreamermm/trunk/tools/m4/class_boxedtype_ncopy.m4
Modified:
   gstreamermm/trunk/ChangeLog
   gstreamermm/trunk/examples/element_link/element_link.cc
   gstreamermm/trunk/examples/media_player_gtkmm/player_window.cc
   gstreamermm/trunk/examples/ogg_player/main.cc
   gstreamermm/trunk/examples/ogg_player_gtkmm/main.cc
   gstreamermm/trunk/examples/ogg_player_gtkmm/player_window.cc
   gstreamermm/trunk/gstreamer/src/caps.ccg
   gstreamermm/trunk/gstreamer/src/caps.hg
   gstreamermm/trunk/gstreamer/src/event.ccg
   gstreamermm/trunk/gstreamer/src/event.hg
   gstreamermm/trunk/gstreamer/src/message.ccg
   gstreamermm/trunk/gstreamer/src/message.hg
   gstreamermm/trunk/gstreamer/src/query.ccg
   gstreamermm/trunk/gstreamer/src/query.hg
   gstreamermm/trunk/gstreamer/src/structure.ccg
   gstreamermm/trunk/gstreamer/src/structure.hg
   gstreamermm/trunk/tests/test-caps-structures.cc
   gstreamermm/trunk/tests/test-event-wrap.cc
   gstreamermm/trunk/tests/test-message-wrap.cc
   gstreamermm/trunk/tests/test-query-wrap.cc
   gstreamermm/trunk/tools/m4/convert.m4

Modified: gstreamermm/trunk/examples/element_link/element_link.cc
==============================================================================
--- gstreamermm/trunk/examples/element_link/element_link.cc	(original)
+++ gstreamermm/trunk/examples/element_link/element_link.cc	Sat May 17 20:34:30 2008
@@ -20,7 +20,6 @@
  */
 
 #include <gstreamermm.h>
-#include <stdexcept>
 #include <iostream>
 
 int main(int argc, char** argv)
@@ -42,14 +41,14 @@
   // We must add the elements to the pipeline before linking them:
   pipeline->add(element_source)->add(element_filter)->add(element_sink);
 
-  // Link
+  // Link the elements together:
   try
   {
     element_source->link(element_filter)->link(element_sink);
   }
   catch(const std::runtime_error& error)
   {
-    std::cout << error.what() << std::endl;
+    std::cout << "Exception while linking: " << error.what() << std::endl;
   }
 
   return 0;

Modified: gstreamermm/trunk/examples/media_player_gtkmm/player_window.cc
==============================================================================
--- gstreamermm/trunk/examples/media_player_gtkmm/player_window.cc	(original)
+++ gstreamermm/trunk/examples/media_player_gtkmm/player_window.cc	Sat May 17 20:34:30 2008
@@ -117,7 +117,7 @@
   if(message->get_message_type() != Gst::MESSAGE_ELEMENT)
     return Gst::BUS_PASS;
 
-  if(!message->get_structure()->has_name("prepare-xwindow-id"))
+  if(!message->get_structure().has_name("prepare-xwindow-id"))
      return Gst::BUS_PASS;
 
   Glib::RefPtr<Gst::Element> element =
@@ -177,16 +177,24 @@
   Glib::RefPtr<Gst::Buffer> buffer = Glib::RefPtr<Gst::Buffer>::cast_dynamic(data);
 
   if(buffer) {
-    Glib::Value<int> widthValue;
-    Glib::Value<int> heightValue;
+    Glib::Value<int> width_value;
+    Glib::Value<int> height_value;
 
     Glib::RefPtr<Gst::Caps> caps = buffer->get_caps();
-    caps->get_structure(0)->get_field("width", widthValue);
-    caps->get_structure(0)->get_field("height", heightValue);
 
-    m_video_area.set_size_request(widthValue.get(), heightValue.get());
-    resize(1, 1);     // Resize to minimum when first playing by making size
-    check_resize();   // smallest then resizing according to video new size
+    const Gst::Structure structure = caps->get_structure(0);
+    if(structure)
+    {
+      structure.get_field("width", width_value);
+      structure.get_field("height", height_value);
+    }
+
+    m_video_area.set_size_request(width_value.get(), height_value.get());
+
+    // Resize to minimum when first playing by making size 
+    // smallest then resizing according to video new size:
+    resize(1, 1);
+    check_resize();
   }
 
   pad->remove_buffer_probe(m_pad_probe_id);
@@ -277,7 +285,7 @@
   }
   else
   {
-    std::cerr << "Could not seek!" << std::endl;
+    std::cerr << "Could not seek." << std::endl;
     return false;
   }
 }
@@ -298,7 +306,7 @@
       display_label_progress(newPos, m_duration);
     }
     else
-      std::cerr << "Could not seek!" << std::endl;
+      std::cerr << "Could not seek." << std::endl;
   }
 }
 
@@ -334,7 +342,7 @@
       display_label_progress(newPos, m_duration);
     }
     else
-      std::cerr << "Could not seek!" << std::endl;
+      std::cerr << "Could not seek." << std::endl;
   }
 }
 

Modified: gstreamermm/trunk/examples/ogg_player/main.cc
==============================================================================
--- gstreamermm/trunk/examples/ogg_player/main.cc	(original)
+++ gstreamermm/trunk/examples/ogg_player/main.cc	Sat May 17 20:34:30 2008
@@ -101,7 +101,15 @@
   // We can now link this pad with the audio decoder
   std::cout << "Dynamic pad created. Linking parser/decoder." << std::endl;
   Glib::RefPtr<Gst::Pad> sinkPad = decoder->get_pad("sink");
-  newPad->link(sinkPad);
+
+  try
+  {
+    newPad->link(sinkPad);
+  }
+  catch(const std::runtime_error& ex)
+  {
+    std::cerr << "Exception caught while linking: " << ex.what() << std::endl;
+  }
 }
 
 bool on_sink_pad_have_data(const Glib::RefPtr<Gst::Pad>& pad,
@@ -181,7 +189,8 @@
   Glib::RefPtr<Gst::Bus> bus = pipeline->get_bus();
   bus->add_watch( sigc::ptr_fun(&on_bus_message) );
 
-  // Put all the elements in a pipeline, linked to each other:
+
+  // Put all the elements in a pipeline:
   try
   {
     pipeline->add(source)->add(parser)->add(decoder)->add(conv)->add(sink);
@@ -192,22 +201,30 @@
     return -1;
   }
 
-  // Link together:
-  // TODO: Why isn't this done during add()?:
-  source->link(parser);
-
-  // We cannot link the parser and decoder yet, 
-  // because the parser uses dynamic pads. For that,
-  // we set a pad-added signal handler:
-  parser->signal_pad_added().connect( sigc::ptr_fun(&on_parser_pad_added) );
 
-  decoder->link(conv)->link(sink);
+  // Link the elements together:
+  try
+  {
+    source->link(parser);
+
+    // We cannot link the parser and decoder yet, 
+    // because the parser uses dynamic pads.
+    // So we do it later in a pad-added signal handler:
+    parser->signal_pad_added().connect( sigc::ptr_fun(&on_parser_pad_added) );
+
+    decoder->link(conv)->link(sink);
+  }
+  catch(const std::runtime_error& ex)
+  {
+    std::cout << "Exception while linking elements: " << ex.what() << std::endl;
+  }
+
 
   // Call on_timeout function at a 200ms
   // interval to regularly print the position of the stream
   Glib::signal_timeout().connect(sigc::ptr_fun(&on_timeout), 200);
 
-  // Now set to playing and start the main loop:
+  // Now set the whole pipeline to playing and start the main loop:
   std::cout << "Setting to PLAYING." << std::endl;
   pipeline->set_state(Gst::STATE_PLAYING);
   std::cout << "Running." << std::endl;

Modified: gstreamermm/trunk/examples/ogg_player_gtkmm/main.cc
==============================================================================
--- gstreamermm/trunk/examples/ogg_player_gtkmm/main.cc	(original)
+++ gstreamermm/trunk/examples/ogg_player_gtkmm/main.cc	Sat May 17 20:34:30 2008
@@ -33,9 +33,17 @@
 
 void on_parser_pad_added(const Glib::RefPtr<Gst::Pad>& newPad)
 {
-  // We can now link this pad with the audio decoder
+  // We can now link this pad with the audio decoder.
   Glib::RefPtr<Gst::Pad> sinkPad = decoder->get_pad("sink");
-  newPad->link(sinkPad);
+
+  try
+  {
+    newPad->link(sinkPad);
+  }
+  catch(const std::runtime_error& ex)
+  {
+    std::cerr << "Exception caught while linking: " << ex.what() << std::endl;
+  }
 }
 
 int
@@ -50,26 +58,47 @@
   // Create the elements
   // Reads file from disk
   Glib::RefPtr<Gst::Element> source = Gst::ElementFactory::create_element("filesrc");
+  if(!source)
+  {
+    std::cerr << "filesrc element could not be created" << std::endl;
+    return -1;
+  }
 
   // Parses the ogg streams into elementary streams (note that an ogg file may contain a video stream too)
   Glib::RefPtr<Gst::Element> parser = Gst::ElementFactory::create_element("oggdemux");
+  if(!parser)
+  {
+    std::cerr << "oggdemux element could not be created" << std::endl;
+    return -1;
+  }
 
   // Decodes a vorbis stream
-  decoder = Gst::ElementFactory::create_element("vorbisdec", "vorbis-decoder");
+  decoder = Gst::ElementFactory::create_element("vorbisdec");
+  if(!decoder)
+  {
+    std::cerr << "vorbisdec element could not be created" << std::endl;
+    return -1;
+  }
 
-  // Converts audio() to a format which can be used by the next element
+  // Converts audio to a format which can be used by the next element
   Glib::RefPtr<Gst::Element> conv = Gst::ElementFactory::create_element("audioconvert");
+  if(!conv)
+  {
+    std::cerr << "audioconvert element could not be created" << std::endl;
+    return -1;
+  }
 
   // Outputs sound to an ALSA audio device
   Glib::RefPtr<Gst::Element> sink = Gst::ElementFactory::create_element("alsasink");
-
-  if (!pipeline || !source || !parser || !decoder || !conv || !sink)
+  if(!sink)
   {
-    std::cerr << "One element could not be created" << std::endl;
+    std::cerr << "sink element could not be created" << std::endl;
     return -1;
   }
 
+
   // Put all elements in a pipeline:
+  // TODO: Bin::add() does not actually throw an exception. It probably should.
   try
   {
     pipeline->add(source)->add(parser)->add(decoder)->add(conv)->add(sink);
@@ -80,18 +109,26 @@
     return -1;
   }
 
-  // Link together:
-  source->link(parser);
 
-  // We cannot link the parser and decoder yet, 
-  // because the parser uses dynamic pads. For that,
-  // we set a pad-added signal handler:
-  parser->signal_pad_added().connect( sigc::ptr_fun(&on_parser_pad_added) );
+  // Link the elements together:
+  try
+  {
+    source->link(parser);
 
-  decoder->link(conv)->link(sink);
+    // We cannot link the parser and decoder yet, 
+    // because the parser uses dynamic pads.
+    // So we do it later in a pad-added signal handler:
+    parser->signal_pad_added().connect( sigc::ptr_fun(&on_parser_pad_added) );
 
-  PlayerWindow mainWindow(source, pipeline);
+    decoder->link(conv)->link(sink);
+  }
+  catch(const std::runtime_error& ex)
+  {
+    std::cout << "Exception while linking elements: " << ex.what() << std::endl;
+  }
 
+  // Create our window and show it:
+  PlayerWindow mainWindow(source, pipeline);
   kit.run(mainWindow);
 
   // Clean up nicely:

Modified: gstreamermm/trunk/examples/ogg_player_gtkmm/player_window.cc
==============================================================================
--- gstreamermm/trunk/examples/ogg_player_gtkmm/player_window.cc	(original)
+++ gstreamermm/trunk/examples/ogg_player_gtkmm/player_window.cc	Sat May 17 20:34:30 2008
@@ -75,12 +75,13 @@
   m_open_button.signal_clicked().connect(
     sigc::mem_fun(*this, &PlayerWindow::on_button_open) );
 
-  // get the bus from the pipeline
-  Glib::RefPtr<Gst::Bus> bus = main_pipeline->get_bus();
-
   // Add a bus watch to receive messages from pipeline's bus
-  m_watch_id = bus->add_watch(
-    sigc::mem_fun( *this, &PlayerWindow::on_bus_message) );
+  Glib::RefPtr<Gst::Bus> bus = main_pipeline->get_bus();
+  if(bus)
+  {
+    m_watch_id = bus->add_watch(
+      sigc::mem_fun( *this, &PlayerWindow::on_bus_message) );
+  }
 
   m_progress_scale.set_sensitive(false);
   m_play_button.set_sensitive(false);
@@ -99,13 +100,16 @@
 // This function is used to receive asynchronous messages from main_pipeline's bus
 bool PlayerWindow::on_bus_message(const Glib::RefPtr<Gst::Bus>& /* bus */, const Glib::RefPtr<Gst::Message>& message)
 {
-  switch (message->get_message_type())
+  switch(message->get_message_type())
   {
     case Gst::MESSAGE_EOS:
+      //We reached the end of the file, so stop playing:
       on_button_stop();
       break;
     case Gst::MESSAGE_ERROR:
     {
+      //There was an error, so stop playing, 
+      //and output some information to stdout:
       Glib::RefPtr<Gst::MessageError> error_message =
         Glib::RefPtr<Gst::MessageError>::cast_dynamic(message);
       if(error_message)
@@ -144,11 +148,11 @@
   m_pause_button.show();
 
   // Call on_timeout function at a 200ms
-  // interval to regularly update the position of the stream
+  // interval to regularly update the position of the stream:
   m_progress_connection = Glib::signal_timeout().connect(
     sigc::mem_fun(*this, &PlayerWindow::on_timeout), 200);
 
-  // set Gstmm pipeline to play mode
+  // Set the pipeline to play mode:
   m_main_pipeline->set_state(Gst::STATE_PLAYING);
 }
  
@@ -160,10 +164,10 @@
   m_pause_button.hide();
   m_play_button.show();
 
-  // disconnect progress callback
+  // Disconnect progress callback:
   m_progress_connection.disconnect();
   
-  // set Gstmm pipeline to pause mode
+  // Set the pipeline to pause mode:
   m_main_pipeline->set_state(Gst::STATE_PAUSED);
 }
  
@@ -180,10 +184,10 @@
   m_pause_button.hide();
   m_play_button.show();
 
-  // disconnect progress callback
+  // Disconnect progress callback:
   m_progress_connection.disconnect();
 
-  // set Gstmm pipeline to inactive mode
+  // Set the pipeline to inactive mode:
   m_main_pipeline->set_state(Gst::STATE_NULL);
   display_label_progress(0, m_duration);
   m_progress_scale.set_value(0);
@@ -191,45 +195,45 @@
 
 bool PlayerWindow::on_scale_value_changed(Gtk::ScrollType /* type_not_used */, double value)
 {
-  gint64 newPos = gint64(value * m_duration);
+  const gint64 new_pos = gint64(value * m_duration);
 
-  if(m_main_pipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, newPos))
+  if(m_main_pipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, new_pos))
   {
-    display_label_progress(newPos, m_duration);
+    display_label_progress(new_pos, m_duration);
     return true;
   }
   else
   {
-    std::cerr << "Could not seek!" << std::endl;
+    std::cerr << "Could not seek." << std::endl;
     return false;
   }
 }
 
 void PlayerWindow::on_button_rewind()
 {
-  static const gint64 skipAmount = GST_SECOND * 2;
+  static const gint64 skip_amount = GST_SECOND * 2;
 
   gint64 pos = 0;
   Gst::Format fmt = Gst::FORMAT_TIME;
 
   if(m_main_pipeline->query_position(fmt, pos))
   {
-    const gint64 newPos = (pos > skipAmount) ? (pos - skipAmount) : 0;
+    const gint64 new_pos = (pos > skip_amount) ? (pos - skip_amount) : 0;
 
-    if(m_main_pipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, newPos))
+    if(m_main_pipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, new_pos))
     {
-      display_label_progress(newPos, m_duration);
-      m_progress_scale.set_value(double(newPos) / m_duration);
+      display_label_progress(new_pos, m_duration);
+      m_progress_scale.set_value(double(new_pos) / m_duration);
     }
     else
-      std::cerr << "Could not seek!" << std::endl;
+      std::cerr << "Could not seek." << std::endl;
   }
 }
 
 void PlayerWindow::on_button_forward()
 {
   //TODO: Wrap GST_SECOND:
-  static const gint64 skipAmount = GST_SECOND * 3;
+  static const gint64 skip_amount = GST_SECOND * 3;
 
   gint64 pos = 0;
   Gst::Format fmt = Gst::FORMAT_TIME;
@@ -243,11 +247,11 @@
 
     posQuery->parse(fmt, pos);
 
-    gint64 newPos = ((pos + skipAmount) < m_duration) ? (pos + skipAmount) :
-      m_duration;
+    const gint64 new_pos =
+      ((pos + skip_amount) < m_duration) ? (pos + skip_amount) : m_duration;
 
     Glib::RefPtr<Gst::Event> event = Gst::EventSeek::create(1.0, fmt,
-      Gst::SEEK_FLAG_FLUSH, Gst::SEEK_TYPE_SET, newPos,
+      Gst::SEEK_FLAG_FLUSH, Gst::SEEK_TYPE_SET, new_pos,
       Gst::SEEK_TYPE_NONE, -1);
 
     Glib::RefPtr<Gst::EventSeek> seekEvent =
@@ -255,11 +259,11 @@
 
     if(m_main_pipeline->send_event(seekEvent))
     {
-      m_progress_scale.set_value(double(newPos) / m_duration);
-      display_label_progress(newPos, m_duration);
+      m_progress_scale.set_value(double(new_pos) / m_duration);
+      display_label_progress(new_pos, m_duration);
     }
     else
-      std::cerr << "Could not seek!" << std::endl;
+      std::cerr << "Could not seek." << std::endl;
   }
 }
 
@@ -314,21 +318,21 @@
 void PlayerWindow::display_label_progress(gint64 pos, gint64 len)
 {
   std::ostringstream locationStream(std::ostringstream::out);
-  std::ostringstream durationStream(std::ostringstream::out);
-
   locationStream << std::right << std::setfill('0') << 
     std::setw(3) << Gst::get_hours(pos) << ":" <<
     std::setw(2) << Gst::get_minutes(pos) << ":" <<
     std::setw(2) << Gst::get_seconds(pos) << "." <<
     std::setw(9) << std::left << Gst::get_fractional_seconds(pos);
 
+  std::ostringstream durationStream(std::ostringstream::out);
   durationStream << std::right << std::setfill('0') <<
     std::setw(3) << Gst::get_hours(len) << ":" <<
     std::setw(2) << Gst::get_minutes(len) << ":" <<
     std::setw(2) << Gst::get_seconds(len) << "." <<
     std::setw(9) << std::left << Gst::get_fractional_seconds(len);
 
-  m_progress_label.set_text(locationStream.str() + " / " + durationStream.str());
+  m_progress_label.set_text(
+    locationStream.str() + " / " + durationStream.str() );
 }
 
 PlayerWindow::~PlayerWindow()

Modified: gstreamermm/trunk/gstreamer/src/caps.ccg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/caps.ccg	(original)
+++ gstreamermm/trunk/gstreamer/src/caps.ccg	Sat May 17 20:34:30 2008
@@ -26,8 +26,7 @@
 namespace Gst
 {
 
-Glib::RefPtr<Caps>
-Caps::create_any()
+Glib::RefPtr<Caps> Caps::create_any()
 {
   return Glib::wrap(gst_caps_new_any());
 }
@@ -38,8 +37,7 @@
   creates a GstStructure for the GstCaps and will not be called, we must create
   our own GstStructure here and append it to the GstCaps.
 */
-Glib::RefPtr<Caps>
-Caps::create_simple(const Glib::ustring& media_type)
+Glib::RefPtr<Caps> Caps::create_simple(const Glib::ustring& media_type)
 {
   Glib::RefPtr<Caps> result = Glib::wrap(gst_caps_new_empty());
   GstStructure* gst_struct = gst_structure_empty_new(media_type.c_str());
@@ -47,55 +45,39 @@
   return result;
 }
 
-Glib::RefPtr<Caps>
-Caps::create(Structure& structure)
+Glib::RefPtr<Caps> Caps::create(const Structure& structure)
 {
-  //Since caps now owns structure, do not let wrapper destroy structure (caps
-  //will do that itself)
-  structure.set_destroy(false);
-
-  return Glib::wrap(gst_caps_new_full(structure.gobj()));
+  //We take a copy because gst_caps_append_structure() wants to take ownership:
+  GstStructure* copy = gst_structure_copy(structure.gobj());
+  return Glib::wrap(gst_caps_new_full(copy));
 }
 
-void Caps::append_structure(Structure& structure)
+void Caps::append_structure(const Structure& structure)
 {
-  //Since caps now owns structure, do not let wrapper destroy structure (caps
-  //will do that itself)
-  structure.set_destroy(false);
-
-  gst_caps_append_structure(gobj(), structure.gobj());
+  //We take a copy because gst_caps_append_structure() wants to take ownership:
+  GstStructure* copy = gst_structure_copy(structure.gobj());
+  gst_caps_append_structure(gobj(), copy);
 }
 
-void Caps::merge_structure(Structure& structure)
+void Caps::merge_structure(const Structure& structure)
 {
-  //Since caps now owns structure, do not let wrapper destroy structure (caps
-  //will do that itself)
-  structure.set_destroy(false);
-
-  gst_caps_merge_structure(gobj(), structure.gobj());
+  //We take a copy because gst_caps_append_structure() wants to take ownership:
+  GstStructure* copy = gst_structure_copy(structure.gobj());
+  gst_caps_merge_structure(gobj(), copy);
 }
 
-const Structure* Caps::get_structure(guint idx) const
+Structure Caps::get_structure(guint idx) const
 {
-  static std::map<guint,Structure> structures;
-
   GstStructure* structure = gst_caps_get_structure(gobj(), idx);
-
-  if (structure)
-  {
-    if (structures[idx].gobj() != structure) {
-      Structure temp(structure, false /*don't copy*/, false /*don't destroy*/);
-      structures[idx].swap(temp);
-    }
-    return &structures[idx];
-  }
-
-  return NULL;
+  if(structure)
+    return Structure(structure, true /* take_copy */);
+  else
+    return Structure(); //Use operator bool() to detect this.
 }
 
 //TODO: Want to return RefPtr to Caps but using RefPtr in expressions such
 //TODO: as 'caps->set_simple(name1, value1)->set_simple(name2, value2)' a
-//TODO: causes Structure immutability warnings because the Caps is referenced
+//TODO: causes gstreamer Structure immutability warnings because the Caps is referenced
 //TODO: more than once in the expression
 /*
   This method is implemented in place of gst_caps_set_simple which is a
@@ -113,7 +95,12 @@
 
   //Use Gst::Structure so gstremermm GTypes like Gst::Value<Gst::IntRange> are
   //converted to GStreamer types when they are stored in structure
-  const_cast<Structure*>(get_structure(0))->set_field(name, value);
+
+  //The result of gst_caps_get_structure() should not be modified, according to its documentation,
+  //but we are reimplementing gst_caps_set_simple() which does that:
+  GstStructure* structure = gst_caps_get_structure(gobj(), 0);
+  if(structure)
+    Structure::_set_gstructure_field(structure, name, value);
 
   //return Glib::wrap(gobj(), true);
 }

Modified: gstreamermm/trunk/gstreamer/src/caps.hg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/caps.hg	(original)
+++ gstreamermm/trunk/gstreamer/src/caps.hg	Sat May 17 20:34:30 2008
@@ -29,9 +29,8 @@
 
 struct Structure;
 
-/** Gst::Caps â A structure describing sets of media formats.
- * Gst::Caps (capabilities) are lighweight refcounted objects describing media
- * types. They are composed of an array of Gst::Structure.
+/** Gst::Caps (capabilities) are lightweight objects describing media
+ * formats. They are composed of an array of Gst::Structure.
  *
  * Gst::Caps are exposed on Gst::PadTemplate to describe all possible types a
  * given pad can handle. They are also stored in the Gst::Registry along with a
@@ -70,13 +69,13 @@
    */
   static Glib::RefPtr<Caps> create_simple(const Glib::ustring& media_type);
 
-  /** Creates a new Gst::Caps and adds the first Gst::Structure given. The
-   * structure is not copied; the returned Gst::Caps owns the structure.
+  /** Creates a new Gst::Caps and adds the given Gst::Structure.
+   * Use append_structure() to add additional structures.
    *
    * @param first_struct the first structure to add
    * @return Returns the new Gst::Caps
    */
-  static Glib::RefPtr<Caps> create(Structure& first_struct);
+  static Glib::RefPtr<Caps> create(const Structure& first_struct);
 
   _WRAP_METHOD(static Glib::RefPtr<Caps> create_from_string(const Glib::ustring& string), gst_caps_from_string)
 
@@ -92,25 +91,27 @@
    *
    * @param structure the Gst::Structure to append
    */
-  void append_structure(Structure& structure);
+  void append_structure(const Structure& structure);
 
-  /** Appendsa  structure to caps if its not already expressed by caps. The
+  /** Appends a structure to caps if its not already expressed by caps. The
    * structure is not copied. This Caps becomes the owner of @a structure.
    *
    * @param structure the Gst::Structure to merge
    */
-  void merge_structure(Structure& structure);
+  void merge_structure(const Structure& structure);
 
   /** Finds the structure in caps that has the index @a idx, and returns it.
    *
    * @param index the index of the structure
    * @return the Gst::Structure corresponding to index
    */
-  const Structure* get_structure(guint idx) const;
+  Structure get_structure(guint idx) const;
 
   _WRAP_METHOD(void remove_structure(guint idx), gst_caps_remove_structure)
   _WRAP_METHOD(guint size() const, gst_caps_get_size)
 
+  //TODO: Avoid forcing applications to use Glib::Value<>. See what TreeModel does.
+
   /** Sets fields in a simple Gst::Caps. A simple Gst::Caps is one that only
    * has one structure.
    *
@@ -120,7 +121,8 @@
   void set_simple(const Glib::ustring& name, const Glib::ValueBase& value);
   _IGNORE(gst_caps_set_simple)
 
-  _WRAP_METHOD(void set_simple_valist(char* field, const va_list& varargs), gst_caps_set_simple_valist)
+  //This does not seem useful: _WRAP_METHOD(void set_simple_valist(char* field, const va_list& varargs), gst_caps_set_simple_valist)
+  _IGNORE(gst_caps_set_simple_valist)
 
   _WRAP_METHOD(bool is_any() const, gst_caps_is_any)
   _WRAP_METHOD(bool empty() const, gst_caps_is_empty)

Modified: gstreamermm/trunk/gstreamer/src/event.ccg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/event.ccg	(original)
+++ gstreamermm/trunk/gstreamer/src/event.ccg	Sat May 17 20:34:30 2008
@@ -37,14 +37,12 @@
   return Glib::QueryQuark(gst_event_type_to_quark(GstEventType(t)));
 }
 
-const Structure* Event::get_structure()
+Structure Event::get_structure() const
 {
   static Structure structure;
 
-  GstStructure* gst_structure = const_cast<GstStructure*>(gst_event_get_structure(gobj()));
-  Structure temp(gst_structure, false /*don't copy*/, false /*don't destroy*/);
-  structure.swap(temp);
-  return &structure;
+  GstStructure* gst_structure = const_cast<GstStructure*>(gst_event_get_structure(const_cast<GstEvent*>(gobj())));
+  return Structure(gst_structure, true /* take_copy */);
 }
 
 bool Event::is_downstream() const

Modified: gstreamermm/trunk/gstreamer/src/event.hg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/event.hg	(original)
+++ gstreamermm/trunk/gstreamer/src/event.hg	Sat May 17 20:34:30 2008
@@ -119,9 +119,9 @@
   static Glib::RefPtr<Event> wrap(GstEvent* event, bool take_copy=false);
 
   /** Get the structure of an event.
-   * @return The Gst::Structure of the event (unmodifiable)
+   * @return The Gst::Structure of the event.
    */
-  const Structure* get_structure();
+  Structure get_structure() const;
 
   /** Check if an event can travel downstream.
    */

Modified: gstreamermm/trunk/gstreamer/src/message.ccg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/message.ccg	(original)
+++ gstreamermm/trunk/gstreamer/src/message.ccg	Sat May 17 20:34:30 2008
@@ -37,15 +37,12 @@
   return Glib::QueryQuark(gst_message_type_to_quark(GstMessageType(t)));
 }
 
-const Structure*
-Message::get_structure()
+Structure Message::get_structure() const
 {
   static Structure structure;
 
-  GstStructure* gst_structure = const_cast<GstStructure*>(gst_message_get_structure(gobj()));
-  Structure temp(gst_structure, false /*don't copy*/, false /*don't destroy*/);
-  structure.swap(temp);
-  return &structure;
+  GstStructure* gst_structure = const_cast<GstStructure*>(gst_message_get_structure(const_cast<GstMessage*>(gobj())));
+  return Structure(gst_structure, true /* take_copy */);
 }
 
 MessageApplication::MessageApplication(GstMessage* castitem)

Modified: gstreamermm/trunk/gstreamer/src/message.hg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/message.hg	(original)
+++ gstreamermm/trunk/gstreamer/src/message.hg	Sat May 17 20:34:30 2008
@@ -59,10 +59,11 @@
  _CLASS_GSTMINIOBJECT(Message, GstMessage, GST_MESSAGE, Gst::MiniObject, GstMiniObject)
  _IGNORE(gst_message_ref, gst_message_unref)
 public:
+
   /** Get the structure of a message.
-   * @return The Gst::Structure of the message (unmodifiable)
+   * @return The Gst::Structure of the message.
    */
-  const Structure* get_structure();
+  Structure get_structure() const;
 
 public:
   /** Wrap a GstMessage* in a C++ instance, creating an instance of a

Modified: gstreamermm/trunk/gstreamer/src/query.ccg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/query.ccg	(original)
+++ gstreamermm/trunk/gstreamer/src/query.ccg	Sat May 17 20:34:30 2008
@@ -35,14 +35,10 @@
   return Glib::QueryQuark(gst_query_type_to_quark(GstQueryType(t)));
 }
 
-const Structure* Query::get_structure()
+Structure Query::get_structure() const
 {
-  static Structure structure;
-
-  GstStructure* gst_structure = const_cast<GstStructure*>(gst_query_get_structure(gobj()));
-  Structure temp(gst_structure, false /*don't copy*/, false /*don't destroy*/);
-  structure.swap(temp);
-  return &structure;
+  GstStructure* gst_structure = const_cast<GstStructure*>(gst_query_get_structure(const_cast<GstQuery*>(gobj())));
+  return Structure(gst_structure, true /* take_copy */);
 }
 
 bool get_details(QueryType type, QueryTypeDefinition &def)

Modified: gstreamermm/trunk/gstreamer/src/query.hg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/query.hg	(original)
+++ gstreamermm/trunk/gstreamer/src/query.hg	Sat May 17 20:34:30 2008
@@ -49,10 +49,11 @@
   _CLASS_GSTMINIOBJECT(Query, GstQuery, GST_QUERY, Gst::MiniObject, GstMiniObject)
 
 public:
+
   /** Get the structure of a query.
-   * @return The Structure of the query (unmodifiable)
+   * @return The Structure of the query.
    */
-  const Structure* get_structure();
+  Structure get_structure() const;
 
 public:
   _MEMBER_GET(query_type, type, QueryType, GstQueryType)

Modified: gstreamermm/trunk/gstreamer/src/structure.ccg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/structure.ccg	(original)
+++ gstreamermm/trunk/gstreamer/src/structure.ccg	Sat May 17 20:34:30 2008
@@ -58,6 +58,11 @@
   gobject_ = gst_structure_empty_new(name.c_str());
 }
 
+Structure::operator bool() const
+{
+  return gobject_ != 0;
+}
+
 void
 Structure::get_field(const Glib::ustring& name, Glib::ValueBase& value) const
 {
@@ -67,14 +72,21 @@
 Structure&
 Structure::set_field(const Glib::ustring& fieldname, const Glib::ValueBase& value)
 {
-  GType type = G_VALUE_TYPE(value.gobj());
+  _set_gstructure_field(gobj(), fieldname, value);
+
+  return *this;
+}
+
+void Structure::_set_gstructure_field(GstStructure* cstructure, const Glib::ustring& fieldname, const Glib::ValueBase& value)
+{
+  const GType type = G_VALUE_TYPE(value.gobj());
 
   if (type == Glib::Value<Fourcc>::value_type())
   {
      const Glib::Value<Fourcc>* fourcc =
         static_cast< const Glib::Value<Fourcc>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_FOURCC,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_FOURCC,
         fourcc->get().get_fourcc(), NULL);
   }
   else if (type == Glib::Value<IntRange>::value_type())
@@ -82,7 +94,7 @@
      const Glib::Value<IntRange>* range =
         static_cast< const Glib::Value<IntRange>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_INT_RANGE,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_INT_RANGE,
         range->get().min, range->get().max, NULL);
   }
   else if (type == Glib::Value<DoubleRange>::value_type())
@@ -90,7 +102,7 @@
      const Glib::Value<DoubleRange>* range =
         static_cast< const Glib::Value<DoubleRange>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_DOUBLE_RANGE,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_DOUBLE_RANGE,
         range->get().min, range->get().max, NULL);
   }
   else if (type == Glib::Value<Fraction>::value_type())
@@ -98,7 +110,7 @@
      const Glib::Value<Fraction>* fract =
         static_cast< const Glib::Value<Fraction>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_FRACTION,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_FRACTION,
         fract->get().num, fract->get().denom, NULL);
   }
   else if (type == Glib::Value<FractionRange>::value_type())
@@ -106,7 +118,7 @@
      const Glib::Value<FractionRange>* range =
         static_cast< const Glib::Value<FractionRange>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_FRACTION_RANGE,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_FRACTION_RANGE,
          range->get().min.num, range->get().min.denom, range->get().max.num,
              range->get().max.denom, NULL);
   }
@@ -115,7 +127,7 @@
      const Glib::Value<Glib::Date>* date =
         static_cast< const Glib::Value<Glib::Date>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_DATE,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_DATE,
          date->get().gobj(), NULL);
   }
   else if (type == Glib::Value<Structure>::value_type())
@@ -123,7 +135,7 @@
      const Glib::Value<Structure>* obj =
         static_cast< const Glib::Value<Structure>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_STRUCTURE,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_STRUCTURE,
         obj->get().gobj(), NULL);
   }
   else if (type == Glib::Value<MiniObject>::value_type())
@@ -131,13 +143,14 @@
      const Glib::Value<MiniObject>* obj =
         static_cast< const Glib::Value<MiniObject>* >(&value);
 
-     gst_structure_set(gobj(), fieldname.c_str(), GST_TYPE_MINI_OBJECT,
+     gst_structure_set(cstructure, fieldname.c_str(), GST_TYPE_MINI_OBJECT,
         obj->get().gobj(), NULL);
   }
-  else 
-    gst_structure_set_value(gobj(), fieldname.c_str(), value.gobj());
-
-  return *this;
+  else
+  {
+    //TODO: Why not just use this instead of all the if/else stuff above? murrayc
+    gst_structure_set_value(cstructure, fieldname.c_str(), value.gobj());
+  }
 }
 
 Structure&

Modified: gstreamermm/trunk/gstreamer/src/structure.hg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/structure.hg	(original)
+++ gstreamermm/trunk/gstreamer/src/structure.hg	Sat May 17 20:34:30 2008
@@ -45,25 +45,14 @@
  */
 class Structure
 {
-  _CLASS_BOXEDTYPE_NCOPY(Structure, GstStructure, NONE, gst_structure_copy, gst_structure_free)
-
+ _CLASS_BOXEDTYPE(Structure, GstStructure, NONE, gst_structure_copy, gst_structure_free)
 public:
-  /** For example,
-   * bool on_foreach(const Glib::QueryQuark& id, const Glib::ValueBase& value);
-   * The foreach function should return true if foreach operation should
-   * continue, false if operation should stop with false.
-   */
-  typedef sigc::slot<bool, const Glib::QueryQuark&, const Glib::ValueBase&> SlotForeach;
 
-  /** For example,
-   * bool on_map(const Glib::QueryQuark& id, Glib::ValueBase& value);
-   * The map function should return true if map operation should continue,
-   * false if operation should stop with false.
-   */
-  typedef sigc::slot<bool, const Glib::QueryQuark&, Glib::ValueBase&> SlotMap;
+  explicit Structure(const Glib::ustring& name);
 
-public:
-  Structure(const Glib::ustring& name);
+  /** Use this to discover if the Structure is a valid object.
+   */
+  operator bool() const;
 
   _WRAP_METHOD(Glib::ustring get_name() const, gst_structure_get_name)
   _WRAP_METHOD(bool has_name(const Glib::ustring& name) const, gst_structure_has_name)
@@ -92,6 +81,9 @@
    */
   Structure& set_field(const Glib::ustring& fieldname, const Glib::ValueBase& value);
 
+  //Only for use inside gstreamermm:
+  static void _set_gstructure_field(GstStructure* cstructure, const Glib::ustring& fieldname, const Glib::ValueBase& value);
+
   /** Removes the field with the given name. If the field with the given name
    * does not exist, the structure is unchanged. Returns this Gst::Structure
    * for continued setting convenience.
@@ -104,6 +96,13 @@
   _WRAP_METHOD(void remove_all_fields(), gst_structure_remove_all_fields)
   _WRAP_METHOD(GType get_field_type(const Glib::ustring& fieldname) const, gst_structure_get_field_type)
 
+  /** For example,
+   * bool on_foreach(const Glib::QueryQuark& id, const Glib::ValueBase& value);
+   * The foreach function should return true if foreach operation should
+   * continue, false if operation should stop with false.
+   */
+  typedef sigc::slot<bool, const Glib::QueryQuark&, const Glib::ValueBase&> SlotForeach;
+
   /** Calls the provided slot once for each field in the Gst::Structure. The
    * slot must not modify the fields. Also see map_in_place().
    *
@@ -229,6 +228,13 @@
    */
   bool get_fraction(const Glib::ustring& fieldname, Gst::Fraction& fraction) const;
 
+  /** For example,
+   * bool on_map(const Glib::QueryQuark& id, Glib::ValueBase& value);
+   * The map function should return true if map operation should continue,
+   * false if operation should stop with false.
+   */
+  typedef sigc::slot<bool, const Glib::QueryQuark&, Glib::ValueBase&> SlotMap;
+
   /** Calls the provided slot once for each field in the Gst::Structure. In
    * contrast to foreach(), the function may modify but not delete the fields.
    * The structure must be mutable.
@@ -239,7 +245,7 @@
    */
   bool map_in_place(const SlotMap& slot);
 
-  _WRAP_METHOD(Glib::ustring nth_field_name(guint index) const, gst_structure_nth_field_name)
+  _WRAP_METHOD(Glib::ustring get_nth_field_name(guint index) const, gst_structure_nth_field_name)
   _WRAP_METHOD(Glib::ustring to_string() const, gst_structure_to_string)
 
   static Structure create_from_string(const Glib::ustring& the_string);

Modified: gstreamermm/trunk/tests/test-caps-structures.cc
==============================================================================
--- gstreamermm/trunk/tests/test-caps-structures.cc	(original)
+++ gstreamermm/trunk/tests/test-caps-structures.cc	Sat May 17 20:34:30 2008
@@ -54,14 +54,19 @@
 
   for (int i = 0; i < 2; i++) {
     Glib::Value<Glib::ustring> v;
-    const Gst::Structure* s = caps->get_structure(i);
-    s->get_field("message", v);
-    std::cout << s->get_name() << ": " << v.get() << std::endl;
+    const Gst::Structure s = caps->get_structure(i);
+    if(s)
+    {
+      s.get_field("message", v);
+      std::cout << s.get_name() << ": " << v.get() << std::endl;
+    }
   }
 
   caps->remove_structure(1);
 
-  std::cout << "Caps structure index 1 = " << caps->get_structure(1)->get_name() << std::endl;
+  const Gst::Structure structure = caps->get_structure(1);
+  if(structure)
+    std::cout << "Caps structure index 1 = " << structure.get_name() << std::endl;
 
   return 0;
 }

Modified: gstreamermm/trunk/tests/test-event-wrap.cc
==============================================================================
--- gstreamermm/trunk/tests/test-event-wrap.cc	(original)
+++ gstreamermm/trunk/tests/test-event-wrap.cc	Sat May 17 20:34:30 2008
@@ -36,7 +36,9 @@
   std::cout << "event is a Gst::EventLatency: " << (bool)event_latency  << std::endl;
   std::cout << "event type name: '" << Gst::get_name(event->get_event_type()) << "'" << std::endl;
 
-  std::cout << "Event structure name: '" << event->get_structure()->get_name() << "'" << std::endl;
+  const Gst::Structure structure = event->get_structure();
+  if(structure)
+    std::cout << "Event structure name: '" << structure.get_name() << "'" << std::endl;
 
   return 0;
 }

Modified: gstreamermm/trunk/tests/test-message-wrap.cc
==============================================================================
--- gstreamermm/trunk/tests/test-message-wrap.cc	(original)
+++ gstreamermm/trunk/tests/test-message-wrap.cc	Sat May 17 20:34:30 2008
@@ -40,7 +40,9 @@
   std::cout << "message is a Gst::MessageWarning: " << (bool)message_warning  << std::endl;
   std::cout << "message type name: '" << Gst::get_name(message->get_message_type()) << "'"  << std::endl;
 
-  std::cout << "Message structure name: '" << message->get_structure()->get_name() << "'" << std::endl;
+  const Gst::Structure structure = message->get_structure();
+  if(structure)
+    std::cout << "Message structure name: '" << structure.get_name() << "'" << std::endl;
 
   return 0;
 }

Modified: gstreamermm/trunk/tests/test-query-wrap.cc
==============================================================================
--- gstreamermm/trunk/tests/test-query-wrap.cc	(original)
+++ gstreamermm/trunk/tests/test-query-wrap.cc	Sat May 17 20:34:30 2008
@@ -36,7 +36,9 @@
   std::cout << "query is a Gst::QueryPosition: " << (bool)query_position  << std::endl;
   std::cout << "query type name: '" << Gst::get_name(query->get_query_type()) << "'" << std::endl;
 
-  std::cout << "Query structure name: '" << query->get_structure()->get_name() << "'" << std::endl;
+  const Gst::Structure structure = query->get_structure();
+  if(structure)
+    std::cout << "Query structure name: '" << structure.get_name() << "'" << std::endl;
 
   return 0;
 }

Modified: gstreamermm/trunk/tools/m4/convert.m4
==============================================================================
--- gstreamermm/trunk/tools/m4/convert.m4	(original)
+++ gstreamermm/trunk/tools/m4/convert.m4	Sat May 17 20:34:30 2008
@@ -2,5 +2,4 @@
 include(convert_glib.m4)
 include(convert_gst.m4)
 include(class_gstminiobject.m4)
-include(class_boxedtype_ncopy.m4)
 include(class_boxedtype_ncopy_extra.m4)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]