Commit d99eb6d2 authored by Sebastian Dröge's avatar Sebastian Dröge
Browse files

Update everything for the removal of the interface library and mixer/tuner interfaces

parent 71fc2584
......@@ -79,7 +79,6 @@ EXTRA_HFILES = \
$(top_srcdir)/ext/taglib/gstid3v2mux.h \
$(top_srcdir)/ext/pulse/pulsesink.h \
$(top_srcdir)/ext/pulse/pulsesrc.h \
$(top_srcdir)/ext/pulse/pulsemixer.h \
$(top_srcdir)/ext/speex/gstspeexenc.h \
$(top_srcdir)/ext/speex/gstspeexdec.h \
$(top_srcdir)/ext/wavpack/gstwavpackdec.h \
......
......@@ -2,9 +2,6 @@ plugin_LTLIBRARIES = libgstpulse.la
libgstpulse_la_SOURCES = \
plugin.c \
pulsemixer.c \
pulsemixerctrl.c \
pulsemixertrack.c \
pulseprobe.c \
pulsesink.c \
pulsesrc.c \
......@@ -12,15 +9,12 @@ libgstpulse_la_SOURCES = \
libgstpulse_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(PULSE_CFLAGS)
libgstpulse_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_API_VERSION) \
-lgstinterfaces-$(GST_API_VERSION) -lgstpbutils-$(GST_API_VERSION) \
-lgstpbutils-$(GST_API_VERSION) \
$(GST_BASE_LIBS) $(GST_LIBS) $(PULSE_LIBS)
libgstpulse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstpulse_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = \
pulsemixerctrl.h \
pulsemixer.h \
pulsemixertrack.h \
pulseprobe.h \
pulsesink.h \
pulsesrc.h \
......
......@@ -27,7 +27,6 @@
#include "pulsesink.h"
#include "pulsesrc.h"
#include "pulsemixer.h"
GST_DEBUG_CATEGORY (pulse_debug);
......@@ -49,10 +48,6 @@ plugin_init (GstPlugin * plugin)
GST_TYPE_PULSESRC))
return FALSE;
if (!gst_element_register (plugin, "pulsemixer", GST_RANK_NONE,
GST_TYPE_PULSEMIXER))
return FALSE;
GST_DEBUG_CATEGORY_INIT (pulse_debug, "pulse", 0, "PulseAudio elements");
return TRUE;
}
......
/*
* 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.
*/
/**
* SECTION:element-pulsemixer
* @see_also: pulsesrc, pulsesink
*
* This element lets you adjust sound input and output levels for the
* PulseAudio sound server. It supports the GstMixer interface, which can be
* used to obtain a list of available mixer tracks. Set the mixer element to
* READY state before using the GstMixer interface on it.
*
* <refsect2>
* <title>Example pipelines</title>
* <para>
* pulsemixer can't be used in a sensible way in gst-launch.
* </para>
* </refsect2>
*/
#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);
GST_IMPLEMENT_PULSEMIXER_CTRL_METHODS (GstPulseMixer, gst_pulsemixer);
#define gst_pulsemixer_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstPulseMixer, gst_pulsemixer, GST_TYPE_ELEMENT,
G_IMPLEMENT_INTERFACE (GST_TYPE_MIXER,
gst_pulsemixer_mixer_interface_init));
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_pulsemixer_finalize;
gobject_class->get_property = gst_pulsemixer_get_property;
gobject_class->set_property = 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_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_DEVICE,
g_param_spec_string ("device", "Device",
"The PulseAudio sink or source to control", NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
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 | G_PARAM_STATIC_STRINGS));
gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (g_class),
"PulseAudio Mixer",
"Generic/Audio",
"Control sound input and output levels for PulseAudio",
"Lennart Poettering");
}
static void
gst_pulsemixer_init (GstPulseMixer * this)
{
this->mixer = NULL;
this->server = NULL;
this->device = NULL;
this->probe =
gst_pulseprobe_new (G_OBJECT (this), 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);
if (this->probe)
gst_pulseprobe_set_server (this->probe, this->server);
break;
case PROP_DEVICE:
g_free (this->device);
this->device = g_value_dup_string (value);
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_take_string (value, 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);
GstStateChangeReturn res;
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
if (!this->mixer)
this->mixer =
gst_pulsemixer_ctrl_new (G_OBJECT (this), this->server,
this->device, GST_PULSEMIXER_UNKNOWN);
break;
default:
;
}
res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) {
case GST_STATE_CHANGE_READY_TO_NULL:
if (this->mixer) {
gst_pulsemixer_ctrl_free (this->mixer);
this->mixer = NULL;
}
break;
default:
;
}
return res;
}
/*
* 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.
*/
#ifndef __GST_PULSEMIXER_H__
#define __GST_PULSEMIXER_H__
#include <gst/gst.h>
#include <pulse/pulseaudio.h>
#include <pulse/thread-mainloop.h>
#include "pulsemixerctrl.h"
#include "pulseprobe.h"
G_BEGIN_DECLS
#define GST_TYPE_PULSEMIXER \
(gst_pulsemixer_get_type())
#define GST_PULSEMIXER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PULSEMIXER,GstPulseMixer))
#define GST_PULSEMIXER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PULSEMIXER,GstPulseMixerClass))
#define GST_IS_PULSEMIXER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PULSEMIXER))
#define GST_IS_PULSEMIXER_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PULSEMIXER))
typedef struct _GstPulseMixer GstPulseMixer;
typedef struct _GstPulseMixerClass GstPulseMixerClass;
struct _GstPulseMixer
{
GstElement parent;
gchar *server, *device;
GstPulseMixerCtrl *mixer;
GstPulseProbe *probe;
};
struct _GstPulseMixerClass
{
GstElementClass parent_class;
};
GType gst_pulsemixer_get_type (void);
G_END_DECLS
#endif /* __GST_PULSEMIXER_H__ */
/*-*- Mode: C; c-basic-offset: 2 -*-*/
/*
* 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 <gst/gst.h>
#include "pulsemixerctrl.h"
#include "pulsemixertrack.h"
#include "pulseutil.h"
GST_DEBUG_CATEGORY_EXTERN (pulse_debug);
#define GST_CAT_DEFAULT pulse_debug
static void
gst_pulsemixer_ctrl_context_state_cb (pa_context * context, void *userdata)
{
GstPulseMixerCtrl *c = GST_PULSEMIXER_CTRL (userdata);
/* Called from the background thread! */
switch (pa_context_get_state (context)) {
case PA_CONTEXT_READY:
case PA_CONTEXT_TERMINATED:
case PA_CONTEXT_FAILED:
pa_threaded_mainloop_signal (c->mainloop, 0);
break;
case PA_CONTEXT_UNCONNECTED:
case PA_CONTEXT_CONNECTING:
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
break;
}
}
static void
gst_pulsemixer_ctrl_sink_info_cb (pa_context * context, const pa_sink_info * i,
int eol, void *userdata)
{
GstPulseMixerCtrl *c = userdata;
gboolean vol_chg = FALSE;
gboolean old_mute;
/* Called from the background thread! */
if (c->outstandig_queries > 0)
c->outstandig_queries--;
if (c->ignore_queries > 0 || c->time_event) {
if (c->ignore_queries > 0)
c->ignore_queries--;
return;
}
if (!i && eol < 0) {
c->operation_success = FALSE;
pa_threaded_mainloop_signal (c->mainloop, 0);
return;
}
if (eol)
return;
g_free (c->name);
g_free (c->description);
c->name = g_strdup (i->name);
c->description = g_strdup (i->description);
c->index = i->index;
c->channel_map = i->channel_map;
vol_chg = !pa_cvolume_equal (&c->volume, &i->volume);
c->volume = i->volume;
old_mute = c->muted;
c->muted = !!i->mute;
c->type = GST_PULSEMIXER_SINK;
if (c->track) {
GstMixerTrackFlags flags = c->track->flags;
flags =
(flags & ~GST_MIXER_TRACK_MUTE) | (c->muted ? GST_MIXER_TRACK_MUTE : 0);
c->track->flags = flags;
}
c->operation_success = TRUE;
pa_threaded_mainloop_signal (c->mainloop, 0);
if (vol_chg && c->track) {
gint volumes[PA_CHANNELS_MAX];
gint i;
for (i = 0; i < c->volume.channels; i++)
volumes[i] = (gint) (c->volume.values[i]);
GST_LOG_OBJECT (c->object, "Sending volume change notification");
gst_mixer_volume_changed (GST_MIXER (c->object), c->track, volumes);
}
if ((c->muted != old_mute) && c->track) {
GST_LOG_OBJECT (c->object, "Sending mute toggled notification");
gst_mixer_mute_toggled (GST_MIXER (c->object), c->track, c->muted);
}
}
static void
gst_pulsemixer_ctrl_source_info_cb (pa_context * context,
const pa_source_info * i, int eol, void *userdata)
{
GstPulseMixerCtrl *c = userdata;
gboolean vol_chg = FALSE;
gboolean old_mute;
/* Called from the background thread! */
if (c->outstandig_queries > 0)
c->outstandig_queries--;
if (c->ignore_queries > 0 || c->time_event) {
if (c->ignore_queries > 0)
c->ignore_queries--;
return;
}
if (!i && eol < 0) {
c->operation_success = FALSE;
pa_threaded_mainloop_signal (c->mainloop, 0);
return;
}
if (eol)
return;
g_free (c->name);
g_free (c->description);
c->name = g_strdup (i->name);
c->description = g_strdup (i->description);
c->index = i->index;
c->channel_map = i->channel_map;
vol_chg = !pa_cvolume_equal (&c->volume, &i->volume);
c->volume = i->volume;
old_mute = c->muted;
c->muted = !!i->mute;
c->type = GST_PULSEMIXER_SOURCE;
if (c->track) {
GstMixerTrackFlags flags = c->track->flags;
flags =
(flags & ~GST_MIXER_TRACK_MUTE) | (c->muted ? GST_MIXER_TRACK_MUTE : 0);
c->track->flags = flags;
}
c->operation_success = TRUE;
pa_threaded_mainloop_signal (c->mainloop, 0);
if (vol_chg && c->track) {
gint volumes[PA_CHANNELS_MAX];
gint i;
for (i = 0; i < c->volume.channels; i++)
volumes[i] = (gint) (c->volume.values[i]);
GST_LOG_OBJECT (c->object, "Sending volume change notification");
gst_mixer_volume_changed (GST_MIXER (c->object), c->track, volumes);
}
if ((c->muted != old_mute) && c->track) {
GST_LOG_OBJECT (c->object, "Sending mute toggled notification");
gst_mixer_mute_toggled (GST_MIXER (c->object), c->track, c->muted);
}
}
static void
gst_pulsemixer_ctrl_subscribe_cb (pa_context * context,
pa_subscription_event_type_t t, uint32_t idx, void *userdata)
{
GstPulseMixerCtrl *c = GST_PULSEMIXER_CTRL (userdata);
pa_operation *o = NULL;
/* Called from the background thread! */
if (c->index != idx)
return;
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE)
return;
if (c->type == GST_PULSEMIXER_SINK)
o = pa_context_get_sink_info_by_index (c->context, c->index,
gst_pulsemixer_ctrl_sink_info_cb, c);
else
o = pa_context_get_source_info_by_index (c->context, c->index,
gst_pulsemixer_ctrl_source_info_cb, c);
if (!o) {
GST_WARNING_OBJECT (c->object, "Failed to get sink info: %s",
pa_strerror (pa_context_errno (c->context)));
return;
}
pa_operation_unref (o);
c->outstandig_queries++;
}
static void
gst_pulsemixer_ctrl_success_cb (pa_context * context, int success,
void *userdata)
{
GstPulseMixerCtrl *c = (GstPulseMixerCtrl *) userdata;
c->operation_success = !!success;
pa_threaded_mainloop_signal (c->mainloop, 0);
}
#define CHECK_DEAD_GOTO(c, label) \
G_STMT_START { \
if (!(c)->context || \
!PA_CONTEXT_IS_GOOD(pa_context_get_state((c)->context))) { \
GST_WARNING_OBJECT ((c)->object, "Not connected: %s", \
(c)->context ? pa_strerror(pa_context_errno((c)->context)) : "NULL"); \
goto label; \
} \
} G_STMT_END
static gboolean
gst_pulsemixer_ctrl_open (GstPulseMixerCtrl * c)
{
int e;
gchar *name;
pa_operation *o = NULL;
g_assert (c);
GST_DEBUG_OBJECT (c->object, "ctrl open");
c->mainloop = pa_threaded_mainloop_new ();
if (!c->mainloop)
return FALSE;
e = pa_threaded_mainloop_start (c->mainloop);
if (e < 0)
return FALSE;
name = gst_pulse_client_name ();
pa_threaded_mainloop_lock (c->mainloop);
if (!(c->context =
pa_context_new (pa_threaded_mainloop_get_api (c->mainloop), name))) {
GST_WARNING_OBJECT (c->object, "Failed to create context");
goto unlock_and_fail;
}