Hello community,

here is the log from the commit of package pasystray for openSUSE:Factory 
checked in at 2016-07-20 09:24:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/pasystray (Old)
 and      /work/SRC/openSUSE:Factory/.pasystray.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "pasystray"

Changes:
--------
--- /work/SRC/openSUSE:Factory/pasystray/pasystray.changes      2016-01-12 
16:13:33.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.pasystray.new/pasystray.changes 2016-07-20 
09:24:28.000000000 +0200
@@ -1,0 +2,33 @@
+Mon Jul 18 11:42:38 UTC 2016 - [email protected]
+
+- Version bump to 0.6.0:
+  * start pavucontrol with ctrl-click on status icon
+  * update systray icon on default sink change  
+  * add context menu option to move all in/outputs to sink/source
+  * update the volume icon of non-default sinks
+  * To fix notifications for changes of their volume level
+  * possible to set the volume icon for notifications independent of the tray 
icon
+  * use gauges for volume notifications
+  * set notification icon when changing systray icon
+  * send notifications only on volume / mute changes
+  * add option to always send notifications on volume change
+  * log systray implementation
+  * add option to include monitors
+  * support disabling status icon support
+  * include volume and muted state in item name
+  * set notification urgency to low
+  * minor Housekeeping for README
+  * deprecate --max-volume in favor of --volume-max
+  * add option to disable all notifications
+  * re-add volume-max option handling
+  * update manpage with --volume-inc
+  * add option to set volume increment
+  * add TODO entries for feature requests
+  * stop using stock GtkButton
+  * check mii only where needed
+  * start pavucontrol with ctrl-click on status icon
+  * pasystray.desktop: Add missing semicolon to "Keywords"
+
+- Removed patch icon_keywords_fix.patch (fixed in upstream) 
+
+-------------------------------------------------------------------

Old:
----
  icon_keywords_fix.patch
  pasystray-0.5.2.tar.gz

New:
----
  pasystray-0.6.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ pasystray.spec ++++++
--- /var/tmp/diff_new_pack.Ar81tO/_old  2016-07-20 09:24:29.000000000 +0200
+++ /var/tmp/diff_new_pack.Ar81tO/_new  2016-07-20 09:24:29.000000000 +0200
@@ -22,16 +22,15 @@
 %define build_wayland_backend 1
 %endif
 Name:           pasystray
-Version:        0.5.2
+Version:        0.6.0
 Release:        0
 Summary:        PulseAudio system tray
 License:        LGPL-2.1+
 Group:          System/GUI/Other
 Url:            https://github.com/christophgysin/pasystray
 Source:         
https://github.com/christophgysin/pasystray/archive/pasystray-%{version}.tar.gz
-# pasystray.desktop: Add missing semicolon to "Keywords"
-Patch0:         icon_keywords_fix.patch
 BuildRequires:  automake
+BuildRequires:  pkgconfig
 BuildRequires:  update-desktop-files
 BuildRequires:  pkgconfig(avahi-glib)
 BuildRequires:  pkgconfig(avahi-ui)
@@ -65,7 +64,6 @@
 
 %prep
 %setup -q -n %{name}-%{name}-%{version}
-%patch0 -p1
 
 %build
 autoreconf -fi
@@ -73,7 +71,7 @@
 make %{?_smp_mflags}
 
 %install
-make DESTDIR=%{buildroot} install %{?_smp_mflags}
+make %{?_smp_mflags} DESTDIR=%{buildroot} install
 %suse_update_desktop_file  -u -r 
%{buildroot}%{_datadir}/applications/pasystray.desktop AudioVideo Mixer
 %suse_update_desktop_file  -u -r 
%{buildroot}%{_sysconfdir}/xdg/autostart/pasystray.desktop AudioVideo Mixer
 
@@ -85,7 +83,8 @@
 %{_bindir}/pasystray
 %{_datadir}/applications/pasystray.desktop
 %{_datadir}/icons/hicolor/scalable/apps/pasystray.svg
-%{_mandir}/man1/pasystray.1.gz
+%{_mandir}/man1/pasystray.1%{ext_man}
 %{_datadir}/pasystray/pasystray.glade
 %{_datadir}/pixmaps/pasystray.png
 
+%changelog

++++++ pasystray-0.5.2.tar.gz -> pasystray-0.6.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/.travis.sh 
new/pasystray-pasystray-0.6.0/.travis.sh
--- old/pasystray-pasystray-0.5.2/.travis.sh    1970-01-01 01:00:00.000000000 
+0100
+++ new/pasystray-pasystray-0.6.0/.travis.sh    2016-07-17 12:41:33.000000000 
+0200
@@ -0,0 +1,14 @@
+#!/bin/bash
+set -euo pipefail
+
+export CC=${USE_CC:-$CC}
+
+$CC --version
+
+aclocal
+autoconf
+autoheader
+automake --add-missing
+./configure ${EXTRA_CONF:-} || (cat config.log; exit 1)
+make
+make test
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/.travis.yml 
new/pasystray-pasystray-0.6.0/.travis.yml
--- old/pasystray-pasystray-0.5.2/.travis.yml   2015-05-05 21:25:16.000000000 
+0200
+++ new/pasystray-pasystray-0.6.0/.travis.yml   2016-07-17 12:41:33.000000000 
+0200
@@ -1,9 +1,22 @@
+addons:
+  apt:
+    sources:
+      - ubuntu-toolchain-r-test
+      - llvm-toolchain-precise-3.7
+    packages:
+      - gcc-4.9
+      - clang-3.7
+      - libgtk-3-dev
+      - libpulse-dev
+      - libnotify-dev
+      - libappindicator3-dev
 language: c
