ekiga r7117 - in trunk: . lib/engine/components/gstreamer po



Author: jpuydt
Date: Sun Sep 28 12:19:51 2008
New Revision: 7117
URL: http://svn.gnome.org/viewvc/ekiga?rev=7117&view=rev

Log:
New gstreamer audio output code

Added:
   trunk/lib/engine/components/gstreamer/gst-audiooutput.cpp
   trunk/lib/engine/components/gstreamer/gst-audiooutput.h
Modified:
   trunk/ChangeLog
   trunk/configure.ac
   trunk/lib/engine/components/gstreamer/Makefile.am
   trunk/lib/engine/components/gstreamer/gst-main.cpp
   trunk/po/POTFILES.in

Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac	(original)
+++ trunk/configure.ac	Sun Sep 28 12:19:51 2008
@@ -514,11 +514,15 @@
   PKG_CHECK_MODULES([GSTREAMER], [gstreamer-plugins-base-0.10 gstreamer-interfaces-0.10])
   CPPFLAGS_save="$CPPFLAGS"
   CPPFLAGS="$CPPFLAGS $GSTREAMER_CFLAGS"
+  AC_CHECK_HEADER(gst/app/gstappbuffer.h,,found_gstreamer=no)
   AC_CHECK_HEADER(gst/app/gstappsink.h,,found_gstreamer=no)
+  AC_CHECK_HEADER(gst/app/gstappsrc.h,,found_gstreamer=no)
   CPPFLAGS="$CPPFLAGS_save"
   LIBS_save="$LIBS"
   LIBS="$LIBS $GSTREAMER_LIBS"
+  AC_CHECK_LIB(gstapp-0.10,gst_app_buffer_new,,found_gstreamer=no)
   AC_CHECK_LIB(gstapp-0.10,gst_app_sink_pull_buffer,,found_gstreamer=no)
+  AC_CHECK_LIB(gstapp-0.10,gst_app_src_push_buffer,,found_gstreamer=no)
   LIBS="$LIBS_save"
 
   if test "x$found_gstreamer" = "xno"; then

Modified: trunk/lib/engine/components/gstreamer/Makefile.am
==============================================================================
--- trunk/lib/engine/components/gstreamer/Makefile.am	(original)
+++ trunk/lib/engine/components/gstreamer/Makefile.am	Sun Sep 28 12:19:51 2008
@@ -19,6 +19,8 @@
 	$(gstreamer_dir)/gst-videoinput.h \
 	$(gstreamer_dir)/gst-videoinput.cpp \
 	$(gstreamer_dir)/gst-audioinput.h \
-	$(gstreamer_dir)/gst-audioinput.cpp
+	$(gstreamer_dir)/gst-audioinput.cpp \
+	$(gstreamer_dir)/gst-audiooutput.h \
+	$(gstreamer_dir)/gst-audiooutput.cpp
 
 libgmgstreamer_la_LDFLAGS = -export-dynamic -no-undefined $(SIGC_LIBS) $(GSTREAMER_LIBS) $(PTLIB_LIBS)

