Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package pasystray for openSUSE:Factory checked in at 2022-05-04 15:11:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pasystray (Old) and /work/SRC/openSUSE:Factory/.pasystray.new.1538 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pasystray" Wed May 4 15:11:00 2022 rev:10 rq:974795 version:0.8.0 Changes: -------- --- /work/SRC/openSUSE:Factory/pasystray/pasystray.changes 2021-03-05 13:45:14.679620467 +0100 +++ /work/SRC/openSUSE:Factory/.pasystray.new.1538/pasystray.changes 2022-05-04 15:11:23.084189298 +0200 @@ -1,0 +2,15 @@ +Tue May 3 18:17:39 UTC 2022 - Ferdinand Thiessen <r...@fthiessen.de> + +- Update to version 0.8.0 + * volume: calculate notify value to always be between 0-100 + fixes volume-max not working + * Fix null unref in pulseaudio_terminate + * Prefer symbolic icons, use microphone sensitivity icons. + * Import X11 volume control key grabber from pa-applet and + use for volume control + * Use volume max for icon instead of avg + * Listen to activate events of menu items + The new `activate` handlers substitute the current click + handlers for default left click events + +------------------------------------------------------------------- Old: ---- pasystray-0.7.1.tar.gz New: ---- pasystray-0.8.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pasystray.spec ++++++ --- /var/tmp/diff_new_pack.jn4SmN/_old 2022-05-04 15:11:23.620189957 +0200 +++ /var/tmp/diff_new_pack.jn4SmN/_new 2022-05-04 15:11:23.624189961 +0200 @@ -1,7 +1,7 @@ # # spec file for package pasystray # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,21 +16,14 @@ # -%if 0%{?suse_version} == 1315 -%define build_wayland_backend 0 -%define stdc99 1 -%else -%define build_wayland_backend 1 -%define stdc99 0 -%endif Name: pasystray -Version: 0.7.1 +Version: 0.8.0 Release: 0 Summary: PulseAudio system tray License: LGPL-2.1-or-later Group: System/GUI/Other URL: https://github.com/christophgysin/pasystray -Source: https://github.com/christophgysin/pasystray/archive/pasystray-%{version}.tar.gz +Source: https://github.com/christophgysin/pasystray/archive/refs/tags/%{version}.tar.gz#/%{name}-%{version}.tar.gz BuildRequires: automake BuildRequires: pkgconfig BuildRequires: update-desktop-files @@ -40,10 +33,12 @@ BuildRequires: pkgconfig(gdk-3.0) BuildRequires: pkgconfig(gdk-broadway-3.0) BuildRequires: pkgconfig(gdk-x11-3.0) +BuildRequires: pkgconfig(gdk-wayland-3.0) BuildRequires: pkgconfig(gtk+-3.0) BuildRequires: pkgconfig(gtk+-broadway-3.0) BuildRequires: pkgconfig(gtk+-unix-print-3.0) BuildRequires: pkgconfig(gtk+-x11-3.0) +BuildRequires: pkgconfig(gtk+-wayland-3.0) BuildRequires: pkgconfig(libnotify) BuildRequires: pkgconfig(libpulse) BuildRequires: pkgconfig(libpulse-mainloop-glib) @@ -57,10 +52,6 @@ Suggests: paprefs Suggests: pavucontrol Suggests: pavumeter -%if %{build_wayland_backend} -BuildRequires: pkgconfig(gdk-wayland-3.0) -BuildRequires: pkgconfig(gtk+-wayland-3.0) -%endif %description A replacement for the deprecated padevchooser @@ -68,15 +59,12 @@ Pasystray allows setting the default PulseAudio source/sink and moving streams on the fly between sources/sinks without restarting the client applications. %prep -%setup -q -n %{name}-%{name}-%{version} +%setup -q %build -%if %{stdc99} -export CFLAGS="%{optflags} --std=c99" -%endif autoreconf -fi %configure --sysconfdir=%{_sysconfdir} -make %{?_smp_mflags} +%make_build %install %make_install ++++++ pasystray-0.7.1.tar.gz -> pasystray-0.8.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/.github/workflows/build.yml new/pasystray-0.8.0/.github/workflows/build.yml --- old/pasystray-pasystray-0.7.1/.github/workflows/build.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/pasystray-0.8.0/.github/workflows/build.yml 2021-10-21 20:54:40.000000000 +0200 @@ -0,0 +1,52 @@ +name: build + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + env: + - { CC: gcc, CFLAGS: --std=c99 } + - { CC: gcc, CFLAGS: --std=c99, EXTRA_CONF: --with-gtk=2 } + - { CC: gcc, CFLAGS: --std=c99, EXTRA_CONF: --disable-avahi } + - { CC: gcc, CFLAGS: --std=c99, EXTRA_CONF: --disable-notify } + - { CC: gcc, CFLAGS: --std=c99, EXTRA_CONF: --disable-x11 } + - { CC: gcc, CFLAGS: --std=c99, EXTRA_CONF: --disable-statusicon } + - { CC: gcc, CFLAGS: --std=c99, EXTRA_CONF: --disable-appindicator} + - { CC: gcc, CFLAGS: --std=c11 } + - { CC: clang, CFLAGS: --std=c99 } + - { CC: clang, CFLAGS: --std=c11 } + env: ${{ matrix.env }} + steps: + - name: apt-get update + run: sudo apt-get update + - name: apt-get install + run: > + sudo apt-get install --no-install-recommends + libgtk2.0-dev + libgtk-3-dev + libpulse-dev + libnotify-dev + libappindicator3-dev + - name: CC version + run: $CC --version + - name: git checkout + uses: actions/checkout@v2 + - name: autotools + run: | + aclocal + autoconf + autoheader + automake --add-missing + - name: configure + run: ./configure ${EXTRA_CONF:-} || (cat config.log; exit 1) + - name: make + run: make + - name: make test + run: make test diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/.travis.sh new/pasystray-0.8.0/.travis.sh --- old/pasystray-pasystray-0.7.1/.travis.sh 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/.travis.sh 1970-01-01 01:00:00.000000000 +0100 @@ -1,14 +0,0 @@ -#!/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.7.1/.travis.yml new/pasystray-0.8.0/.travis.yml --- old/pasystray-pasystray-0.7.1/.travis.yml 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/.travis.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,27 +0,0 @@ -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 -script: ./.travis.sh -env: - - CFLAGS=--std=c99 - - CFLAGS=--std=c99 EXTRA_CONF=--with-gtk=2 - - CFLAGS=--std=c99 EXTRA_CONF=--disable-avahi - - CFLAGS=--std=c99 EXTRA_CONF=--disable-notify - - CFLAGS=--std=c99 EXTRA_CONF=--disable-x11 - - CFLAGS=--std=c99 EXTRA_CONF=--disable-statusicon - - CFLAGS=--std=c99 EXTRA_CONF=--disable-appindicator - - 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.7.1/README.md new/pasystray-0.8.0/README.md --- old/pasystray-pasystray-0.7.1/README.md 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/README.md 2021-10-21 20:54:40.000000000 +0200 @@ -1,6 +1,6 @@ PulseAudio System Tray ====================== -[](https://travis-ci.org/christophgysin/pasystray) +[](https://github.com/christophgysin/pasystray/actions/workflows/build.yml) A replacement for the deprecated padevchooser. @@ -39,9 +39,9 @@ over source/sink: * scroll up/down: adjust the volume of respective stream -* left-click: set as default sink/source +* left-click: set as default source/sink * middle-click / alt + left-click: toggle mute -* right-click: open menu to rename source/sink +* right-click: open menu to move all outputs/inputs to this source/sink or rename it over playback/record stream: * scroll up/down: adjust the volume of respective stream diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/configure.ac new/pasystray-0.8.0/configure.ac --- old/pasystray-pasystray-0.7.1/configure.ac 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/configure.ac 2021-10-21 20:54:40.000000000 +0200 @@ -1,6 +1,6 @@ # This file is part of PaSystray # -# Copyright (C) 2011-2019 Christoph Gysin +# Copyright (C) 2011-2021 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.7.1], [christoph.gy...@gmail.com], [pasystray], +AC_INIT([pasystray], [0.8.0], [christoph.gy...@gmail.com], [pasystray], [http://github.com/christophgysin/pasystray]) AC_CONFIG_SRCDIR([src/pasystray.c]) AC_CONFIG_HEADERS([src/config.h]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/man/pasystray.1 new/pasystray-0.8.0/man/pasystray.1 --- old/pasystray-pasystray-0.7.1/man/pasystray.1 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/man/pasystray.1 2021-10-21 20:54:40.000000000 +0200 @@ -53,11 +53,11 @@ .IP \[bu] Scroll up/down: adjust volume .IP \[bu] -Left-click: set as default sink/source +Left-click: set as default source/sink .IP \[bu] Middle-click / Alt + Left-click: toggle mute .IP \[bu] -Right-click: rename +Right-click: open menu to move all outputs/inputs to this source/sink or rename it .LP Playback/record stream menu item: .IP \[bu] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/Makefile.am new/pasystray-0.8.0/src/Makefile.am --- old/pasystray-pasystray-0.7.1/src/Makefile.am 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/src/Makefile.am 2021-10-21 20:54:40.000000000 +0200 @@ -50,6 +50,12 @@ x11-property.c \ x11-property.h +if HAVE_X11 +pasystray_SOURCES += \ + x11-key-grabber.c \ + x11-key-grabber.h +endif + pasystray_LDADD = \ $(AM_LDADD) \ $(GTK_LIBS) \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/menu_info.c new/pasystray-0.8.0/src/menu_info.c --- old/pasystray-pasystray-0.7.1/src/menu_info.c 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/src/menu_info.c 2021-10-21 20:54:40.000000000 +0200 @@ -369,6 +369,8 @@ break; } + g_signal_connect(item->widget, "activate", + G_CALLBACK(menu_info_item_activated), item); g_signal_connect(item->widget, "button-press-event", G_CALLBACK(menu_info_item_clicked), item); gtk_widget_add_events(item->widget, GDK_SCROLL_MASK); @@ -448,6 +450,9 @@ g_signal_connect(subitem->widget, "button-press-event", G_CALLBACK(menu_info_subitem_clicked), subitem); + + g_signal_connect(subitem->widget, "activate", + G_CALLBACK(menu_info_subitem_activated), subitem); } void menu_info_subitem_update(menu_info_t* mi, uint32_t index, const char* name, @@ -500,6 +505,23 @@ return g_hash_table_find(mi->items, desc_equal, (gpointer)desc); } +void menu_info_item_activated(GtkWidget* item, menu_info_item_t* mii) +{ + if (GTK_IS_CHECK_MENU_ITEM(item) + && !gtk_check_menu_item_get_active(GTK_MENU_ITEM(item))) + { + /* Ignore activation of deselected item */ + return; + } + + g_debug("[menu_info] subitem activated: %s %s", + menu_info_type_name(mii->menu_info->type), + mii->name); + + /* on left-click, set device as default */ + pulseaudio_set_default(mii); +} + void menu_info_item_clicked(GtkWidget* item, GdkEventButton* event, menu_info_item_t* mii) { @@ -573,13 +595,18 @@ } } -void menu_info_subitem_clicked(GtkWidget* item, GdkEventButton* event, - menu_info_item_t* mii) -{ - 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); +void menu_info_subitem_activated(GtkWidget* item, menu_info_item_t* mii) { + + if (GTK_IS_CHECK_MENU_ITEM(item) + && !gtk_check_menu_item_get_active(GTK_MENU_ITEM(item))) + { + /* Ignore activation of deselected item */ + return; + } + + g_debug("[menu_info] subitem activated: %s %s", + menu_info_type_name(mii->menu_info->type), + mii->name); switch(mii->menu_info->type) { @@ -597,6 +624,15 @@ } } +void menu_info_subitem_clicked(GtkWidget* item, GdkEventButton* event, + menu_info_item_t* mii) +{ + 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); +} + void menu_info_item_move_all_cb(GtkWidget* item, GdkEventButton* event, void* userdata) { menu_info_item_t* mii = userdata; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/menu_info.h new/pasystray-0.8.0/src/menu_info.h --- old/pasystray-pasystray-0.7.1/src/menu_info.h 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/src/menu_info.h 2021-10-21 20:54:40.000000000 +0200 @@ -58,8 +58,11 @@ struct settings_t_ { int volume_max; int volume_inc; + gboolean reverse_scroll; gboolean icon_tooltip; gboolean monitors; + // Grab volume control keys + gboolean key_grabbing; // Notification options below gboolean n_new; gboolean n_sink; @@ -127,10 +130,12 @@ menu_info_item_t* menu_info_item_get_by_name(menu_info_t* mi, const char* name); menu_info_item_t* menu_info_item_get_by_desc(menu_info_t* mi, const char* desc); +void menu_info_item_activated(GtkWidget* item, menu_info_item_t* mii); void menu_info_item_clicked(GtkWidget* item, GdkEventButton* event, menu_info_item_t* mii); void menu_info_item_scrolled(GtkWidget* item, GdkEventScroll* event, menu_info_item_t* mii); +void menu_info_subitem_activated(GtkWidget* item, menu_info_item_t* mii); void menu_info_subitem_clicked(GtkWidget* item, GdkEventButton* event, menu_info_item_t* mii); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/options.c new/pasystray-0.8.0/src/options.c --- old/pasystray-pasystray-0.7.1/src/options.c 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/src/options.c 2021-10-21 20:54:40.000000000 +0200 @@ -28,11 +28,13 @@ static gboolean version = FALSE; static gboolean debug = FALSE; static int volume_max = 0; -static int volume_inc = 1; +static int volume_inc = 2; +static gboolean reverse_scroll = FALSE; static gboolean icon_tooltip = TRUE; static gboolean no_notify = FALSE; static gboolean always_notify = FALSE; static gboolean monitors = FALSE; +static gboolean key_grabbing = FALSE; static gchar **notify_mode; static GOptionEntry entries[] = @@ -41,13 +43,16 @@ { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Print debugging information", NULL }, { "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-icon-tooltip", 't', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, + { "reverse-scroll", 'r', 0, G_OPTION_ARG_NONE, + &reverse_scroll, "Reverse volume scroll direction", NULL }, + { "no-icon-tooltip", 't', 0, G_OPTION_ARG_NONE, &icon_tooltip, "Disable the status icon tooltip for the connected state", NULL }, { "no-notify", 'n', 0, G_OPTION_ARG_NONE, &no_notify, "Deprecated, use --notify=none instead", NULL }, { "always-notify", 'a', 0, G_OPTION_ARG_NONE, &always_notify, "Deprecated, use --notify=all instead", NULL }, { "include-monitors", 'n', 0, G_OPTION_ARG_NONE, &monitors, "Include monitor sources", NULL }, + { "key-grabbing", 'g', 0, G_OPTION_ARG_NONE, &key_grabbing, "Grab volume control keys", NULL }, { "notify", 'N', 0, G_OPTION_ARG_STRING_ARRAY, ¬ify_mode, "Set notification options, use --notify=help for a list of valid options", "OPTION" }, { .long_name = NULL } @@ -114,12 +119,13 @@ settings->volume_max = volume_max; } - settings->volume_inc = 1; + settings->volume_inc = 2; if(volume_inc > 0) { settings->volume_inc = volume_inc; } + settings->reverse_scroll = reverse_scroll; settings->icon_tooltip = icon_tooltip; notify_default(settings); @@ -212,4 +218,5 @@ } settings->monitors = monitors; + settings->key_grabbing = key_grabbing; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/pasystray.c new/pasystray-0.8.0/src/pasystray.c --- old/pasystray-pasystray-0.7.1/src/pasystray.c 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/src/pasystray.c 2021-10-21 20:54:40.000000000 +0200 @@ -31,6 +31,7 @@ #include "pulseaudio.h" #include "avahi.h" #include "x11-property.h" +#include "x11-key-grabber.h" static GMainLoop* loop; static menu_infos_t* mis; @@ -51,7 +52,7 @@ init(&settings); g_main_loop_run(loop); - destroy(); + destroy(&settings); return EXIT_SUCCESS; } @@ -73,6 +74,11 @@ pulseaudio_init(mis); avahi_start(mis); + +#ifdef HAVE_X11 + if (settings->key_grabbing) + key_grabber_grab_keys(mis); +#endif } void quit() @@ -80,8 +86,13 @@ g_main_loop_quit(loop); } -void destroy() +void destroy(settings_t* settings) { +#ifdef HAVE_X11 + if (settings->key_grabbing) + key_grabber_ungrab_keys(mis); +#endif + pulseaudio_destroy(); avahi_destroy(); menu_infos_destroy(mis); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/pasystray.gtk2.glade new/pasystray-0.8.0/src/pasystray.gtk2.glade --- old/pasystray-pasystray-0.7.1/src/pasystray.gtk2.glade 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/src/pasystray.gtk2.glade 2021-10-21 20:54:40.000000000 +0200 @@ -2,32 +2,6 @@ <interface> <requires lib="gtk+" version="2.16"/> <!-- interface-naming-policy toplevel-contextual --> - <object class="GtkAboutDialog" id="aboutdialog"> - <property name="can_focus">False</property> - <property name="border_width">5</property> - <property name="icon_name">pasystray</property> - <property name="type_hint">dialog</property> - <property name="program_name">pasystray</property> - <property name="copyright" translatable="yes">Copyright ?? 2011-2016</property> - <property name="comments" translatable="yes">PulseAudio system tray</property> - <property name="authors">Christoph Gysin <christoph.gy...@gmail.com></property> - <property name="logo_icon_name">pasystray</property> - <child internal-child="vbox"> - <object class="GtkVBox" id="aboutdialog-vbox"> - <property name="can_focus">False</property> - <child internal-child="action_area"> - <object class="GtkHButtonBox" id="aboutdialog-action_area"> - <property name="can_focus">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - </object> - </child> - </object> <object class="GtkMessageDialog" id="errordialog"> <property name="can_focus">False</property> <property name="border_width">5</property> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/pasystray.gtk3.glade new/pasystray-0.8.0/src/pasystray.gtk3.glade --- old/pasystray-pasystray-0.7.1/src/pasystray.gtk3.glade 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/src/pasystray.gtk3.glade 2021-10-21 20:54:40.000000000 +0200 @@ -2,42 +2,6 @@ <!-- Generated with glade 3.18.3 --> <interface> <requires lib="gtk+" version="3.0"/> - <object class="GtkAboutDialog" id="aboutdialog"> - <property name="can_focus">False</property> - <property name="border_width">5</property> - <property name="icon_name">pasystray</property> - <property name="type_hint">dialog</property> - <property name="program_name">pasystray</property> - <property name="copyright" translatable="yes">Copyright ?? 2011-2016</property> - <property name="comments" translatable="yes">PulseAudio system tray</property> - <property name="authors">Christoph Gysin <christoph.gy...@gmail.com></property> - <property name="logo_icon_name">pasystray</property> - <property name="license_type">lgpl-2-1</property> - <child internal-child="vbox"> - <object class="GtkBox" id="aboutdialog-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="aboutdialog-action_area"> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="has_default">True</property> - <property name="layout_style">end</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="pack_type">end</property> - <property name="position">0</property> - </packing> - </child> - <child> - <placeholder/> - </child> - </object> - </child> - </object> <object class="GtkMessageDialog" id="errordialog"> <property name="can_focus">False</property> <property name="border_width">5</property> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/pulseaudio_action.c new/pasystray-0.8.0/src/pulseaudio_action.c --- old/pasystray-pasystray-0.7.1/src/pulseaudio_action.c 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/src/pulseaudio_action.c 2021-10-21 20:54:40.000000000 +0200 @@ -162,15 +162,15 @@ /* increment/decrement in 2% steps */ pa_cvolume* volume; if(inc < 0) - volume = pa_cvolume_dec(mii->volume, -inc * PA_VOLUME_NORM / 50); + volume = pa_cvolume_dec(mii->volume, -inc * PA_VOLUME_NORM / 100); else if(inc > 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, + volume = pa_cvolume_inc_clamp(mii->volume, inc * PA_VOLUME_NORM / 100, PA_VOLUME_NORM * volume_max / 100); else - volume = pa_cvolume_inc(mii->volume, inc * PA_VOLUME_NORM / 50); + volume = pa_cvolume_inc(mii->volume, inc * PA_VOLUME_NORM / 100); } else return; @@ -276,11 +276,15 @@ 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; + gint volume = (pa_cvolume_max(mii->volume)*100+PA_VOLUME_NORM/2)/PA_VOLUME_NORM; + + int volume_max = mii->menu_info->menu_infos->settings.volume_max; + gint value = (volume_max > 0) ? volume * 100 / volume_max : volume; + if(!mii->notify) - mii->notify = notify(msg, NULL, mii->icon, volume); + mii->notify = notify(msg, NULL, mii->icon, value); else - notify_update(mii->notify, msg, NULL, mii->icon, volume); + notify_update(mii->notify, msg, NULL, mii->icon, value); g_free(msg); } @@ -361,5 +365,8 @@ void pulseaudio_terminate(void) { - pa_operation_unref(pa_context_exit_daemon(context, NULL, NULL)); + pa_operation* exit_op = pa_context_exit_daemon(context, NULL, NULL); + if (exit_op) { + pa_operation_unref(exit_op); + } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/systray.c new/pasystray-0.8.0/src/systray.c --- old/pasystray-pasystray-0.7.1/src/systray.c 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/src/systray.c 2021-10-21 20:54:40.000000000 +0200 @@ -19,6 +19,7 @@ USA. ***/ +#include <glib/gi18n.h> #include "systray.h" #include "pasystray.h" @@ -28,6 +29,7 @@ #include "systray_impl.h" static const char* COMMAND_PAMAN = "paman"; +static const char* COMMAND_PAEQUALIZER = "qpaeq"; static const char* COMMAND_PAVUCONTROL = "pavucontrol"; static const char* COMMAND_PAVUMETER = "pavumeter"; static const char* COMMAND_PAVUMETER_REC = "pavumeter --record"; @@ -52,6 +54,7 @@ systray_menu_add_separator(mis->menu); systray_menu_add_application(mis->menu, "_Manager...", NULL, COMMAND_PAMAN); + systray_menu_add_application(mis->menu, "_Equalizer...", NULL, COMMAND_PAEQUALIZER); systray_menu_add_application(mis->menu, "Volume _Control...", NULL, COMMAND_PAVUCONTROL); systray_menu_add_application(mis->menu, "Volume Meter (_Playback)...", NULL, COMMAND_PAVUMETER); systray_menu_add_application(mis->menu, "Volume Meter (_Recording)...", NULL, COMMAND_PAVUMETER_REC); @@ -204,33 +207,14 @@ GtkWidget* systray_add_item(GtkMenuShell* menu, const char* desc, const char* tooltip, const char* icon) { - 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); + GtkWidget* item = gtk_image_menu_item_new_with_mnemonic(desc); 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 + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image); } - 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); @@ -346,9 +330,22 @@ void systray_about_dialog() { - GtkDialog* dialog = ui_aboutdialog(); - g_signal_connect_swapped(dialog, "response", G_CALLBACK(gtk_widget_hide), dialog); - gtk_widget_show_all(GTK_WIDGET(dialog)); + char *authors[] = { _("Christoph Gysin <christoph.gy...@gmail.com>"), + NULL }; + + gtk_show_about_dialog(NULL, + "program-name", "pasystray", + "version", PACKAGE_VERSION, + "logo-icon-name", "pasystray", + "comments", _("PulseAudio system tray"), + "authors", authors, + "copyright", _("Copyright ?? 2011-2016"), +#if GTK_CHECK_VERSION(3,0,0) + "license-type", GTK_LICENSE_LGPL_2_1, +#endif + "website", PACKAGE_URL, + "website-label", PACKAGE_URL, + NULL); } void systray_click_cb(GtkStatusIcon* icon, GdkEventButton* ev, gpointer userdata) @@ -411,14 +408,15 @@ void systray_scroll_cb(guint state, GdkScrollDirection direction, menu_infos_t* mis) { int inc = 0; + int reverse_factor = mis->settings.reverse_scroll ? -1 : 1; switch(direction) { case GDK_SCROLL_UP: - inc = mis->settings.volume_inc; + inc = reverse_factor * mis->settings.volume_inc; break; case GDK_SCROLL_DOWN: - inc = -mis->settings.volume_inc; + inc = reverse_factor * -mis->settings.volume_inc; break; default: return; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/ui.c new/pasystray-0.8.0/src/ui.c --- old/pasystray-pasystray-0.7.1/src/ui.c 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/src/ui.c 2021-10-21 20:54:40.000000000 +0200 @@ -20,12 +20,42 @@ ***/ #include <glib.h> +#include "menu_info.h" #include "ui.h" #include "config.h" #include "systray_impl.h" +typedef enum { + ICON_IDX_MUTED = 0, + ICON_IDX_LOW = 1, + ICON_IDX_MEDIUM = 2, + ICON_IDX_HIGH = 3 +} icon_idx_t; + +enum { ICON_IDX_COUNT = 4 }; + +typedef const gchar* icon_set_t[ICON_IDX_COUNT]; + +static icon_set_t volume_icon_names = { + [ICON_IDX_MUTED] = "audio-volume-muted", + [ICON_IDX_LOW] = "audio-volume-low", + [ICON_IDX_MEDIUM] = "audio-volume-medium", + [ICON_IDX_HIGH] = "audio-volume-high" +}; + +static icon_set_t mic_icon_names = { + [ICON_IDX_MUTED] = "microphone-sensitivity-muted", + [ICON_IDX_LOW] = "microphone-sensitivity-low", + [ICON_IDX_MEDIUM] = "microphone-sensitivity-medium", + [ICON_IDX_HIGH] = "microphone-sensitivity-high" +}; + +static icon_set_t ui_icon_names[MENU_COUNT]; + static GtkBuilder* builder; +static void ui_load_icons(void); + void ui_load() { builder = gtk_builder_new(); @@ -50,6 +80,8 @@ g_free(local_file); g_free(local_file_src); + ui_load_icons(); + if(!ret) { g_error("[ui] %s", error->message); @@ -60,21 +92,23 @@ { g_debug("pulseaudio_set_volume_icon(%s)", mii->name); - pa_volume_t volume = pa_cvolume_avg(mii->volume); + pa_volume_t volume = pa_cvolume_max(mii->volume); g_debug("volume:%u%s", volume, mii->mute ? " muted" : ""); const char* icon_name = NULL; + icon_idx_t idx; - if(volume == PA_VOLUME_MUTED || mii->mute) - icon_name = "audio-volume-muted"; + if(mii->mute) + idx = ICON_IDX_MUTED; else if(volume < (PA_VOLUME_NORM / 3)) - icon_name = "audio-volume-low"; + idx = ICON_IDX_LOW; else if(volume < (PA_VOLUME_NORM / 3 * 2)) - icon_name = "audio-volume-medium"; + idx = ICON_IDX_MEDIUM; else - icon_name = "audio-volume-high"; + idx = ICON_IDX_HIGH; + icon_name = ui_icon_names[mii->menu_info->type][idx]; g_free(mii->icon); mii->icon = g_strdup(icon_name); } @@ -89,17 +123,6 @@ systray_impl_set_icon(mis->systray, mii->icon); } -GtkDialog* ui_aboutdialog() -{ - GtkAboutDialog* aboutdialog = (GtkAboutDialog*) gtk_builder_get_object(builder, "aboutdialog"); - - gtk_about_dialog_set_version(aboutdialog, PACKAGE_VERSION); - gtk_about_dialog_set_website(aboutdialog, PACKAGE_URL); - gtk_about_dialog_set_website_label(aboutdialog, PACKAGE_URL); - - return GTK_DIALOG(aboutdialog); -} - GtkDialog* ui_renamedialog() { return (GtkDialog*) gtk_builder_get_object(builder, "renamedialog"); @@ -126,3 +149,24 @@ return GTK_DIALOG(dialog); } + +static const gchar* ui_find_icon_name(GtkIconTheme* theme, const gchar* name, const gchar* fallback) +{ + const gchar* s = g_strdup_printf("%s-symbolic", name); + if(gtk_icon_theme_has_icon(theme, s)) + return s; + g_free(s); + if(gtk_icon_theme_has_icon(theme, name)) + return g_strdup(name); + return g_strdup(fallback); +} + +static void ui_load_icons(void) { + GtkIconTheme* theme = gtk_icon_theme_get_default(); + for(menu_type_t mt = 0; mt < MENU_COUNT; mt++) { + const gchar** preferred_names = (mt == MENU_SOURCE ? mic_icon_names : volume_icon_names); + for(icon_idx_t i = 0; i < ICON_IDX_COUNT; i++) { + ui_icon_names[mt][i] = ui_find_icon_name(theme, preferred_names[i], volume_icon_names[i]); + } + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/ui.h new/pasystray-0.8.0/src/ui.h --- old/pasystray-pasystray-0.7.1/src/ui.h 2019-01-02 19:15:05.000000000 +0100 +++ new/pasystray-0.8.0/src/ui.h 2021-10-21 20:54:40.000000000 +0200 @@ -28,7 +28,6 @@ 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(); GtkLabel* ui_renamedialog_label(); GtkEntry* ui_renamedialog_entry(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/x11-key-grabber.c new/pasystray-0.8.0/src/x11-key-grabber.c --- old/pasystray-pasystray-0.7.1/src/x11-key-grabber.c 1970-01-01 01:00:00.000000000 +0100 +++ new/pasystray-0.8.0/src/x11-key-grabber.c 2021-10-21 20:54:40.000000000 +0200 @@ -0,0 +1,247 @@ +/* + * This file is part of pa-applet. + * + * ?? 2012 Fernando Tarl?? Cardoso Lemos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <glib.h> +#include <gdk/gdkx.h> +#include <gtk/gtk.h> +#include <X11/Xlib.h> + +#include "x11-key-grabber.h" +#include "pulseaudio_action.h" + +#define NUM_KEYS_TO_GRAB 4 + +void volume_raise_cb(unsigned int state, menu_infos_t *mis) +{ + menu_info_t* mi = &mis->menu_info[(state & ControlMask) ? MENU_SOURCE : MENU_SINK]; + menu_info_item_t* mii = menu_info_item_get_by_name(mi, mi->default_name); + + g_debug("[key_grabber] %sXF86AudioRaiseVolume pressed\n", (state & ControlMask) ? "Ctrl-" : ""); + if(mii) + pulseaudio_volume(mii, mis->settings.volume_inc); +} + +void volume_lower_cb(unsigned int state, menu_infos_t *mis) +{ + menu_info_t* mi = &mis->menu_info[(state & ControlMask) ? MENU_SOURCE : MENU_SINK]; + menu_info_item_t* mii = menu_info_item_get_by_name(mi, mi->default_name); + + g_debug("[key_grabber] %sXF86AudioLowerVolume pressed\n", (state & ControlMask) ? "Ctrl-" : ""); + if(mii) + pulseaudio_volume(mii, -mis->settings.volume_inc); +} + +void volume_mute_cb(unsigned int state, menu_infos_t *mis) { + menu_info_t* mi = &mis->menu_info[(state & ControlMask) ? MENU_SOURCE : MENU_SINK]; + menu_info_item_t* mii = menu_info_item_get_by_name(mi, mi->default_name); + + g_debug("[key_grabber] %sXF86AudioMute pressed\n", (state & ControlMask) ? "Ctrl-" : ""); + if(mii) + pulseaudio_toggle_mute(mii); +} + +void mic_mute_cb(unsigned int state, menu_infos_t *mis) { + menu_info_t* mi = &mis->menu_info[MENU_SOURCE]; + menu_info_item_t* mii = menu_info_item_get_by_name(mi, mi->default_name); + + g_debug("[key_grabber] XF86AudioMicMute pressed\n"); + if(mii) + pulseaudio_toggle_mute(mii); +} + +static key_grabber_cb *grabbers[NUM_KEYS_TO_GRAB] = { + volume_raise_cb, + volume_lower_cb, + volume_mute_cb, + mic_mute_cb +}; + +static const char *keysym_names[NUM_KEYS_TO_GRAB] = { + "XF86AudioRaiseVolume", + "XF86AudioLowerVolume", + "XF86AudioMute", + "XF86AudioMicMute" +}; + +static KeyCode grabbed_keys[NUM_KEYS_TO_GRAB] = { 0, }; + +static GdkFilterReturn filter_func(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) +{ + // Skip events other than key presses + XEvent *xevent = (XEvent *)gdk_xevent; + if (xevent->type != KeyPress) + return GDK_FILTER_CONTINUE; + + // Find a match for the key press + XKeyEvent *keyevent = (XKeyEvent *)xevent; + for (int i = 0; i < NUM_KEYS_TO_GRAB; ++i) { + if (keyevent->keycode == grabbed_keys[i]) { + if (grabbers[i] != NULL) + (*grabbers[i])(keyevent->state, data); + return GDK_FILTER_REMOVE; + } + } + + // Continue processing this event + return GDK_FILTER_CONTINUE; +} + +void key_grabber_grab_keys(menu_infos_t *mis) +{ + // Find the X11 display + GdkDisplay *gdkDisplay = gdk_display_get_default(); + Display *dpy = GDK_DISPLAY_XDISPLAY(gdkDisplay); + + // Resolve the keysym names into keycodes + for (int i = 0; i < NUM_KEYS_TO_GRAB; ++i) { + // Resolve the keysym name into a keysym first + KeySym keysym = XStringToKeysym(keysym_names[i]); + if (keysym == NoSymbol) { + g_printerr("Failed to resolve %s into a keysym\n", keysym_names[i]); + continue; + } + + // Resolve the keysym into a keycode + grabbed_keys[i] = XKeysymToKeycode(dpy, keysym); + if (grabbed_keys[i] == 0) { + g_printerr("Failed to resolve %s into a keycode\n", keysym_names[i]); + continue; + } + } + + int numScreens = 1; +#if GDK_VERSION_CUR_STABLE < G_ENCODE_VERSION(3, 10) + numScreens = gdk_display_get_n_screens(gdkDisplay); +#endif + + // Grab the keys for all screens + for (int i = 0; i < numScreens; ++i) { +#if GTK_CHECK_VERSION(3,20,0) + GdkScreen *screen = gdk_display_get_default_screen(gdkDisplay); +#else + GdkScreen *screen = gdk_display_get_screen(gdkDisplay, i); +#endif + if (screen == NULL) + continue; + + // Find the X11 root window + GdkWindow *gdkRoot = gdk_screen_get_root_window(screen); + Window root = GDK_WINDOW_XID(gdkRoot); + + for (int i = 0; i < NUM_KEYS_TO_GRAB; ++i) { + // Ignore the keys that we couldn't resolve + KeyCode keycode = grabbed_keys[i]; + if (keycode == 0) + continue; + + // Try to grab the keycodes with any modifiers +#if GTK_CHECK_VERSION(3,22,0) + gdk_x11_display_error_trap_push(gdkDisplay); +#else + gdk_error_trap_push(); +#endif + XGrabKey(dpy, keycode, AnyModifier, root, True, GrabModeAsync, GrabModeAsync); + +#if GTK_CHECK_VERSION(3,22,0) + gdk_display_flush(gdkDisplay); +#else + gdk_flush(); +#endif + + // Handle errors +#if GTK_CHECK_VERSION(3,22,0) + if (gdk_x11_display_error_trap_pop(gdkDisplay)) +#else + if (gdk_error_trap_pop()) +#endif + g_printerr("Failed to grab %s\n", keysym_names[i]); + } + + // Register for X events + gdk_window_add_filter(gdkRoot, filter_func, mis); + } +} + +void key_grabber_ungrab_keys(menu_infos_t *mis) +{ + // Find the X11 display + GdkDisplay *gdkDisplay = gdk_display_get_default(); + Display *dpy = GDK_DISPLAY_XDISPLAY(gdkDisplay); + + int numScreens = 1; +#if GDK_VERSION_CUR_STABLE < G_ENCODE_VERSION(3, 10) + numScreens = gdk_display_get_n_screens(gdkDisplay); +#endif + + // Ungrab the keys for all screens + for (int i = 0; i < numScreens; ++i) { +#if GTK_CHECK_VERSION(3,20,0) + GdkScreen *screen = gdk_display_get_default_screen(gdkDisplay); +#else + GdkScreen *screen = gdk_display_get_screen(gdkDisplay, i); +#endif + if (screen == NULL) + continue; + + // Find the X11 root window + GdkWindow *gdkRoot = gdk_screen_get_root_window(screen); + Window root = GDK_WINDOW_XID(gdkRoot); + + for (int i = 0; i < NUM_KEYS_TO_GRAB; ++i) { + // Ignore the keys that we couldn't resolve + KeyCode keycode = grabbed_keys[i]; + if (keycode == 0) + continue; + + // Ungrab everything +#if GTK_CHECK_VERSION(3,22,0) + gdk_x11_display_error_trap_push(gdkDisplay); +#else + gdk_error_trap_push(); +#endif + XUngrabKey(dpy, keycode, AnyModifier, root); + +#if GTK_CHECK_VERSION(3,22,0) + gdk_display_flush(gdkDisplay); + + if (gdk_x11_display_error_trap_pop(gdkDisplay)) +#else + gdk_flush(); + + if (gdk_error_trap_pop()) +#endif + g_printerr("Failed to ungrab %s\n", keysym_names[i]); + } + + // Unregister for X events + gdk_window_remove_filter(gdkRoot, filter_func, mis); + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pasystray-pasystray-0.7.1/src/x11-key-grabber.h new/pasystray-0.8.0/src/x11-key-grabber.h --- old/pasystray-pasystray-0.7.1/src/x11-key-grabber.h 1970-01-01 01:00:00.000000000 +0100 +++ new/pasystray-0.8.0/src/x11-key-grabber.h 2021-10-21 20:54:40.000000000 +0200 @@ -0,0 +1,47 @@ +/* + * This file is part of pa-applet. + * + * ?? 2012 Fernando Tarl?? Cardoso Lemos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef KEY_GRABBER_H +#define KEY_GRABBER_H + +#include <glib.h> + +#include "menu_info.h" + +typedef void (key_grabber_cb)(unsigned int, menu_infos_t *); + +void key_grabber_grab_keys(menu_infos_t *); +void key_grabber_ungrab_keys(menu_infos_t *); +void key_grabber_register_volume_raise_callback(key_grabber_cb cb); +void key_grabber_register_volume_lower_callback(key_grabber_cb cb); +void key_grabber_register_volume_mute_callback(key_grabber_cb cb); + +#endif