Re: Testing Gstmm Element seeking



José Alburquerque wrote:
José Alburquerque wrote:
José Alburquerque wrote:
Murray Cumming wrote:
I think we'll need to have an extra PKG_CONFIG check for examples cflags and libs, and maybe add a --disable-examples configure option. gtkmm has
a --disable-examples option already.


The const references seem odd here:

+  _WRAP_METHOD(bool seek(Format format, SeekFlags flags, const gint64&
position), gst_element_seek_simple)
   _WRAP_METHOD(bool seek(const double& rate, Format format, SeekFlags
flags, SeekType current_type, const gint64& current_position, SeekType
stop_type, const gint64& stop_position), gst_element_seek)

I don't see the point of passing a const refererence when it could just
be passed by value. Could you change that, please?

Sure. I'll also look into the PKG_CONFIG and "--disable-examples" options.

-Jose
I've fixed the references. I also added initial "GstEvent" wrapping (that I had started yesterday). I'm still not sure how to include PKG_CONFIG options for the new example and where to enable the --disable-examples options. Would you help me out a little. Thanks.

Never mind the request for a little help. I'm looking at the automake docs and I think I've almost got this working also. I'll send a final diff as soon as I have this going. Thanks.

I think I've got things working.  Is this ok?

-Jose
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 109)
+++ ChangeLog	(working copy)
@@ -1,3 +1,29 @@
+2007-12-21  José Alburquerque  <jaalburquerque cox com>
+
+	* configure.ac: added --enable-examples option
+	* examples/Makefile.am: added ogg_player_gtkmm to list of directories
+	* examples/ogg_player/main.cc: fixed time output formatting
+	* examples/ogg_player_gtkmm/Makefile.am: added automake compilation
+	file for ogg_player_gtkmm example
+	* examples/ogg_player_gtkmm/PlayerWindow.cc: added source files for
+	* examples/ogg_player_gtkmm/PlayerWindow.h:  for ogg_player_gtkmm
+	* examples/ogg_player_gtkmm/main.cc:         examples
+	* gst/gstmm.h: added <gstmm/query.h> and <gstmm/event.h>
+	* gst/src/Makefile_list_of_hg.am_fragment: added query.hg and event.hg
+	to general hg files
+	* gst/src/caps.hg: made some hidden methods public
+	* gst/src/clock.ccg: renamed get_millesconds() to more appropriate
+	name get_fractional_seconds(); added get_milliseconds(),
+	get_microseconds() and get_nanoseconds()
+	* gst/src/clock.hg: added declarations for get_microseconds(),
+	get_nanoseconds() and get_fractional_seconds()
+	* gst/src/element.hg: renamed seek_simple() method to (overloaded)
+	seek() and fixed seek methods unneeded constant references
+	* gst/src/event.ccg: added new file
+	* gst/src/event.hg: added initial declaration for Gst::Event class
+	* gst/src/query.ccg: added new file
+	* gst/src/query.hg: added initial declaration for Gst::Query class
+
 2007-12-13  José Alburquerque  <jaalburquerque cox com>
 
 	* examples/ogg_player/main.cc: Changed pos and len to type gint64
Index: gst/src/element.hg
===================================================================
--- gst/src/element.hg	(revision 109)
+++ gst/src/element.hg	(working copy)
@@ -89,8 +89,8 @@
   bool query_duration(Format& format) const;
   _WRAP_METHOD(bool query_duration(Format& format, gint64& duration) const, gst_element_query_duration)
 
-  _WRAP_METHOD(bool seek_simple(Format format, SeekFlags flags, const gint64& position), gst_element_seek_simple)
-  _WRAP_METHOD(bool seek(const double& rate, Format format, SeekFlags flags, SeekType current_type, const gint64& current_position, SeekType stop_type, const gint64& stop_position), gst_element_seek)
+  _WRAP_METHOD(bool seek(Format format, SeekFlags flags, gint64 position), gst_element_seek_simple)
+  _WRAP_METHOD(bool seek(double rate, Format format, SeekFlags flags, SeekType current_type, gint64 current_position, SeekType stop_type, gint64 stop_position), gst_element_seek)
 
   _IGNORE(gst_element_link, gst_element_get_compatible_pad, gst_element_link_many)
 