Added: trunk/lib/engine/components/gstreamer/gst-audiooutput.cpp
==============================================================================
--- (empty file)
+++ trunk/lib/engine/components/gstreamer/gst-audiooutput.cpp	Sun Sep 28 12:19:51 2008
@@ -0,0 +1,319 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2008 Damien Sandras
+ *
+ * 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 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                         gst-audiooutput.cpp  -  description
+ *                         ------------------------------------
+ *   begin                : Sat 27 September 2008
+ *   copyright            : (C) 2008 by Julien Puydt
+ *   description          : Gstreamer audio output code
+ *
+ */
+
+#include "config.h"
+
+#include "gst-audiooutput.h"
+
+#include <gst/interfaces/propertyprobe.h>
+#include <gst/app/gstappsrc.h>
+#include <gst/app/gstappbuffer.h>
+
+#include <string.h>
+
+GST::AudioOutputManager::AudioOutputManager ()
+{
+  detect_devices ();
+}
+
+GST::AudioOutputManager::~AudioOutputManager ()
+{
+}
+
+void
+GST::AudioOutputManager::get_devices (std::vector<Ekiga::AudioOutputDevice>& devices)
+{
+  detect_devices ();
+
+  for (std::map<std::string, std::string>::const_iterator iter
+	 = devices_by_name.begin ();
+       iter != devices_by_name.end ();
+       ++iter) {
+
+    Ekiga::AudioOutputDevice device;
+    device.type = "GStreamer";
+    device.source = "GStreamer";
+    device.name = iter->first;
+    devices.push_back (device);
+  }
+}
+
+bool
+GST::AudioOutputManager::set_device (Ekiga::AudioOutputPS ps,
+				     const Ekiga::AudioOutputDevice& device)
+{
+  bool result = false;
+
+  if (device.type == "GStreamer"
+      && device.source == "GStreamer"
+      && devices_by_name.find (device.name) != devices_by_name.end ()) {
+
+    unsigned ii = (ps == Ekiga::primary)?0:1;
+    current_state[ii].opened = false;
+    current_state[ii].device = device;
+    result = true;
+  }
+  return result;
+}
+
+bool
+GST::AudioOutputManager::open (Ekiga::AudioOutputPS ps,
+			       unsigned channels,
+			       unsigned samplerate,
+			       unsigned bits_per_sample)
+{
+  bool result = false;
+  unsigned ii = (ps == Ekiga::primary)?0:1;
+  gchar* command = NULL;
+  GError* error = NULL;
+  GstState current;
+
+  command = g_strdup_printf ("appsrc max_buffers=2 drop=true"
+			     " caps=audio/x-raw-int"
+			     ",rate=%d"
+			     ",channels=%d"
+			     ",width=%d"
+			     " name=ekiga_src"
+			     " ! %s",
+			     samplerate, channels, bits_per_sample,
+			     devices_by_name[current_state[ii].device.name].c_str ());
+  g_print ("Pipeline: %s\n", command);
+  pipeline[ii] = gst_parse_launch (command, &error);
+
+  if (error == NULL) {
+
+    (void)gst_element_set_state (pipeline[ii], GST_STATE_PLAYING);
+
+    // this will make us wait so we can return the right value...
+    (void)gst_element_get_state (pipeline[ii],
+				 &current,
+				 NULL,
+				 GST_SECOND);
+
+    if (current != GST_STATE_PLAYING) {
+
+      gst_element_set_state (pipeline[ii], GST_STATE_NULL);
+      gst_object_unref (GST_OBJECT (pipeline[ii]));
+      pipeline[ii] = NULL;
+      result = false;
+    } else {
+
+      Ekiga::AudioOutputSettings settings;
+      GstElement* volume = NULL;
+      gfloat val;
+
+      volume = gst_bin_get_by_name (GST_BIN (pipeline[ii]), "ekiga_volume");
+      if (volume != NULL) {
+
+	g_object_get (G_OBJECT (volume),
+		      "volume", &val,
+		      NULL);
+	settings.volume = (unsigned)(255*val);
+	settings.modifyable = true;
+	g_object_unref (volume);
+      } else {
+
+	settings.modifyable = false;
+      }
+      current_state[ii].channels = channels;
+      current_state[ii].samplerate = samplerate;
+      current_state[ii].bits_per_sample = bits_per_sample;
+      device_opened.emit (ps, current_state[ii].device, settings);
+      result = true;
+    }
+
+  } else {
+
+    g_error_free (error);
+    result = false;
+  }
+
+  g_free (command);
+
+  current_state[ii].opened = result;
+  return result;
+}
+
+void
+GST::AudioOutputManager::close (Ekiga::AudioOutputPS ps)
+{
+  unsigned ii = (ps == Ekiga::primary)?0:1;
+  if (pipeline[ii] != NULL) {
+
+    gst_element_set_state (pipeline[ii], GST_STATE_NULL);
+    g_object_unref (pipeline[ii]);
+    pipeline[ii] = NULL;
+    device_closed.emit (ps, current_state[ii].device);
+  }
+  current_state[ii].opened = false;
+}
+
+void
+GST::AudioOutputManager::set_buffer_size (Ekiga::AudioOutputPS /*ps*/,
+					  unsigned /*buffer_size*/,
+					  unsigned /*num_buffers*/)
+{
+  // FIXME: do I care?
+}
+
+bool
+GST::AudioOutputManager::set_frame_data (Ekiga::AudioOutputPS ps,
+					 const char* data,
+					 unsigned size,
+					 unsigned& written)
+{
+  bool result = false;
+  unsigned ii = (ps == Ekiga::primary)?0:1;
+  gchar* tmp = NULL;
+  GstBuffer* buffer = NULL;
+  GstElement* src = NULL;
+
+  written = 0;
+
+  g_return_val_if_fail (GST_IS_BIN (pipeline[ii]), false);
+
+  src = gst_bin_get_by_name (GST_BIN (pipeline[ii]), "ekiga_src");
+
+  if (src != NULL) {
+
+    tmp = (gchar*)g_malloc (size);
+    memcpy (tmp, data, size);
+    buffer = gst_app_buffer_new (tmp, size,
+				 (GstAppBufferFinalizeFunc)g_free, tmp);
+    gst_app_src_push_buffer (GST_APP_SRC (src), buffer);
+    written = size;
+    result = true;
+    gst_buffer_unref (buffer);
+    g_object_unref (src);
+  }
+
+  return result;
+}
+
+void
+GST::AudioOutputManager::set_volume (Ekiga::AudioOutputPS ps,
+				     unsigned valu)
+{
+  unsigned ii = (ps == Ekiga::primary)?0:1;
+  GstElement* volume = NULL;
+  gfloat valf;
+
+  valf = valu / 255.0;
+
+  volume = gst_bin_get_by_name (GST_BIN (pipeline[ii]), "ekiga_volume");
+  if (volume != NULL) {
+
+    g_object_set (G_OBJECT (volume),
+		  "volume", valf,
+		  NULL);
+    g_object_unref (volume);
+  }
+}
+
+bool
+GST::AudioOutputManager::has_device (const std::string& /*source*/,
+				     const std::string& device_name,
+				     Ekiga::AudioOutputDevice& /*device*/)
+{
+  return (devices_by_name.find (device_name) != devices_by_name.end ());
+}
+
+void
+GST::AudioOutputManager::detect_devices ()
+{
+  devices_by_name.clear ();
+  detect_fakesink_devices ();
+  detect_alsasink_devices ();
+}
+
+void
+GST::AudioOutputManager::detect_fakesink_devices ()
+{
+  GstElement* elt = NULL;
+
+  elt = gst_element_factory_make ("fakesink", "fakesinkpresencetest");
+
+  if (elt != NULL) {
+
+    devices_by_name[_("Silent")] = "fakesink";
+    gst_object_unref (GST_OBJECT (elt));
+  }
+}
+
+void
+GST::AudioOutputManager::detect_alsasink_devices ()
+{
+  GstElement* elt = NULL;
+
+  elt = gst_element_factory_make ("alsasink", "alsasinkpresencetest");
+
+  if (elt != NULL) {
+
+    GstPropertyProbe* probe = NULL;
+    const GParamSpec* pspec = NULL;
+    GValueArray* array = NULL;
+
+    gst_element_set_state (elt, GST_STATE_PAUSED);
+    probe = GST_PROPERTY_PROBE (elt);
+    pspec = gst_property_probe_get_property (probe, "device");
+
+    array = gst_property_probe_probe_and_get_values (probe, pspec);
+    if (array != NULL) {
+
+      for (guint index = 0; index < array->n_values; index++) {
+
+	GValue* device = NULL;
+	gchar* name = NULL;
+	gchar* descr = NULL;
+
+	device = g_value_array_get_nth (array, index);
+	g_object_set_property (G_OBJECT (elt), "device", device);
+	g_object_get (G_OBJECT (elt), "device-name", &name, NULL);
+	descr = g_strdup_printf (" volume name=ekiga_volume ! alsasink device=%s",
+				 g_value_get_string (device));
+
+	devices_by_name[name] = descr;
+	g_free (name);
+	g_free (descr);
+      }
+      g_value_array_free (array);
+    }
+
+    gst_element_set_state (elt, GST_STATE_NULL);
+    gst_object_unref (GST_OBJECT (elt));
+  }
+}

