diff options
author | Sebastian Dröge <slomo@circular-chaos.org> | 2008-06-10 06:45:33 +0000 |
---|---|---|
committer | Sebastian Dröge <slomo@circular-chaos.org> | 2008-06-10 06:45:33 +0000 |
commit | f3b03cd77318bccf2fd0d724a3f3f6d457b4277f (patch) | |
tree | 70b67fcb0e3bea880994ff6d44e853495e3ea0fa /ext/pulse/pulsemixer.c | |
parent | 660d958685e84e0334c038c03824de7ebee14ca7 (diff) |
Add pulseaudio GStreamer element from gst-pulse. Development will continue here instead of pulseaudio SVN. Fixes bug ...
Original commit message from CVS:
* configure.ac:
* ext/pulse/Makefile.am:
* ext/pulse/plugin.c: (plugin_init):
* ext/pulse/pulsemixer.c: (gst_pulsemixer_interface_supported),
(gst_pulsemixer_implements_interface_init),
(gst_pulsemixer_init_interfaces), (gst_pulsemixer_base_init),
(gst_pulsemixer_class_init), (gst_pulsemixer_init),
(gst_pulsemixer_finalize), (gst_pulsemixer_set_property),
(gst_pulsemixer_get_property), (gst_pulsemixer_change_state):
* ext/pulse/pulsemixer.h:
* ext/pulse/pulsemixerctrl.c:
(gst_pulsemixer_ctrl_context_state_cb),
(gst_pulsemixer_ctrl_sink_info_cb),
(gst_pulsemixer_ctrl_source_info_cb),
(gst_pulsemixer_ctrl_subscribe_cb),
(gst_pulsemixer_ctrl_success_cb), (gst_pulsemixer_ctrl_open),
(gst_pulsemixer_ctrl_close), (gst_pulsemixer_ctrl_new),
(gst_pulsemixer_ctrl_free), (gst_pulsemixer_ctrl_list_tracks),
(gst_pulsemixer_ctrl_timeout_event), (restart_time_event),
(gst_pulsemixer_ctrl_set_volume), (gst_pulsemixer_ctrl_get_volume),
(gst_pulsemixer_ctrl_set_record), (gst_pulsemixer_ctrl_set_mute):
* ext/pulse/pulsemixerctrl.h:
* ext/pulse/pulsemixertrack.c: (gst_pulsemixer_track_class_init),
(gst_pulsemixer_track_init), (gst_pulsemixer_track_new):
* ext/pulse/pulsemixertrack.h:
* ext/pulse/pulseprobe.c: (gst_pulseprobe_context_state_cb),
(gst_pulseprobe_sink_info_cb), (gst_pulseprobe_source_info_cb),
(gst_pulseprobe_invalidate), (gst_pulseprobe_open),
(gst_pulseprobe_enumerate), (gst_pulseprobe_close),
(gst_pulseprobe_new), (gst_pulseprobe_free),
(gst_pulseprobe_get_properties), (gst_pulseprobe_needs_probe),
(gst_pulseprobe_probe_property), (gst_pulseprobe_get_values),
(gst_pulseprobe_set_server):
* ext/pulse/pulseprobe.h:
* ext/pulse/pulsesink.c: (gst_pulsesink_base_init),
(gst_pulsesink_class_init), (gst_pulsesink_init),
(gst_pulsesink_destroy_stream), (gst_pulsesink_destroy_context),
(gst_pulsesink_finalize), (gst_pulsesink_dispose),
(gst_pulsesink_set_property), (gst_pulsesink_get_property),
(gst_pulsesink_context_state_cb), (gst_pulsesink_stream_state_cb),
(gst_pulsesink_stream_request_cb),
(gst_pulsesink_stream_latency_update_cb), (gst_pulsesink_open),
(gst_pulsesink_close), (gst_pulsesink_prepare),
(gst_pulsesink_unprepare), (gst_pulsesink_write),
(gst_pulsesink_delay), (gst_pulsesink_success_cb),
(gst_pulsesink_reset), (gst_pulsesink_change_title),
(gst_pulsesink_event), (gst_pulsesink_get_type):
* ext/pulse/pulsesink.h:
* ext/pulse/pulsesrc.c: (gst_pulsesrc_interface_supported),
(gst_pulsesrc_implements_interface_init),
(gst_pulsesrc_init_interfaces), (gst_pulsesrc_base_init),
(gst_pulsesrc_class_init), (gst_pulsesrc_init),
(gst_pulsesrc_destroy_stream), (gst_pulsesrc_destroy_context),
(gst_pulsesrc_finalize), (gst_pulsesrc_dispose),
(gst_pulsesrc_set_property), (gst_pulsesrc_get_property),
(gst_pulsesrc_context_state_cb), (gst_pulsesrc_stream_state_cb),
(gst_pulsesrc_stream_request_cb), (gst_pulsesrc_open),
(gst_pulsesrc_close), (gst_pulsesrc_prepare),
(gst_pulsesrc_unprepare), (gst_pulsesrc_read),
(gst_pulsesrc_delay), (gst_pulsesrc_change_state),
(gst_pulsesrc_get_type):
* ext/pulse/pulsesrc.h:
* ext/pulse/pulseutil.c: (gst_pulse_fill_sample_spec),
(gst_pulse_client_name), (gst_pulse_gst_to_channel_map):
* ext/pulse/pulseutil.h:
Add pulseaudio GStreamer element from gst-pulse. Development will
continue here instead of pulseaudio SVN. Fixes bug #400679.
Only changes over gst-pulse SVN are added copyright to the top of
files and coding style changes.
Diffstat (limited to 'ext/pulse/pulsemixer.c')
-rw-r--r-- | ext/pulse/pulsemixer.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/ext/pulse/pulsemixer.c b/ext/pulse/pulsemixer.c new file mode 100644 index 00000000..e2957aa6 --- /dev/null +++ b/ext/pulse/pulsemixer.c @@ -0,0 +1,277 @@ +/* + * GStreamer pulseaudio plugin + * + * Copyright (c) 2004-2008 Lennart Poettering + * + * gst-pulse is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + * + * gst-pulse 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with gst-pulse; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdio.h> + +#include "pulsemixer.h" + +enum +{ + PROP_SERVER = 1, + PROP_DEVICE, + PROP_DEVICE_NAME +}; + +GST_DEBUG_CATEGORY_EXTERN (pulse_debug); +#define GST_CAT_DEFAULT pulse_debug + +static void gst_pulsemixer_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_pulsemixer_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_pulsemixer_finalize (GObject * object); + +static GstStateChangeReturn gst_pulsemixer_change_state (GstElement * element, + GstStateChange transition); + +static void gst_pulsemixer_init_interfaces (GType type); + +GST_IMPLEMENT_PULSEMIXER_CTRL_METHODS (GstPulseMixer, gst_pulsemixer); +GST_IMPLEMENT_PULSEPROBE_METHODS (GstPulseMixer, gst_pulsemixer); +GST_BOILERPLATE_FULL (GstPulseMixer, gst_pulsemixer, GstElement, + GST_TYPE_ELEMENT, gst_pulsemixer_init_interfaces); + +static gboolean +gst_pulsemixer_interface_supported (GstImplementsInterface + * iface, GType interface_type) +{ + GstPulseMixer *this = GST_PULSEMIXER (iface); + + if (interface_type == GST_TYPE_MIXER && this->mixer) + return TRUE; + + if (interface_type == GST_TYPE_PROPERTY_PROBE && this->probe) + return TRUE; + + return FALSE; +} + +static void +gst_pulsemixer_implements_interface_init (GstImplementsInterfaceClass * klass) +{ + klass->supported = gst_pulsemixer_interface_supported; +} + +static void +gst_pulsemixer_init_interfaces (GType type) +{ + static const GInterfaceInfo implements_iface_info = { + (GInterfaceInitFunc) gst_pulsemixer_implements_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo mixer_iface_info = { + (GInterfaceInitFunc) gst_pulsemixer_mixer_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo probe_iface_info = { + (GInterfaceInitFunc) gst_pulsemixer_property_probe_interface_init, + NULL, + NULL, + }; + + g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, + &implements_iface_info); + g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info); + g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE, + &probe_iface_info); +} + +static void +gst_pulsemixer_base_init (gpointer g_class) +{ + + static const GstElementDetails details = + GST_ELEMENT_DETAILS ("PulseAudio Mixer", + "Generic/Audio", + "Control sound input and output levels for PulseAudio", + "Lennart Poettering"); + + gst_element_class_set_details (GST_ELEMENT_CLASS (g_class), &details); +} + +static void +gst_pulsemixer_class_init (GstPulseMixerClass * g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + GObjectClass *gobject_class = G_OBJECT_CLASS (g_class); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_pulsemixer_change_state); + + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_pulsemixer_finalize); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_pulsemixer_get_property); + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_pulsemixer_set_property); + + g_object_class_install_property (gobject_class, + PROP_SERVER, + g_param_spec_string ("server", "Server", + "The PulseAudio server to connect to", NULL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_DEVICE, + g_param_spec_string ("device", "Sink/Source", + "The PulseAudio sink or source to control", NULL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_DEVICE_NAME, + g_param_spec_string ("device-name", "Device name", + "Human-readable name of the sound device", NULL, G_PARAM_READABLE)); +} + +static void +gst_pulsemixer_init (GstPulseMixer * this, GstPulseMixerClass * g_class) +{ + this->mixer = NULL; + this->server = NULL; + this->device = NULL; + + this->probe = + gst_pulseprobe_new (G_OBJECT_GET_CLASS (this), PROP_DEVICE, this->device, + TRUE, TRUE); +} + +static void +gst_pulsemixer_finalize (GObject * object) +{ + GstPulseMixer *this = GST_PULSEMIXER (object); + + g_free (this->server); + g_free (this->device); + + if (this->mixer) { + gst_pulsemixer_ctrl_free (this->mixer); + this->mixer = NULL; + } + + if (this->probe) { + gst_pulseprobe_free (this->probe); + this->probe = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_pulsemixer_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + + GstPulseMixer *this = GST_PULSEMIXER (object); + + switch (prop_id) { + case PROP_SERVER: + g_free (this->server); + this->server = g_value_dup_string (value); + break; + + case PROP_DEVICE: + g_free (this->device); + this->device = g_value_dup_string (value); + + if (this->probe) + gst_pulseprobe_set_server (this->probe, this->device); + + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_pulsemixer_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + + GstPulseMixer *this = GST_PULSEMIXER (object); + + switch (prop_id) { + + case PROP_SERVER: + g_value_set_string (value, this->server); + break; + + case PROP_DEVICE: + g_value_set_string (value, this->device); + break; + + case PROP_DEVICE_NAME: + + if (this->mixer) { + char *t = g_strdup_printf ("%s: %s", + this->mixer->type == GST_PULSEMIXER_SINK ? "Playback" : "Capture", + this->mixer->description); + + g_value_set_string (value, t); + g_free (t); + } else + g_value_set_string (value, NULL); + + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstStateChangeReturn +gst_pulsemixer_change_state (GstElement * element, GstStateChange transition) +{ + GstPulseMixer *this = GST_PULSEMIXER (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + + if (!this->mixer) + this->mixer = + gst_pulsemixer_ctrl_new (this->server, this->device, + GST_PULSEMIXER_UNKNOWN); + + break; + + case GST_STATE_CHANGE_READY_TO_NULL: + + if (this->mixer) { + gst_pulsemixer_ctrl_free (this->mixer); + this->mixer = NULL; + } + + break; + + default: + ; + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + return GST_STATE_CHANGE_SUCCESS; +} |