Index: gst/src/query.ccg
===================================================================
--- gst/src/query.ccg	(revision 0)
+++ gst/src/query.ccg	(revision 0)
@@ -0,0 +1,6 @@
+#include <gst/gstquery.h>
+
+namespace Gst
+{
+
+} //namesapce Gst
Index: gst/src/query.hg
===================================================================
--- gst/src/query.hg	(revision 0)
+++ gst/src/query.hg	(revision 0)
@@ -0,0 +1,15 @@
+#include <gstmm/miniobject.h>
+#include <gstmm/structure.h>
+#include <gstmm/wrap.h>
+_PINCLUDE(gstmm/private/miniobject_p.h)
+_DEFS(gstmm,gst)
+
+namespace Gst
+{
+class Query : public MiniObject
+{
+protected:
+  _CLASS_GSTMINIOBJECT(Query, GstQuery, GST_QUERY, Gst::MiniObject, GstMiniObject)
+};
+
+}//namespace Gst
Index: gst/src/event.ccg
===================================================================
--- gst/src/event.ccg	(revision 0)
+++ gst/src/event.ccg	(revision 0)
@@ -0,0 +1,6 @@
+#include <gst/gstevent.h>
+
+namespace Gst
+{
+
+} //namesapce Gst
Index: gst/src/event.hg
===================================================================
--- gst/src/event.hg	(revision 0)
+++ gst/src/event.hg	(revision 0)
@@ -0,0 +1,15 @@
+#include <gstmm/miniobject.h>
+#include <gstmm/structure.h>
+#include <gstmm/wrap.h>
+_PINCLUDE(gstmm/private/miniobject_p.h)
+_DEFS(gstmm,gst)
+
+namespace Gst
+{
+class Event : public MiniObject
+{
+protected:
+  _CLASS_GSTMINIOBJECT(Event, GstEvent, GST_EVENT, Gst::MiniObject, GstMiniObject)
+};
+
+}//namespace Gst
Index: gst/src/caps.hg
===================================================================
--- gst/src/caps.hg	(revision 109)
+++ gst/src/caps.hg	(working copy)
@@ -8,12 +8,12 @@
 
 class Caps 
 {
-public:
-
   _CLASS_OPAQUE_REFCOUNTED(Caps, GstCaps, NONE, gst_caps_ref, gst_caps_unref)
   _IGNORE(gst_caps_ref, gst_caps_unref)
 
+public:
   //TODO: Why doesn't this use _WRAP_CREATE()?
+  //ANS: Could it be because there are two void methods that create a Caps? -Jose
   static Glib::RefPtr<Caps> create_empty();
   static Glib::RefPtr<Caps> create_any();
   static Glib::RefPtr<Caps> create_full(Structure&);
Index: gst/src/clock.ccg
===================================================================
--- gst/src/clock.ccg	(revision 109)
+++ gst/src/clock.ccg	(working copy)
@@ -25,6 +25,24 @@
 guint get_milliseconds(ClockTime time)
 {
   return GST_CLOCK_TIME_IS_VALID (time) ? \
+        (guint) ((((GstClockTime)(time)) / GST_MSECOND) % 1000) : 999;
+}
+
+guint get_microseconds(ClockTime time)
+{
+  return GST_CLOCK_TIME_IS_VALID (time) ? \
+        (guint) ((((GstClockTime)(time)) / GST_USECOND) % 1000) : 999;
+}
+
+guint get_nanoseconds(ClockTime time)
+{
+  return GST_CLOCK_TIME_IS_VALID (time) ? \
+        (guint) ((((GstClockTime)(time)) / GST_NSECOND) % 1000) : 999;
+}
+
+guint get_fractional_seconds(ClockTime time)
+{
+  return GST_CLOCK_TIME_IS_VALID (time) ? \
         (guint) (((GstClockTime)(time)) % GST_SECOND) : 999999999;
 }
 
Index: gst/src/clock.hg
===================================================================
--- gst/src/clock.hg	(revision 109)
+++ gst/src/clock.hg	(working copy)
@@ -26,6 +26,9 @@
 guint get_minutes(ClockTime time);
 guint get_seconds(ClockTime time);
 guint get_milliseconds(ClockTime time);
+guint get_microseconds(ClockTime time);
+guint get_nanoseconds(ClockTime time);
+guint get_fractional_seconds(ClockTime time);
 
 class Clock : public Object
 {
Index: gst/src/Makefile_list_of_hg.am_fragment
===================================================================
--- gst/src/Makefile_list_of_hg.am_fragment	(revision 109)
+++ gst/src/Makefile_list_of_hg.am_fragment	(working copy)
@@ -4,8 +4,9 @@
 
 files_posix_hg =
 files_win32_hg =
-files_general_hg = enums.hg caps.hg clock.hg element.hg error.hg iterator.hg format.hg pad.hg			\
-	padtemplate.hg structure.hg systemclock.hg xml.hg bin.hg pipeline.hg bus.hg message.hg
+files_general_hg = enums.hg caps.hg clock.hg element.hg error.hg event.hg \
+	iterator.hg format.hg pad.hg padtemplate.hg query.hg structure.hg \
+	systemclock.hg xml.hg bin.hg pipeline.hg bus.hg message.hg
 
 files_general_deprecated_hg =
 
Index: gst/gstmm.h
===================================================================
--- gst/gstmm.h	(revision 109)
+++ gst/gstmm.h	(working copy)
@@ -4,11 +4,13 @@
 #include <gstmm/clock.h>
 #include <gstmm/element.h>
 #include <gstmm/error.h>
+#include <gstmm/event.h>
 #include <gstmm/format.h>
 #include <gstmm/iterator.h>
 #include <gstmm/object.h>
 #include <gstmm/pad.h>
 #include <gstmm/pipeline.h>
+#include <gstmm/query.h>
 #include <gstmm/structure.h>
 #include <gstmm/systemclock.h>
 
Index: configure.ac
===================================================================
--- configure.ac	(revision 109)
+++ configure.ac	(working copy)
@@ -198,7 +198,7 @@
               [AC_HELP_STRING([--enable-use-deprecations],
                               [warn about deprecated usages [default=no]])],,
               [enable_deprecations=no])
-              
+
 if test "x$enable_use_deprecations" = "xyes"; then
    DISABLE_DEPRECATED_CFLAGS="\
 -DG_DISABLE_DEPRECATED \
@@ -220,7 +220,12 @@
 AC_MSG_WARN([Deprecated API will not be built, breaking backwards-compatibility. Do not use this build for distribution packages.])
 fi
 
+AC_ARG_ENABLE(examples,
+  [AC_HELP_STRING([--enable-examples],
+    [enable compilation of example programs [default=yes]])],
+  [enable_examples=$enableval], [enable_examples=yes])
 
+if test "x$enable_examples" = "xyes"; then
 EXAMPLE_SUBDIR="examples"
 AC_CONFIG_FILES([
     examples/Makefile
@@ -228,8 +233,12 @@
     examples/optiongroup/Makefile
     examples/element_link/Makefile
     examples/ogg_player/Makefile
+    examples/ogg_player_gtkmm/Makefile
     ])
 AC_SUBST(EXAMPLE_SUBDIR)
+else
+EXAMPLE_SUBDIR=""
+fi
 
 DEMO_SUBDIR=""
 AC_SUBST(DEMO_SUBDIR)
Index: examples/ogg_player_gtkmm/PlayerWindow.cc
===================================================================
--- examples/ogg_player_gtkmm/PlayerWindow.cc	(revision 0)
+++ examples/ogg_player_gtkmm/PlayerWindow.cc	(revision 0)
@@ -0,0 +1,303 @@
+//           PlayerWindow.cc
+//  Tue Dec 18 18:47:47 2007
+//  Copyright  2007  The gstmm development team
+//  <gtkmm-list gnome org>
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
+
+#include <gtkmm/stock.h>
+#include <gtkmm/filechooserdialog.h>
+#include <gstmm/clock.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include "PlayerWindow.h"
+
+PlayerWindow::PlayerWindow(Glib::RefPtr<Gst::Element> sourceElement,
+                                Glib::RefPtr<Gst::Pipeline> mainPipeline) :
+vBox(false, 5),
+progressLabel("000:00:00.000000000 / 000:00:00.000000000"),
+playButton(Gtk::Stock::MEDIA_PLAY),
+pauseButton(Gtk::Stock::MEDIA_PAUSE),
+stopButton(Gtk::Stock::MEDIA_STOP),
+rewindButton(Gtk::Stock::MEDIA_REWIND),
+forwardButton(Gtk::Stock::MEDIA_FORWARD),
+openButton(Gtk::Stock::OPEN)
+{
+    set_title("Gstmm Ogg Player Example");
+
+    add(vBox);
+    vBox.pack_start(progressLabel);
+    vBox.pack_start(progressScale);
+    vBox.pack_start(buttonBox);
+
+    progressLabel.set_alignment(Gtk::ALIGN_CENTER);
+
+    progressScale.set_range(0, 1);
+    progressScale.set_draw_value(false);
+    progressScale.signal_change_value().connect(
+                sigc::mem_fun(*this, &PlayerWindow::on_scale_value_changed));
+
+    buttonBox.pack_start(playButton);
+    buttonBox.pack_start(pauseButton);
+    buttonBox.pack_start(stopButton);
+    buttonBox.pack_start(rewindButton);
+    buttonBox.pack_start(forwardButton);
+    buttonBox.pack_start(openButton);
+
+    playButton.signal_clicked().connect(sigc::mem_fun(*this,
+                                          &PlayerWindow::on_play));
+    pauseButton.signal_clicked().connect(sigc::mem_fun(*this,
+                                          &PlayerWindow::on_pause));
+    stopButton.signal_clicked().connect(sigc::mem_fun(*this,
+                                          &PlayerWindow::on_stop));
+    rewindButton.signal_clicked().connect(sigc::mem_fun(*this,
+                                          &PlayerWindow::on_rewind));
+    forwardButton.signal_clicked().connect(sigc::mem_fun(*this,
+                                          &PlayerWindow::on_forward));
+    openButton.signal_clicked().connect(sigc::mem_fun(*this,
+                                          &PlayerWindow::on_open));
+
+	// get the bus from the pipeline
+	Glib::RefPtr<Gst::Bus> bus = mainPipeline->get_bus();
+
+	// Add a bus watch to receive messages from pipeline's bus
+	bus->add_watch( sigc::mem_fun( *this, &PlayerWindow::on_bus_message) );
+
+    progressScale.set_sensitive(false);
+    playButton.set_sensitive(false);
+    pauseButton.set_sensitive(false);
+    stopButton.set_sensitive(false);
+    rewindButton.set_sensitive(false);
+    forwardButton.set_sensitive(false);
+
+    this->sourceElement = sourceElement;
+    this->mainPipeline = mainPipeline;
+
+    show_all_children();
+    pauseButton.hide();
+}
+
+// This function is used to receive asynchronous messages from mainPipeline's bus
+bool PlayerWindow::on_bus_message(const Glib::RefPtr<Gst::Bus>& bus,
+					const Glib::RefPtr<Gst::Message>& message)
+{
+    switch (message->get_message_type())
+    {
+        case Gst::MESSAGE_EOS:
+            on_stop();
+            break;
+        case Gst::MESSAGE_ERROR:
+        {
+            Glib::RefPtr<Gst::MessageError> msgError =
+                Glib::RefPtr<Gst::MessageError>::cast_dynamic(message);
+            if(msgError)
+            {
+                Glib::Error err;
+                std::string debug; //TODO: Maybe this should be an optional parameter.
+                msgError->parse(err, debug);
+                std::cerr << "Error: " << err.what() << std::endl;
+            }
+            else
+                std::cerr << "Error." << std::endl;
+
+            on_stop();
+            break;
+        }
+        default:
+        {
+        //std::cout << "debug: on_bus_message: unhandled message=" << G_OBJECT_TYPE_NAME(message->gobj()) << std::endl;
+        }
+        break;
+    }
+
+    return true;
+}
+
+void PlayerWindow::on_play(void)
+{
+    progressScale.set_sensitive(true);
+    playButton.set_sensitive(false);
+    pauseButton.set_sensitive(true);
+    stopButton.set_sensitive(true);
+    rewindButton.set_sensitive(true);
+    forwardButton.set_sensitive(true);
+    openButton.set_sensitive(false);
+
+    playButton.hide();
+    pauseButton.show();
+
+	// Call update_stream_progress function at a 200ms
+	// interval to regularly update the position of the stream
+	progressConnection = Glib::signal_timeout().connect(sigc::mem_fun(*this,
+                             &PlayerWindow::update_stream_progress), 200);
+
+    // set Gstmm pipeline to play mode
+	mainPipeline->set_state(Gst::STATE_PLAYING);
+}
+ 
+void PlayerWindow::on_pause(void)
+{
+    playButton.set_sensitive(true);
+    pauseButton.set_sensitive(false);
+
+    pauseButton.hide();
+    playButton.show();
+
+    // disconnect progress callback
+    progressConnection.disconnect();
+    
+    // set Gstmm pipeline to pause mode
+	mainPipeline->set_state(Gst::STATE_PAUSED);
+}
+ 
+void PlayerWindow::on_stop(void)
+{
+    progressScale.set_sensitive(false);
+    playButton.set_sensitive(true);
+    pauseButton.set_sensitive(false);
+    stopButton.set_sensitive(false);
+    rewindButton.set_sensitive(false);
+    forwardButton.set_sensitive(false);
+    openButton.set_sensitive(true);
+
+    pauseButton.hide();
+    playButton.show();
+
+    // disconnect progress callback
+    progressConnection.disconnect();
+
+    // set Gstmm pipeline to inactive mode
+	mainPipeline->set_state(Gst::STATE_NULL);
+    display_label_progress(0, duration);
+    progressScale.set_value(0);
+}
+
+bool PlayerWindow::on_scale_value_changed(Gtk::ScrollType type, double value)
+{
+    gint64 newPos = gint64(value * duration);
+
+    if (mainPipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, newPos))
+        display_label_progress(newPos, duration);
+    else
+        std::cerr << "Could not seek!" << std::endl;
+}
+
+void PlayerWindow::on_rewind(void)
+{
+    static const gint64 skipAmount = GST_SECOND * 2;
+
+    gint64 pos;
+    Gst::Format fmt = Gst::FORMAT_TIME;
+
+    if (mainPipeline->query_position(fmt, pos))
+    {
+        gint64 newPos = (pos > skipAmount) ? (pos - skipAmount) : 0;
+
+        if (mainPipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, newPos)) {
+            display_label_progress(newPos, duration);
+            progressScale.set_value(double(newPos) / duration);
+        }
+        else
+            std::cerr << "Could not seek!" << std::endl;
+    }
+}
+
+void PlayerWindow::on_forward(void)
+{
+    static const gint64 skipAmount = GST_SECOND * 3;
+
+    gint64 pos;
+    Gst::Format fmt = Gst::FORMAT_TIME;
+
+    if (mainPipeline->query_position(fmt, pos))
+    {
+        gint64 newPos = ((pos + skipAmount) < duration) ? (pos + skipAmount) :
+            duration;
+
+        if (mainPipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, newPos))
+        {
+            progressScale.set_value(double(newPos) / duration);
+            display_label_progress(newPos, duration);
+        }
+        else
+            std::cerr << "Could not seek!" << std::endl;
+    }
+}
+
+void PlayerWindow::on_open(void)
+{
+    static Glib::ustring workingDir = Glib::get_home_dir();
+    
+    Gtk::FileChooserDialog chooser(*this,
+                        "Select Ogg file", Gtk::FILE_CHOOSER_ACTION_OPEN);
+
+    Gtk::FileFilter filter;
+    filter.add_mime_type("application/ogg");
+    filter.set_name("Ogg files");
+    
+    chooser.set_filter(filter);
+
+    chooser.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+    chooser.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
+    
+    chooser.set_current_folder(workingDir);
+    
+    int response = chooser.run();
+    
+    if (response == Gtk::RESPONSE_OK) {
+        workingDir = chooser.get_current_folder();
+
+        // Set filename property on the file source. Also add a message handler:
+        sourceElement->set_property("location", chooser.get_filename());
+        set_title(Glib::filename_display_basename(chooser.get_filename()));
+
+        playButton.set_sensitive(true);
+        display_label_progress(0, 0);
+    }
+}
+
+bool PlayerWindow::update_stream_progress(void)
+{
+    Gst::Format fmt = Gst::FORMAT_TIME;
+    gint64 pos = 0;
+
+    if (mainPipeline->query_position(fmt, pos)
+    && mainPipeline->query_duration(fmt, duration)) {
+        progressScale.set_value(double(pos) / duration);
+        display_label_progress(pos, duration);
+    }
+
+   return true;
+}
+
+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);
+
+    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);
+
+    progressLabel.set_text(locationStream.str() + " / " + durationStream.str());
+}
Index: examples/ogg_player_gtkmm/main.cc
===================================================================
--- examples/ogg_player_gtkmm/main.cc	(revision 0)
+++ examples/ogg_player_gtkmm/main.cc	(revision 0)
@@ -0,0 +1,97 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * main.cc
+ * Copyright (C) The gstmm development team 2007 <gtkmm-list gnome org>
+ * 
+ * main.cc is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * main.cc 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gtkmm/main.h>
+#include <gstmm/init.h>
+#include <gstmm/element.h>
+#include <gstmm/pipeline.h>
+#include <iostream>
+#include "PlayerWindow.h"
+
+Glib::RefPtr<Gst::Pipeline> pipeline;
+Glib::RefPtr<Gst::Element> decoder;
+
+void on_parser_pad_added(const Glib::RefPtr<Gst::Pad>& newPad)
+{
+    // We can now link this pad with the audio decoder
+    Glib::RefPtr<Gst::Pad> sinkPad = decoder->get_pad("sink");
+    newPad->link(sinkPad);
+}
+
+int
+main (int argc, char *argv[])
+{
+    Gtk::Main kit(argc, argv);
+    Gst::init(argc, argv);
+
+    // Create the pipeline
+    pipeline = Gst::Pipeline::create("audio-player");
+
+    // Create the elements
+    // Reads file from disk
+    Glib::RefPtr<Gst::Element> source = Gst::Element::create("filesrc", "file-source");
+
+    // Parses the ogg streams into elementary streams (note that an ogg file may contain a video stream too)
+    Glib::RefPtr<Gst::Element> parser = Gst::Element::create("oggdemux", "ogg-parser");
+
+    // Decodes a vorbis stream
+    decoder = Gst::Element::create("vorbisdec", "vorbis-decoder");
+
+    // Converts audio() to a format which can be used by the next element
+    Glib::RefPtr<Gst::Element> conv = Gst::Element::create("audioconvert", "converter");
+
+    // Outputs sound to an ALSA audio device
+    Glib::RefPtr<Gst::Element> sink = Gst::Element::create("alsasink", "alsa-output");
+
+    if (!pipeline || !source || !parser || !decoder || !conv || !sink)
+    {
+        std::cerr << "One element could not be created" << std::endl;
+        return -1;
+    }
+
+    // Put all elements in a pipeline:
+    try
+    {
+        pipeline->add(source)->add(parser)->add(decoder)->add(conv)->add(sink);
+    }
+    catch(const Glib::Error& ex)
+    {
+        std::cerr << "Error while adding elements to the pipeline: " << ex.what() << std::endl;
+        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) );
+
+    decoder->link(conv)->link(sink);
+
+    PlayerWindow mainWindow(source, pipeline);
+
+    kit.run(mainWindow);
+
+    // Clean up nicely:
+    pipeline->set_state(Gst::STATE_NULL);
+
+    return 0;
+}
Index: examples/ogg_player_gtkmm/Makefile.am
===================================================================
--- examples/ogg_player_gtkmm/Makefile.am	(revision 0)
+++ examples/ogg_player_gtkmm/Makefile.am	(revision 0)
@@ -0,0 +1,7 @@
+include $(top_srcdir)/examples/Makefile.am_fragment
+
+#Build the executable, but don't install it.
+noinst_PROGRAMS = oggplayer
+oggplayer_SOURCES = main.cc PlayerWindow.cc
+oggplayer_CXXFLAGS = `pkg-config gtkmm-2.4 --cflags` $(AM_CXXFLAGS)
+oggplayer_LDFLAGS = `pkg-config gtkmm-2.4 --libs`
Index: examples/ogg_player_gtkmm/PlayerWindow.h
===================================================================
--- examples/ogg_player_gtkmm/PlayerWindow.h	(revision 0)
+++ examples/ogg_player_gtkmm/PlayerWindow.h	(revision 0)
@@ -0,0 +1,75 @@
+/***************************************************************************
+ *            PlayerWindow.h
+ *
+ *  Tue Dec 18 18:48:33 2007
+ *  Copyright  2007  The gstmm development team
+ *  <gtkmm-list gnome org>
+ ****************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program 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 General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
+ */
+ 
+#ifndef _PLAYERWINDOW_H
+#define _PLAYERWINDOW_H
+
+#include <gtkmm/window.h>
+#include <gtkmm/box.h>
+#include <gtkmm/buttonbox.h>
+#include <gtkmm/label.h>
+#include <gtkmm/button.h>
+#include <gtkmm/scale.h>
+#include <gstmm/element.h>
+#include <gstmm/pipeline.h>
+
+class PlayerWindow : public Gtk::Window
+{
+public:
+    PlayerWindow(Glib::RefPtr<Gst::Element> sourceElement,
+                 Glib::RefPtr<Gst::Pipeline> mainPipeline);
+protected:
+    Gtk::VBox vBox;
+    Gtk::HButtonBox buttonBox;
+    Gtk::Label progressLabel;
+    Gtk::HScale progressScale;
+    Gtk::Button playButton;
+    Gtk::Button pauseButton;
+    Gtk::Button stopButton;
+    Gtk::Button rewindButton;
+    Gtk::Button forwardButton;
+    Gtk::Button openButton;
+protected:
+    virtual bool on_bus_message(const Glib::RefPtr<Gst::Bus>& bus,
+                            const Glib::RefPtr<Gst::Message>& message);
+    virtual void on_play(void);
+    virtual void on_pause(void);
+    virtual void on_stop(void);
+    virtual bool on_scale_value_changed(Gtk::ScrollType type, double value);
+    virtual void on_rewind(void);
+    virtual void on_forward(void);
+    virtual void on_open(void);
+protected:
+    bool update_stream_progress(void);
+    void display_label_progress(gint64 pos, gint64 len);
+private:
+    Glib::RefPtr<Gst::Element> sourceElement;
+    Glib::RefPtr<Gst::Pipeline> mainPipeline;
+    gint64 duration;
+    sigc::connection progressConnection;
+};
+
+#endif /* _PLAYERWINDOW_H */
+
+ 
Index: examples/ogg_player/main.cc
===================================================================
--- examples/ogg_player/main.cc	(revision 109)
+++ examples/ogg_player/main.cc	(working copy)
@@ -16,16 +16,18 @@
  if (pipeline->query_position(fmt, pos)
    && pipeline->query_duration(fmt, len)) {
 
-   std::cout << "Time: " << std::setfill('0') << 
+   std::cout << std::right << "Time: " << 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) << Gst::get_milliseconds(pos);
+     std::setw(9) << std::left << Gst::get_fractional_seconds(pos);
 
-   std::cout << "/" << std::setw(3) << Gst::get_hours(len) << ":" <<
+   std::cout << std::right << "/" <<
+     std::setw(3) << Gst::get_hours(len) << ":" <<
      std::setw(2) << Gst::get_minutes(len) << ":" <<
      std::setw(2) << Gst::get_seconds(len) << "." <<
-     std::setw(9) << Gst::get_milliseconds(len) << std::endl << std::flush;
+     std::setw(9) << std::left << Gst::get_fractional_seconds(len) <<
+     std::endl << std::flush;
  }
 
  return true;
Index: examples/Makefile.am
===================================================================
--- examples/Makefile.am	(revision 109)
+++ examples/Makefile.am	(working copy)
@@ -1,4 +1,4 @@
-example_dirs = init element_link ogg_player optiongroup
+example_dirs = init element_link ogg_player ogg_player_gtkmm optiongroup
 
 SUBDIRS = $(example_dirs)
 EXTRA_DIST = README Makefile.am_fragment


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