-before_install:
-    - sudo apt-get update -qq
-    - sudo apt-get install -qq libgtk-3-dev libpulse-dev libavahi-client-dev 
libavahi-glib-dev libnotify-dev libappindicator3-dev
-before_script:
-    - aclocal
-    - autoconf
-    - autoheader
-    - automake --add-missing
+script: ./.travis.sh
+env:
+  - CFLAGS=--std=c99
+  - CFLAGS=--std=c99 EXTRA_CONF=--with-gtk=2
+  - USE_CC=gcc-4.9 CFLAGS=--std=c99
+  - USE_CC=gcc-4.9 CFLAGS=--std=c11
+  - USE_CC=clang-3.7 CFLAGS=--std=c99
+  - USE_CC=clang-3.7 CFLAGS=--std=c11
+sudo: false
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/README.md 
new/pasystray-pasystray-0.6.0/README.md
--- old/pasystray-pasystray-0.5.2/README.md     2015-05-05 21:25:16.000000000 
+0200
+++ new/pasystray-pasystray-0.6.0/README.md     2016-07-17 12:41:33.000000000 
+0200
@@ -1,10 +1,10 @@
-PulseAudio system tray
+PulseAudio System Tray
 ======================
 [![Build 
Status](https://travis-ci.org/christophgysin/pasystray.png?branch=master)](https://travis-ci.org/christophgysin/pasystray)
 
-A replacement for the deprecated padevchooser
+A replacement for the deprecated padevchooser.
 
-Pasystray allows setting the default PulseAudio source/sink and moving
+pasystray allows setting the default PulseAudio source/sink and moving
 streams on the fly between sources/sinks without restarting the client
 applications.
 
@@ -12,13 +12,11 @@
 --------
 
 * switch default sink/source
-* move playback/record stream to different sink/source on the fly
+* move playback/record stream to a different sink/source on the fly
 * detect pulseaudio instances on the network with avahi
 * set X property PULSE_SERVER (like padevchooser's "set default server")
 * adjust volume/toggle mute of sinks/sources and playback/record streams
-* rename devices
-
-Renaming devices needs module-device-manager to be loaded in pulseaudio.
+* rename devices (pulseaudio must have module-device-manager loaded)
 
 To detect remote sinks/sources you need to enable module-zeroconf-discover on
 the local PulseAudio instance and module-zeroconf-publish on the remote side.
@@ -28,10 +26,12 @@
 $ PULSE_SERVER=remote_host pasystray
 ```
 
-Mouse bindings
+Mouse Bindings
 --------------
 
 over status icon:
+* left/right-click: open menu
+* ctrl + left-click: start pavucontrol
 * middle-click / alt + left-click: toggle mute default sink
 * ctrl + middle-click / ctrl + alt + left-click: toggle mute default source
 * scroll up/down: adjust the default sink volume
@@ -50,9 +50,9 @@
 Troubleshooting
 ---------------
 
-If pasystray icon is not displayed in your Unity system tray, you will have
+If the pasystray icon is not displayed in your Unity system tray, you will have
 to whitelist it. Read this for instructions:
 
http://askubuntu.com/questions/30742/how-do-i-access-and-enable-more-icons-to-be-in-the-system-tray
 
-For ubuntu 13.04 and above, AppIndicator is mandatory. Unfortunatly, the
-ctrl-click/ctrl-scroll bindings don't work with AppIndicator.
+For Ubuntu 13.04 and above, AppIndicator is mandatory. Unfortunately, the
+ctrl + click / ctrl + scroll bindings don't work with AppIndicator.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/TODO 
new/pasystray-pasystray-0.6.0/TODO
--- old/pasystray-pasystray-0.5.2/TODO  2015-05-05 21:25:16.000000000 +0200
+++ new/pasystray-pasystray-0.6.0/TODO  2016-07-17 12:41:33.000000000 +0200
@@ -1,3 +1,4 @@
+TODO:
 verify all mouse bindings works
 
 BUGS:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/configure.ac 
new/pasystray-pasystray-0.6.0/configure.ac
--- old/pasystray-pasystray-0.5.2/configure.ac  2015-05-05 21:25:16.000000000 
+0200
+++ new/pasystray-pasystray-0.6.0/configure.ac  2016-07-17 12:41:33.000000000 
+0200
@@ -1,6 +1,6 @@
 #  This file is part of PaSystray
 #
-#  Copyright (C) 2011-2015  Christoph Gysin
+#  Copyright (C) 2011-2016  Christoph Gysin
 #
 #  PaSystray is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU Lesser General Public License as
@@ -19,7 +19,7 @@
 
 AC_PREREQ([2.68])
 
-AC_INIT([pasystray], [0.5.2], [[email protected]], [pasystray],
+AC_INIT([pasystray], [0.6.0], [[email protected]], [pasystray],
         [http://github.com/christophgysin/pasystray])
 AC_CONFIG_SRCDIR([src/pasystray.c])
 AC_CONFIG_HEADERS([src/config.h])
@@ -38,6 +38,7 @@
 AC_MSG_RESULT($GTK_VERSION)
 
 PKG_CHECK_MODULES(GTK, [ $GTK_VERSION ])
+AC_DEFINE_UNQUOTED(GTK_VERSION_MAJOR, $with_gtk, [Have GTK version?])
 AC_SUBST(GTK_CFLAGS)
 AC_SUBST(GTK_LIBS)
 
@@ -100,12 +101,28 @@
 AS_IF([test "x$HAVE_X11" = x1], AC_DEFINE([HAVE_X11], 1,
       [Have X11?]))
 
+### optional gtk stausicon support ###########################################
+AC_ARG_ENABLE([statusicon],
+    AS_HELP_STRING([--disable-statusicon], [Disable optional statusicon 
support]))
+
+AS_IF([test "x$enable_statusicon" != xno],
+    HAVE_STATUSICON=1, HAVE_STATUSICON=0)
+
+AC_SUBST(HAVE_STATUSICON)
+AM_CONDITIONAL([HAVE_STATUSICON], [test "x$HAVE_STATUSICON" = x1])
+AS_IF([test "x$HAVE_STATUSICON" = x1], AC_DEFINE([HAVE_STATUSICON], 1,
+      [Have StatusIcon?]))
+
 ### optional libappindicator support 
###########################################
 AC_ARG_ENABLE([appindicator],
     AS_HELP_STRING([--disable-appindicator], [Disable optional appindicator 
support]))
 
+case ${with_gtk} in
+    2) APPINDICATOR_VERSION=appindicator-0.1;;
+    3) APPINDICATOR_VERSION=appindicator3-0.1;;
+esac
 AS_IF([test "x$enable_appindicator" != xno],
-    [PKG_CHECK_MODULES(APPINDICATOR, [ appindicator3-0.1 ], 
HAVE_APPINDICATOR=1,
+    [PKG_CHECK_MODULES(APPINDICATOR, [ $APPINDICATOR_VERSION ], 
HAVE_APPINDICATOR=1,
                        HAVE_APPINDICATOR=0)], HAVE_APPINDICATOR=0)
 
 AS_IF([test "x$enable_appindicator" = xyes && test "x$HAVE_APPINDICATOR" = x0],
@@ -116,7 +133,7 @@
 AC_SUBST(HAVE_APPINDICATOR)
 AM_CONDITIONAL([HAVE_APPINDICATOR], [test "x$HAVE_APPINDICATOR" = x1])
 AS_IF([test "x$HAVE_APPINDICATOR" = x1], AC_DEFINE([HAVE_APPINDICATOR], 1,
-      [Have APPINDICATOR?]))
+      [Have AppIndicator?]))
 
################################################################################
 
 if test "x$GCC" = xyes -o "x$CLANG" = xyes; then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/data/pasystray.desktop 
new/pasystray-pasystray-0.6.0/data/pasystray.desktop
--- old/pasystray-pasystray-0.5.2/data/pasystray.desktop        2015-05-05 
21:25:16.000000000 +0200
+++ new/pasystray-pasystray-0.6.0/data/pasystray.desktop        2016-07-17 
12:41:33.000000000 +0200
@@ -8,4 +8,4 @@
 StartupNotify=true
 Type=Application
 Categories=AudioVideo;Audio;
-Keywords=pulseaudio;tray;system tray;applet;volume
+Keywords=pulseaudio;tray;system tray;applet;volume;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/man/pasystray.1 
new/pasystray-pasystray-0.6.0/man/pasystray.1
--- old/pasystray-pasystray-0.5.2/man/pasystray.1       2015-05-05 
21:25:16.000000000 +0200
+++ new/pasystray-pasystray-0.6.0/man/pasystray.1       2016-07-17 
12:41:33.000000000 +0200
@@ -94,8 +94,20 @@
 .B \-d, \-\-debug
 Print debugging information.
 .TP
-.B \-m, \-\-max-volume=N
+.B \-m, \-\-volume-max=N
 Set the maximum volume (in percent).
+.TP
+.B \-i, \-\-volume-inc=N
+Set the volume increment.
+.TP
+.B \-n, \-\-no-notify
+Disable all notifications.
+.TP
+.B \-a, \-\-always-notify
+Enable notifications for all changes in pulsaudio.
+.TP
+.B \-\-include-monitors
+Show monitor sources.
 .SH SEE ALSO
 .BR pulseaudio (1),
 .BR pactl (1).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pasystray-pasystray-0.5.2/scripts/ubuntu-build-deps.sh 
new/pasystray-pasystray-0.6.0/scripts/ubuntu-build-deps.sh
--- old/pasystray-pasystray-0.5.2/scripts/ubuntu-build-deps.sh  1970-01-01 
01:00:00.000000000 +0100
+++ new/pasystray-pasystray-0.6.0/scripts/ubuntu-build-deps.sh  2016-07-17 
12:41:33.000000000 +0200
@@ -0,0 +1,4 @@
+apt-get install \
+    build-essential automake autoconf pkg-config \
+    libgtk-3-dev libpulse-dev libpulse-mainloop-glib0 \
+    libnotify-dev libavahi-glib-dev libappindicator3-dev
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/menu_info.c 
new/pasystray-pasystray-0.6.0/src/menu_info.c
--- old/pasystray-pasystray-0.5.2/src/menu_info.c       2015-05-05 
21:25:16.000000000 +0200
+++ new/pasystray-pasystray-0.6.0/src/menu_info.c       2016-07-17 
12:41:33.000000000 +0200
@@ -19,6 +19,7 @@
   USA.
 ***/
 
+#include <string.h>
 #include <glib.h>
 
 #include "menu_info.h"
@@ -189,6 +190,30 @@
     return -1;
 }
 
+char* menu_info_item_label(menu_info_item_t* mii)
+{
+    gchar* desc = mii->desc;
+
+    const size_t DESC_MAX = 80;
+    gchar desc_buf[DESC_MAX + 1];
+    if (strlen(mii->desc) > DESC_MAX)
+    {
+        g_snprintf(desc_buf, DESC_MAX+1, "%.*s...", (int)DESC_MAX-3, 
mii->desc);
+        desc = desc_buf;
+    }
+
+    if(!mii->volume)
+        return g_strdup(desc);
+
+    char vol_buf[PA_CVOLUME_SNPRINT_MAX];
+    gchar* label = g_strdup_printf("%s %s%s",
+        desc,
+        pa_volume_snprint(vol_buf, sizeof(vol_buf), mii->volume->values[0]),
+        mii->mute ? " [muted]" : "");
+
+    return label;
+}
+
 void menu_info_item_update(menu_info_t* mi, uint32_t index, const char* name,
         const char* desc, const pa_cvolume* vol, int mute, char* tooltip,
         const char* icon, const char* address, uint32_t target)
@@ -206,13 +231,22 @@
         return;
     }
 
+    menu_infos_t* mis = item->menu_info->menu_infos;
+
     g_debug("[menu_info] updating %s %u %s (target: %d)",
             menu_info_type_name(item->menu_info->type), index, desc, 
(int)target);
 
     g_free(item->name);
     item->name = g_strdup(name);
+
     g_free(item->desc);
     item->desc = g_strdup(desc);
+
+    /* only notify on volume / mute changes */
+    int notify = 0;
+    if ((vol && !pa_cvolume_equal(item->volume, vol)) || mute != item->mute)
+        notify = 1;
+
     g_free(item->volume);
     item->volume = g_memdup(vol, sizeof(pa_cvolume));
     item->mute = mute;
@@ -223,7 +257,10 @@
     menu_type_t submenu_type = menu_info_submenu_type(mi->type);
     menu_info_t* submenu = &mi->menu_infos->menu_info[submenu_type];
 
-    gtk_menu_item_set_label(GTK_MENU_ITEM(item->widget), desc);
+    gchar* label = menu_info_item_label(item);
+    gtk_menu_item_set_label(GTK_MENU_ITEM(item->widget), label);
+    g_free(label);
+
     systray_set_tooltip(GTK_WIDGET(item->widget), tooltip);
 
     switch(mi->type)
@@ -231,10 +268,11 @@
         case MENU_SERVER:
         case MENU_MODULE:
             g_debug("[menu_info] *** unhandled %s update! (index: %u, desc: 
%s)",
-                    menu_info_type_name(mi->type), index, desc);
+                    menu_info_type_name(mi->type), index, item->desc);
             break;
         case MENU_SINK:
         case MENU_SOURCE:
+            ui_set_volume_icon(item); // update sink item
             systray_update_item_in_all_submenus(item, submenu);
             break;
         case MENU_INPUT:
@@ -246,6 +284,9 @@
     /* if this is the default sink, update status icon acording to volume */
     if(mi->type == MENU_SINK && item == menu_info_item_get_by_name(mi, 
mi->default_name))
         ui_update_systray_icon(item);
+
+    if(notify && mis->settings.notify == NOTIFY_ALWAYS)
+        pulseaudio_update_volume_notification(item);
 }
 
 void menu_info_item_add(menu_info_t* mi, uint32_t index, const char* name,
@@ -286,7 +327,7 @@
     switch(mi->type)
     {
         case MENU_SERVER:
-            item->widget = systray_add_radio_item(mi, desc, tooltip);
+            item->widget = systray_add_radio_item(item, tooltip);
             gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item->widget),
                     (item->address == mi->default_name) ||
                     (item->address && mi->default_name &&
@@ -295,20 +336,24 @@
         case MENU_SINK:
         case MENU_SOURCE:
             item->context = menu_info_item_context_menu(item);
-            item->widget = systray_add_radio_item(mi, desc, tooltip);
+            item->widget = systray_add_radio_item(item, tooltip);
             gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item->widget),
                     g_str_equal(mi->default_name, item->name));
             systray_add_item_to_all_submenus(item, submenu);
             break;
         case MENU_INPUT:
         case MENU_OUTPUT:
+        {
+            gchar* label = menu_info_item_label(item);
             item->widget = systray_menu_add_submenu(mi->menu, item->submenu,
-                    desc, tooltip, icon);
+                    label, tooltip, icon);
+            g_free(label);
             systray_add_all_items_to_submenu(submenu, item);
             break;
+        }
         case MENU_MODULE:
             item->context = menu_info_item_context_menu(item);
-            item->widget = systray_add_menu_item(mi, desc, tooltip, icon);
+            item->widget = systray_add_menu_item(mi, item->desc, tooltip, 
icon);
             break;
     }
 
@@ -342,19 +387,30 @@
 
         case MENU_SINK:
         case MENU_SOURCE:
+        {
+            menu_type_t type = (mii->menu_info->type == MENU_SINK) ? 
MENU_INPUT : MENU_OUTPUT;
+            gchar* label = g_strdup_printf("move all %ss here",
+                    menu_info_type_name(type));
+            item = gtk_menu_item_new_with_label(label);
+            g_free(label);
+            g_signal_connect(item, "button-press-event",
+                    G_CALLBACK(menu_info_item_move_all_cb), mii);
+            gtk_menu_shell_append(menu, item);
+
             item = gtk_menu_item_new_with_label("rename");
             g_signal_connect(item, "button-press-event",
                     G_CALLBACK(menu_info_item_rename_cb), mii);
+            gtk_menu_shell_append(menu, item);
             break;
-
+        }
         case MENU_MODULE:
             item = gtk_menu_item_new_with_label("unload");
             g_signal_connect(item, "button-press-event",
                     G_CALLBACK(menu_info_module_unload_cb), mii);
+            gtk_menu_shell_append(menu, item);
             break;
     }
 
-    gtk_menu_shell_append(menu, item);
     gtk_widget_show_all(GTK_WIDGET(menu));
     return menu;
 }
@@ -368,7 +424,7 @@
     subitem->name = g_strdup(name);
     subitem->desc = g_strdup(desc);
     subitem->menu_info = mi;
-    subitem->widget = systray_add_radio_item(mi, desc, tooltip);
+    subitem->widget = systray_add_radio_item(subitem, tooltip);
 
     gboolean active = mi->parent->target == index;
     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem->widget), 
active);
@@ -395,8 +451,10 @@
     g_debug("[menu_info] updating subitem %s %u '%s' %s", 
menu_info_type_name(mi->type),
             index, desc, active ? " (active)" : "");
 
-    if(!g_str_equal(item->desc, desc))
-        gtk_menu_item_set_label(GTK_MENU_ITEM(item->widget), desc);
+    gchar* label = menu_info_item_label(item);
+    gtk_menu_item_set_label(GTK_MENU_ITEM(item->widget), label);
+    g_free(label);
+
     if(active)
         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item->widget), 
TRUE);
 }
@@ -433,8 +491,10 @@
 void menu_info_item_clicked(GtkWidget* item, GdkEventButton* event,
         menu_info_item_t* mii)
 {
-    g_debug("[systray] button-press-event mod:%s button:%i",
-            (event->state & GDK_CONTROL_MASK) ? "ctrl" : "", event->button);
+    g_debug("[menu_info] item clicked mod:%s%s button:%i",
+            (event->state & GDK_CONTROL_MASK) ? "[ctrl]" : "",
+            (event->state & GDK_MOD1_MASK) ? "[alt]" : "",
+            event->button);
 
     switch(event->button)
     {
@@ -464,22 +524,24 @@
 void menu_info_item_scrolled(GtkWidget* item, GdkEventScroll* event,
         menu_info_item_t* mii)
 {
-    g_debug("[systray] scroll-event mod:%s dir:%s",
+    g_debug("[menu_info] scroll-event mod:%s dir:%s",
             (event->state & GDK_CONTROL_MASK) ? "ctrl" : "",
             (event->direction == GDK_SCROLL_UP) ? "up" :
             (event->direction == GDK_SCROLL_DOWN) ? "down" :
             (event->direction == GDK_SCROLL_LEFT) ? "left" :
             (event->direction == GDK_SCROLL_RIGHT) ? "right" : "???");
 
+    menu_infos_t* mis = mii->menu_info->menu_infos;
+
     int inc = 0;
 
     switch(event->direction)
     {
         case GDK_SCROLL_UP:
-            inc = 1;
+            inc = mis->settings.volume_inc;
             break;
         case GDK_SCROLL_DOWN:
-            inc = -1;
+            inc = -mis->settings.volume_inc;
             break;
         default:
             return;
@@ -499,13 +561,13 @@
     }
 }
 
-void menu_info_subitem_clicked(GtkWidget* item, GdkEvent* event,
+void menu_info_subitem_clicked(GtkWidget* item, GdkEventButton* event,
         menu_info_item_t* mii)
 {
-    g_debug("move %s %s to %s %s",
-            menu_info_type_name(mii->menu_info->parent->menu_info->type),
-            mii->menu_info->parent->desc,
-            menu_info_type_name(mii->menu_info->type), mii->desc);
+    g_debug("[menu_info] subitem clicked mod:%s%s button:%i",
+            (event->state & GDK_CONTROL_MASK) ? "[ctrl]" : "",
+            (event->state & GDK_MOD1_MASK) ? "[alt]" : "",
+            event->button);
 
     switch(mii->menu_info->type)
     {
@@ -523,9 +585,16 @@
     }
 }
 
+void menu_info_item_move_all_cb(GtkWidget* item, GdkEventButton* event, void* 
userdata)
+{
+    menu_info_item_t* mii = userdata;
+    pulseaudio_move_all(mii);
+}
+
 void menu_info_item_rename_cb(GtkWidget* item, GdkEventButton* event, void* 
userdata)
 {
-    menu_info_item_rename_dialog(userdata);
+    menu_info_item_t* mii = userdata;
+    menu_info_item_rename_dialog(mii);
 }
 
 void menu_info_item_rename_dialog(menu_info_item_t* mii)
@@ -533,7 +602,7 @@
     gtk_menu_popdown(GTK_MENU(mii->menu_info->menu_infos->menu));
 
     char* title = g_strdup_printf("Rename %s %s",
-            menu_info_type_name(mii->menu_info->type), mii->desc);
+            menu_info_type_name(mii->menu_info->type), mii->name);
     char* text = g_strdup_printf("%s to:", title);
 
     GtkDialog* dialog = ui_renamedialog();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/menu_info.h 
new/pasystray-pasystray-0.6.0/src/menu_info.h
--- old/pasystray-pasystray-0.5.2/src/menu_info.h       2015-05-05 
21:25:16.000000000 +0200
+++ new/pasystray-pasystray-0.6.0/src/menu_info.h       2016-07-17 
12:41:33.000000000 +0200
@@ -55,8 +55,17 @@
     char* default_name;
 };
 
+typedef enum {
+    NOTIFY_NEVER,
+    NOTIFY_DEFAULT,
+    NOTIFY_ALWAYS,
+} notify_t;
+
 struct settings_t_ {
-    int max_volume;
+    int volume_max;
+    int volume_inc;
+    notify_t notify;
+    gboolean monitors;
 };
 typedef struct settings_t_ settings_t;
 
@@ -97,6 +106,8 @@
 
 const char* menu_info_type_name(menu_type_t type);
 menu_type_t menu_info_submenu_type(menu_type_t menu_type);
+char* menu_info_item_label(menu_info_item_t* mii);
+
 void menu_info_item_add(menu_info_t* mi, uint32_t index, const char* name,
         const char* desc, const pa_cvolume* vol, int mute, char* tooltip,
         const char* icon, const char* address, uint32_t target);
@@ -116,9 +127,11 @@
         menu_info_item_t* mii);
 void menu_info_item_scrolled(GtkWidget* item, GdkEventScroll* event,
         menu_info_item_t* mii);
-void menu_info_subitem_clicked(GtkWidget* item, GdkEvent* event,
+void menu_info_subitem_clicked(GtkWidget* item, GdkEventButton* event,
         menu_info_item_t* mii);
 
+void menu_info_item_move_all_cb(GtkWidget* item, GdkEventButton* event, void* 
userdata);
+
 void menu_info_item_rename_cb(GtkWidget* item, GdkEventButton* event, void* 
userdata);
 void menu_info_item_rename_dialog(menu_info_item_t* mii);
 void menu_info_item_rename_error(menu_info_item_t* mii);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/notify.c 
new/pasystray-pasystray-0.6.0/src/notify.c
--- old/pasystray-pasystray-0.5.2/src/notify.c  2015-05-05 21:25:16.000000000 
+0200
+++ new/pasystray-pasystray-0.6.0/src/notify.c  2016-07-17 12:41:33.000000000 
+0200
@@ -49,16 +49,23 @@
                 error->code);
 }
 
-notify_handle_t notify(const char* msg, const char* body, const char* icon)
+notify_handle_t notify(const char* msg, const char* body, const char* icon, 
gint value)
 {
     NotifyNotification* n = notify_notification_new(msg, body, icon);
+    notify_notification_set_urgency(n, NOTIFY_URGENCY_LOW);
+    notify_notification_set_timeout(n, 2000); // timeout in ms
+    if(value > -1)
+        notify_notification_set_hint_int32 (n, "value", value);
     notify_show(n);
     return (notify_handle_t) n;
 }
 
-void notify_update(notify_handle_t h, const char* msg, const char* body, const 
char* icon)
+void notify_update(notify_handle_t h, const char* msg, const char* body, const 
char* icon, gint value)
 {
     NotifyNotification* n = (NotifyNotification*) h;
+    notify_notification_set_timeout(n, 2000); // timeout in ms
+    if(value > -1)
+        notify_notification_set_hint_int32 (n, "value", value);
 
     if(!notify_notification_update(n, msg, body, icon))
         g_error("[notify] invalid arguments passed to notify_update()");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/notify.h 
new/pasystray-pasystray-0.6.0/src/notify.h
--- old/pasystray-pasystray-0.5.2/src/notify.h  2015-05-05 21:25:16.000000000 
+0200
+++ new/pasystray-pasystray-0.6.0/src/notify.h  2016-07-17 12:41:33.000000000 
+0200
@@ -27,7 +27,7 @@
 typedef void* notify_handle_t;
 
 void notify_initialize();
-notify_handle_t notify(const char* msg, const char* body, const char* icon);
-void notify_update(notify_handle_t h, const char* msg, const char* body, const 
char* icon);
+notify_handle_t notify(const char* msg, const char* body, const char* icon, 
gint value);
+void notify_update(notify_handle_t h, const char* msg, const char* body, const 
char* icon, gint value);
 
 #endif /* PASYSTRAY_NOTIFY_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/options.c 
new/pasystray-pasystray-0.6.0/src/options.c
--- old/pasystray-pasystray-0.5.2/src/options.c 2015-05-05 21:25:16.000000000 
+0200
+++ new/pasystray-pasystray-0.6.0/src/options.c 2016-07-17 12:41:33.000000000 
+0200
@@ -27,29 +27,33 @@
 
 static gboolean version = FALSE;
 static gboolean debug = FALSE;
-static int max_volume = 0;
+static int volume_max = 0;
+static int volume_inc = 1;
+static gboolean no_notify = FALSE;
+static gboolean always_notify = FALSE;
+static gboolean monitors = FALSE;
 
 static GOptionEntry entries[] =
 {
     { "version", 'V', 0, G_OPTION_ARG_NONE, &version, "print version and 
exit", NULL },
     { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "print debugging 
information", NULL },
-    { "max-volume", 'm', 0, G_OPTION_ARG_INT, &max_volume, "maximum volume (in 
percent)", "N" },
+    { "max-volume", 0, 0, G_OPTION_ARG_INT, &volume_max, "deprecated, use 
volume-max instead", "N" },
+    { "volume-max", 'm', 0, G_OPTION_ARG_INT, &volume_max, "maximum volume (in 
percent)", "N" },
+    { "volume-inc", 'i', 0, G_OPTION_ARG_INT, &volume_inc, "volume increment", 
"N" },
+    { "no-notify", 'n', 0, G_OPTION_ARG_NONE, &no_notify, "disable all 
notifications", NULL },
+    { "always-notify", 'a', 0, G_OPTION_ARG_NONE, &always_notify,
+        "enable notifications for all changes in pulsaudio", NULL },
+    { "include-monitors", 'n', 0, G_OPTION_ARG_NONE, &monitors, "include 
monitor sources", NULL },
     { .long_name = NULL }
 };
 
-void parse_options(int argc, char *argv[], settings_t* settings)
+GOptionEntry* get_options()
 {
-    GError *error = NULL;
-    GOptionContext *context;
-
-    context = g_option_context_new(NULL);
-    g_option_context_add_main_entries(context, entries, NULL);
-    g_option_context_add_group(context, gtk_get_option_group(TRUE));
-    if(!g_option_context_parse(context, &argc, &argv, &error))
-    {
-        g_error("option parsing failed: %s\n", error->message);
-    }
+    return entries;
+}
 
+void parse_options(settings_t* settings)
+{
     if(version)
     {
         g_print("%s\n", VERSION);
@@ -61,8 +65,27 @@
         setenv("G_MESSAGES_DEBUG", "pasystray", 1);
     }
 
-    if(max_volume > 0)
+    settings->volume_max = 0;
+    if(volume_max > 0)
+    {
+        settings->volume_max = volume_max;
+    }
+
+    settings->volume_inc = 1;
+    if(volume_inc > 0)
+    {
+        settings->volume_inc = volume_inc;
+    }
+
+    settings->notify = NOTIFY_DEFAULT;
+    if(no_notify)
     {
-        settings->max_volume = max_volume;
+        settings->notify = NOTIFY_NEVER;
     }
+    if(always_notify)
+    {
+        settings->notify = NOTIFY_ALWAYS;
+    }
+
+    settings->monitors = monitors;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/options.h 
new/pasystray-pasystray-0.6.0/src/options.h
--- old/pasystray-pasystray-0.5.2/src/options.h 2015-05-05 21:25:16.000000000 
+0200
+++ new/pasystray-pasystray-0.6.0/src/options.h 2016-07-17 12:41:33.000000000 
+0200
@@ -24,6 +24,7 @@
 
 #include "menu_info.h"
 
-void parse_options(int argc, char *argv[], settings_t* settings);
+GOptionEntry* get_options();
+void parse_options(settings_t* settings);
 
 #endif /* PASYSTRAY_OPTIONS_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/pasystray.c 
new/pasystray-pasystray-0.6.0/src/pasystray.c
--- old/pasystray-pasystray-0.5.2/src/pasystray.c       2015-05-05 
21:25:16.000000000 +0200
+++ new/pasystray-pasystray-0.6.0/src/pasystray.c       2016-07-17 
12:41:33.000000000 +0200
@@ -19,6 +19,7 @@
   USA.
 ***/
 
+#include <glib.h>
 #include <gtk/gtk.h>
 
 #include "pasystray.h"
@@ -36,15 +37,23 @@
 
 int main(int argc, char *argv[])
 {
+    GOptionEntry* options = get_options();
+    GError *error = NULL;
+    gtk_init_with_args(&argc, &argv, NULL, options, NULL, &error);
+    if(error)
+    {
+        g_print("option parsing failed: %s\n", error->message);
+        return EXIT_FAILURE;
+    }
+
     settings_t settings;
-    parse_options(argc, argv, &settings);
-    gtk_init(&argc, &argv);
+    parse_options(&settings);
 
     init(&settings);
     g_main_loop_run(loop);
     destroy();
 
-    return 0;
+    return EXIT_SUCCESS;
 }
 
 void init(settings_t* settings)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/pasystray.glade 
new/pasystray-pasystray-0.6.0/src/pasystray.glade
--- old/pasystray-pasystray-0.5.2/src/pasystray.glade   2015-05-05 
21:25:16.000000000 +0200
+++ new/pasystray-pasystray-0.6.0/src/pasystray.glade   2016-07-17 
12:41:33.000000000 +0200
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
 <interface>
-  <!-- interface-requires gtk+ 3.0 -->
+  <requires lib="gtk+" version="3.0"/>
   <object class="GtkAboutDialog" id="aboutdialog">
     <property name="can_focus">False</property>
     <property name="border_width">5</property>
@@ -37,37 +38,50 @@
       </object>
     </child>
   </object>
-  <object class="GtkDialog" id="renamedialog">
+  <object class="GtkMessageDialog" id="errordialog">
     <property name="can_focus">False</property>
     <property name="border_width">5</property>
-    <property name="title" translatable="yes">Rename &lt;device&gt; 
&lt;name&gt;</property>
-    <property name="type_hint">normal</property>
+    <property name="title" translatable="yes">Error</property>
+    <property name="resizable">False</property>
+    <property name="type_hint">dialog</property>
+    <property name="message_type">error</property>
+    <property name="buttons">ok</property>
+    <property name="text" translatable="yes">An error occurred</property>
     <child internal-child="vbox">
-      <object class="GtkBox" id="dialog-vbox">
+      <object class="GtkBox" id="messagedialog-vbox2">
         <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <child>
-          <object class="GtkLabel" id="label">
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="messagedialog-action_area2">
             <property name="can_focus">False</property>
-            <property name="label" translatable="yes">Rename &lt;device&gt; 
&lt;old name&gt; to:</property>
           </object>
           <packing>
             <property name="expand">False</property>
-            <property name="fill">True</property>
+            <property name="fill">False</property>
             <property name="position">0</property>
           </packing>
         </child>
+      </object>
+    </child>
+  </object>
+  <object class="GtkDialog" id="renamedialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Rename &lt;device&gt; 
&lt;name&gt;</property>
+    <property name="type_hint">normal</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
         <child internal-child="action_area">
           <object class="GtkButtonBox" id="dialog-action_area3">
             <property name="can_focus">False</property>
             <property name="layout_style">end</property>
             <child>
               <object class="GtkButton" id="cancelbutton">
-                <property name="label">gtk-cancel</property>
+                <property name="label">Cancel</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">False</property>
-                <property name="use_stock">True</property>
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -77,10 +91,10 @@
             </child>
             <child>
               <object class="GtkButton" id="okbutton">
-                <property name="label">gtk-ok</property>
+                <property name="label">OK</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">False</property>
-                <property name="use_stock">True</property>
+                <property name="image_position">bottom</property>
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -97,6 +111,17 @@
           </packing>
         </child>
         <child>
+          <object class="GtkLabel" id="label">
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Rename &lt;device&gt; 
&lt;old name&gt; to:</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
           <object class="GtkEntry" id="entry">
             <property name="can_focus">True</property>
             <property name="has_focus">True</property>
@@ -119,14 +144,4 @@
       <action-widget response="-5">okbutton</action-widget>
     </action-widgets>
   </object>
-  <object class="GtkMessageDialog" id="errordialog">
-    <property name="can_focus">False</property>
-    <property name="border_width">5</property>
-    <property name="resizable">False</property>
-    <property name="type_hint">dialog</property>
-    <property name="title" translatable="yes">Error</property>
-    <property name="text" translatable="yes">An error occurred</property>
-    <property name="message_type">GTK_MESSAGE_ERROR</property>
-    <property name="buttons">GTK_BUTTONS_OK</property>
-  </object>
 </interface>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/pulseaudio.c 
new/pasystray-pasystray-0.6.0/src/pulseaudio.c
--- old/pasystray-pasystray-0.5.2/src/pulseaudio.c      2015-05-05 
21:25:16.000000000 +0200
+++ new/pasystray-pasystray-0.6.0/src/pulseaudio.c      2016-07-17 
12:41:33.000000000 +0200
@@ -31,16 +31,13 @@
 
 static pa_glib_mainloop* m = NULL;
 static pa_proplist* context_proplist = NULL;
-static char* server = NULL;
 
 void pulseaudio_init(menu_infos_t* mis)
 {
     if(!(m = pa_glib_mainloop_new(g_main_context_default())))
         pulseaudio_quit("pa_glib_mainloop_new() failed.");
 
-    pulseaudio_prepare_context(mis);
-
-    pulseaudio_connect();
+    pulseaudio_connect(mis);
 }
 
 void pulseaudio_destroy()
@@ -62,15 +59,37 @@
     pa_context_set_state_callback(context, pulseaudio_context_state_cb, mis);
 }
 
-void pulseaudio_connect()
+void pulseaudio_connect(menu_infos_t* mis)
 {
-    if(pa_context_connect(context, server, PA_CONTEXT_NOFLAGS, NULL) < 0)
+    pulseaudio_prepare_context(mis);
+
+    if(pa_context_connect(context, NULL, PA_CONTEXT_NOFAIL, NULL) < 0)
     {
-        g_warning("pa_context_connect() failed: ");
-        pulseaudio_quit(pa_strerror(pa_context_errno(context)));
+        g_warning("pa_context_connect() failed: %s",
+            pa_strerror(pa_context_errno(context)));
     }
 }
 
+void pulseaudio_reconnect_cb(pa_mainloop_api *api, pa_time_event *event, const 
struct timeval *tv, void *userdata)
+{
+    menu_infos_t* mis = userdata;
+    pulseaudio_connect(mis);
+}
+
+void pulseaudio_reconnect(menu_infos_t* mis)
+{
+    systray_impl_set_icon(mis->systray, "pasystray");
+
+    pa_mainloop_api* api = pa_glib_mainloop_get_api(m);
+
+    struct timeval tv;
+    struct timeval* delay_tv = pa_gettimeofday(&tv);
+    pa_timeval_add(delay_tv, 1 * PA_USEC_PER_SEC);
+
+    // reconnect with 1s delay
+    api->time_new(api, delay_tv, pulseaudio_reconnect_cb, mis);
+}
+
 void pulseaudio_context_state_cb(pa_context* c, void* userdata)
 {
     menu_infos_t* mis = userdata;
@@ -109,9 +128,8 @@
             menu_infos_clear(mis);
             pa_context_unref(context);
 
-            pulseaudio_prepare_context(mis);
             g_debug("[pulseaudio] trying again...");
-            pulseaudio_connect();
+            pulseaudio_reconnect(mis);
             break;
 
         case PA_CONTEXT_TERMINATED:
@@ -119,9 +137,8 @@
             menu_infos_clear(mis);
             pa_context_unref(context);
 
-            pulseaudio_prepare_context(mis);
             g_debug("[pulseaudio] reconnecting...");
-            pulseaudio_connect();
+            pulseaudio_reconnect(mis);
             break;
 
         case PA_CONTEXT_CONNECTING:
@@ -358,14 +375,16 @@
     if(is_last)
         return;
 
-    if(is_new)
+    menu_info_t* mi = userdata;
+    menu_infos_t* mis = mi->menu_infos;
+
+    if(is_new && mis->settings.notify != NOTIFY_NEVER)
     {
         gchar* msg = g_strdup_printf("new sink \"%s\"", i->description);
-        notify(msg, i->name, NULL);
+        notify(msg, i->name, NULL, -1);
         g_free(msg);
     }
 
-    menu_info_t* mi = userdata;
     char* tooltip = sink_info_str(i);
     menu_info_item_update(mi, i->index, i->name, i->description, &i->volume,
             i->mute, tooltip, NULL, NULL, -1);
@@ -400,18 +419,20 @@
 
     const char* class = pa_proplist_gets(i->proplist, PA_PROP_DEVICE_CLASS);
 
+    menu_info_t* mi = userdata;
+    menu_infos_t* mis = mi->menu_infos;
+
     // ignore monitors
-    if(class && g_str_equal(class, "monitor"))
+    if(!mis->settings.monitors && class && g_str_equal(class, "monitor"))
         return;
 
-    if(is_new)
+    if(is_new && mis->settings.notify != NOTIFY_NEVER)
     {
         gchar* msg = g_strdup_printf("new source \"%s\"", i->description);
-        notify(msg, i->name, NULL);
+        notify(msg, i->name, NULL, -1);
         g_free(msg);
     }
 
-    menu_info_t* mi = userdata;
     char* tooltip = source_info_str(i);
     menu_info_item_update(mi, i->index, i->name, i->description, &i->volume,
             i->mute, tooltip, NULL, NULL, -1);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/pulseaudio.h 
new/pasystray-pasystray-0.6.0/src/pulseaudio.h
--- old/pasystray-pasystray-0.5.2/src/pulseaudio.h      2015-05-05 
21:25:16.000000000 +0200
+++ new/pasystray-pasystray-0.6.0/src/pulseaudio.h      2016-07-17 
12:41:33.000000000 +0200
@@ -29,7 +29,8 @@
 void pulseaudio_init(menu_infos_t* mis);
 void pulseaudio_destroy();
 void pulseaudio_prepare_context(menu_infos_t* mis);
-void pulseaudio_connect();
+void pulseaudio_connect(menu_infos_t* mis);
+void pulseaudio_reconnect(menu_infos_t* mis);
 void pulseaudio_start();
 
 void pulseaudio_context_state_cb(pa_context* c, void* userdata);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/pulseaudio_action.c 
new/pasystray-pasystray-0.6.0/src/pulseaudio_action.c
--- old/pasystray-pasystray-0.5.2/src/pulseaudio_action.c       2015-05-05 
21:25:16.000000000 +0200
+++ new/pasystray-pasystray-0.6.0/src/pulseaudio_action.c       2016-07-17 
12:41:33.000000000 +0200
@@ -25,6 +25,7 @@
 #include <pulse/ext-device-manager.h>
 
 #include "notify.h"
+#include "ui.h"
 #include "x11-property.h"
 
 extern pa_context* context;
@@ -63,23 +64,58 @@
 {
     menu_info_item_t* mii = userdata;
 
-    if(!success)
+    if(success)
+    {
+        if(mii->menu_info->type == MENU_SINK)
+            ui_update_systray_icon(mii);
+    }
+    else
         g_warning("failed to set default to %s \"%s\"!\n",
                 menu_info_type_name(mii->menu_info->type), mii->name);
 }
 
 void pulseaudio_move_input_to_sink(menu_info_item_t* input, menu_info_item_t* 
sink)
 {
+    g_debug("[pulseaudio_action] move input %s to sink %s",
+            input->desc, sink->desc);
+
     pa_operation_unref(pa_context_move_sink_input_by_index(context, 
input->index,
                 sink->index, pulseaudio_move_success_cb, input));
 }
 
 void pulseaudio_move_output_to_source(menu_info_item_t* output, 
menu_info_item_t* source)
 {
+    g_debug("[pulseaudio_action] move output %s to source %s",
+            output->desc, source->desc);
+
     pa_operation_unref(pa_context_move_source_output_by_index(context, 
output->index,
                 source->index, pulseaudio_move_success_cb, output));
 }
 
+void pulseaudio_move_all(menu_info_item_t* mii)
+{
+    menu_infos_t* mis = mii->menu_info->menu_infos;
+    menu_type_t target_type = mii->menu_info->type;
+    menu_type_t source_type = (target_type == MENU_SINK) ? MENU_INPUT : 
MENU_OUTPUT;
+
+    g_debug("[pulseaudio_action] move all %s to %s %s",
+            menu_info_type_name(source_type),
+            menu_info_type_name(target_type),
+            mii->desc);
+
+    GHashTableIter iter;
+    gpointer key;
+    gpointer value;
+    g_hash_table_iter_init(&iter, mis->menu_info[MENU_INPUT].items);
+    while (g_hash_table_iter_next(&iter, &key, &value))
+    {
+        if (target_type == MENU_SINK)
+            pulseaudio_move_input_to_sink(value, mii);
+        else if (target_type == MENU_SOURCE)
+            pulseaudio_move_output_to_source(value, mii);
+    }
+}
+
 void pulseaudio_move_success_cb(pa_context *c, int success, void *userdata)
 {
     menu_info_item_t* to = userdata;
@@ -125,10 +161,10 @@
         volume = pa_cvolume_dec(mii->volume, -inc * PA_VOLUME_NORM / 50);
     else if(inc > 0)
     {
-        int max_volume = mii->menu_info->menu_infos->settings.max_volume;
-        if(max_volume > 0)
+        int volume_max = mii->menu_info->menu_infos->settings.volume_max;
+        if(volume_max > 0)
             volume = pa_cvolume_inc_clamp(mii->volume, inc * PA_VOLUME_NORM / 
50,
-                    PA_VOLUME_NORM * max_volume / 100);
+                    PA_VOLUME_NORM * volume_max / 100);
         else
             volume = pa_cvolume_inc(mii->volume, inc * PA_VOLUME_NORM / 50);
     }
@@ -175,21 +211,30 @@
         return;
     }
 
-    pulseaudio_update_volume_notification(mii);
+    menu_infos_t* mis = mii->menu_info->menu_infos;
+
+    /* update sink icon */
+    if(mii->menu_info->type == MENU_SINK || mii->menu_info->type == 
MENU_SOURCE)
+        ui_set_volume_icon(mii);
+
+    if(mis->settings.notify != NOTIFY_NEVER)
+    {
+        pulseaudio_update_volume_notification(mii);
+    }
 }
 
 void pulseaudio_update_volume_notification(menu_info_item_t* mii)
 {
-    char vol[PA_CVOLUME_SNPRINT_MAX];
-    gchar* msg = g_strdup_printf("%s %s: %s%s",
-                menu_info_type_name(mii->menu_info->type), mii->desc,
-                pa_cvolume_snprint(vol, sizeof(vol), mii->volume),
-                mii->mute ? " [muted]" : "");
+    gchar* label = menu_info_item_label(mii);
+    gchar* msg = g_strdup_printf("%s %s",
+                menu_info_type_name(mii->menu_info->type), label);
+    g_free(label);
 
+    gint volume = (mii->volume->values[0]*100+PA_VOLUME_NORM/2)/PA_VOLUME_NORM;
     if(!mii->notify)
-        mii->notify = notify(msg, NULL, mii->icon);
+        mii->notify = notify(msg, NULL, mii->icon, volume);
     else
-        notify_update(mii->notify, msg, NULL, mii->icon);
+        notify_update(mii->notify, msg, NULL, mii->icon, volume);
 
     g_free(msg);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/pulseaudio_action.h 
new/pasystray-pasystray-0.6.0/src/pulseaudio_action.h
--- old/pasystray-pasystray-0.5.2/src/pulseaudio_action.h       2015-05-05 
21:25:16.000000000 +0200
+++ new/pasystray-pasystray-0.6.0/src/pulseaudio_action.h       2016-07-17 
12:41:33.000000000 +0200
@@ -30,6 +30,7 @@
 
 void pulseaudio_move_input_to_sink(menu_info_item_t* input, menu_info_item_t* 
sink);
 void pulseaudio_move_output_to_source(menu_info_item_t* output, 
menu_info_item_t* source);
+void pulseaudio_move_all(menu_info_item_t* mii);
 void pulseaudio_move_success_cb(pa_context *c, int success, void *userdata);
 
 void pulseaudio_rename(menu_info_item_t* mii, const char* name);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/systray.c 
new/pasystray-pasystray-0.6.0/src/systray.c
--- old/pasystray-pasystray-0.5.2/src/systray.c 2015-05-05 21:25:16.000000000 
+0200
+++ new/pasystray-pasystray-0.6.0/src/systray.c 2016-07-17 12:41:33.000000000 
+0200
@@ -27,6 +27,12 @@
 #include "ui.h"
 #include "systray_impl.h"
 
+static const char* COMMAND_PAMAN = "paman";
+static const char* COMMAND_PAVUCONTROL = "pavucontrol";
+static const char* COMMAND_PAVUMETER = "pavumeter";
+static const char* COMMAND_PAVUMETER_REC = "pavumeter --record";
+static const char* COMMAND_PAPREFS = "paprefs";
+
 void systray_create(menu_infos_t* mis)
 {
     systray_menu_create(mis);
@@ -45,12 +51,6 @@
     systray_rootmenu_add_submenu(mis, MENU_MODULE, "_Modules", "list-add");
     systray_menu_add_separator(mis->menu);
 
-    static const char* COMMAND_PAMAN = "paman";
-    static const char* COMMAND_PAVUCONTROL = "pavucontrol";
-    static const char* COMMAND_PAVUMETER = "pavumeter";
-    static const char* COMMAND_PAVUMETER_REC = "pavumeter --record";
-    static const char* COMMAND_PAPREFS = "paprefs";
-
     systray_menu_add_application(mis->menu, "_Manager...", NULL, 
COMMAND_PAMAN);
     systray_menu_add_application(mis->menu, "Volume _Control...", NULL, 
COMMAND_PAVUCONTROL);
     systray_menu_add_application(mis->menu, "Volume Meter (_Playback)...", 
NULL, COMMAND_PAVUMETER);
@@ -156,9 +156,12 @@
     systray_add_placeholder(mi);
 }
 
-GtkWidget* systray_add_radio_item(menu_info_t* mi, const char* desc, const 
char* tooltip)
+GtkWidget* systray_add_radio_item(menu_info_item_t* mii, const char* tooltip)
 {
-    GtkWidget* item = gtk_radio_menu_item_new_with_label(mi->group, desc);
+    menu_info_t* mi = mii->menu_info;
+    gchar* label = menu_info_item_label(mii);
+    GtkWidget* item = gtk_radio_menu_item_new_with_label(mi->group, label);
+    g_free(label);
 
     if(tooltip)
         systray_set_tooltip(item, tooltip);
@@ -192,18 +195,30 @@
 {
     GtkWidget* item = gtk_menu_item_new();
 
+#if GTK_VERSION_MAJOR == 2
+    GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
+#else
     GtkWidget* hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+#endif
     gtk_container_add(GTK_CONTAINER(item), hbox);
 
     if(icon)
     {
         GtkWidget* image = gtk_image_new_from_icon_name(icon, 
GTK_ICON_SIZE_MENU);
+#if GTK_VERSION_MAJOR == 2
+        gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
+#else
         gtk_container_add(GTK_CONTAINER(hbox), image);
+#endif
     }
 
     GtkWidget* label = gtk_label_new(NULL);
     gtk_label_set_text_with_mnemonic(GTK_LABEL(label), desc);
+#if GTK_VERSION_MAJOR == 2
+    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 15);
+#else
     gtk_container_add(GTK_CONTAINER(hbox), label);
+#endif
 
     if(tooltip)
         systray_set_tooltip(item, tooltip);
@@ -331,39 +346,68 @@
     menu_info_t* mi = &mis->menu_info[(ev->state & GDK_CONTROL_MASK) ? 
MENU_SOURCE : MENU_SINK];
     menu_info_item_t* mii = menu_info_item_get_by_name(mi, mi->default_name);
 
+    g_debug("[systray] click mod:%s%s button:%i",
+            (ev->state & GDK_CONTROL_MASK) ? "[ctrl]" : "",
+            (ev->state & GDK_MOD1_MASK) ? "[alt]" : "",
+            ev->button);
+
     switch(ev->button)
     {
         case 1:
             /* on alt + left-click, toggle mute default sink */
-            if((ev->state & GDK_MOD1_MASK) && mii)
-                pulseaudio_toggle_mute(mii);
+            if(ev->state & GDK_MOD1_MASK)
+            {
+                if(mii)
+                    pulseaudio_toggle_mute(mii);
+            }
+            /* on ctrl + left-click, start pavucontrol */
+            else if(ev->state & GDK_CONTROL_MASK)
+            {
+                g_spawn_command_line_async(COMMAND_PAVUCONTROL, NULL);
+            }
             /* on left-click, show menu */
             else
-                gtk_menu_popup(GTK_MENU(mis->menu), NULL, NULL, 
gtk_status_icon_position_menu, icon, ev->button, ev->time);
+            {
+                gtk_menu_popup(GTK_MENU(mis->menu), NULL, NULL,
+#if HAVE_STATUSICON
+                        gtk_status_icon_position_menu,
+#else
+                        NULL,
+#endif
+                        icon, ev->button, ev->time);
+            }
             break;
         case 2:
             /* on middle-click, toggle mute default sink */
             if(mii)
+            {
                 pulseaudio_toggle_mute(mii);
+            }
             break;
         case 3:
             /* on right-click, show menu */
-            gtk_menu_popup(GTK_MENU(mis->menu), NULL, NULL, 
gtk_status_icon_position_menu, icon, ev->button, ev->time);
+            gtk_menu_popup(GTK_MENU(mis->menu), NULL, NULL,
+#if HAVE_STATUSICON
+                    gtk_status_icon_position_menu,
+#else
+                    NULL,
+#endif
+                    icon, ev->button, ev->time);
             break;
     }
 }
 
-void systray_scroll_cb(systray_t* systray, guint state, GdkScrollDirection 
direction, menu_infos_t* mis)
+void systray_scroll_cb(guint state, GdkScrollDirection direction, 
menu_infos_t* mis)
 {
     int inc = 0;
 
     switch(direction)
     {
         case GDK_SCROLL_UP:
-            inc = 1;
+            inc = mis->settings.volume_inc;
             break;
         case GDK_SCROLL_DOWN:
-            inc = -1;
+            inc = -mis->settings.volume_inc;
             break;
         default:
             return;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/systray.h 
new/pasystray-pasystray-0.6.0/src/systray.h
--- old/pasystray-pasystray-0.5.2/src/systray.h 2015-05-05 21:25:16.000000000 
+0200
+++ new/pasystray-pasystray-0.6.0/src/systray.h 2016-07-17 12:41:33.000000000 
+0200
@@ -44,7 +44,7 @@
 GtkWidget* systray_add_menu_item(menu_info_t* mi, const char* desc, const 
char* tooltip, const char* icon);
 void systray_remove_menu_item(menu_info_t* mi, GtkWidget* item);
 
-GtkWidget* systray_add_radio_item(menu_info_t* m, const char* desc, const 
char* tooltip);
+GtkWidget* systray_add_radio_item(menu_info_item_t* mii, const char* tooltip);
 void systray_remove_radio_item(menu_info_t* mi, GtkWidget* item);
 
 GtkWidget* systray_add_item(GtkMenuShell* menu, const char* desc, const char* 
tooltip, const char* icon);
@@ -60,7 +60,7 @@
 void systray_about_dialog();
 
 void systray_click_cb(GtkStatusIcon* icon, GdkEventButton* ev, gpointer 
userdata);
-void systray_scroll_cb(systray_t* systray, guint state, GdkScrollDirection 
direction, menu_infos_t* mis);
+void systray_scroll_cb(guint state, GdkScrollDirection direction, 
menu_infos_t* mis);
 void start_application_cb(GtkMenuItem* menuitem, const char* command);
 
 void systray_set_tooltip(GtkWidget* item, const char* tooltip);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/systray_impl.c 
new/pasystray-pasystray-0.6.0/src/systray_impl.c
--- old/pasystray-pasystray-0.5.2/src/systray_impl.c    2015-05-05 
21:25:16.000000000 +0200
+++ new/pasystray-pasystray-0.6.0/src/systray_impl.c    2016-07-17 
12:41:33.000000000 +0200
@@ -30,15 +30,14 @@
 
 static void systray_impl_scroll_cb(AppIndicator* appind, gint delta, 
GdkScrollDirection direction, gpointer userdata)
 {
-    systray_t systray = appind;
     guint state = 0; // TODO: get modifiers?
     menu_infos_t* mis = userdata;
-    systray_scroll_cb(systray, state, direction, mis);
+    systray_scroll_cb(state, direction, mis);
 }
 
 systray_t systray_impl_create(menu_infos_t* mis)
 {
-    g_debug("creating systray implementation using AppIndicator");
+    g_debug("[systray_impl] using AppIndicator");
 
     AppIndicator* appind = app_indicator_new("pasystray", "pasystray", 
APP_INDICATOR_CATEGORY_HARDWARE);
     app_indicator_set_status(appind, APP_INDICATOR_STATUS_ACTIVE);
@@ -58,15 +57,14 @@
 {
     // TODO: set tooltip?
 }
-#else
+#elif HAVE_STATUSICON
 
 #include "ui.h"
 
 static void systray_impl_scroll_cb(GtkStatusIcon* icon, GdkEventScroll* ev, 
gpointer userdata)
 {
-    systray_t systray = icon;
     menu_infos_t* mis = userdata;
-    systray_scroll_cb(systray, ev->state, ev->direction, mis);
+    systray_scroll_cb(ev->state, ev->direction, mis);
 }
 
 static GtkStatusIcon* systray_impl_create_statusicon()
@@ -103,7 +101,7 @@
 
 systray_t systray_impl_create(menu_infos_t* mis)
 {
-    g_debug("creating systray implementation using GtkStatusIcon");
+    g_debug("[systray_impl] using GtkStatusIcon");
 
     GtkStatusIcon* icon = systray_impl_create_statusicon();
     g_signal_connect(icon, "button-press-event", G_CALLBACK(systray_click_cb), 
mis);
@@ -153,4 +151,47 @@
     gtk_status_icon_set_tooltip_markup(icon, markup);
 }
 
+#else
+
+static void systray_impl_scroll_cb(GtkImage* image, GdkEventScroll* ev, 
gpointer userdata)
+{
+    menu_infos_t* mis = userdata;
+    systray_scroll_cb(ev->state, ev->direction, mis);
+}
+
+systray_t systray_impl_create(menu_infos_t* mis)
+{
+    g_debug("[systray_impl] using GtkWindow");
+
+    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    gtk_window_set_title(GTK_WINDOW(window), "pasystray");
+
+    GtkWidget *button = gtk_menu_button_new();
+    gtk_container_add(GTK_CONTAINER(window), button);
+    gtk_menu_button_set_popup(GTK_MENU_BUTTON(button), GTK_WIDGET(mis->menu));
+    gtk_widget_add_events(button, GDK_SCROLL_MASK);
+    g_signal_connect(button, "button-press-event", 
G_CALLBACK(systray_click_cb), mis);
+    g_signal_connect(button, "scroll-event", 
G_CALLBACK(systray_impl_scroll_cb), mis);
+
+    GtkWidget *image = gtk_image_new();
+    gtk_image_set_from_icon_name(GTK_IMAGE(image), "pasystray", 
GTK_ICON_SIZE_DIALOG);
+    gtk_button_set_image(GTK_BUTTON(button), image);
+
+    gtk_widget_show_all(window);
+
+    return image;
+}
+
+void systray_impl_set_icon(systray_t systray, const char* icon_name)
+{
+    GtkImage *image = systray;
+    gtk_image_set_from_icon_name(image, icon_name, GTK_ICON_SIZE_DIALOG);
+}
+
+void systray_impl_set_tooltip(systray_t systray, const char* markup)
+{
+    GtkImage *image = systray;
+    gtk_widget_set_tooltip_markup(GTK_WIDGET(image), markup);
+}
+
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/ui.c 
new/pasystray-pasystray-0.6.0/src/ui.c
--- old/pasystray-pasystray-0.5.2/src/ui.c      2015-05-05 21:25:16.000000000 
+0200
+++ new/pasystray-pasystray-0.6.0/src/ui.c      2016-07-17 12:41:33.000000000 
+0200
@@ -52,9 +52,9 @@
     }
 }
 
-void ui_update_systray_icon(menu_info_item_t* mii)
+void ui_set_volume_icon(menu_info_item_t* mii)
 {
-    g_debug("pulseaudio_update_systray_icon(%s)", mii->name);
+    g_debug("pulseaudio_set_volume_icon(%s)", mii->name);
 
     pa_volume_t volume = pa_cvolume_avg(mii->volume);
 
@@ -71,8 +71,18 @@
     else
         icon_name = "audio-volume-high";
 
+    g_free(mii->icon);
+    mii->icon = g_strdup(icon_name);
+}
+
+void ui_update_systray_icon(menu_info_item_t* mii)
+{
+    g_debug("pulseaudio_update_systray_icon(%s)", mii->name);
+
+    ui_set_volume_icon(mii);
+
     menu_infos_t* mis = mii->menu_info->menu_infos;
-    systray_impl_set_icon(mis->systray, icon_name);
+    systray_impl_set_icon(mis->systray, mii->icon);
 }
 
 GtkDialog* ui_aboutdialog()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pasystray-pasystray-0.5.2/src/ui.h 
new/pasystray-pasystray-0.6.0/src/ui.h
--- old/pasystray-pasystray-0.5.2/src/ui.h      2015-05-05 21:25:16.000000000 
+0200
+++ new/pasystray-pasystray-0.6.0/src/ui.h      2016-07-17 12:41:33.000000000 
+0200
@@ -26,6 +26,7 @@
 #include <gtk/gtk.h>
 
 void ui_load();
+void ui_set_volume_icon(menu_info_item_t* mii);
 void ui_update_systray_icon(menu_info_item_t* mii);
 GtkDialog* ui_aboutdialog();
 GtkDialog* ui_renamedialog();


Reply via email to