diff --git a/xfce4-mixer-4.11.0.20210123git-libalsa-1.2.4.patch b/xfce4-mixer-4.11.0.20210123git-libalsa-1.2.4.patch new file mode 100644 index 0000000..96c1d70 --- /dev/null +++ b/xfce4-mixer-4.11.0.20210123git-libalsa-1.2.4.patch @@ -0,0 +1,1603 @@ +--- + configure.ac.in | 18 + libxfce4mixer/Makefile.am | 25 + libxfce4mixer/audio.h | 8 + libxfce4mixer/libxfce4mixer.c | 40 + + libxfce4mixer/libxfce4mixer.h | 2 + libxfce4mixer/xfce-mixer-preferences.h | 3 + libxfce4mixer/xfce-mixer-track-combo.c | 3 + libxfce4mixer/xfce-mixer-track-combo.h | 3 + libxfce4mixer/xfce-mixer-track-type.h | 2 + libxfce4mixer/xfce4-mixer-alsa.c | 974 +++++++++++++++++++++++++++++++ + libxfce4mixer/xfce4-mixer-alsa.h | 192 ++++++ + panel-plugin/Makefile.am | 15 + panel-plugin/xfce-plugin-dialog.c | 3 + panel-plugin/xfce-plugin-dialog.h | 3 + xfce4-mixer/Makefile.am | 11 + xfce4-mixer/xfce-mixer-container.c | 3 + xfce4-mixer/xfce-mixer-controls-dialog.c | 3 + xfce4-mixer/xfce-mixer-option.c | 3 + xfce4-mixer/xfce-mixer-switch.c | 3 + xfce4-mixer/xfce-mixer-track.c | 3 + xfce4-mixer/xfce-mixer-window.c | 4 + 21 files changed, 1278 insertions(+), 43 deletions(-) + +--- a/libxfce4mixer/libxfce4mixer.c ++++ b/libxfce4mixer/libxfce4mixer.c +@@ -31,8 +31,7 @@ + + #include + +-#include +-#include ++#include "audio.h" + + #include + +@@ -40,8 +39,10 @@ + + + ++#ifndef XFCE4_MIXER_ALSA + static gboolean _xfce_mixer_filter_mixer (GstMixer *mixer, + gpointer user_data); ++#endif + static void _xfce_mixer_add_track_labels (gpointer data, + gpointer user_data); + static void _xfce_mixer_init_mixer (gpointer data, +@@ -88,7 +89,11 @@ xfce_mixer_init (void) + gtk_icon_theme_append_search_path (icon_theme, MIXER_DATADIR G_DIR_SEPARATOR_S "icons"); + + /* Get list of all available mixer devices */ ++#ifdef XFCE4_MIXER_ALSA ++ mixers = gst_mixer_probe_devices (); ++#else + mixers = gst_audio_default_registry_mixer_filter (_xfce_mixer_filter_mixer, FALSE, &counter); ++#endif + + /* Create a GstBus for notifications */ + bus = gst_bus_new (); +@@ -396,6 +401,9 @@ xfce_mixer_get_max_volume (gint *volumes + + + ++static void set_mixer_name (GstMixer *mixer, const gchar *name); ++ ++#ifndef XFCE4_MIXER_ALSA + static gboolean + _xfce_mixer_filter_mixer (GstMixer *mixer, + gpointer user_data) +@@ -427,8 +435,24 @@ _xfce_mixer_filter_mixer (GstMixer *mixe + /* Free device name */ + g_free (device_name); + ++ set_mixer_name (mixer, name); ++ g_free (name); ++ ++ /* Keep the mixer (we want all devices to be visible) */ ++ return TRUE; ++} ++#endif /* !XFCE4_MIXER_ALSA */ ++ ++static void ++set_mixer_name (GstMixer *mixer, const gchar *name) ++{ ++ gint length; ++ const gchar *p; ++ gchar *internal_name; ++ + /* Set name to be used by xfce4-mixer */ +- g_object_set_data_full (G_OBJECT (mixer), "xfce-mixer-name", name, (GDestroyNotify) g_free); ++ g_object_set_data_full (G_OBJECT (mixer), "xfce-mixer-name", ++ g_strdup (name), (GDestroyNotify) g_free); + + /* Count alpha-numeric characters in the name */ + for (length = 0, p = name; *p != '\0'; ++p) +@@ -442,15 +466,11 @@ _xfce_mixer_filter_mixer (GstMixer *mixe + internal_name[length++] = *p; + internal_name[length] = '\0'; + +- /* Remember name for use by xfce4-mixer */ ++ /* Set name to be used by xfce4-mixer */ + g_object_set_data_full (G_OBJECT (mixer), "xfce-mixer-internal-name", internal_name, (GDestroyNotify) g_free); +- +- /* Keep the mixer (we want all devices to be visible) */ +- return TRUE; + } + + +- + static void + _xfce_mixer_add_track_labels (gpointer data, + gpointer user_data) +@@ -492,6 +512,10 @@ _xfce_mixer_init_mixer (gpointer data, + { + GstMixer *card = GST_MIXER (data); + ++#ifdef XFCE4_MIXER_ALSA ++ set_mixer_name (card, gst_mixer_get_card_name (card)); ++#endif ++ + /* Add custom labels to all tracks */ + _xfce_mixer_add_track_labels (card, NULL); + +--- a/libxfce4mixer/libxfce4mixer.h ++++ b/libxfce4mixer/libxfce4mixer.h +@@ -26,7 +26,7 @@ + + #include + +-#include ++#include "audio.h" + + #include "xfce-mixer-preferences.h" + #include "xfce-mixer-card-combo.h" +--- /dev/null ++++ b/libxfce4mixer/xfce4-mixer-alsa.h +@@ -0,0 +1,192 @@ ++/* ++ * Simple alternative GstMixer implementation with ALSA-native API ++ */ ++ ++#ifndef __XFCE4_MIXER_ALSA_H ++#define __XFCE4_MIXER_ALSA_H ++ ++G_BEGIN_DECLS ++ ++/* ++ * GstMixer ++ */ ++ ++GType gst_mixer_get_type (void); ++ ++#define GST_TYPE_MIXER \ ++ (gst_mixer_get_type ()) ++#define GST_MIXER(obj) \ ++ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MIXER, GstMixer)) ++#define GST_MIXER_CLASS(klass) \ ++ (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MIXER, GstMixerClass)) ++#define GST_IS_MIXER(obj) \ ++ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MIXER)) ++#define GST_IS_MIXER_CLASS(klass) \ ++ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MIXER)) ++#define GST_MIXER_GET_CLASS(inst) \ ++ (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_MIXER, GstMixerClass)) ++ ++typedef struct _GstMixer GstMixer; ++typedef struct _GstMixerClass GstMixerClass; ++ ++typedef enum { ++ GST_MIXER_FLAG_NONE = 0, ++ GST_MIXER_FLAG_AUTO_NOTIFICATIONS = (1<<0), ++ GST_MIXER_FLAG_HAS_WHITELIST = (1<<1), ++ GST_MIXER_FLAG_GROUPING = (1<<2), ++} GstMixerFlags; ++ ++typedef enum { ++ GST_MIXER_MESSAGE_INVALID, ++ GST_MIXER_MESSAGE_MUTE_TOGGLED, ++ GST_MIXER_MESSAGE_RECORD_TOGGLED, ++ GST_MIXER_MESSAGE_VOLUME_CHANGED, ++ GST_MIXER_MESSAGE_OPTION_CHANGED, ++ GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED, ++ GST_MIXER_MESSAGE_MIXER_CHANGED ++} GstMixerMessageType; ++ ++struct _GstMixer { ++ GstElement element; ++ GList *tracklist; ++ void *handle; /* snd_mixer_t */ ++ const char *name; ++ const gchar *card_name; ++ GSource *src; ++}; ++ ++struct _GstMixerClass { ++ GstElementClass parent_class; ++}; ++ ++const GList *gst_mixer_list_tracks (GstMixer *mixer); ++ ++static inline GstMixerFlags ++gst_mixer_get_mixer_flags (GstMixer * mixer) ++{ ++ return GST_MIXER_FLAG_AUTO_NOTIFICATIONS; ++} ++ ++GstMixerMessageType gst_mixer_message_get_type (GstMessage *message); ++ ++int gst_mixer_new (const char *name, GstMixer **mixer_ret); ++GList *gst_mixer_probe_devices (void); ++const gchar *gst_mixer_get_card_name (GstMixer *mixer); ++ ++/* ++ * GstMixerTrack ++ */ ++ ++GType gst_mixer_track_get_type (void); ++ ++#define GST_TYPE_MIXER_TRACK \ ++ (gst_mixer_track_get_type ()) ++#define GST_MIXER_TRACK(obj) \ ++ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MIXER_TRACK, \ ++ GstMixerTrack)) ++#define GST_MIXER_TRACK_CLASS(klass) \ ++ (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MIXER_TRACK, \ ++ GstMixerTrackClass)) ++#define GST_IS_MIXER_TRACK(obj) \ ++ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MIXER_TRACK)) ++#define GST_IS_MIXER_TRACK_CLASS(klass) \ ++ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MIXER_TRACK)) ++ ++typedef struct _GstMixerTrack GstMixerTrack; ++typedef struct _GstMixerTrackClass GstMixerTrackClass; ++ ++typedef enum { ++ GST_MIXER_TRACK_INPUT = (1<<0), ++ GST_MIXER_TRACK_OUTPUT = (1<<1), ++ GST_MIXER_TRACK_MUTE = (1<<2), ++ GST_MIXER_TRACK_RECORD = (1<<3), ++ GST_MIXER_TRACK_MASTER = (1<<4), ++ GST_MIXER_TRACK_SOFTWARE = (1<<5), ++ GST_MIXER_TRACK_NO_RECORD = (1<<6), ++ GST_MIXER_TRACK_NO_MUTE = (1<<7), ++ GST_MIXER_TRACK_WHITELIST = (1<<8), ++ GST_MIXER_TRACK_READONLY = (1<<9), ++ GST_MIXER_TRACK_WRITEONLY = (1<<10) ++} GstMixerTrackFlags; ++ ++struct _GstMixerTrack { ++ GObject parent; ++ void *element; ++ gchar *label; ++ gchar *untranslated_label; ++ guint index; ++ GstMixerTrackFlags flags; ++ gint num_channels; ++ gint *volumes; ++ gint min_volume; ++ gint max_volume; ++ GstMixerTrack *shared_mute; ++ gboolean has_volume; ++ gboolean has_switch; ++}; ++ ++struct _GstMixerTrackClass { ++ GObjectClass parent; ++}; ++ ++#define GST_MIXER_TRACK_HAS_FLAG(track, flag) ((track)->flags & (flag)) ++ ++void gst_mixer_get_volume (GstMixer *mixer, GstMixerTrack *track, gint *volumes); ++void gst_mixer_set_volume (GstMixer *mixer, GstMixerTrack *track, gint *volumes); ++void gst_mixer_set_mute (GstMixer *mixer, GstMixerTrack *track, gboolean mute); ++void gst_mixer_set_record (GstMixer *mixer, GstMixerTrack *track, gboolean record); ++ ++void gst_mixer_message_parse_mute_toggled (GstMessage *message, ++ GstMixerTrack **track, ++ gboolean *mute); ++void gst_mixer_message_parse_record_toggled (GstMessage *message, ++ GstMixerTrack **track, ++ gboolean *record); ++void gst_mixer_message_parse_volume_changed (GstMessage *message, ++ GstMixerTrack **track, ++ gint **volumes, ++ gint *num_channels); ++ ++/* ++ * GstMixerOptions ++ */ ++ ++GType gst_mixer_options_get_type (void); ++ ++#define GST_TYPE_MIXER_OPTIONS \ ++ (gst_mixer_options_get_type ()) ++#define GST_MIXER_OPTIONS(obj) \ ++ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MIXER_OPTIONS, GstMixerOptions)) ++#define GST_MIXER_OPTIONS_CLASS(klass) \ ++ (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MIXER_OPTIONS, GstMixerOptionsClass)) ++#define GST_IS_MIXER_OPTIONS(obj) \ ++ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MIXER_OPTIONS)) ++#define GST_IS_MIXER_OPTIONS_CLASS(klass) \ ++ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MIXER_OPTIONS)) ++#define GST_MIXER_OPTIONS_GET_CLASS(inst) \ ++ (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_MIXER_OPTIONS, GstMixerOptionsClass)) ++ ++typedef struct _GstMixerOptions GstMixerOptions; ++typedef struct _GstMixerOptionsClass GstMixerOptionsClass; ++ ++struct _GstMixerOptions { ++ GstMixerTrack parent; ++ GList *values; ++}; ++ ++struct _GstMixerOptionsClass { ++ GstMixerTrackClass parent; ++}; ++ ++void gst_mixer_set_option (GstMixer * mixer, GstMixerOptions * opts, gchar * value); ++const gchar * gst_mixer_get_option (GstMixer * mixer, GstMixerOptions * opts); ++GList * gst_mixer_options_get_values (GstMixerOptions *mixer_options); ++void gst_mixer_message_parse_option_changed (GstMessage *message, ++ GstMixerOptions ** options, ++ const gchar **value); ++void gst_mixer_message_parse_options_list_changed (GstMessage *message, ++ GstMixerOptions **options); ++ ++G_END_DECLS ++ ++#endif /* __XFCE4_MIXER_ALSA_H */ +--- a/libxfce4mixer/xfce-mixer-preferences.h ++++ b/libxfce4mixer/xfce-mixer-preferences.h +@@ -24,8 +24,7 @@ + + #include + +-#include +-#include ++#include "audio.h" + + G_BEGIN_DECLS + +--- a/libxfce4mixer/xfce-mixer-track-combo.c ++++ b/libxfce4mixer/xfce-mixer-track-combo.c +@@ -27,8 +27,7 @@ + + #include + +-#include +-#include ++#include "audio.h" + + #include "libxfce4mixer.h" + #include "xfce-mixer-track-type.h" +--- a/libxfce4mixer/xfce-mixer-track-combo.h ++++ b/libxfce4mixer/xfce-mixer-track-combo.h +@@ -24,8 +24,7 @@ + + #include + +-#include +-#include ++#include "audio.h" + + G_BEGIN_DECLS + +--- a/libxfce4mixer/xfce-mixer-track-type.h ++++ b/libxfce4mixer/xfce-mixer-track-type.h +@@ -22,7 +22,7 @@ + #define __XFCE_TRACK_TYPE_H__ + + #include +-#include ++#include "audio.h" + + G_BEGIN_DECLS + +--- /dev/null ++++ b/libxfce4mixer/xfce4-mixer-alsa.c +@@ -0,0 +1,974 @@ ++/* ++ * Simple alternative GstMixer implementation with ALSA-native API ++ */ ++ ++#include "config.h" ++#include "audio.h" ++ ++#include ++ ++#define GST_MIXER_MESSAGE_NAME "gst-mixer-message" ++ ++/* ++ * GstMixer ++ */ ++ ++G_DEFINE_TYPE (GstMixer, gst_mixer, GST_TYPE_ELEMENT); ++ ++static void gst_mixer_init (GstMixer *mixer) ++{ ++} ++ ++static void gst_mixer_dispose (GObject * object) ++{ ++ GstMixer *mixer = GST_MIXER (object); ++ ++ if (mixer->src) { ++ g_source_destroy (mixer->src); ++ mixer->src = NULL; ++ } ++ ++ if (mixer->handle) { ++ snd_mixer_close (mixer->handle); ++ mixer->handle = NULL; ++ } ++ ++ g_list_free_full (mixer->tracklist, g_object_unref); ++ mixer->tracklist = NULL; ++ ++ g_free ((gpointer *) mixer->name); ++ mixer->name = NULL; ++ ++ g_free ((gpointer *) mixer->card_name); ++ mixer->card_name = NULL; ++ ++ G_OBJECT_CLASS (gst_mixer_parent_class)->dispose (object); ++} ++ ++static void gst_mixer_class_init (GstMixerClass *klass) ++{ ++ GstElementClass *element_klass = GST_ELEMENT_CLASS (klass); ++ GObjectClass *object_klass = G_OBJECT_CLASS (klass); ++ ++ gst_element_class_set_static_metadata (element_klass, ++ "ALSA mixer", "Generic/Audio", ++ "Control audio mixer via ALSA API", ++ "Takashi Iwai "); ++ ++ object_klass->dispose = gst_mixer_dispose; ++} ++ ++/* ++ * GstMixerTrack ++ */ ++ ++G_DEFINE_TYPE (GstMixerTrack, gst_mixer_track, G_TYPE_OBJECT); ++ ++static void gst_mixer_track_init (GstMixerTrack *track) ++{ ++} ++ ++static void notify_mute_change (GstMixer *mixer, GstMixerTrack *track, ++ gboolean mute) ++{ ++ GstStructure *s; ++ GstMessage *m; ++ ++ s = gst_structure_new (GST_MIXER_MESSAGE_NAME, ++ "type", G_TYPE_STRING, "mute-toggled", ++ "track", GST_TYPE_MIXER_TRACK, track, ++ "mute", G_TYPE_BOOLEAN, mute, ++ NULL); ++ m = gst_message_new_element (GST_OBJECT (mixer), s); ++ gst_element_post_message (GST_ELEMENT (mixer), m); ++} ++ ++static void update_mute (GstMixer *mixer, GstMixerTrack *track, gboolean mute) ++{ ++ int old_flag = track->flags & GST_MIXER_TRACK_MUTE; ++ ++ if (mute) { ++ track->flags |= GST_MIXER_TRACK_MUTE; ++ if (track->shared_mute) ++ track->shared_mute->flags |= GST_MIXER_TRACK_MUTE; ++ } else { ++ track->flags &= ~GST_MIXER_TRACK_MUTE; ++ if (track->shared_mute) ++ track->shared_mute->flags &= ~GST_MIXER_TRACK_MUTE; ++ } ++ ++ if ((track->flags & GST_MIXER_TRACK_MUTE) != old_flag) ++ notify_mute_change (mixer, track, mute); ++} ++ ++static void notify_recording_change (GstMixer *mixer, GstMixerTrack *track, ++ gboolean recording) ++{ ++ GstStructure *s; ++ GstMessage *m; ++ ++ s = gst_structure_new (GST_MIXER_MESSAGE_NAME, ++ "type", G_TYPE_STRING, "record-toggled", ++ "track", GST_TYPE_MIXER_TRACK, track, ++ "record", G_TYPE_BOOLEAN, recording, ++ NULL); ++ m = gst_message_new_element (GST_OBJECT (mixer), s); ++ gst_element_post_message (GST_ELEMENT (mixer), m); ++} ++ ++static void update_recording (GstMixer *mixer, GstMixerTrack *track, ++ gboolean recording) ++{ ++ int old_flag = track->flags & GST_MIXER_TRACK_RECORD; ++ ++ if (recording) ++ track->flags |= GST_MIXER_TRACK_RECORD; ++ else ++ track->flags &= ~GST_MIXER_TRACK_RECORD; ++ ++ if ((track->flags & GST_MIXER_TRACK_RECORD) != old_flag) ++ notify_recording_change (mixer, track, recording); ++} ++ ++static void notify_volume_change (GstMixer *mixer, GstMixerTrack *track) ++{ ++ GstStructure *s; ++ GstMessage *m; ++ GValue l = { 0, }; ++ GValue v = { 0, }; ++ int i; ++ ++ s = gst_structure_new (GST_MIXER_MESSAGE_NAME, ++ "type", G_TYPE_STRING, "volume-changed", ++ "track", GST_TYPE_MIXER_TRACK, track, ++ NULL); ++ g_value_init (&l, GST_TYPE_ARRAY); ++ g_value_init (&v, G_TYPE_INT); ++ ++ for (i = 0; i < track->num_channels; i++) { ++ g_value_set_int (&v, track->volumes[i]); ++ gst_value_array_append_value (&l, &v); ++ } ++ ++ gst_structure_set_value (s, "volumes", &l); ++ g_value_unset (&v); ++ g_value_unset (&l); ++ ++ m = gst_message_new_element (GST_OBJECT (mixer), s); ++ gst_element_post_message (GST_ELEMENT (mixer), m); ++} ++ ++static void track_update (GstMixer *mixer, GstMixerTrack *track) ++{ ++ gboolean vol_changed = FALSE; ++ int i; ++ ++ if (track->flags & GST_MIXER_TRACK_OUTPUT) { ++ int audible = 0; ++ if (track->has_switch) { ++ for (i = 0; i < track->num_channels; i++) { ++ int v = 0; ++ snd_mixer_selem_get_playback_switch (track->element, i, &v); ++ if (v) ++ audible = 1; ++ } ++ } ++ ++ if (track->has_volume) { ++ for (i = 0; i < track->num_channels; i++) { ++ long vol = 0; ++ snd_mixer_selem_get_playback_volume (track->element, i, &vol); ++ if (track->volumes[i] != vol) ++ vol_changed = TRUE; ++ track->volumes[i] = vol; ++ if (!track->has_switch && ++ vol > track->min_volume) ++ audible = 1; ++ } ++ } ++ ++ update_mute (mixer, track, !audible); ++ } ++ ++ if (track->flags & GST_MIXER_TRACK_INPUT) { ++ int recording = 0; ++ if (track->has_switch) { ++ for (i = 0; i < track->num_channels; i++) { ++ int v = 0; ++ snd_mixer_selem_get_capture_switch (track->element, i, &v); ++ if (v) ++ recording = 1; ++ } ++ } ++ ++ if (track->has_volume) { ++ for (i = 0; i < track->num_channels; i++) { ++ long vol = 0; ++ snd_mixer_selem_get_capture_volume (track->element, i, &vol); ++ if (track->volumes[i] != vol) ++ vol_changed = TRUE; ++ track->volumes[i] = vol; ++ if (!track->has_switch && ++ vol > track->min_volume) ++ recording = 1; ++ } ++ } ++ ++ update_recording (mixer, track, recording); ++ } ++ ++ if (vol_changed) ++ notify_volume_change (mixer, track); ++} ++ ++static GstMixerTrack *track_new (snd_mixer_elem_t *element, int num, ++ int flags, gboolean append_capture) ++{ ++ GstMixerTrack *track; ++ const char *name; ++ ++ track = (GstMixerTrack *) g_object_new (GST_TYPE_MIXER_TRACK, NULL); ++ track->index = snd_mixer_selem_get_index (element); ++ track->element = element; ++ track->flags = flags; ++ ++ if (flags & GST_MIXER_TRACK_OUTPUT) { ++ while (snd_mixer_selem_has_playback_channel (element, ++ track->num_channels)) ++ track->num_channels++; ++ } else if (flags & GST_MIXER_TRACK_INPUT) { ++ while (snd_mixer_selem_has_capture_channel (element, ++ track->num_channels)) ++ track->num_channels++; ++ } ++ ++ track->volumes = g_new (gint, track->num_channels); ++ ++ name = snd_mixer_selem_get_name (element); ++ track->untranslated_label = g_strdup (name); ++ ++ if (!num) ++ track->label = g_strdup_printf ("%s%s", name, ++ append_capture ? " Capture" : ""); ++ else ++ track->label = g_strdup_printf ("%s%s %d", name, ++ append_capture ? " Capture" : "", ++ num); ++ ++ return track; ++} ++ ++enum { ++ ARG_0, ++ ARG_LABEL, ++ ARG_UNTRANSLATED_LABEL, ++ ARG_INDEX, ++}; ++ ++static void gst_mixer_track_get_property (GObject *object, guint prop_id, ++ GValue *value, GParamSpec *pspec) ++{ ++ GstMixerTrack *track = GST_MIXER_TRACK (object); ++ ++ switch (prop_id) { ++ case ARG_LABEL: ++ g_value_set_string (value, track->label); ++ break; ++ case ARG_UNTRANSLATED_LABEL: ++ g_value_set_string (value, track->untranslated_label); ++ break; ++ case ARG_INDEX: ++ g_value_set_uint (value, track->index); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void gst_mixer_track_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec * pspec) ++{ ++ GstMixerTrack *track; ++ ++ track = GST_MIXER_TRACK (object); ++ ++ switch (prop_id) { ++ case ARG_LABEL: ++ g_free (track->label); ++ track->label = g_value_dup_string (value); ++ break; ++ case ARG_UNTRANSLATED_LABEL: ++ g_free (track->untranslated_label); ++ track->untranslated_label = g_value_dup_string (value); ++ break; ++ case ARG_INDEX: ++ track->index = g_value_get_uint (value); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void gst_mixer_track_dispose (GObject * object) ++{ ++ GstMixerTrack *track = GST_MIXER_TRACK (object); ++ ++ if (track->label) { ++ g_free (track->label); ++ track->label = NULL; ++ } ++ ++ if (track->untranslated_label) { ++ g_free (track->untranslated_label); ++ track->untranslated_label = NULL; ++ } ++ ++ G_OBJECT_CLASS (gst_mixer_track_parent_class)->dispose (object); ++} ++ ++static void gst_mixer_track_class_init (GstMixerTrackClass * klass) ++{ ++ GObjectClass *object_klass = G_OBJECT_CLASS (klass); ++ ++ object_klass->get_property = gst_mixer_track_get_property; ++ object_klass->set_property = gst_mixer_track_set_property; ++ ++ g_object_class_install_property (object_klass, ARG_UNTRANSLATED_LABEL, ++ g_param_spec_string ("untranslated-label", ++ "Untranslated track label", ++ "The untranslated label assigned to the track (since 0.10.13)", ++ NULL, ++ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); ++ ++ g_object_class_install_property (object_klass, ARG_LABEL, ++ g_param_spec_string ("label", "Track label", ++ "The label assigned to the track (may be translated)", ++ NULL, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_STATIC_STRINGS)); ++ ++ g_object_class_install_property (object_klass, ARG_INDEX, ++ g_param_spec_uint ("index", "Index", ++ "Track index", ++ 0, G_MAXUINT, 0, ++ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); ++ ++ object_klass->dispose = gst_mixer_track_dispose; ++} ++ ++static void get_playback_min_max (GstMixerTrack *track) ++{ ++ if (track->has_volume) { ++ long min = 0, max = 0; ++ snd_mixer_selem_get_playback_volume_range (track->element, &min, &max); ++ track->min_volume = min; ++ track->max_volume = max; ++ } ++} ++ ++static void get_capture_min_max (GstMixerTrack *track) ++{ ++ if (track->has_volume) { ++ long min = 0, max = 0; ++ snd_mixer_selem_get_capture_volume_range (track->element, &min, &max); ++ track->min_volume = min; ++ track->max_volume = max; ++ } ++} ++ ++static GstMixerTrack *get_named_playback_track (GstMixer *mixer, ++ const char *name) ++{ ++ GList *item; ++ GstMixerTrack *track; ++ ++ for (item = mixer->tracklist; item; item = item->next) { ++ track = GST_MIXER_TRACK (item->data); ++ if (! (track->flags & GST_MIXER_TRACK_OUTPUT)) ++ continue; ++ if (!strcmp (track->label, name)) ++ return track; ++ } ++ return NULL; ++} ++ ++static void mark_master_track (GstMixer *mixer) ++{ ++ GList *item; ++ GstMixerTrack *track; ++ ++ if ((track = get_named_playback_track (mixer, "Master")) || ++ (track = get_named_playback_track (mixer, "Front")) || ++ (track = get_named_playback_track (mixer, "PCM")) || ++ (track = get_named_playback_track (mixer, "Speaker"))) ++ goto found; ++ ++ /* If not found, take a mono track with both volume and switch */ ++ for (item = mixer->tracklist; item; item = item->next) { ++ track = GST_MIXER_TRACK (item->data); ++ if (! (track->flags & GST_MIXER_TRACK_OUTPUT)) ++ continue; ++ if (track->has_volume && track->has_switch && ++ track->num_channels == 1) ++ goto found; ++ } ++ ++ /* If not found, take any track with both volume and switch */ ++ for (item = mixer->tracklist; item; item = item->next) { ++ track = GST_MIXER_TRACK (item->data); ++ if (! (track->flags & GST_MIXER_TRACK_OUTPUT)) ++ continue; ++ if (track->has_volume && track->has_switch) ++ goto found; ++ } ++ ++ /* If not found, take any track with volume */ ++ for (item = mixer->tracklist; item; item = item->next) { ++ track = GST_MIXER_TRACK (item->data); ++ if (! (track->flags & GST_MIXER_TRACK_OUTPUT)) ++ continue; ++ if (track->has_volume) ++ goto found; ++ } ++ ++ return; ++ ++ found: ++ track->flags |= GST_MIXER_TRACK_MASTER; ++ return; ++} ++ ++static int mixer_elem_callback (snd_mixer_elem_t *elem, unsigned int mask) ++{ ++ GstMixer *mixer = snd_mixer_elem_get_callback_private (elem); ++ GList *item; ++ ++ for (item = mixer->tracklist; item; item = item->next) { ++ GstMixerTrack *track = GST_MIXER_TRACK (item->data); ++ if (track->element == elem) ++ track_update (mixer, track); ++ } ++ ++ return 0; ++} ++ ++static int mixer_callback (snd_mixer_t *ctl, unsigned int mask, ++ snd_mixer_elem_t *elem) ++{ ++ GstMixer *mixer = snd_mixer_get_callback_private (ctl); ++ ++ snd_mixer_handle_events (mixer->handle); ++ return 0; ++} ++ ++const GList *gst_mixer_list_tracks (GstMixer *mixer) ++{ ++ return mixer->tracklist; ++} ++ ++static gboolean same_volumes (gint num_channels, const gint *volumes) ++{ ++ gint i; ++ ++ for (i = 1; i < num_channels; i++) { ++ if (volumes[0] != volumes[i]) ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++void gst_mixer_set_volume (GstMixer *mixer, GstMixerTrack *track, gint *volumes) ++{ ++ gint i; ++ ++ track_update (mixer, track); ++ ++ if (!track->has_volume) ++ return; ++ ++ for (i = 0; i < track->num_channels; i++) ++ track->volumes[i] = volumes[i]; ++ ++ if (track->flags & GST_MIXER_TRACK_OUTPUT) { ++ if (!track->has_switch && (track->flags & GST_MIXER_TRACK_MUTE)) ++ return; ++ if (same_volumes (track->num_channels, volumes)) { ++ snd_mixer_selem_set_playback_volume_all (track->element, ++ volumes[0]); ++ } else { ++ for (i = 0; i < track->num_channels; i++) ++ snd_mixer_selem_set_playback_volume (track->element, i, ++ volumes[i]); ++ } ++ } else { ++ if (!track->has_switch && ! (track->flags & GST_MIXER_TRACK_RECORD)) ++ return; ++ if (same_volumes (track->num_channels, volumes)) { ++ snd_mixer_selem_set_capture_volume_all (track->element, ++ volumes[0]); ++ } else { ++ for (i = 0; i < track->num_channels; i++) ++ snd_mixer_selem_set_capture_volume (track->element, i, ++ volumes[i]); ++ } ++ } ++} ++ ++void gst_mixer_get_volume (GstMixer *mixer, GstMixerTrack *track, gint *volumes) ++{ ++ int i; ++ ++ if (!track->has_volume) ++ return; ++ ++ track_update (mixer, track); ++ for (i = 0; i < track->num_channels; i++) ++ volumes[i] = track->volumes[i]; ++} ++ ++void gst_mixer_set_mute (GstMixer *mixer, GstMixerTrack *track, gboolean mute) ++{ ++ int i; ++ ++ if (track->flags & GST_MIXER_TRACK_INPUT) { ++ if (track->shared_mute) ++ track = track->shared_mute; ++ else ++ return; ++ } ++ ++ track_update (mixer, track); ++ ++ mute = !!mute; ++ if (mute == !! (track->flags & GST_MIXER_TRACK_MUTE)) ++ return; ++ ++ update_mute (mixer, track, mute); ++ ++ if (track->has_switch) { ++ snd_mixer_selem_set_playback_switch_all (track->element, !mute); ++ } else { ++ for (i = 0; i < track->num_channels; i++) { ++ long vol = mute ? track->min_volume : track->volumes[i]; ++ snd_mixer_selem_set_playback_volume (track->element, i, vol); ++ } ++ } ++} ++ ++void gst_mixer_set_record (GstMixer * mixer, GstMixerTrack *track, gboolean record) ++{ ++ int i; ++ ++ if (! (track->flags & GST_MIXER_TRACK_INPUT)) ++ return; ++ ++ track_update (mixer, track); ++ ++ record = !!record; ++ if (record == !! (track->flags & GST_MIXER_TRACK_RECORD)) ++ return; ++ ++ if (record) ++ track->flags |= GST_MIXER_TRACK_RECORD; ++ else ++ track->flags &= ~GST_MIXER_TRACK_RECORD; ++ ++ if (track->has_switch) { ++ snd_mixer_selem_set_capture_switch_all (track->element, record); ++ } else { ++ for (i = 0; i < track->num_channels; i++) { ++ long vol = record ? track->volumes[i] : track->min_volume; ++ snd_mixer_selem_set_capture_volume (track->element, i, vol); ++ } ++ } ++} ++ ++GstMixerMessageType ++gst_mixer_message_get_type (GstMessage * message) ++{ ++ const GstStructure *s; ++ const gchar *m_type; ++ ++ s = gst_message_get_structure (message); ++ m_type = gst_structure_get_string (s, "type"); ++ if (!m_type) ++ return GST_MIXER_MESSAGE_INVALID; ++ ++ if (g_str_equal (m_type, "mute-toggled")) ++ return GST_MIXER_MESSAGE_MUTE_TOGGLED; ++ else if (g_str_equal (m_type, "record-toggled")) ++ return GST_MIXER_MESSAGE_RECORD_TOGGLED; ++ else if (g_str_equal (m_type, "volume-changed")) ++ return GST_MIXER_MESSAGE_VOLUME_CHANGED; ++ else if (g_str_equal (m_type, "option-changed")) ++ return GST_MIXER_MESSAGE_OPTION_CHANGED; ++ else if (g_str_equal (m_type, "options-list-changed")) ++ return GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED; ++ else if (g_str_equal (m_type, "mixer-changed")) ++ return GST_MIXER_MESSAGE_MIXER_CHANGED; ++ ++ return GST_MIXER_MESSAGE_INVALID; ++} ++ ++static void message_parse_track (const GstStructure *s, GstMixerTrack **track) ++{ ++ if (track) { ++ const GValue *v = gst_structure_get_value (s, "track"); ++ *track = (GstMixerTrack *)g_value_get_object (v); ++ } ++} ++ ++void gst_mixer_message_parse_mute_toggled (GstMessage *message, ++ GstMixerTrack **track, ++ gboolean *mute) ++{ ++ const GstStructure *s = gst_message_get_structure (message); ++ ++ message_parse_track (s, track); ++ if (mute) ++ gst_structure_get_boolean (s, "mute", mute); ++} ++ ++void gst_mixer_message_parse_record_toggled (GstMessage *message, ++ GstMixerTrack **track, ++ gboolean *record) ++{ ++ const GstStructure *s = gst_message_get_structure (message); ++ ++ message_parse_track (s, track); ++ if (record) ++ gst_structure_get_boolean (s, "record", record); ++} ++ ++void gst_mixer_message_parse_volume_changed (GstMessage *message, ++ GstMixerTrack **track, ++ gint **volumes, ++ gint *num_channels) ++{ ++ const GstStructure *s = gst_message_get_structure (message); ++ ++ message_parse_track (s, track); ++ if (volumes || num_channels) { ++ gint n_chans, i; ++ const GValue *v = gst_structure_get_value (s, "volumes"); ++ ++ n_chans = gst_value_array_get_size (v); ++ if (num_channels) ++ *num_channels = n_chans; ++ ++ if (volumes) { ++ *volumes = g_new (gint, n_chans); ++ for (i = 0; i < n_chans; i++) { ++ const GValue *e = gst_value_array_get_value (v, i); ++ ++ (*volumes)[i] = g_value_get_int (e); ++ } ++ } ++ } ++} ++ ++/* ++ * GstMixerOptions ++ */ ++ ++G_DEFINE_TYPE (GstMixerOptions, gst_mixer_options, GST_TYPE_MIXER_TRACK); ++ ++static GstMixerOptions * ++mixer_options_new (snd_mixer_elem_t *element, int num) ++{ ++ GstMixerOptions *opt; ++ GstMixerTrack *track; ++ const char *label; ++ int i; ++ ++ label = snd_mixer_selem_get_name (element); ++ opt = g_object_new (GST_TYPE_MIXER_OPTIONS, ++ "untranslated-label", label, ++ "index", snd_mixer_selem_get_index (element), ++ NULL); ++ track = GST_MIXER_TRACK (opt); ++ track->element = element; ++ if (!num) ++ track->label = g_strdup (label); ++ else ++ track->label = g_strdup_printf ("%s %d", label, num); ++ ++ num = snd_mixer_selem_get_enum_items (element); ++ for (i = 0; i < num; i++) { ++ char str[256]; ++ if (snd_mixer_selem_get_enum_item_name (element, i, sizeof(str), str) < 0) ++ break; ++ opt->values = g_list_append (opt->values, g_strdup (str)); ++ } ++ ++ return opt; ++} ++ ++static void gst_mixer_options_dispose (GObject * object) ++{ ++ GstMixerOptions *opt = GST_MIXER_OPTIONS (object); ++ ++ g_list_free_full (opt->values, g_free); ++ opt->values = NULL; ++ ++ G_OBJECT_CLASS (gst_mixer_options_parent_class)->dispose (object); ++} ++ ++static void gst_mixer_options_init (GstMixerOptions *opt) ++{ ++} ++ ++static void gst_mixer_options_class_init (GstMixerOptionsClass * klass) ++{ ++ GObjectClass *object_klass = G_OBJECT_CLASS (klass); ++ ++ object_klass->dispose = gst_mixer_options_dispose; ++} ++ ++const gchar *gst_mixer_get_option (GstMixer *mixer, GstMixerOptions *opt) ++{ ++ unsigned int idx; ++ ++ if (snd_mixer_selem_get_enum_item (opt->parent.element, 0, &idx) < 0) ++ return "error"; ++ return g_list_nth_data (opt->values, idx); ++} ++ ++void gst_mixer_set_option (GstMixer *mixer, GstMixerOptions *opt, ++ gchar *value) ++{ ++ int n = 0; ++ GList *item; ++ ++ for (item = opt->values; item; item = item->next, n++) { ++ if (!strcmp (item->data, value)) { ++ snd_mixer_selem_set_enum_item (opt->parent.element, 0, n); ++ break; ++ } ++ } ++} ++ ++GList *gst_mixer_options_get_values (GstMixerOptions *opt) ++{ ++ return opt->values; ++} ++ ++static void message_parse_options (const GstStructure *s, ++ GstMixerOptions ** options) ++{ ++ if (options) { ++ const GValue *v = gst_structure_get_value (s, "options"); ++ *options = (GstMixerOptions *) g_value_get_object (v); ++ } ++} ++ ++void gst_mixer_message_parse_option_changed (GstMessage *message, ++ GstMixerOptions ** options, ++ const gchar **value) ++{ ++ const GstStructure *s = gst_message_get_structure (message); ++ ++ message_parse_options (s, options); ++ if (value) ++ *value = gst_structure_get_string (s, "value"); ++} ++ ++void gst_mixer_message_parse_options_list_changed (GstMessage *message, ++ GstMixerOptions **options) ++{ ++ const GstStructure *s = gst_message_get_structure (message); ++ ++ message_parse_options (s, options); ++} ++ ++/* ++ */ ++ ++static void create_track_list (GstMixer *mixer) ++{ ++ snd_mixer_elem_t *element, *temp; ++ GList *item; ++ ++ if (mixer->tracklist) ++ return; ++ ++ for (element = snd_mixer_first_elem (mixer->handle); element; ++ element = snd_mixer_elem_next (element)) { ++ GstMixerTrack *play_track = NULL; ++ GstMixerTrack *cap_track = NULL; ++ const gchar *name = snd_mixer_selem_get_name (element); ++ int index = 0; ++ int has_volume, has_switch; ++ ++ for (item = mixer->tracklist; item; item = item->next) { ++ temp = GST_MIXER_TRACK (item->data)->element; ++ if (strcmp (name, snd_mixer_selem_get_name (temp)) == 0) ++ index++; ++ } ++ ++ has_volume = snd_mixer_selem_has_playback_volume (element); ++ has_switch = snd_mixer_selem_has_playback_switch (element); ++ if (has_volume || has_switch) { ++ play_track = track_new (element, index, ++ GST_MIXER_TRACK_OUTPUT, FALSE); ++ play_track->has_volume = has_volume; ++ play_track->has_switch = has_switch; ++ get_playback_min_max (play_track); ++ } ++ ++ has_volume = snd_mixer_selem_has_capture_volume (element); ++ has_switch = snd_mixer_selem_has_capture_switch (element); ++ if (play_track && snd_mixer_selem_has_common_volume (element)) ++ has_volume = 0; ++ if (play_track && snd_mixer_selem_has_common_switch (element)) ++ has_switch = 0; ++ if (has_volume || has_switch) { ++ cap_track = track_new (element, index, ++ GST_MIXER_TRACK_INPUT, ++ play_track != NULL); ++ cap_track->has_volume = has_volume; ++ cap_track->has_switch = has_switch; ++ get_capture_min_max (cap_track); ++ } ++ ++ if (play_track && cap_track) { ++ play_track->shared_mute = cap_track; ++ cap_track->shared_mute = play_track; ++ } ++ ++ if (play_track) { ++ track_update (mixer, play_track); ++ mixer->tracklist = g_list_append (mixer->tracklist, play_track); ++ } ++ ++ if (cap_track) { ++ track_update (mixer, cap_track); ++ mixer->tracklist = g_list_append (mixer->tracklist, cap_track); ++ } ++ ++ if (snd_mixer_selem_is_enumerated (element)) { ++ mixer->tracklist = g_list_append (mixer->tracklist, ++ mixer_options_new (element, index)); ++ } ++ ++ snd_mixer_elem_set_callback_private (element, mixer); ++ snd_mixer_elem_set_callback (element, mixer_elem_callback); ++ } ++ ++ mark_master_track (mixer); ++} ++ ++static gboolean mixer_src_callback (gpointer user_data) ++{ ++ GstMixer *mixer = (GstMixer *)user_data; ++ ++ snd_mixer_handle_events (mixer->handle); ++ return TRUE; ++} ++ ++static gboolean mixer_src_dispatch (GSource *source, ++ GSourceFunc callback, ++ gpointer user_data) ++{ ++ return callback (user_data); ++} ++ ++static void mixer_src_attach (GstMixer *mixer) ++{ ++ static GSourceFuncs func = { ++ .dispatch = mixer_src_dispatch, ++ }; ++ struct pollfd pfd; ++ ++ if (snd_mixer_poll_descriptors (mixer->handle, &pfd, 1) != 1) ++ return; ++ ++ mixer->src = g_source_new (&func, sizeof (*mixer->src)); ++ g_source_add_unix_fd (mixer->src, pfd.fd, G_IO_IN | G_IO_ERR); ++ g_source_set_callback (mixer->src, mixer_src_callback, mixer, NULL); ++ g_source_attach (mixer->src, g_main_context_default ()); ++} ++ ++/* ++ * These are new functions that didn't exist in the original gstreamer API; ++ * instead of lengthy probing using factory, just provide a simpler method ++ */ ++ ++int gst_mixer_new (const char *name, GstMixer **mixer_ret) ++{ ++ GstMixer *mixer; ++ snd_hctl_t *hctl; ++ int err; ++ ++ mixer = (GstMixer *) g_object_new (GST_TYPE_MIXER, NULL); ++ mixer->name = g_strdup (name); ++ ++ err = snd_mixer_open ((snd_mixer_t **) &mixer->handle, 0); ++ if (err < 0) ++ return err; ++ ++ err = snd_mixer_attach (mixer->handle, name); ++ if (err < 0) ++ goto error; ++ ++ err = snd_mixer_selem_register (mixer->handle, NULL, NULL); ++ if (err < 0) ++ goto error; ++ ++ err = snd_mixer_load (mixer->handle); ++ if (err < 0) ++ goto error; ++ ++ snd_mixer_get_hctl (mixer->handle, name, &hctl); ++ { ++ snd_ctl_card_info_t *info; ++ ++ snd_ctl_card_info_alloca (&info); ++ snd_ctl_card_info (snd_hctl_ctl (hctl), info); ++ mixer->card_name = g_strdup_printf ("%s (Alsa mixer)", ++ snd_ctl_card_info_get_name (info)); ++ } ++ ++ snd_mixer_set_callback_private (mixer->handle, mixer); ++ snd_mixer_set_callback (mixer->handle, mixer_callback); ++ ++ create_track_list (mixer); ++ ++ mixer_src_attach (mixer); ++ ++ *mixer_ret = mixer; ++ return 0; ++ ++ error: ++ gst_object_unref (mixer); ++ return err; ++} ++ ++GList *gst_mixer_probe_devices (void) ++{ ++ int card = -1; ++ GList *card_list = NULL; ++ ++ while (snd_card_next(&card) >= 0 && card >= 0) { ++ GstMixer *mixer; ++ char name [16]; ++ int err; ++ ++ sprintf (name, "hw:%d", card); ++ err = gst_mixer_new (name, &mixer); ++ if (err < 0) ++ continue; ++ card_list = g_list_append (card_list, mixer); ++ } ++ ++ return card_list; ++} ++ ++const gchar *gst_mixer_get_card_name (GstMixer *mixer) ++{ ++ return mixer->card_name; ++} +--- a/panel-plugin/xfce-plugin-dialog.c ++++ b/panel-plugin/xfce-plugin-dialog.c +@@ -25,8 +25,7 @@ + + #include + +-#include +-#include ++#include "../libxfce4mixer/audio.h" + + #include + #include +--- a/panel-plugin/xfce-plugin-dialog.h ++++ b/panel-plugin/xfce-plugin-dialog.h +@@ -24,8 +24,7 @@ + + #include + +-#include +-#include ++#include "../libxfce4mixer/audio.h" + + G_BEGIN_DECLS + +--- a/xfce4-mixer/xfce-mixer-container.c ++++ b/xfce4-mixer/xfce-mixer-container.c +@@ -23,8 +23,7 @@ + #include + #endif + +-#include +-#include ++#include "../libxfce4mixer/audio.h" + + #include + #include +--- a/xfce4-mixer/xfce-mixer-controls-dialog.c ++++ b/xfce4-mixer/xfce-mixer-controls-dialog.c +@@ -23,8 +23,7 @@ + #include + #endif + +-#include +-#include ++#include "../libxfce4mixer/audio.h" + + #include + #include +--- a/xfce4-mixer/xfce-mixer-option.c ++++ b/xfce4-mixer/xfce-mixer-option.c +@@ -23,8 +23,7 @@ + #include + #endif + +-#include +-#include ++#include "../libxfce4mixer/audio.h" + + #include + #include +--- a/xfce4-mixer/xfce-mixer-switch.c ++++ b/xfce4-mixer/xfce-mixer-switch.c +@@ -23,8 +23,7 @@ + #include + #endif + +-#include +-#include ++#include "../libxfce4mixer/audio.h" + + #include + #include +--- a/xfce4-mixer/xfce-mixer-track.c ++++ b/xfce4-mixer/xfce-mixer-track.c +@@ -27,8 +27,7 @@ + #include + #endif + +-#include +-#include ++#include "../libxfce4mixer/audio.h" + + #include + #include +--- a/xfce4-mixer/xfce-mixer-window.c ++++ b/xfce4-mixer/xfce-mixer-window.c +@@ -23,9 +23,7 @@ + #include + #endif + +-#include +-#include +-#include ++#include "../libxfce4mixer/audio.h" + + #include + #include +--- a/libxfce4mixer/Makefile.am ++++ b/libxfce4mixer/Makefile.am +@@ -17,7 +17,14 @@ libxfce4mixer_la_SOURCES = \ + xfce-mixer-preferences.h \ + xfce-mixer-preferences.c \ + xfce-mixer-debug.h \ +- xfce-mixer-debug.c ++ xfce-mixer-debug.c \ ++ audio.h ++ ++if XFCE4_MIXER_ALSA ++libxfce4mixer_la_SOURCES += \ ++ xfce4-mixer-alsa.h \ ++ xfce4-mixer-alsa.c ++endif + + libxfce4mixer_la_CPPFLAGS = \ + -I$(top_builddir) \ +@@ -35,7 +42,12 @@ libxfce4mixer_la_CFLAGS = \ + $(LIBXFCE4UI_CFLAGS) \ + $(XFCONF_CFLAGS) \ + $(DBUS_GLIB_CFLAGS) \ +- $(GST_PLUGINS_BASE_CFLAGS) ++ $(GST_CFLAGS) ++ ++if XFCE4_MIXER_ALSA ++libxfce4mixer_la_CFLAGS += \ ++ $(ALSA_CFLAGS) ++endif + + libxfce4mixer_la_LDFLAGS = \ + -no-undefined +@@ -48,6 +60,13 @@ libxfce4mixer_la_LIBADD = \ + $(LIBXFCE4UI_LIBS) \ + $(XFCONF_LIBS) \ + $(DBUS_GLIB_LIBS) \ +- $(GST_PLUGINS_BASE_LIBS) \ ++ $(GST_LIBS) ++ ++if XFCE4_MIXER_ALSA ++libxfce4mixer_la_LIBADD += \ ++ $(ALSA_LIBS) ++else ++libxfce4mixer_la_LIBADD += \ + -lgstaudio-0.10 \ + -lgstinterfaces-0.10 ++endif +--- a/panel-plugin/Makefile.am ++++ b/panel-plugin/Makefile.am +@@ -27,7 +27,7 @@ libmixer_la_CFLAGS = \ + $(LIBXFCE4UI_CFLAGS) \ + $(LIBXFCE4PANEL_CFLAGS) \ + $(XFCONF_CFLAGS) \ +- $(GST_PLUGINS_BASE_CFLAGS) \ ++ $(GST_CFLAGS) \ + $(KEYBINDER_CFLAGS) + + libmixer_la_DEPENDENCIES = \ +@@ -48,11 +48,18 @@ libmixer_la_LIBADD = \ + $(LIBXFCE4UI_LIBS) \ + $(LIBXFCE4PANEL_LIBS) \ + $(XFCONF_LIBS) \ +- $(GST_PLUGINS_BASE_LIBS) \ +- -lgstaudio-0.10 \ +- -lgstinterfaces-0.10 \ ++ $(GST_LIBS) \ + $(KEYBINDER_LIBS) + ++if XFCE4_MIXER_ALSA ++libmixer_la_LIBADD += \ ++ $(ALSA_LIBS) ++else ++libmixer_la_LIBADD += \ ++ -lgstaudio-0.10 \ ++ -lgstinterfaces-0.10 ++endif ++ + desktopdir = $(datadir)/xfce4/panel/plugins + + desktop_in_files = mixer.desktop.in +--- a/xfce4-mixer/Makefile.am ++++ b/xfce4-mixer/Makefile.am +@@ -34,7 +34,7 @@ xfce4_mixer_CFLAGS = \ + $(LIBXFCE4UTIL_CFLAGS) \ + $(LIBXFCE4UI_CFLAGS) \ + $(XFCONF_CFLAGS) \ +- $(GST_PLUGINS_BASE_CFLAGS) ++ $(GST_CFLAGS) + + xfce4_mixer_DEPENDENCIES = \ + $(top_builddir)/libxfce4mixer/libxfce4mixer.la +@@ -47,9 +47,16 @@ xfce4_mixer_LDFLAGS = \ + $(LIBXFCE4UTIL_LIBS) \ + $(LIBXFCE4UI_LIBS) \ + $(XFCONF_LIBS) \ +- $(GST_PLUGINS_BASE_LIBS) \ ++ $(GST_LIBS) ++ ++if XFCE4_MIXER_ALSA ++xfce4_mixer_LDFLAGS += \ ++ $(ALSA_LIBS) ++else ++xfce4_mixer_LDFLAGS += \ + -lgstaudio-0.10 \ + -lgstinterfaces-0.10 ++endif + + dist_man_MANS = xfce4-mixer.1 + +--- /dev/null ++++ b/libxfce4mixer/audio.h +@@ -0,0 +1,8 @@ ++#ifdef XFCE4_MIXER_ALSA ++#include ++#include "xfce4-mixer-alsa.h" ++#else ++#include ++#include ++#include ++#endif +--- a/configure.ac.in ++++ b/configure.ac.in +@@ -96,13 +96,29 @@ dnl *********************************** + XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.42.0]) + XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.42.0]) + XDT_CHECK_PACKAGE([DBUS_GLIB], [dbus-glib-1], [0.84]) +-XDT_CHECK_PACKAGE([GST_PLUGINS_BASE], [gstreamer-plugins-base-0.10], [0.10.25]) + XDT_CHECK_PACKAGE([GTK], [gtk+-3.0], [3.14.0]) + XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.12.0]) + XDT_CHECK_PACKAGE([LIBXFCE4UI], [libxfce4ui-2], [4.12.0]) + XDT_CHECK_PACKAGE([LIBXFCE4PANEL], [libxfce4panel-2.0], [4.12.0]) + XDT_CHECK_PACKAGE([XFCONF], [libxfconf-0], [4.12.0]) + ++AC_MSG_CHECKING(for audio engine) ++AC_ARG_WITH(audio, ++ AS_HELP_STRING([--with-audio], ++ [audio engine, either gstmixer or alsa (default)]), ++ audio="$withval", audio="alsa") ++ ++if test "$audio" = "gstmixer"; then ++ AC_MSG_RESULT(gstreamer-0.10 native mixer) ++ XDT_CHECK_PACKAGE([GST], [gstreamer-plugins-base-0.10], [0.10.25]) ++else ++ AC_MSG_RESULT(gstreamer-1.0 ALSA mixer) ++ XDT_CHECK_PACKAGE([GST], [gstreamer-1.0], [1.0]) ++ XDT_CHECK_PACKAGE([ALSA], [alsa], [0.9]) ++ AC_DEFINE([XFCE4_MIXER_ALSA], 1, [Built-in ALSA-based gstreamer mixer i/f]) ++fi ++AM_CONDITIONAL([XFCE4_MIXER_ALSA], [test x"$audio" != x"gstmixer"]) ++ + dnl *********************************** + dnl *** Check for optional packages *** + dnl diff --git a/xfce4-mixer-4.11.0.20210123git-no-full-debug-default-for-git.patch b/xfce4-mixer-4.11.0.20210123git-no-full-debug-default-for-git.patch new file mode 100644 index 0000000..e37557c --- /dev/null +++ b/xfce4-mixer-4.11.0.20210123git-no-full-debug-default-for-git.patch @@ -0,0 +1,16 @@ +--- + configure.ac.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/configure.ac.in ++++ b/configure.ac.in +@@ -32,7 +32,7 @@ m4_define([xfce4_mixer_version], [xfce4_ + dnl ******************************************* + dnl *** Debugging support for git snapshots *** + dnl ******************************************* +-m4_define([mixer_debug_default], [ifelse(xfce4_mixer_version_tag(), [git], [full], [minimum])]) ++m4_define([mixer_debug_default], [minimum]) + + dnl *************************** + dnl *** Initialize autoconf *** + diff --git a/xfce4-mixer.spec b/xfce4-mixer.spec index 212cf9d..4b60eda 100644 --- a/xfce4-mixer.spec +++ b/xfce4-mixer.spec @@ -1,75 +1,80 @@ %define majver %(echo %version | cut -d. -f1-2) Name: xfce4-mixer -Version: 4.11.0 -Release: 2mamba +Version: 4.11.0.20210123git +Release: 1mamba Summary: Volume control plugin for the Xfce 4 panel Group: Graphical Desktop/Applications/Multimedia Vendor: openmamba Distribution: openmamba Packager: Silvan Calarco URL: http://www.xfce.org/ -Source: http://archive.xfce.org/src/apps/xfce4-mixer/%{majver}/xfce4-mixer-%{version}.tar.bz2 +Source: https://github.com/xfce-mirror/xfce4-mixer.git/master@ce642ac52e0bed7495261694fd630748bf71157f/xfce4-mixer-%{version}.tar.bz2 #Source: http://www.xfce.org/archive/xfce-%{version}/src/xfce4-mixer-%{version}.tar.bz2 +Patch0: xfce4-mixer-4.11.0.20210123git-libalsa-1.2.4.patch +Patch1: xfce4-mixer-4.11.0.20210123git-no-full-debug-default-for-git.patch License: GPL -BuildRoot: %{_tmppath}/%{name}-%{version}-root ## AUTOBUILDREQ-BEGIN BuildRequires: glibc-devel +BuildRequires: ldconfig +BuildRequires: libICE-devel +BuildRequires: libSM-devel +BuildRequires: libX11-devel +BuildRequires: libXau-devel +BuildRequires: libXdmcp-devel +BuildRequires: libalsa-devel BuildRequires: libatk-devel +BuildRequires: libbrotli-devel +BuildRequires: libbsd-devel +BuildRequires: libbzip2-devel BuildRequires: libcairo-devel BuildRequires: libdbus-devel BuildRequires: libdbus-glib-devel -BuildRequires: libexpat-devel -BuildRequires: libfontconfig-devel BuildRequires: libfreetype-devel BuildRequires: libgdk-pixbuf-devel -BuildRequires: libGL-devel BuildRequires: libglib-devel -BuildRequires: libglitz-devel -BuildRequires: libgst-plugins-base-devel +BuildRequires: libgraphite2-devel BuildRequires: libgstreamer-devel BuildRequires: libgtk-devel -BuildRequires: libICE-devel +BuildRequires: libharfbuzz-devel BuildRequires: libpango-devel -BuildRequires: libpixman-devel +BuildRequires: libpcre-devel BuildRequires: libpng-devel -BuildRequires: libpthread-stubs-devel -BuildRequires: libselinux-devel -BuildRequires: libSM-devel BuildRequires: libstartup-notification-devel -BuildRequires: libstdc++6-devel +BuildRequires: libsystemd-devel BuildRequires: libuuid-devel -BuildRequires: libX11-devel -BuildRequires: libXau-devel BuildRequires: libxcb-devel -BuildRequires: libxcb-util-devel -BuildRequires: libXdmcp-devel -BuildRequires: libxfce4util-devel -BuildRequires: libxfcegui4-devel -BuildRequires: libxml2-devel -BuildRequires: libXrender-devel -BuildRequires: libz-devel -BuildRequires: udev-devel -BuildRequires: xfce4-panel-devel -BuildRequires: xfconf-devel -## AUTOBUILDREQ-END -BuildRequires: libxfce4util-devel >= 4.12.1-1mamba -BuildRequires: libunique1-devel BuildRequires: libxfce4ui-devel -Requires: xfce4-panel >= 4.4.0 +BuildRequires: libxfce4util-devel +BuildRequires: libxfconf-devel +BuildRequires: libz-devel +BuildRequires: xfce4-panel-devel +## AUTOBUILDREQ-END +BuildRequires: libxfce4util-devel >= 4.16.0 +BuildRequires: libunique1-devel +BuildRequires: libxfce4ui-devel >= 4.16.0 +Requires: xfce4-panel >= 4.16.0 +BuildRoot: %{_tmppath}/%{name}-%{version}-root %description xfce4-mixer is the volume control plugin for the Xfce 4 panel. Includes a simple sound mixer. +%debug_package + %prep %setup -q +%patch0 -p1 +%patch1 -p1 + +NOCONFIGURE=1 ./autogen.sh %build -%configure --enable-final +%configure \ + --enable-maintainer-mode + %make -j1 %install [ "%{buildroot}" != / ] && rm -rf "%{buildroot}" -make install DESTDIR=$RPM_BUILD_ROOT mandir=%{_mandir} %makeinstall %find_lang %{name} @@ -82,12 +87,14 @@ touch --no-create %{_datadir}/icons/hicolor || : if [ -x %{_bindir}/gtk-update-icon-cache ]; then %{_bindir}/gtk-update-icon-cache --quiet %{_datadir}/icons/hicolor || : fi +: %postun touch --no-create %{_datadir}/icons/hicolor || : if [ -x %{_bindir}/gtk-update-icon-cache ]; then %{_bindir}/gtk-update-icon-cache --quiet %{_datadir}/icons/hicolor || : fi +: %files -f %{name}.lang %defattr(-,root,root) @@ -95,17 +102,22 @@ fi %{_libdir}/xfce4/panel/plugins/libmixer.la %{_libdir}/xfce4/panel/plugins/libmixer.so %{_datadir}/applications/xfce4-mixer.desktop -%{_mandir}/man1/xfce4-mixer.1.gz %{_datadir}/pixmaps/xfce4-mixer/chain-broken.png %{_datadir}/pixmaps/xfce4-mixer/chain.png -%dir %{_datadir}/xfce4-mixer/* -%{_datadir}/xfce4-mixer/icons/hicolor/16x16/status/audio-input-microphone-muted.png -%{_datadir}/xfce4-mixer/icons/hicolor/scalable/status/audio-input-microphone-muted.svg +%{_datadir}/xfce4/mixer/icons/hicolor/16x16/status/audio-input-microphone-muted.png +%{_datadir}/xfce4/mixer/icons/hicolor/scalable/status/audio-input-microphone-muted.svg %{_datadir}/xfce4/panel/plugins/mixer.desktop +%{_mandir}/man1/xfce4-mixer.1* %doc AUTHORS COPYING #ChangeLog NEWS README %changelog +* Sat Jan 23 2021 Silvan Calarco 4.11.0.20210123git-1mamba +- update to 4.11.0.20210123git + +* Sat Jan 23 2021 Silvan Calarco 4.11.0-3mamba +- rebuilt with xfce 4.16 + * Thu Mar 26 2015 Silvan Calarco 4.11.0-2mamba - rebuilt by autoport with build requirements: libxfce4util-devel>=4.12.1-1mamba