Added: trunk/lib/engine/components/gstreamer/gst-audiooutput.h
==============================================================================
--- (empty file)
+++ trunk/lib/engine/components/gstreamer/gst-audiooutput.h	Sun Sep 28 12:19:51 2008
@@ -0,0 +1,97 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2008 Damien Sandras
+ *
+ * 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 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                         gst-audiooutput.h  -  description
+ *                         ------------------------------------
+ *   begin                : Sat 27 September 2008
+ *   copyright            : (C) 2008 by Julien Puydt
+ *   description          : Gstreamer audio output code
+ *
+ */
+
+#ifndef __GST_AUDIOOUTPUT_H__
+#define __GST_AUDIOOUTPUT_H__
+
+#include "audiooutput-manager.h"
+#include <gst/gst.h>
+
+#include <map>
+
+namespace GST
+{
+  class AudioOutputManager: public Ekiga::AudioOutputManager
+  {
+  public:
+
+    AudioOutputManager ();
+
+    ~AudioOutputManager ();
+
+    void get_devices (std::vector<Ekiga::AudioOutputDevice>& devices);
+
+    bool set_device (Ekiga::AudioOutputPS ps,
+		     const Ekiga::AudioOutputDevice& device);
+
+    bool open (Ekiga::AudioOutputPS ps,
+	       unsigned channels,
+	       unsigned samplerate,
+	       unsigned bits_per_sample);
+
+    void close (Ekiga::AudioOutputPS ps);
+
+    void set_buffer_size (Ekiga::AudioOutputPS ps,
+			  unsigned buffer_size,
+			  unsigned num_buffers);
+
+    bool set_frame_data (Ekiga::AudioOutputPS ps,
+			 const char* data,
+			 unsigned size,
+			 unsigned& written);
+
+    void set_volume (Ekiga::AudioOutputPS ps,
+		     unsigned volume);
+
+    bool has_device (const std::string& source,
+		     const std::string& device_name,
+		     Ekiga::AudioOutputDevice& device);
+  private:
+
+    void detect_devices ();
+    void detect_fakesink_devices ();
+    void detect_alsasink_devices ();
+
+    /* we take a user-readable name, and get the string describing
+     * the actual device */
+    std::map<std::string, std::string> devices_by_name;
+
+    GstElement* pipeline[2];
+  };
+};
+
+#endif

Modified: trunk/lib/engine/components/gstreamer/gst-main.cpp
==============================================================================
--- trunk/lib/engine/components/gstreamer/gst-main.cpp	(original)
+++ trunk/lib/engine/components/gstreamer/gst-main.cpp	Sun Sep 28 12:19:51 2008
@@ -39,9 +39,12 @@
 
 #include "videoinput-core.h"
 #include "audioinput-core.h"
+#include "audiooutput-core.h"
 
 #include "gst-videoinput.h"
 #include "gst-audioinput.h"
+#include "gst-audiooutput.h"
+#include "gst-videoinput.h"
 
 bool
 gstreamer_init (Ekiga::ServiceCore& core,
@@ -49,23 +52,31 @@
 		char** argv[])
 {
   bool result = false;
-  Ekiga::VideoInputCore* videoinput_core = NULL;
   Ekiga::AudioInputCore* audioinput_core = NULL;
-
-  videoinput_core
-    = dynamic_cast<Ekiga::VideoInputCore*>(core.get ("videoinput-core"));
+  Ekiga::AudioOutputCore* audiooutput_core = NULL;
+  Ekiga::VideoInputCore* videoinput_core = NULL;
 
   audioinput_core
     = dynamic_cast<Ekiga::AudioInputCore*>(core.get ("audioinput-core"));
 
-  if (videoinput_core != NULL && audioinput_core != NULL) {
+  audiooutput_core
+    = dynamic_cast<Ekiga::AudioOutputCore*>(core.get ("audiooutput-core"));
+
+  videoinput_core
+    = dynamic_cast<Ekiga::VideoInputCore*>(core.get ("videoinput-core"));
+
+  if (audioinput_core != NULL
+      && audiooutput_core != NULL
+      && videoinput_core != NULL) {
 
     GST::VideoInputManager* video = new GST::VideoInputManager ();
-    GST::AudioInputManager* audio = new GST::AudioInputManager ();
+    GST::AudioInputManager* audioin = new GST::AudioInputManager ();
+    GST::AudioOutputManager* audioout = new GST::AudioOutputManager ();
 
     gst_init (argc, argv);
+    audioinput_core->add_manager (*audioin);
+    audiooutput_core->add_manager (*audioout);
     videoinput_core->add_manager (*video);
-    audioinput_core->add_manager (*audio);
     result = true;
   }
 

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Sun Sep 28 12:19:51 2008
@@ -9,6 +9,7 @@
 lib/engine/addressbook/ldap/ldap-book.cpp
 lib/engine/addressbook/skel/contact-core.cpp
 lib/engine/components/gstreamer/gst-audioinput.cpp
+lib/engine/components/gstreamer/gst-audiooutput.cpp
 lib/engine/components/gstreamer/gst-videoinput.cpp
 lib/engine/gui/gtk-frontend/addressbook-window.cpp
 lib/engine/gui/gtk-frontend/book-view-gtk.cpp



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