diff -Nru goodvibes-0.3.6/AUTHORS.in goodvibes-0.4.2/AUTHORS.in --- goodvibes-0.3.6/AUTHORS.in 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/AUTHORS.in 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -@PACKAGE_AUTHOR_NAME@ @PACKAGE_AUTHOR_EMAIL@ diff -Nru goodvibes-0.3.6/autogen.sh goodvibes-0.4.2/autogen.sh --- goodvibes-0.3.6/autogen.sh 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/autogen.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -#!/bin/sh -# Run this to generate all the initial makefiles, etc. - -set -e - -echo "Running $0..." - -# Check installed commands -if ! command -v autoreconf >/dev/null 2>&1; then - echo >&2 "*** 'autoreconf' not found, please install it ***" - exit 1 -fi - -if ! command -v pkg-config >/dev/null 2>&1; then - echo >&2 "*** 'pkg-config' not found, please install it ***" - exit 1 -fi - -# Enable pre-commit hook -if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ]; then - # This part is allowed to fail - cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \ - chmod +x .git/hooks/pre-commit && \ - echo "Activated pre-commit hook." || : -fi - -# Autoreconf -autoreconf --force --install --verbose - -# Done -echo "Done, please type './configure' to continue." - diff -Nru goodvibes-0.3.6/configure.ac goodvibes-0.4.2/configure.ac --- goodvibes-0.3.6/configure.ac 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/configure.ac 1970-01-01 00:00:00.000000000 +0000 @@ -1,211 +0,0 @@ -# Process this file with autoconf - -# Init autoconf -# 2.60: obsoleting plenty of stuff -AC_PREREQ([2.60]) -AC_INIT([goodvibes], [0.3.6]) -: ${CPPFLAGS="-std=gnu99 -Wall -Wextra -Wshadow"} - -# Init automake -# 1.11: silent-rules -# 1.14: obsoleting AM_PROG_CC_C_O -AM_INIT_AUTOMAKE([1.14 foreign subdir-objects]) -AM_SILENT_RULES([yes]) - -# Load our own set of m4 macros -AC_CONFIG_MACRO_DIRS([m4]) - -# Additional package information -GV_ADD_GLOBAL_VAR([PACKAGE_CAMEL_NAME], ["Goodvibes"]) -GV_ADD_GLOBAL_VAR([PACKAGE_ALLCAPS_NAME], ["GOODVIBES"]) -GV_ADD_GLOBAL_VAR([PACKAGE_LONG_NAME], ["Goodvibes Radio Player"]) -GV_ADD_GLOBAL_VAR([PACKAGE_APPLICATION_ID], ["com.elboulangero.Goodvibes"]) -GV_ADD_GLOBAL_VAR([PACKAGE_APPLICATION_PATH], ["/com/elboulangero/Goodvibes"]) -GV_ADD_GLOBAL_VAR([PACKAGE_AUTHOR_NAME], ["Arnaud Rebillout"]) -GV_ADD_GLOBAL_VAR([PACKAGE_AUTHOR_EMAIL], [""]) -GV_ADD_GLOBAL_VAR([PACKAGE_COPYRIGHT], ["Copyright (C) 2015-2017"]) -GV_ADD_GLOBAL_VAR([PACKAGE_HOMEPAGE], ["http://goodvibes.elboulangero.com"]) - -# ------------------------------------- # -# Toolchain # -# ------------------------------------- # - -AS_ECHO(["---- Toolchain ----"]) - -AC_PROG_CC() -AC_PROG_INSTALL() -PKG_PROG_PKG_CONFIG() - -# To build static libraries (libcaphe) -AC_PROG_RANLIB() -AM_PROG_AR() - -# For glib settings -GLIB_GSETTINGS() - -# ------------------------------------- # -# Internationalization (i18n) # -# ------------------------------------- # - -AS_ECHO(["---- I18n ----"]) - -# Init gettext -AM_GNU_GETTEXT([external]) -AM_GNU_GETTEXT_VERSION([0.19.7]) - -# ------------------------------------- # -# Mandatory dependencies # -# ------------------------------------- # - -# Check for core dependencies -# - gio-unix-2.0 is needed for libcaphe. In a perfect world, libcaphe -# (and therefore gio-unix-2.0) should depend on the inhibitor feature. - -AS_ECHO(["---- Core ----"]) - -PKG_CHECK_MODULES([GLIB], [glib-2.0, gobject-2.0, gio-2.0, gio-unix-2.0 >= 2.44]) -PKG_CHECK_MODULES([LIBSOUP], [libsoup-2.4 >= 2.42]) -PKG_CHECK_MODULES([GST], [gstreamer-1.0, gstreamer-base-1.0, gstreamer-audio-1.0 >= 1.4.4]) - -# Libcaphe flags -CAPHE_CFLAGS="-I../libcaphe/" -CAPHE_LIBS="../libcaphe/caphe/libcaphe.a" -AC_SUBST(CAPHE_CFLAGS) -AC_SUBST(CAPHE_LIBS) - -# ------------------------------------- # -# Optional dependencies # -# ------------------------------------- # - -# The default behavior is as following: -# - a feature that doesn't require an extra library is enabled. -# - a feature that requires an extra library is set to 'auto', -# and will be enabled only if the required library is found. - -feat_noextra="yes" -feat_extra="auto" - -# The default behavior can be modified with the '--enable-all' switch. -# If you want to use it, expect the following behavior: -# - --enable-all Build a full-featured version (maximum dependencies). -# This will force the compilation of every feature, -# and fail the build if a dependency is not met. -# - --disable-all Build a lightweight version (minimum dependencies). -# This will exclude every feature from the build. - -AC_ARG_ENABLE(all, AS_HELP_STRING([--enable-all], [Enable every features])) - -if test -n "$enable_all"; then - feat_noextra="$enable_all" - feat_extra="$enable_all" -fi - -# For a higher degree of granularity, every feature has its own switch. -# If you want to use it, expect the following behavior: -# - --enable-FEATURE Force the compilation of a feature, and fail -# the build if dependencies are not met. -# - --disable-FEATURE Exclude a feature from the build. - -# Check for ui dependencies -# Notice that the UI is managed as a feature here. - -AS_ECHO(["---- Ui ----"]) - -GV_FEATURE_ENABLE([ui], [Gtk+ graphical user interface], [$feat_extra]) -GV_FEATURE_PKG_CHECK([ui], [UI], [gtk+-3.0 >= 3.12.0]) -AM_CONDITIONAL([UI_ENABLED], [test "$enable_ui" = "yes"]) - -# Check for core features dependencies - -AS_ECHO(["---- Core Features ----"]) - -GV_FEATURE_ENABLE([console_output], [console output support], [$feat_noextra]) -GV_FEATURE_ENABLE([dbus_server], [dbus server support], [$feat_noextra]) -GV_FEATURE_ENABLE([inhibitor], [inhibitor support], [$feat_noextra]) - -AM_CONDITIONAL([CONSOLE_OUTPUT_ENABLED], [test "$enable_console_output" = "yes"]) -AM_CONDITIONAL([DBUS_SERVER_ENABLED], [test "$enable_dbus_server" = "yes"]) -AM_CONDITIONAL([INHIBITOR_ENABLED], [test "$enable_inhibitor" = "yes"]) - -# Check for ui features dependencies -# If the ui is disabled, ensure features are disabled as well. - -AS_ECHO(["---- Ui Features ----"]) - -if test "$enable_ui" = "no"; then - feat_noextra="no" - feat_extra="no" -fi - -GV_FEATURE_ENABLE([hotkeys], [hotkeys support], [$feat_extra]) -GV_FEATURE_ENABLE([notifications], [notifications support], [$feat_noextra]) - -GV_FEATURE_PKG_CHECK([hotkeys], [HOTKEYS], [keybinder-3.0 >= 0.3]) - -AM_CONDITIONAL([HOTKEYS_ENABLED], [test "$enable_hotkeys" = "yes"]) -AM_CONDITIONAL([NOTIFICATIONS_ENABLED], [test "$enable_notifications" = "yes"]) - -# ------------------------------------- # -# Output files # -# ------------------------------------- # - -AS_ECHO(["---- Output Files ----"]) - -# Files to be created -AC_CONFIG_FILES([ -AUTHORS -Makefile -data/Makefile -data/$PACKAGE_NAME.1 -data/$PACKAGE_NAME-client.1 -data/$PACKAGE_APPLICATION_ID.service.in -data/$PACKAGE_APPLICATION_ID.desktop.in -data/$PACKAGE_APPLICATION_ID.gschema.xml -libcaphe/Makefile -libcaphe/caphe/Makefile -libcaphe/tests/Makefile -po/Makefile.in -src/Makefile -]) - -AC_OUTPUT() - -# ------------------------------------- # -# Summary # -# ------------------------------------- # - -# String for silent rules -is_silent_rules_enabled=no -if test "$AM_DEFAULT_VERBOSITY" = "0"; then - is_silent_rules_enabled=yes -fi - -AS_ECHO([" -------------------------------------------------------------- - - ~ $PACKAGE_LONG_NAME - $PACKAGE_VERSION ~ - - Core - ---- - Console output : $enable_console_output - D-Bus server : $enable_dbus_server - Inhibitor : $enable_inhibitor - - Ui : $enable_ui - -- - Hotkeys : $enable_hotkeys - Notifications : $enable_notifications - - Build - ----- - Silent rules : $is_silent_rules_enabled - CC : $CC - CFLAGS : $CFLAGS - CPPFLAGS : $CPPFLAGS - LDFLAGS : $LDFLAGS - LIBS : $LIBS - -------------------------------------------------------------- - -Configuration finished, please type 'make' to compile."]) - diff -Nru goodvibes-0.3.6/data/com.elboulangero.Goodvibes.desktop.in.in goodvibes-0.4.2/data/com.elboulangero.Goodvibes.desktop.in.in --- goodvibes-0.3.6/data/com.elboulangero.Goodvibes.desktop.in.in 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/com.elboulangero.Goodvibes.desktop.in.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -[Desktop Entry] -Name=@PACKAGE_LONG_NAME@ -GenericName=Radio Player -Comment=Play web radios -# TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! -Keywords=Audio;Radio;Player; -Categories=GTK;AudioVideo;Audio;Player; -Type=Application -# TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! -Icon=@PACKAGE_NAME@ -Exec=@PACKAGE_NAME@ -DBusActivatable=true -MimeType=audio/*; diff -Nru goodvibes-0.3.6/data/com.elboulangero.Goodvibes.gschema.xml.in goodvibes-0.4.2/data/com.elboulangero.Goodvibes.gschema.xml.in --- goodvibes-0.3.6/data/com.elboulangero.Goodvibes.gschema.xml.in 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/com.elboulangero.Goodvibes.gschema.xml.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,116 +0,0 @@ - - - - - - - false - Enable custom pipeline - Whether the custom output pipeline is enabled - - - '' - Custom pipeline string - Custom output pipeline description - - - 100 - - Volume - The playback volume (in percent) - - - false - Mute - Whether playback is muted - - - true - Repeat - Whether to repeat when next/prev reaches the end - - - false - Shuffle - Whether to use shuffled playlist on next/prev - - - false - Autoplay - Whether to start playing automatically on startup - - - '' - Current station uri - The uri of the current station - - - - - - - (-1, -1) - Main window size - The size of the main window (use -1 for no specific size) - - - (-1, -1) - Main window position - The position of the main window (use -1 for no specific position) - - - false - Autoset main window height - Automatically set the main window position - - - 'default' - Theme variant - Prefer a different variant of the theme (if available) - - - 'toggle' - Middle click action - Action for middle click on the status icon - - - 'station' - Scroll action - Action for mouse scroll on the status icon - - - - - - - false - Enable the feature - Whether to enable the feature - - - - - false - - - - true - - - - true - - - - false - - - - false - - - - false - - - diff -Nru goodvibes-0.3.6/data/com.elboulangero.Goodvibes.service.in.in goodvibes-0.4.2/data/com.elboulangero.Goodvibes.service.in.in --- goodvibes-0.3.6/data/com.elboulangero.Goodvibes.service.in.in 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/com.elboulangero.Goodvibes.service.in.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -[D-BUS Service] -Name=@PACKAGE_APPLICATION_ID@ -Exec=bindir/@PACKAGE_NAME@ --background diff -Nru goodvibes-0.3.6/data/goodvibes.1.in goodvibes-0.4.2/data/goodvibes.1.in --- goodvibes-0.3.6/data/goodvibes.1.in 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/goodvibes.1.in 2018-11-10 06:04:58.000000000 +0000 @@ -1,21 +1,21 @@ -.TH "@PACKAGE_ALLCAPS_NAME@" "1" "February 2017" +.TH "@PACKAGE@" "1" "July 2018" "@package@ @version@" .SH NAME -@PACKAGE_NAME@ \- a lightweight internet radio player for GNU/Linux +@package@ \- a lightweight internet radio player for GNU/Linux .SH SYNOPSIS -.B @PACKAGE_NAME@ +.B @package@ [OPTIONS...] [STATION] .SH DESCRIPTION -.B @PACKAGE_CAMEL_NAME@ +.B @Package@ is a lightweight internet radio player for GNU/Linux. It offers a simple way to have your favorite radio stations at easy reach. It provides everything you can expect from a modern media player: multimedia keys binding, mpris2 support, notifications, and sleep inhibition. It can be launched with or without GUI, and comes with a command-line client. .PP -This manual page is only a short reference for @PACKAGE_CAMEL_NAME@. -Complete documentation is available at \fI\%@PACKAGE_HOMEPAGE@\fR\&. +This manual page is only a short reference for @Package@. +Complete documentation is available at \fI\%@homepage@\fR\&. .SH OPTIONS .TP @@ -42,10 +42,10 @@ Launch as a status icon (deprecated on modern desktops). .SH AUTHORS -Written by @PACKAGE_AUTHOR_NAME@. +Written by @author@. .SH SEE ALSO .nf -.BR @PACKAGE_NAME@-client (1) -\fI\%@PACKAGE_HOMEPAGE@\fR\& +.BR @package@-client (1) +\fI\%@homepage@\fR\& .fi diff -Nru goodvibes-0.3.6/data/goodvibes-client.1.in goodvibes-0.4.2/data/goodvibes-client.1.in --- goodvibes-0.3.6/data/goodvibes-client.1.in 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/goodvibes-client.1.in 2018-11-10 06:04:58.000000000 +0000 @@ -1,24 +1,24 @@ -.TH "@PACKAGE_ALLCAPS_NAME@-CLIENT" "1" "February 2017" +.TH "@PACKAGE@-CLIENT" "1" "July 2018" "@package@-client @version@" .SH NAME -@PACKAGE_NAME@-client \- command-line client for @PACKAGE_NAME@ +@package@-client \- command-line client for @package@ .SH SYNOPSIS -.B @PACKAGE_NAME@-client +.B @package@-client [OPTIONS...] .SH DESCRIPTION -.B @PACKAGE_NAME@-client -is the command-line client for @PACKAGE_NAME@. -It communicates through the native D-Bus interface, which therefore must be enabled in @PACKAGE_NAME@. +.B @package@-client +is the command-line client for @package@. +It communicates through the native D-Bus interface, which therefore must be enabled in @package@. -For more details, type '@PACKAGE_NAME@-client help'. +For more details, type '@package@-client help'. .SH AUTHORS -Written by @PACKAGE_AUTHOR_NAME@. +Written by @author@. .SH SEE ALSO .nf -.BR @PACKAGE_NAME@ (1) -\fI\%@PACKAGE_HOMEPAGE@\fR\& +.BR @package@ (1) +\fI\%@homepage@\fR\& .fi Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/16x16/apps/goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/16x16/apps/goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/16x16/apps/io.gitlab.Goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/16x16/apps/io.gitlab.Goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/22x22/apps/goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/22x22/apps/goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/22x22/apps/io.gitlab.Goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/22x22/apps/io.gitlab.Goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/24x24/apps/goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/24x24/apps/goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/24x24/apps/io.gitlab.Goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/24x24/apps/io.gitlab.Goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/256x256/apps/goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/256x256/apps/goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/256x256/apps/io.gitlab.Goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/256x256/apps/io.gitlab.Goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/32x32/apps/goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/32x32/apps/goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/32x32/apps/io.gitlab.Goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/32x32/apps/io.gitlab.Goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/48x48/apps/goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/48x48/apps/goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/48x48/apps/io.gitlab.Goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/48x48/apps/io.gitlab.Goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/512x512/apps/goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/512x512/apps/goodvibes.png differ Binary files /tmp/tmpktsMax/WyOapCEmUH/goodvibes-0.3.6/data/icons/hicolor/512x512/apps/io.gitlab.Goodvibes.png and /tmp/tmpktsMax/aUqatdj30N/goodvibes-0.4.2/data/icons/hicolor/512x512/apps/io.gitlab.Goodvibes.png differ diff -Nru goodvibes-0.3.6/data/icons/hicolor/symbolic/apps/goodvibes-symbolic.svg goodvibes-0.4.2/data/icons/hicolor/symbolic/apps/goodvibes-symbolic.svg --- goodvibes-0.3.6/data/icons/hicolor/symbolic/apps/goodvibes-symbolic.svg 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/icons/hicolor/symbolic/apps/goodvibes-symbolic.svg 1970-01-01 00:00:00.000000000 +0000 @@ -1,157 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - Hector Lahminewski - - - - - - - - - diff -Nru goodvibes-0.3.6/data/icons/hicolor/symbolic/apps/io.gitlab.Goodvibes-symbolic.svg goodvibes-0.4.2/data/icons/hicolor/symbolic/apps/io.gitlab.Goodvibes-symbolic.svg --- goodvibes-0.3.6/data/icons/hicolor/symbolic/apps/io.gitlab.Goodvibes-symbolic.svg 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/data/icons/hicolor/symbolic/apps/io.gitlab.Goodvibes-symbolic.svg 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + Hector Lahminewski + + + + + + + + + diff -Nru goodvibes-0.3.6/data/icons/meson.build goodvibes-0.4.2/data/icons/meson.build --- goodvibes-0.3.6/data/icons/meson.build 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/data/icons/meson.build 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +themes = [ + [ 'hicolor', [ + [ '16x16', gv_icon_name + '.png' ], + [ '22x22', gv_icon_name + '.png' ], + [ '24x24', gv_icon_name + '.png' ], + [ '32x32', gv_icon_name + '.png' ], + [ '48x48', gv_icon_name + '.png' ], + [ '256x256', gv_icon_name + '.png' ], + [ '512x512', gv_icon_name + '.png' ], + [ 'symbolic', gv_icon_name + '-symbolic.svg' ], + ]] +] + +foreach i : themes + theme = i[0] + sizes = i[1] + foreach i : sizes + size = i[0] + icon = i[1] + install_data(join_paths(theme, size, 'apps', icon), + install_dir : join_paths(datadir, 'icons', theme, size, 'apps') + ) + endforeach +endforeach diff -Nru goodvibes-0.3.6/data/icons/src/goodvibes-favicon.svg goodvibes-0.4.2/data/icons/src/goodvibes-favicon.svg --- goodvibes-0.3.6/data/icons/src/goodvibes-favicon.svg 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/icons/src/goodvibes-favicon.svg 2018-11-10 06:04:58.000000000 +0000 @@ -17,7 +17,6 @@ version="1.1" inkscape:version="0.92.3pre0 (0ab9bec, 2018-03-03)" sodipodi:docname="goodvibes-favicon.svg" - inkscape:export-filename="/Users/jbx/Desktop/gooV5-0.png" inkscape:export-xdpi="300" inkscape:export-ydpi="300"> + inkscape:export-ydpi="150" /> + inkscape:export-ydpi="150" /> diff -Nru goodvibes-0.3.6/data/io.gitlab.Goodvibes.appdata.xml.in goodvibes-0.4.2/data/io.gitlab.Goodvibes.appdata.xml.in --- goodvibes-0.3.6/data/io.gitlab.Goodvibes.appdata.xml.in 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/data/io.gitlab.Goodvibes.appdata.xml.in 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,53 @@ + + + io.gitlab.Goodvibes + Goodvibes + Play web radios + CC0-1.0 + GPL-3.0+ + + +

+ Goodvibes is a simple internet radio player for GNU/Linux. +

+

+ It comes with every basic features you can expect from an audio player, + such as multimedia keys, notifications, system sleep inhibition, and + MPRIS2 support. +

+
+ + + + https://goodvibes.gitlab.io/appdata/screenshot-2018-11-10-light.png + + + https://goodvibes.gitlab.io/appdata/screenshot-2018-11-10-light-prefs.png + + + https://goodvibes.gitlab.io/appdata/screenshot-2018-11-10-dark-with-appmenu.png + + + + + + + + + + + + https://gitlab.com/goodvibes/goodvibes + https://gitlab.com/goodvibes/goodvibes/issues + https://goodvibes.readthedocs.io + https://hosted.weblate.org/projects/goodvibes + + io.gitlab.Goodvibes.desktop + goodvibes + + + goodvibes + + + elboulangero_at_gmail.com +
diff -Nru goodvibes-0.3.6/data/io.gitlab.Goodvibes.desktop.in goodvibes-0.4.2/data/io.gitlab.Goodvibes.desktop.in --- goodvibes-0.3.6/data/io.gitlab.Goodvibes.desktop.in 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/data/io.gitlab.Goodvibes.desktop.in 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,13 @@ +[Desktop Entry] +Name=Goodvibes +GenericName=Radio Player +Comment=Play web radios +# TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +Keywords=Audio;Radio;Player; +Categories=GTK;AudioVideo;Audio;Player; +Type=Application +# TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! +Icon=io.gitlab.Goodvibes +Exec=goodvibes %u +DBusActivatable=true +MimeType=audio/*; diff -Nru goodvibes-0.3.6/data/io.gitlab.Goodvibes.gschema.xml.in goodvibes-0.4.2/data/io.gitlab.Goodvibes.gschema.xml.in --- goodvibes-0.3.6/data/io.gitlab.Goodvibes.gschema.xml.in 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/data/io.gitlab.Goodvibes.gschema.xml.in 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,116 @@ + + + + + + + false + Enable custom pipeline + Whether the custom output pipeline is enabled + + + '' + Custom pipeline string + Custom output pipeline description + + + 100 + + Volume + The playback volume (in percent) + + + false + Mute + Whether playback is muted + + + true + Repeat + Whether to repeat when next/prev reaches the end + + + false + Shuffle + Whether to use shuffled playlist on next/prev + + + false + Autoplay + Whether to start playing automatically on startup + + + '' + Current station uri + The uri of the current station + + + + + + + (-1, -1) + Main window size + The size of the main window (use -1 for no specific size) + + + (-1, -1) + Main window position + The position of the main window (use -1 for no specific position) + + + false + Autoset main window height + Automatically set the main window position + + + 'default' + Theme variant + Prefer a different variant of the theme (if available) + + + 'toggle' + Middle click action + Action for middle click on the status icon + + + 'station' + Scroll action + Action for mouse scroll on the status icon + + + + + + + false + Enable the feature + Whether to enable the feature + + + + + false + + + + true + + + + true + + + + false + + + + false + + + + false + + + diff -Nru goodvibes-0.3.6/data/io.gitlab.Goodvibes.service.in goodvibes-0.4.2/data/io.gitlab.Goodvibes.service.in --- goodvibes-0.3.6/data/io.gitlab.Goodvibes.service.in 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/data/io.gitlab.Goodvibes.service.in 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=@dbus_name@ +Exec=@bindir@/@binary@ --background diff -Nru goodvibes-0.3.6/data/Makefile.am goodvibes-0.4.2/data/Makefile.am --- goodvibes-0.3.6/data/Makefile.am 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/Makefile.am 1970-01-01 00:00:00.000000000 +0000 @@ -1,109 +0,0 @@ -EXTRA_DIST = -DISTCLEANFILES = -CLEANFILES = - -# ----------------------------------------------------- # -# D-Bus Service File # -# ----------------------------------------------------- # - -servicedir = $(datadir)/dbus-1/services -service_in_in_files = @PACKAGE_APPLICATION_ID@.service.in.in -service_in_files = @PACKAGE_APPLICATION_ID@.service.in -service_DATA = $(service_in_files:.in=) - -# Rule to make the service file with bindir expanded -$(service_DATA): $(service_in_files) Makefile - @sed -e "s|bindir|$(bindir)|" $< > $@ - -EXTRA_DIST += $(service_in_in_files) -DISTCLEANFILES += $(service_in_files) -CLEANFILES += $(service_DATA) - -# ----------------------------------------------------- # -# Desktop File # -# ----------------------------------------------------- # - -desktopdir = $(datadir)/applications -desktop_in_in_files = @PACKAGE_APPLICATION_ID@.desktop.in.in -desktop_in_files = $(desktop_in_in_files:.in=) -desktop_DATA = $(desktop_in_files:.in=) - -# Translate with gettext -%.desktop: %.desktop.in - msgfmt --desktop -d $(top_srcdir)/po --template $< -o $@ - -EXTRA_DIST += $(desktop_in_in_files) -DISTCLEANFILES += $(desktop_in_files) -CLEANFILES += $(desktop_DATA) - -# ----------------------------------------------------- # -# GSettings Schemas # -# ----------------------------------------------------- # - -gsettings_ENUM_NAMESPACE = @PACKAGE_APPLICATION_ID@ -gsettings_ENUM_FILES = $(shell find $(top_srcdir)/src -type f -name '*.h') -gsettings_SCHEMAS = @PACKAGE_APPLICATION_ID@.gschema.xml - -@GSETTINGS_RULES@ - -# Compile schemas for running from the source tree -gschemas.compiled: $(gsettings_SCHEMAS:.xml=.valid) - $(AM_V_GEN) $(GLIB_COMPILE_SCHEMAS) . - -all-local: gschemas.compiled - -EXTRA_DIST += $(gsettings_SCHEMAS).in -DISTCLEANFILES += $(gsettings_SCHEMAS) -CLEANFILES += gschemas.compiled - -# ----------------------------------------------------- # -# Icons # -# ----------------------------------------------------- # - -icon16dir = $(datadir)/icons/hicolor/16x16/apps -icon16_DATA = icons/hicolor/16x16/apps/@PACKAGE_NAME@.png -icon22dir = $(datadir)/icons/hicolor/22x22/apps -icon22_DATA = icons/hicolor/22x22/apps/@PACKAGE_NAME@.png -icon24dir = $(datadir)/icons/hicolor/24x24/apps -icon24_DATA = icons/hicolor/24x24/apps/@PACKAGE_NAME@.png -icon32dir = $(datadir)/icons/hicolor/32x32/apps -icon32_DATA = icons/hicolor/32x32/apps/@PACKAGE_NAME@.png -icon48dir = $(datadir)/icons/hicolor/48x48/apps -icon48_DATA = icons/hicolor/48x48/apps/@PACKAGE_NAME@.png -icon256dir = $(datadir)/icons/hicolor/256x256/apps -icon256_DATA = icons/hicolor/256x256/apps/@PACKAGE_NAME@.png -icon512dir = $(datadir)/icons/hicolor/512x512/apps -icon512_DATA = icons/hicolor/512x512/apps/@PACKAGE_NAME@.png -iconsymdir = $(datadir)/icons/hicolor/symbolic/apps -iconsym_DATA = icons/hicolor/symbolic/apps/@PACKAGE_NAME@-symbolic.svg - -EXTRA_DIST += \ - $(icon16_DATA) \ - $(icon22_DATA) \ - $(icon24_DATA) \ - $(icon32_DATA) \ - $(icon48_DATA) \ - $(icon256_DATA) \ - $(icon512_DATA) \ - $(iconsym_DATA) \ - icons/src/@PACKAGE_NAME@-large.svg \ - icons/src/@PACKAGE_NAME@-small.svg - -# ----------------------------------------------------- # -# Manual Pages # -# ----------------------------------------------------- # - -man1_in_files = $(wildcard *.1.in) -man1_MANS = $(man1_in_files:.in=) - -EXTRA_DIST += $(man1_in_files) -DISTCLEANFILES += $(man1_MANS) - -# ----------------------------------------------------- # -# Ui Files # -# ----------------------------------------------------- # - -uidir = $(pkgdatadir)/ui -ui_DATA = $(wildcard ui/*.glade) - -EXTRA_DIST += $(ui_DATA) diff -Nru goodvibes-0.3.6/data/meson.build goodvibes-0.4.2/data/meson.build --- goodvibes-0.3.6/data/meson.build 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/data/meson.build 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,255 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# My understanding of meson (a beginner guide) +# +# 'configure step' and 'build step' +# +# *Configure files* are generated early when creating the build directory with +# 'meson 'builddir', and afterward Meson automatically update these files if +# the source changes. Therefore, my understanding is that there's no need to +# declare a dependency to ensure configure files are up-to-date: they're always +# up-to-date. +# +# However, custom_target() has a 'depend_files:' keyword for declaring +# dependencies on files. It's unclear if we need to use it for configure files. +# I'd say no need. +# +# *Build targets* are, on the other hand, part of a dependency chain, and the +# 'depends:' keyword must be used to indicate a dependency. This is mandatory. +# +# 'source dir' and 'build dir' +# +# Meson has a clear concept of 'source dir' and 'build dir'. +# +# When you give a relative path to 'input:', meson assumes it's relative to +# 'source dir'. Beware when you need to use configure files as inputs, as they +# live in 'build dir'. +# +# References +# +# +# +# Credit for this file goes to . + +# ----------------------------------------------------- # +# D-Bus Service File # +# ----------------------------------------------------- # +# + +services_dir = join_paths(datadir, 'dbus-1/services') + +service_conf = configuration_data() +service_conf.set('bindir', bindir) +service_conf.set('binary', gv_binary) +service_conf.set('dbus_name', gv_application_id) + +configure_file( + input: gv_application_id + '.service.in', + output: gv_application_id + '.service', + configuration: service_conf, + install_dir: services_dir, +) + +# XXX It would be nice to have a tool to validate the service file. + +# ----------------------------------------------------- # +# Desktop File # +# ----------------------------------------------------- # +# + +# XXX It would be nice to have desktop.in created with configure_file(), +# so that we can do some variable substitution, like for the other data +# files here. However, it means that the POTFILES should list the built +# file, which lives in the build dir. Right now it doesn't work. +# https://github.com/mesonbuild/meson/issues/1733 + +applications_dir = join_paths(datadir, 'applications') + +desktop_file = i18n.merge_file( + input: gv_application_id + '.desktop.in', + output: gv_application_id + '.desktop', + po_dir: '../po', + type: 'desktop', + install: true, + install_dir: applications_dir, +) + +desktop_utils = find_program('desktop-file-validate', required: false) +if desktop_utils.found() + test('Validate desktop file', desktop_utils, + args: [ desktop_file ], + ) +endif + +# ----------------------------------------------------- # +# Appstream File # +# ----------------------------------------------------- # +# + +appstream_dir = join_paths(datadir, 'metainfo') + +appstream_file = i18n.merge_file( + input: gv_application_id + '.appdata.xml.in', + output: gv_application_id + '.appdata.xml', + po_dir: '../po', + type: 'xml', + install: true, + install_dir: appstream_dir, +) + +appstream_util = find_program('appstream-util', required: false) +if appstream_util.found() + # Relaxed validation, our screenshots don't meet the expectations + # (16:9 without padding is definitely not suitable). + test('Validate appstream file', appstream_util, + args: [ 'validate-relax', appstream_file ] + ) +endif + +# ----------------------------------------------------- # +# GSettings Schemas # +# ----------------------------------------------------- # +# + +schemas_dir = join_paths(datadir, 'glib-2.0', 'schemas') + +schema_conf = configuration_data() +schema_conf.set('id', gv_application_id) +schema_conf.set('path', gv_application_path) + +schema_file = configure_file( + input: gv_application_id + '.gschema.xml.in', + output: gv_application_id + '.gschema.xml', + configuration: schema_conf, + install_dir: schemas_dir, +) + +#gv_settings = gnome.compile_schemas( +# depend_files: schema_file +#) + +# Generate enums.xml file. +# XXX gnome.compile_schemas() can't generate the enum.xml file automatically, +# like it was done with the autotools. We need to do it explicitly. +# https://github.com/mesonbuild/meson/issues/1687 +# XXX It's unfortunate that we have to list the headers here, +# maybe that would be better done in src/ ? +enum_headers = [ + '../src/ui/gv-main-window.h', + '../src/ui/gv-status-icon.h', +] + +generate_enums = gnome.mkenums(gv_application_id + '.enums.xml', + sources: enum_headers, + comments: '', + fhead: '', + vhead: ' <@type@ id="' + gv_application_id + '.@EnumName@">', + vprod: ' ', + vtail: ' ', + ftail: '', + install_header: true, + install_dir: schemas_dir +) + +# Compile schemas for running the application in-tree +# XXX We use a custom target, because gnome.compile_schemas() +# would run in the source dir rather than the build dir, hence +# missing the generated 'enums.xml' file. +# https://github.com/mesonbuild/meson/issues/1687 +compile_schemas = custom_target('glib-compile-schemas', + output: 'gschemas.compiled', + build_by_default: true, + install: false, + command: [ + find_program('glib-compile-schemas'), + meson.current_build_dir(), + ], + depends: [ generate_enums ], +) + +compile_schemas = find_program('glib-compile-schemas', required: false) +if compile_schemas.found() + test('Validate schema file', compile_schemas, + args: [ '--strict', '--dry-run', meson.current_build_dir() ], +# Requires meson >= 0.46, commenting for now +# depends: [ generate_enums ], + ) +endif + +# ----------------------------------------------------- # +# Old GSettings Schemas # +# ----------------------------------------------------- # + +# In version 4.1, I changed application ID to io.gitlab.Goodvibes. +# This means changing the path and names of all the data files, +# including gsettings schema files. And it turns out that the only +# way to access the settings with the old app id (for migrating it +# to the new app id) is to actually keep on shipping gschema and enum +# files with the old name. So that's what we're doing here. + +old_application_id = 'com.elboulangero.Goodvibes' +old_application_path = '/com/elboulangero/Goodvibes' + +old_schema_conf = configuration_data() +old_schema_conf.set('id', old_application_id) +old_schema_conf.set('path', old_application_path) + +old_schema_file = configure_file( + input: gv_application_id + '.gschema.xml.in', + output: old_application_id + '.gschema.xml', + configuration: old_schema_conf, + install_dir: schemas_dir, +) + +old_generate_enums = gnome.mkenums(old_application_id + '.enums.xml', + sources: enum_headers, + comments: '', + fhead: '', + vhead: ' <@type@ id="' + old_application_id + '.@EnumName@">', + vprod: ' ', + vtail: ' ', + ftail: '', + install_header: true, + install_dir: schemas_dir +) + +# ----------------------------------------------------- # +# Manual Pages # +# ----------------------------------------------------- # + +# XXX That would be nice to use install_man(), however right now +# it's not possible to use it with generated files. So we have +# to use a custom target and zip the files manually. +# https://github.com/mesonbuild/meson/issues/1550 + +manuals_dir = join_paths(mandir, 'man1') + +manual_conf = configuration_data() +manual_conf.set('package', gv_name_lowercase) +manual_conf.set('Package', gv_name_camelcase) +manual_conf.set('PACKAGE', gv_name_uppercase) +manual_conf.set('version', gv_version) +manual_conf.set('homepage', gv_homepage) +manual_conf.set('author', gv_author_name) + +gzip = find_program('gzip', required: true) + +foreach exe: [ 'goodvibes', 'goodvibes-client' ] + tmp_man_file = configure_file( + input: exe + '.1.in', + output: exe + '.1', + configuration: manual_conf, + ) + custom_target('man-' + exe, + command: [ gzip, '--keep', '--force', tmp_man_file ], + output: exe + '.1.gz', + install: true, + install_dir: manuals_dir, + ) +endforeach + +# ------------------------------------------------------- # +# Subdirectories # +# ------------------------------------------------------- # + +subdir('icons') diff -Nru goodvibes-0.3.6/data/ui/app-menu.glade goodvibes-0.4.2/data/ui/app-menu.glade --- goodvibes-0.3.6/data/ui/app-menu.glade 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/ui/app-menu.glade 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ - - - -
- - Add Station - app.add-station - <Primary>a - -
-
- - Preferences - app.preferences - -
-
- - Online Help - app.help - F1 - - - About - app.about - - - Close UI - app.close-ui - <Primary>c - - - Quit - app.quit - <Primary>q - -
-
-
diff -Nru goodvibes-0.3.6/data/ui/main-window.glade goodvibes-0.4.2/data/ui/main-window.glade --- goodvibes-0.3.6/data/ui/main-window.glade 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/ui/main-window.glade 1970-01-01 00:00:00.000000000 +0000 @@ -1,228 +0,0 @@ - - - - - - True - False - media-skip-forward-symbolic - - - True - False - media-playback-start-symbolic - - - True - False - media-skip-backward-symbolic - - - True - False - media-playlist-repeat-symbolic - - - True - False - media-playlist-shuffle-symbolic - - - True - False - 6 - 6 - 6 - 6 - vertical - - - True - False - vertical - - - True - False - No station selected - end - - - - - - False - True - 0 - - - - - True - False - Stopped - end - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - start - - - True - True - True - play_image - none - True - - - True - True - 0 - True - - - - - True - True - True - prev_image - none - True - - - True - True - 1 - True - - - - - True - True - True - next_image - none - True - - - True - True - 2 - True - - - - - True - True - True - repeat_image - none - True - - - True - True - 3 - True - True - - - - - True - True - True - shuffle_image - none - True - - - True - True - 4 - True - True - - - - - True - True - False - True - none - vertical - audio-volume-muted-symbolic -audio-volume-high-symbolic -audio-volume-low-symbolic -audio-volume-medium-symbolic - - - True - True - center - center - none - - - - - True - True - center - center - none - - - - - True - True - 5 - True - True - - - - - False - True - 1 - - - - - True - True - in - - - - - - True - True - 2 - - - - diff -Nru goodvibes-0.3.6/data/ui/menubar.glade goodvibes-0.4.2/data/ui/menubar.glade --- goodvibes-0.3.6/data/ui/menubar.glade 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/ui/menubar.glade 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ - - - - - Menu -
- - Add Station - app.add-station - <Primary>a - -
-
- - Preferences - app.preferences - -
-
- - Close UI - app.close-ui - <Primary>c - - - Quit - app.quit - <Primary>q - -
-
- - Help -
- - Online Help - app.help - F1 - -
-
- - About - app.about - -
-
-
-
diff -Nru goodvibes-0.3.6/data/ui/prefs-window.glade goodvibes-0.4.2/data/ui/prefs-window.glade --- goodvibes-0.3.6/data/ui/prefs-window.glade 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/ui/prefs-window.glade 1970-01-01 00:00:00.000000000 +0000 @@ -1,617 +0,0 @@ - - - - - - 100 - 1 - 10 - - - True - False - vertical - - - True - True - - - True - False - vertical - - - True - False - 0 - none - - - True - False - - - Autoplay on Startup - True - True - False - True - - - 0 - 0 - - - - - Custom Output Pipeline - True - True - False - True - True - - - 0 - 1 - - - - - True - False - 6 - - - True - True - True - - - False - True - 0 - - - - - Apply - True - True - True - - - False - True - 1 - - - - - 0 - 2 - - - - - - - True - False - Playback - - - - - False - True - 0 - - - - - True - False - 0 - none - - - True - False - end - - - True - True - - - 1 - 0 - - - - - True - False - end - Prevent sleep while playing - - - 0 - 0 - - - - - - - True - False - System - - - - - False - True - 1 - - - - - True - False - 0 - none - - - True - False - end - - - True - True - - - 1 - 0 - - - - - True - True - - - 1 - 1 - - - - - True - False - end - Native D-Bus Server - - - 0 - 0 - - - - - True - False - end - MPRIS2 D-Bus Server - - - 0 - 1 - - - - - - - True - False - D-Bus - - - - - False - True - 2 - - - - - - - True - False - Misc - - - False - - - - - True - False - vertical - - - True - False - 0 - none - - - True - False - end - - - Autoset Window Height - True - True - False - True - - - 0 - 1 - - - - - True - False - end - Theme Variant - - - 0 - 0 - - - - - True - False - 0 - - System Default - Prefer Dark - Prefer Light - - - - 1 - 0 - - - - - - - - - - True - False - Window - - - - - False - True - 0 - - - - - True - False - 0 - none - - - True - False - end - - - True - False - start - Send Notifications - - - 0 - 0 - - - - - True - True - - - 1 - 0 - - - - - - - True - False - Notifications - - - - - False - True - 1 - - - - - True - False - 0 - none - - - True - False - end - - - True - True - - - 1 - 0 - - - - - True - False - Console Output - - - 0 - 0 - - - - - - - True - False - Console - - - - - False - True - 2 - - - - - 1 - - - - - True - False - Display - - - 1 - False - - - - - True - False - vertical - - - True - False - 0 - none - - - True - False - end - - - True - True - - - 1 - 0 - - - - - True - False - end - Multimedia Hotkeys - - - 0 - 0 - - - - - - - True - False - Keyboard - - - - - False - True - 0 - - - - - True - False - 0 - none - - - True - False - end - - - True - False - end - Middle Click - - - 0 - 0 - - - - - True - False - 0 - - Toggle Play/Pause - Mute - - - - 1 - 0 - - - - - True - False - end - Scrolling - - - 0 - 1 - - - - - True - False - 0 - - Change Station - Change Volume - - - - 1 - 1 - - - - - - - True - False - Mouse (Status Icon Mode) - - - - - False - True - 1 - - - - - 2 - - - - - True - False - Controls - - - 2 - False - - - - - True - True - 0 - - - - - True - False - end - - - Close - True - True - True - - - True - True - 0 - - - - - False - True - 1 - - - - diff -Nru goodvibes-0.3.6/data/ui/station-dialog.glade goodvibes-0.4.2/data/ui/station-dialog.glade --- goodvibes-0.3.6/data/ui/station-dialog.glade 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/ui/station-dialog.glade 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ - - - - - - True - False - - - True - False - Name - - - 0 - 0 - - - - - True - True - True - - - 1 - 0 - - - - - True - False - URI - - - 0 - 1 - - - - - True - True - True - - - 1 - 1 - - - - diff -Nru goodvibes-0.3.6/data/ui/status-icon-menu.glade goodvibes-0.4.2/data/ui/status-icon-menu.glade --- goodvibes-0.3.6/data/ui/status-icon-menu.glade 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/data/ui/status-icon-menu.glade 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ - - - -
- - Add Station - app.add-station - -
-
- - Preferences - app.preferences - -
-
- - Online Help - app.help - - - About - app.about - - - Quit - app.quit - -
-
-
diff -Nru goodvibes-0.3.6/debian/changelog goodvibes-0.4.2/debian/changelog --- goodvibes-0.3.6/debian/changelog 2018-04-18 23:26:31.000000000 +0000 +++ goodvibes-0.4.2/debian/changelog 2019-01-06 22:51:08.000000000 +0000 @@ -1,3 +1,18 @@ +goodvibes (0.4.2-1) unstable; urgency=medium + + * New upstream release (Closes: #917360) + * Bump Standards-Version to 4.3.0.1 + * Bump debhelper compat level to 12 + * Updated Upstream source code url + * Updated copyright years + * debian/rules + + Switch to meson build system + * debian/patches + + Removed 01_fix_desktop_exec.patch (Upstream has fixed) + + Removed 02_fix_spelling_error.patch (Upstream has fixed) + + -- Elías Alejandro Año Mendoza Sun, 06 Jan 2019 17:51:08 -0500 + goodvibes (0.3.6-1) unstable; urgency=medium * Initial release (Closes: #890420) diff -Nru goodvibes-0.3.6/debian/compat goodvibes-0.4.2/debian/compat --- goodvibes-0.3.6/debian/compat 2018-04-18 23:26:31.000000000 +0000 +++ goodvibes-0.4.2/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -11 diff -Nru goodvibes-0.3.6/debian/control goodvibes-0.4.2/debian/control --- goodvibes-0.3.6/debian/control 2018-04-18 23:26:31.000000000 +0000 +++ goodvibes-0.4.2/debian/control 2019-01-06 22:51:08.000000000 +0000 @@ -3,15 +3,16 @@ Priority: optional Maintainer: Elías Alejandro Año Mendoza Build-Depends: - debhelper (>= 11), + debhelper-compat (= 12), libglib2.0-dev (>= 2.44), libgstreamer-plugins-base1.0-dev (>= 1.4.4), libgstreamer1.0-dev (>= 1.4.4), libgtk-3-dev (>= 3.12), libkeybinder-3.0-dev (>= 0.3), libsoup2.4-dev (>= 2.42), -Standards-Version: 4.1.4 -Homepage: https://github.com/elboulangero/goodvibes + meson (>= 0.40.1) +Standards-Version: 4.3.0.1 +Homepage: https://gitlab.com/goodvibes/goodvibes Vcs-Git: https://salsa.debian.org/debian/goodvibes.git Vcs-Browser: https://salsa.debian.org/debian/goodvibes diff -Nru goodvibes-0.3.6/debian/copyright goodvibes-0.4.2/debian/copyright --- goodvibes-0.3.6/debian/copyright 2018-04-18 23:26:31.000000000 +0000 +++ goodvibes-0.4.2/debian/copyright 2019-01-06 22:51:08.000000000 +0000 @@ -1,9 +1,9 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: goodvibes -Source: https://github.com/elboulangero/goodvibes +Source: https://gitlab.com/goodvibes/goodvibes Files: * -Copyright: 2015-2017 Arnaud Rebillout +Copyright: 2015-2018 Arnaud Rebillout License: GPL-3+ Files: docs/goodvibes.readthedocs.io/_static/css/font-mfizz/* @@ -11,7 +11,7 @@ License: Expat Files: debian/* -Copyright: 2018 Elías Alejandro Año Mendoza +Copyright: 2018-2019 Elías Alejandro Año Mendoza License: GPL-3+ License: GPL-3+ diff -Nru goodvibes-0.3.6/debian/patches/01_fix_desktop_exec.patch goodvibes-0.4.2/debian/patches/01_fix_desktop_exec.patch --- goodvibes-0.3.6/debian/patches/01_fix_desktop_exec.patch 2018-04-18 23:26:31.000000000 +0000 +++ goodvibes-0.4.2/debian/patches/01_fix_desktop_exec.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -Description: Fix desktop entry with %u code - This patch add %u code to Exec entry in Desktop - file to allow support a single URL -Author: Elías Alejandro Año Mendoza -Last-Update: 2018-02-14 - ---- goodvibes.orig/data/com.elboulangero.Goodvibes.desktop.in.in -+++ goodvibes/data/com.elboulangero.Goodvibes.desktop.in.in -@@ -8,6 +8,6 @@ Categories=GTK;AudioVideo;Audio;Player; - Type=Application - # TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! - Icon=@PACKAGE_NAME@ --Exec=@PACKAGE_NAME@ -+Exec=@PACKAGE_NAME@ %u - DBusActivatable=true - MimeType=audio/*; diff -Nru goodvibes-0.3.6/debian/patches/02_fix_spelling_error.patch goodvibes-0.4.2/debian/patches/02_fix_spelling_error.patch --- goodvibes-0.3.6/debian/patches/02_fix_spelling_error.patch 2018-04-18 23:26:31.000000000 +0000 +++ goodvibes-0.4.2/debian/patches/02_fix_spelling_error.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -Description: Fix spelling error in binary - This patch fix a spelling error about a warning message -Author: Elías Alejandro Año Mendoza -Last-Update: 2018-02-14 - ---- goodvibes.orig/src/core/gv-playlist.c -+++ goodvibes/src/core/gv-playlist.c -@@ -404,7 +404,7 @@ on_message_completed(SoupSession *sessio - - /* Was it parsed successfully ? */ - if (priv->streams == NULL) { -- WARNING("Faild to parse playlist"); -+ WARNING("Failed to parse playlist"); - goto end; - } - diff -Nru goodvibes-0.3.6/debian/patches/series goodvibes-0.4.2/debian/patches/series --- goodvibes-0.3.6/debian/patches/series 2018-04-18 23:26:31.000000000 +0000 +++ goodvibes-0.4.2/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -01_fix_desktop_exec.patch -02_fix_spelling_error.patch diff -Nru goodvibes-0.3.6/debian/rules goodvibes-0.4.2/debian/rules --- goodvibes-0.3.6/debian/rules 2018-04-18 23:26:31.000000000 +0000 +++ goodvibes-0.4.2/debian/rules 2019-01-06 22:51:08.000000000 +0000 @@ -1,14 +1,14 @@ #!/usr/bin/make -f export DEB_BUILD_MAINT_OPTIONS = hardening=+all - export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed %: - dh $@ + dh $@ --buildsystem=meson override_dh_auto_configure: - dh_auto_configure -- --enable-all + dh_auto_configure -- --buildtype=debugoptimized \ + -Dc_args="$(CPPFLAGS)" -Dcpp_args="$(CFLAGS)" -Dc_link_args="$(LDFLAGS)" override_dh_installchangelogs: dh_installchangelogs NEWS diff -Nru goodvibes-0.3.6/debian/watch goodvibes-0.4.2/debian/watch --- goodvibes-0.3.6/debian/watch 2018-04-18 23:26:31.000000000 +0000 +++ goodvibes-0.4.2/debian/watch 2019-01-06 22:51:08.000000000 +0000 @@ -1,6 +1,4 @@ version=4 -# GitHub hosted projects -opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%goodvibes-$1.tar.gz%" \ - https://github.com/elboulangero/goodvibes/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate +opts=filenamemangle=s/.*\/goodvibes-v(\d\S+)\.tar\.gz/goodvibes-$1\.tar\.gz/ \ + https://gitlab.com/goodvibes/goodvibes/tags?sort=updated_desc .*/goodvibes-v(\d\S+)\.tar\.gz diff -Nru goodvibes-0.3.6/docs/goodvibes.readthedocs.io/credits.rst goodvibes-0.4.2/docs/goodvibes.readthedocs.io/credits.rst --- goodvibes-0.3.6/docs/goodvibes.readthedocs.io/credits.rst 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/docs/goodvibes.readthedocs.io/credits.rst 2018-11-10 06:04:58.000000000 +0000 @@ -6,7 +6,7 @@ Code ---- -The source code is generously hosted by `GitHub `_. +The source code is generously hosted by `GitLab `_. Goodvibes is open-source and simply couldn't exist without the various open-source libraries it relies on. Here's a non-exhaustive list of projects @@ -40,7 +40,11 @@ Here are the people who translate Goodvibes at the moment: * Michal Čihař - Czech (cs) + * Lukáš Linhart - Czech (cs) * Andreas Kleinert - German (de) + * Vinz - German (de) + * Wolf Berg - German (de) + * Benages - Spanish (es) * Étienne Deparis - French (fr) * Allan Nordhøy - Norwegian Bokmål (nb_NO) * Heimen Stoffels - Dutch (nl) diff -Nru goodvibes-0.3.6/docs/goodvibes.readthedocs.io/downloads.rst goodvibes-0.4.2/docs/goodvibes.readthedocs.io/downloads.rst --- goodvibes-0.3.6/docs/goodvibes.readthedocs.io/downloads.rst 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/docs/goodvibes.readthedocs.io/downloads.rst 2018-11-10 06:04:58.000000000 +0000 @@ -4,6 +4,13 @@ .. include:: icons.rst .. highlight:: none +The easiest way to install Goodvibes is to use the package manager of your +distribution. If your distrib doesn't provide a package, or if you want to +install a more recent version, you can try the following packages, or you can +build Goodvibes from source. + + + |debian-logo| Debian -------------------- @@ -14,7 +21,7 @@ deb http://pkg.elboulangero.com/debian ${codename:?} main EOF - sudo apt-key adv --recv-key FFD52770DD5A8135 + sudo apt-key adv --keyserver keys.gnupg.net --recv-key FFD52770DD5A8135 sudo apt-get update sudo apt-get install goodvibes @@ -55,26 +62,25 @@ goes on Debian, you might need to adapt that a bit for your distribution:: sudo apt install \ - autoconf autopoint build-essential git \ + build-essential git meson \ libglib2.0-dev libsoup2.4-dev \ libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \ libgtk-3-dev libkeybinder-3.0-dev Grab the source code from git:: - git clone https://github.com/elboulangero/goodvibes.git + git clone https://gitlab.com/goodvibes/goodvibes.git cd goodvibes Then build:: - ./autogen.sh - ./configure - make + meson build + ninja -C build -You can run without installing, for testing:: +Install:: - ./goodvibes-launcher.sh + sudo ninja -C build install -Install:: +You can run without installing, for testing:: - sudo make install + ./goodvibes-launcher.sh diff -Nru goodvibes-0.3.6/docs/goodvibes.readthedocs.io/index.rst goodvibes-0.4.2/docs/goodvibes.readthedocs.io/index.rst --- goodvibes-0.3.6/docs/goodvibes.readthedocs.io/index.rst 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/docs/goodvibes.readthedocs.io/index.rst 2018-11-10 06:04:58.000000000 +0000 @@ -53,7 +53,7 @@ `GStreamer `_, and the graphical user interface is written with `GTK+ `_. -**Development** takes place on `GitHub `_, +**Development** takes place on `GitLab `_, and this is where you should head if you want to get in touch. El Boulangero is the main author, and is the one writing these lines right now. diff -Nru goodvibes-0.3.6/docs/goodvibes.readthedocs.io/user-guide.rst goodvibes-0.4.2/docs/goodvibes.readthedocs.io/user-guide.rst --- goodvibes-0.3.6/docs/goodvibes.readthedocs.io/user-guide.rst 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/docs/goodvibes.readthedocs.io/user-guide.rst 2018-11-10 06:04:58.000000000 +0000 @@ -143,10 +143,10 @@ There are a few things to notice here: - * **Don't use the native interface** ``com.elboulangero.Goodvibes``, use the - MPRIS2 interface instead, ie. ``org.mpris.MediaPlayer2.Goodvibes``. The - reason being that when you query Goodvibes on its native interface, it will - be automatically launched by D-Bus in case it's not running. + * **Don't use the native interface** ``io.gitlab.Goodvibes``, use the MPRIS2 + interface instead, ie. ``org.mpris.MediaPlayer2.Goodvibes``. The reason being + that when you query Goodvibes on its native interface, it will automatically + be launched by D-Bus in case it's not running. * If for some reason you really need to use the native interface, then use a D-Bus command-line tool that allows you to disable auto-starting the service. As far as I know, you can only do that with ``busctl --user diff -Nru goodvibes-0.3.6/docs/notes/bookmarks.md goodvibes-0.4.2/docs/notes/bookmarks.md --- goodvibes-0.3.6/docs/notes/bookmarks.md 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/docs/notes/bookmarks.md 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,21 @@ +Bookmarks +========= + + +GLib +---- + +- [First steps with GSettings](https://blog.gtk.org/2017/05/01/first-steps-with-gsettings/) + + + +GTK+ +---- + +- [GTK+ Development Blog](https://blog.gtk.org/) +- [Those “realize” & “map” widget signals](https://blogs.gnome.org/jnelson/2010/10/13/those-realize-map-widget-signals/) +- [Another Container for Gtk+ 3.12 | GtkActionBar](http://worldofgnome.org/another-container-for-gtk-3-12-gtkactionbar/) +- Composite Widgets + - [Announcing Composite Widget Templates](https://blogs.gnome.org/tvb/2013/04/09/announcing-composite-widget-templates/) + - [Embeding GtkBuilder UI definitions into GObject classes!](https://blogs.gnome.org/xjuan/2012/07/13/embeding-gtkbuilder-ui-definitions-into-gobject-classes/) +- [GTK+: Aligning / Justification in text widgets](https://www.murrayc.com/permalink/2015/03/02/gtk-aligning-justification-in-text-widgets/) diff -Nru goodvibes-0.3.6/docs/notes/gobject-lessons-learned.md goodvibes-0.4.2/docs/notes/gobject-lessons-learned.md --- goodvibes-0.3.6/docs/notes/gobject-lessons-learned.md 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/docs/notes/gobject-lessons-learned.md 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,248 @@ +GObject lessons learnt +====================== + +Just sharing the long journey of learning GObject. + + + +How Do I Learn GObject? +----------------------- + +First, you need to bookmark the official documentation. It's the best place to +start, but also a good place to go back afterward. Things that don't make sense +at the first reading will become clear as you go further. + +- [GObject Reference Manual](https://developer.gnome.org/gobject/stable/) + +Second, there's one essential article that nicely sums up the GObject +construction process, and raise some important points around it. This is the +most important blog post you'll come accross, read it again and again. + +- [A gentle introduction to gobject construction](https://blogs.gnome.org/desrt/2012/02/26/a-gentle-introduction-to-gobject-construction/) + +At last, you need some good examples. You will find it first within the GObject +library itself, but you will need more. I recommend the main GObject based +libraries, and applications where development is very active. You will find +sometimes that the code is very up-to-date with the latest best practices, so +it's good to look in different codes. Warm up your git, sharpen your grep, and +there you go! + +- [GLib](https://git.gnome.org/glib) +- [GTK+](https://git.gnome.org/gtk+) +- [GStreamer](https://github.com/GStreamer) +- [Rhythmbox](https://git.gnome.org/rhythmbox) +- [Totem](https://git.gnome.org/totem) + + + +Good Practices +-------------- + +#### Follow The Conventions + +The first place to learn about good practices is the GObject conventions page. +It's more than good practice actually. GObject expects you to follow a few +conventions, so that code generation tools (`glib-mkenum`) and other stuff can +actually work. Don't try to avoid that. + +- [GObject Conventions](https://developer.gnome.org/gobject/stable/gtype-conventions.html) + +#### Use `G_DECLARE_*` And `G_DEFINE_*` + +Do not clutter the header file with too much boilerplate, as it's often seen in +some old GObject-based code. + +- [G_DECLARE_FINAL_DERIVABLE_TYPE](https://blogs.gnome.org/desrt/2015/01/27/g_declare_finalderivable_type/) + +#### Do The Minimum In `_init()` + +There should be almost nothing in the `init()` function. Most of the time, it +just boils down to setting up the private pointer, if any. + +For all the rest, it's better to implement it in the `constructed()` method. + +- [A gentle introduction to gobject construction](https://blogs.gnome.org/desrt/2012/02/26/a-gentle-introduction-to-gobject-construction/) + +#### Always Use A Private Pointer + +You will notice that in here, I never put anything in the object structure. I +ALWAYS use a private structure. + +Using a private structure is particularly useful for derivable objects, since +for these objects, the object structure *must be* defined in the header +(public) to allow inheritance. And of course, you want to keep your private +data private, so it makes sense to define it within the implementation, +therefore using a private structure. + +But when the object is not derivable, and therefore the object structure +*should be* defined in the implementation, what's the point of having a private +struct? +1. Consistency - you want all your objects to look the same. +2. Code Refactoring - when your objects change from final to derivable, or the + other way around, you'll be happy that you don't have to constantly move + your data from the object struct to the priv struct. + +- [Changing quickly between a final and derivable GObject class](https://blogs.gnome.org/swilmet/2015/10/10/changing-quickly-between-a-final-and-derivable-gobject-class/) + +Also, I *always* use a pointer named `priv` to access it. It's just a +convention, but a very common one, and doing it everywhere makes the whole code +consistent. HOWEVER, I've read somewhere that I shouldn't! But I didn't have +time to dig into that yet. + +#### Best Way To Set Properties + +The correct way to set an object pointer. It's not as trivial as it seems. + +- [Use g_set_object() to simplify (and safetyify) GObject property setters](https://tecnocode.co.uk/2014/12/19/use-g_set_object-to-simplify-and-safetyify-gobject-property-setters/) + + + +Quick FAQ +--------- + +#### How To Change A Construct-Only Property Via Inheritance + +This questions is asked on StackOverflow: + +- + +Unfortunately, the answer given by Emmanuele Bassi is wrong: setting the +property in the `constructed()` virtual method won't work. + +Now that I've been dealing with GObject for a while, I see 3 ways to do that: + +- hack around with the `constructor()` method, as suggested in + . +- don't use construct-only properties, use construct properties. Then you can + modify it in `constructed()`. +- set the desired values within a wrapper, ie. `my_inherated_object_new()`. If + you only create your objects with these wrappers, it's fine. However that is + not binding friendly. + +I personally settled for the third solution within Goodvibes. + +#### How To Implement A Singleton + +This is discussed here and there on the Net. + +- [GObject API Reference](https://developer.gnome.org/gobject/unstable/gobject-The-Base-Object-Type.html#GObjectClass) +- [How to make a GObject singleton](https://blogs.gnome.org/xclaesse/2010/02/11/how-to-make-a-gobject-singleton/) + +#### How To Have Protected Fields + +GObject doesn't provide any solution to have protected fields. I managed to do +without up to now, but just in case, here's a workaround. Basically, it's just +about defining the private structure in the header (therefore making it +public), and naming it 'protected' instead of 'private'. + +- [GObject and protected fields – simple hack](http://codica.pl/2008/12/21/gobject-and-protected-fields-simple-hack/) + +#### Any Design Patterns Out There? + +For design pattern examples, the best is to hunt for it directly in the source +code of some big projects. Additionally, here are some discussions about it. + +- +- [GObject design pattern: attached class extension](https://blogs.gnome.org/swilmet/2017/08/09/gobject-design-pattern-attached-class-extension/) + + + +Been there, done that +--------------------- + +#### Should I Set A Property Asynchronously? + +Sometimes, setting a property is just about setting a variable. But at other +times, it might trigger quite a bit of code execution. + +For example, at some point I had an `enable` property, and when I set it to +true, it really enables the whole object, and possibly a lot of things happens. + +For some technical reasons, I had to actually delay the execution of the +enable/disable code, with `g_idle_add()`. And since I wanted the value of the +`enable` property to really represent the state (enabled or disabled), I +decided to change the value of this property only *after* this asynchronous +code was executed. Ie, only when the `g_idle_add` callback runs. Only then the +`notify` signal was sent. + +This seems OK at a first glance. But in practice, there's a problem. The code +that sets the property may not want to receive the notify signal, and therefore +use `g_signal_handler_block()` before setting the property, and +`g_signal_handler_unblock()` after setting it. + +If I set the property asynchronously, and therefore send the notify signal +afterwards in a callback, the code that sets the property will receive the +notify signal, even if it tried to block it. So it creates a bit of an +unexpected behavior for the code setting the property. + +So... Should I set a property asynchronously? The answer is NO. + +For this particular problem of the `enable` property, I solved it by having two +properties: +- `enabled`, readwrite, which reflects how the object is *configured*. + Therefore this property is set synchronously. +- `state`, readable only, which gives the current state of the object, and go + from *disabled* to *enabling* to *enabled*. This property is tied to + `enabled`, but its value changes aynchronously. + +With two properties, one can connect to the `enabled` property to know how the +object is configured, and one can connect to the `state` property to know the +real object state. + +#### Should I Define A Base Class For My Object Hierarchy? + +For example, GStreamer has its own `GstObject`. And at some point, I thought it +was cool, and furthermore it seemed that it would solve some of the problems I +faced. So I defined my own `GvObject` for a while. I then removed it quickly +enough. Here's my feedback from that experience. + +First questions that arises: should all my objects inherit from GvObject? Or +only those who have a solid reason for that? + +At first, I went for the latter, because I thought that if an object has no +reason to inherit GvObject, then it should remain as lightweight and simple as +possible, and inherit GObject. + +So I ended up with a mix of objects that were either GObject derived, either +GvObject derived. It's a bit of a mess suddenly, because the separation between +both, and the reasons for choosing the right parent, was all very unclear. + +Then, serialization kicked in, I wanted to be able to serialize objects to save +it as configuration (I didn't use GSettings by the time). And suddenly I had +another dilemna. If the serialization API targets GvObject, then GObject +derived objects were left out, and couldn't be serialized. On the other hand, +if the API targeted GObject, I couldn't take advantage of some of the specific +features GvObject, that were actually very helpful for serializing. + +Which made me change my mind: if I define a GvObject base-class, then I should +embrace it completely, and have every object inherit it. It looked nice and +consistent now, but I just added an additional layer, I just made things a bit +more complicated, and I was wondering if it was worth it. + +But still, I was happy because now the serialization was easier to implement, +since I embedded some convenient stuff for it within my base class GvObject. + +But then, another problem kicked in. The UI part is implemented by inheriting +GTK widgets. How will I serialize this GObject-derived objects, now that the +serialization API targets the GvObject type? My only solution here was to +rewrite the UI, use composition instead of inheritance, so that my UI objects +could be derived from GvObject and be serializable. + +Which promised to be quite some work of moving code around... + +I didn't do that though. Instead, I came back to GObject for the base class. +For all the problems that I solved with GvObject, I thought again and solved +them differently, and in a better way. + +After all that, I draw some conclusions for myself: + +- Think twice before defining a base class for your object hierarchy. It has + its good points, for sure, but also its drawbacks. +- If you work with GObject-based libraries, be aware that the base class you + define can't help for objects from those libraries, or that you inherit from + those libraries. Your lower denominator for the whole set of classes you deal + with will always be GObject. So, does you base type really helps, or does it + get in the way? +- Ask yourself if you can't solve your problem with an interface instead. + Interface are more flexible. Even if you use objects from other libraries, + you can still inherit them, and implement an interface in the child. diff -Nru goodvibes-0.3.6/docs/notes/implementation-details-core.md goodvibes-0.4.2/docs/notes/implementation-details-core.md --- goodvibes-0.3.6/docs/notes/implementation-details-core.md 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/docs/notes/implementation-details-core.md 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,238 @@ +Implementation Decisions - Core +=============================== + +Some decisions I made early on regarding the implementation. I write it down +here just for my own remembering. + + + +Why Implementing The MPRIS2 D-Bus API First? +-------------------------------------------- + +Implementing the MPRIS2 D-Bus API was one of the first thing I did. It was not +the easiest thing to start with though, but it forced me to implement all the +common features expected from a music player. Once MPRIS2 was implemented, I +knew I had the right design for the core, and indeed, I never had to rework it +afterward. + +So I really recommend that to anyone writing a music player: implement the +MPRIS2 D-Bus API early, it will help you to get the design right, you won't +regret the pain. + + + +Why Not Choosing Python? +------------------------ + +I definitely wanted to implement the MPRIS2 D-Bus API. Which means implementing +a D-Bus server. + +Implementing a fully featured D-Bus server in Python is a bit of a frustrating +experience. Properties are not fully handled. See: + +- + +The quick answer, as I understood it, is that the D-Bus python binding is +broken by design, and there will be no attempt to fix it. This bug will stay +opened forever. + +If you have a look at QuodLibet code, you will see that these guys had to write +quite a bit of code to add support for properties. But they did it well, and +the code is easy to take out of QuodLibet. So my guess is that the best way to +fully implement the MPRIS2 D-Bus API is to copy/paste some code from QL. + +It's suggested here and there to use another Python D-Bus implementation, like +GLib's implementation GDBus, through PyGObject. This is perfect if you're a +D-Bus client, however if you want to implement a D-Bus daemon? Apparently, at +the time of this writing, this is yet to be implemented. See progress here: + +- + +So, with this situation, I decided to write in C instead, as I was sure that I +would be able to implement the MPRIS2 D-Bus API properly, without having to +hack my way around broken things. + +Note that it's probably not an exhaustive view of the situation, and I might +have overlooked other solutions. + +Another reason is that Goodvibes is a minimalistic app doing very little, and +it's pleasant to see it start in a fingersnap. With Python you don't quite get +that, especially if you're the first Python app being launched and there's +nothing cached yet. + +On the other hand, there was a BIG reason to choose Python rather than C: +development time. Writing in Python is so much faster, you have no idea until +you have the chance to maintain both a C and a Python desktop app. + + + +Why Choosing GObject? +--------------------- + +GObject has its cons, that I was very aware of when I started to learn it. As +often when I face a new technology, I was a bit reluctant and only saw the +downside: + +- Boilerplate: there so much copy/paste to do that I ended up writing a script + to automate C/H file creation. +- Magic: some of the boilerplate is hidden by macros. It's great since it saves + code typing, but it's bad since it makes some definitions implicit. So you + end up calling functions or macros that are defined nowhere, and it's a bit + unsettling at first. GObject code looks like dark magic for the newcomer. +- Steep learning curve: yep, learning GObject by yourself can be a bit tedious. + +On the other hand, GObject brings in everything I needed to implement cleanly +this MPRIS2 D-Bus API: + +- signals: from the moment I have signals internally, there's no need to hack + around to send signals on D-Bus. It's trivial. +- properties: same thing. From the moment the code is GObject-oriented, getting + and setting properties through D-Bus is trivial. + +Plus, GObject allows you to write quite clean object-oriented code in C. The +memory management through reference counting is nice and clean. + +And the more you go on working with GObject libraries (GIO, GTK+, GStreamer), +the more you realise that your code benefits from being GObject oriented. You +can use high-level functions, bind your objects here and there, and a lot of +problems are solved by the libraries you use. But these libraries expect +GObjects, so if your code is not written as such, you might be left out and +bitter, rewriting stuff that is already implemented in libraries. + +So that's maybe the most important: if your application lives in a GObject +ecosystem, make it GObject, and it will fit in nicely, good surprises will +abound all along. + +But be aware that GObject is much more than a library. It really changes the +architecture of your application, which basically becomes event-driven. Which +is exactly what you want when you're writting a GUI application. + + + +Why Not Using Gdbus-Codegen? +---------------------------- + +First, I'm not a big fan of code generation. + +Second, as far as I remember, the generated code produces some warnings at +compile time, and I usually compile with the flag `-WError`. It's annoying. + +Third, there's a bug about `Property.EmitsChangedSignal`, that has been pending +forever, and in all likelihood will never be fixed. + +- + +This bug affects the MPRIS2 D-Bus API, so I prefer to stay away from that +`gdbus-codegen` and remain in control of the code. + + + +Why Using Explicit Notify Only? +------------------------------- + +This is just an convention in use in the code, I just find it more logical when +I started, and I never had to come back on this choice. + +For this reason, every property is created with the `G_PARAM_EXPLICIT_NOTIFY` +flag, and emitted only if the value of the property changed. It's a bit more +job on the object where the properties are changed, but it's less job on the +object listening for signals, since they can be sure that they have to do +something when the signal handler is invoked. + + + +Why Having This Feature Thing? +------------------------------ + +You will see in the code that some features are quite isolated from the rest of +the code. First, there's a `GvFeature` object, that is the parent of all +features. Then, features just need to inherit this object, connect to some +signals from the core, and that's it. + +Isolating features is simply a way to keeps things cleanly separated, and to +allow to disable some code at compile time, without having to cripple the code +with `#ifdef`. It's possible thanks to the fact that features just react to +signals. The core of the code itself is blissfully ignorant of the existence of +these features, and never explictly invokes any function from there. + +Features are created once at init, destroyed once at cleanup, and that's the +only place where you will see `#ifdef`. They live in a world of their own. + +Such a strong isolation has some benefits: easier debug and maintenance, +mainly. And it's nice to be able to disable it at compile-time, if ever people +want to integrate the application in an environment where some of these +features don't make sense (like on embedded devices). + +It also forces a better overall design. However, it can be a pain in the ass +when a new feature shows up, and doesn't quite fit in, and the whole thing +needs to be reworked, and all the existing features need to be updated to match +the changes... + +Ultimately, with some improvements, these features could be loaded dynamically, +and from this point they could be called plugins. And then, it's very common to +have plugins in GNU/Linux media player, right? So, these features can be seen +as a poor's man plugin system. + + + +Station List: Shuffle Implementation +------------------------------------ + +Things I've tried and didn't work. + +One idea was that the player would have two StationList objects. One would be +ordered, the other would be shuffled. With that, the 'shuffle problem' is taken +out of the StationList object (which is therefore esier to implement) and is +then solved outside of it. Mainly in the player, I thought. + +In practice, it adds quite a lot of complexity, because these two lists must be +kept in sync (from a more genereal point of view, from the moment you duplicate +data, you need to keep it in sync, and that's why duplicating data is always +something to avoid). Furthermore, the station list is a global variable, that +can be accessed by anyone. How to handle duplication then? + +We could have both list (ordered and shuffled) global. But it would be a mess +for the rest of the code. Always wondering which one you must deal with, and +what if you want to add a new station? So the code is responsible for adding +it to both list? And therefore, the code is responsible for keeping lists in +sync? + +Of course not, the sync between both lists must be automatic, but if both are +global, it means that they both must watch each other's signals to keep in +sync. Or another object must watch both of them and keep them in sync. This +doesn't sound sweet to my ears. + +Another possibility is to have only the ordered station list public, and the +shuffled one private to the player, and then the player would be left with the +responsability to keep the shuffled list in sync, somehow. Hmmm, I don't like +that too much either. + +OK, so let's forget about that. If the shuffle problem is not to be solved +outside of the list, then let's solve it within the list. We could have a +'shuffle' property added to the station list, and that's all. The code set it +to true or false, and doesn't bother anymore. + +It kind of works, but the StationList API becomes confusing. Because if you +look at it as it is, you will notice that some functions are expected to +support the shuffle property (obviously, `next` and `prev` will return a +different value depending on the shuffle property), while other actually don't +care about the shuffle property (`append`, `prepend` only deal with the ordered +list). + +So, completely hiding the 'shuffle' from the outside world is also not a very +good solutions. At some point, when you use the API, you start to find it +confusing. Even if you set the shuffle property, some functions keep on dealing +with an ordered list internally. It's magic, and we don't like magic. + +Actually, from the user point of view, if you enable shuffle, the list still +appears ordered in the ui. It just affects the previous and next actions. And +the best is to see this behavior appearing in the API. + +So in the end, the best implementation of the shuffle I came with is a 50/50: +both the Player object and the StationList object know about it, and both do +their job handling it. It appears explicitely in the StationList API, and only +makes sense for `next` and `prev`. The Player is the 'owner' of the shuffle +setting, and feeds it to StationList when calling methods that require it. + +In the end, this implementation is the most simple, and leaves little place for +magic. I've been happy with it so far. diff -Nru goodvibes-0.3.6/docs/notes/implementation-details-ui.md goodvibes-0.4.2/docs/notes/implementation-details-ui.md --- goodvibes-0.3.6/docs/notes/implementation-details-ui.md 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/docs/notes/implementation-details-ui.md 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,96 @@ +Implementation Decisions - UI +============================= + +Some decisions I made early on regarding the implementation. I write it down +here just for my own remembering. + + + +How much margin and spacing for the UI? +--------------------------------------- + +When designing the UI in Glade, there's no margins by default, so the whole +thing looks ugly at this point. Margins, spacings, paddings and such must be +set, and it's up to me to decide how much. So I wonder: how much? + +I have no idea, and don't especially care, so I let someone else decide for me. +I just followed the guidelines provided by GNOME. + +- [GNOME HUman Interface Guidelines](https://developer.gnome.org/hig/stable/) + + + +Why not using GtkDialog to handle preferences? +---------------------------------------------- + +Mainly, it's because a dialog requires a transient parent, aka another window +that must be the parent. Ever had this warning in your console? + + Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged. + +But Goodvibes might be running in `--status-icon` mode, and in such case it +doesn't really have a main window to speak of. + +Loosely speaking, we could use the popup window as the transient parent, since +it always exists. It's hidden most of the time, but it exists. But it looks a +bit hacky to me. I don't really know why GTK+ needs a transient parent, and +what it expects from this parent, but I'm almost sure the popup window is not +up to the expectation. + +So in the end, I find it cleaner to use a window rather than a dialog. + + + +Should I use the GObject property details in the UI? +---------------------------------------------------- + +Short answer: No! + +It might be tempting though, simply to avoid duplicating strings. + +Indeed, in the preferences dialog, often a setting is mapped to an object's +property. Given that a property already has a nick (that could be mapped to the +setting label) and a blurb (ie. a description that could be mapped to the +setting tooltip), why should we define these strings again in the glade file? +Why don't we just set labels and tooltips from the property nick and blurb in +the C code? + +It's tempting. Even more after reading this piece of the doc: + +- + +However, I have good reasons not to do so, both for the nicks and blurbs +(although in the following, I'll only talk about nicks, for clarity). + +First, there's the context. Let's suppose you have a property that decides what +action should be associated with a middle-click. In your code, an ideal nick +for the property would be "Mouse Middle Click". However, assuming that in the +UI you have a "Mouse" section for the settings related to the mouse, then you +don't want to repeat the word "Mouse". The ideal name for the setting would +then be "Middle Click". + +So, because of a different context, the best name for a property in the code, +and the best name for the corresponding setting in the UI, might be different. + +Second, there's more problems when translation kicks in. Because then, the +property nicks must be translatable, and if I want to be consistent, then +**ALL** the properties should have a translatable nick. It means that those +properties which don't appear in the UI will be translated for nothing. Useless +work for translators, isnt't it? Or should I only translates the nicks that +appear in the UI? But then how do I maintain this mess? What will happen, in +the end, is that I'll have nicks marked as translatable, but don't appear in +the UI, while others appear in the UI but are not marked as translatable... + +The REAL problem, here, is that there will be no warnings for these missing +translations. So there will always be missing translations in each new release. + +So, here are my two main issues: context, and translations. + +In the end, my choice is to use nicks and blurbs only as hints for developpers +passing by. For the UI, I'll define everything in Glade, or in the related C +file. It solves the context issue, and also the translation issue, since Glade +automatically mark strings as translatable, so I don't have to bother. + +More interesting reading: + +- diff -Nru goodvibes-0.3.6/docs/notes/under-the-hood.md goodvibes-0.4.2/docs/notes/under-the-hood.md --- goodvibes-0.3.6/docs/notes/under-the-hood.md 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/docs/notes/under-the-hood.md 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,49 @@ +Under the hood +============== + + + +Features +-------- + +#### Notifications + +Notification support is provided by GApplication. Under the hood, two backends +exist out there: `org.freedesktop.Notifications` and `org.gtk.Notifications`. +Glib gives preference to the Gtk backend in case both are available. + +As of 2018-11, it seems that notifications in Flatpak don't work, using the +Freedesktop runtime 18.08. + +#### Multimedia Keybinding + +Currently implemented with libkeybinder, which works at the X11 level to take +global keybindings. Obviously this won't do with Wayland. + +Another possibility is to use D-Bus: `org.gnome.SettingsDaemon.MediaKeys`, +but this is GNOME-specific as you can see (I think there's also a Mate-specific +`org.mate.SettingsDaemon` D-Bus service). + +There's a discussion at + +But the truth is: keybinding is actually not needed if the desktop already has +some kind of MPRIS2 support, and also grabs the multimedia keys by default. +Which is the case for GNOME and most modern desktops I suspect. In this case, +when a multimedia key is pressed, it's intercepted by GNOME, which forwards +that to the current MPRIS2 player active. + +So the multimedia keybinding feature in Goodvibes is mostly useful for stripped +down desktop environments with no MPRIS2 support. And in this case it's useless +to try the GNOME daemon, so we're just fine implementing X11 keybinding only. + +#### Sleep inhibition + +Gtk+ provides everything through GtkApplication, however when I came accross +it, I had already implemented my stuff through an internal lib "libcaphe". So, +well... Looking into details, I saw that Gtk+ implementation doesn't try to +inhibit with `org.freedesktop.PowerManagement` (I think it's been deprecated +for a while). However at the time I was using a fairly old Openbox system, +which had only this service running to provide sleep inhibition. + +So I kept my own implementation in libcaphe, and I don't use Gtk+ sleep +inhibition. diff -Nru goodvibes-0.3.6/docs/wiki.old/Autotools-Bookmarks.md goodvibes-0.4.2/docs/wiki.old/Autotools-Bookmarks.md --- goodvibes-0.3.6/docs/wiki.old/Autotools-Bookmarks.md 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/docs/wiki.old/Autotools-Bookmarks.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -My Autotools Bookmarks - -- [Autotools Mythbuster](https://autotools.io/index.html) -- Russ Allbery's [Build System Coding Style](https://www.eyrie.org/~eagle/notes/style/build.html) -- Gentoos's [Basics of Autotools](https://devmanual.gentoo.org/general-concepts/autotools/) diff -Nru goodvibes-0.3.6/docs/wiki.old/Background.md goodvibes-0.4.2/docs/wiki.old/Background.md --- goodvibes-0.3.6/docs/wiki.old/Background.md 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/docs/wiki.old/Background.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -Goodvibes was originally inspired by [RadioTray][] from Carlos Ribeiro. The original intention was to have an application that sits in the *notification area* (also called *systray*), without any main window to speak of, just a popup window. However, this notification area has been under big changes over the last years, and is quite a restricted place now. Not suitable for Goodvibes purposes anymore. But let's tell a bit of the story. - -For a long time, application relied on [GtkStatusIcon][] to display an icon in the notification area. With time came the need for a successor. Ubuntu finally came up with [Application Indicators][], based on existing work by KDE. You can read more about it at the [Application Panel Indicators][] page. However, GNOME had their own view on the question, and didn't adopt appindicators. In the end, GNOME finally [deprecated][] GtkStatusIcon in GTK+ 3.14, before completely [removing it][] in GTK+ 4.0. - -If you're interested in this piece of history, there's quite a long discussion on the matter at [The Libappindicator Story][]. - -Well, so what's the situation now ? - -- GNOME (and possibly others) doesn't allow applications to access the notification area. -- Ubuntu (along with most of the other desktops) provides access to the notification area through appindicators. Applications can display an icon, and popup a menu when the icon is clicked. No distinction is made between left or right click. -- Old-school desktops still rely on GtkStatusIcon, which allows displaying anything when clicked (not limited to a menu), and supports any mouse action (left/right/middle click, mouse scrolling). - -The conclusion to be drawn from that is that the notification area is now *optional*. An application shouldn't rely on it to function. It should use it only for convenience when it's available, but should do just as well without it. - -Back to Goodvibes: sitting in the system tray is a thing of the past, let's acknowledge the fact. That's why Goodvibes is now a very standard application, with a main window, eating some space in your panel even if you don't like it. - - - -[radiotray]: http://radiotray.sourceforge.net/ -[gtkstatusicon]: https://developer.gnome.org/gtk3/stable/GtkStatusIcon.html -[application indicators]: https://unity.ubuntu.com/projects/appindicators/ -[application panel indicators]: https://wiki.ubuntu.com/DesktopExperienceTeam/ApplicationIndicators -[deprecated]: https://git.gnome.org/browse/gtk+/commit/?id=cab7dcde1bef1ea589a9f3c4d8512e59ade8a4a2 -[removing it]: https://git.gnome.org/browse/gtk+/commit/?id=d2a8667f835ddce4ac88b9bee143556f9efa93c4 -[the libappindicator story]: https://bethesignal.org/blog/2011/03/12/the-libappindicator-story/ diff -Nru goodvibes-0.3.6/docs/wiki.old/Core-Design-Choices.md goodvibes-0.4.2/docs/wiki.old/Core-Design-Choices.md --- goodvibes-0.3.6/docs/wiki.old/Core-Design-Choices.md 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/docs/wiki.old/Core-Design-Choices.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -Design choices I made along the way, and why. Just for my own remembering. - -1. [Why Implementing The MPRIS2 D-Bus API First ?](#why-implementing-the-mpris2-d-bus-api-first-) -2. [Why Not Choosing Python ?](#why-not-choosing-python-) -3. [Why Choosing GObject ?](#why-choosing-gobject-) -4. [Why Not Using Gdbus-Codegen ?](#why-not-using-gdbus-codegen-) -5. [Why Using Explicit Notify Only ?](#why-using-explicit-notify-only-) -6. [Why Having This Feature Thing ?](#why-having-this-feature-thing-) -7. [Station List: Shuffle Implementation](#station-list-shuffle-implementation) - - - -Why Implementing The MPRIS2 D-Bus API First ? ---------------------------------------------- - -Implementing the MPRIS2 D-Bus API was one of the first thing I did. It was not the easiest thing to start with though, but it forced me to implement all the common features expected from a music player. Once MPRIS2 was implemented, I knew I had the right design for the core, and indeed, I never had to rework it afterward. - -So I really recommend that to anyone writing a music player: implement the MPRIS2 D-Bus API early, it will help you to get the design right, you won't regret the pain. - - - -Why Not Choosing Python ? -------------------------- - -I definitely wanted to implement the MPRIS2 D-Bus API. Which means implementing a D-Bus server. - -Implementing a fully featured D-Bus server in Python is a bit of a frustrating experience. Properties are not fully handled. See: - -- - -The quick answer, as I understood it, is that the D-Bus python binding is broken by design, and there will be no attempt to fix it. This bug will stay forever. - -If you have a look at QuodLibet code, you will see that these guys had to write quite a bit of code to add support for properties. But they did it well, and the code is easy to take out of QuodLibet. So my guess is that the best way to fully implement the MPRIS2 D-Bus API is to copy/paste some code from QL. - -It's suggested here and there to use another Python D-Bus implementation, like GLib's implementation GDBus, through PyGObject. However at the moment of this writing, this is yet to be implemented. See progress here: - -- - -So, with this situation, I decided to write in C instead, where I was sure that implementing the MPRIS2 D-Bus API would be a satisfactory experience. - -Note that it's probably not an exhaustive view of the situation, and I might have overlooked other solutions. - - - -Why Choosing GObject ? ----------------------- - -GObject has its cons, that I was very aware of when I started to learn it. As often when I face a new technology, I was a bit reluctant and only saw the downside: - -- Boilerplate: there so much copy/paste to do that I ended up writing a script to automate C/H file creation. -- Magic: some of the boilerplate is hidden by macros. It's great since it saves code typing, but it's bad since it makes some definitions implicit. So you end up calling functions or macros that are defined nowhere, and it's a bit unsettling at first. GObject code looks like dark magic for the newcomer. -- Steep learning curve: yep, learning GObject by yourself can be a bit tedious. - -On the other hand, GObject brings in everything I needed to implement cleanly this MPRIS2 D-Bus API: - -- signals: from the moment I have signals internally, there's no need to hack around to send signals on D-Bus. It's trivial. -- properties: same thing. From the moment the code is GObject-oriented, getting and setting properties through D-Bus is trivial. - -Plus, GObject allows you to write quite clean object-oriented code in C. The memory management through reference counting is nice and clean. - -And the more you go on working with GObject libraries (GIO, GTK+, GStreamer), the more you realise that your code benefits from being GObject oriented. You can use high-level functions, bind your objects here and there, and a lot of problems are solved by the libraries you use. But these libraries expect GObjects, so if your code is not written as such, you might be left out and bitter, rewriting stuff that is already implemented in libraries. - -So that's maybe the most important: if your application lives in a GObject ecosystem, make it GObject, and it will fit in nicely, good surprises will abound all along. - -But be aware that GObject is much more than a library. It really changes the architecture of your application, which basically becomes event-driven. - - -Why Not Using Gdbus-Codegen ? ------------------------------ - -First, I'm not a big fan of code generation. - -Second, as far as I remember, the generated code produces some warnings at compile time, and I usually compile with the flag `-WError`. It's annoying. - -Third, there's a bug about `Property.EmitsChangedSignal`, that has been pending forever, and in all likelihood will never be fixed. - -- - -This bug affects the MPRIS2 D-Bus API, so I prefer to stay away from that `gdbus-codegen` and remain in control of the code. - - - -Why Using Explicit Notify Only ? --------------------------------- - -This is just an convention in use in the code, I just find it more logical when I started, and I never had to come back on this choice. - -For this reason, every property is created with the `G_PARAM_EXPLICIT_NOTIFY` flag, and emitted only if the value of the property changed. It's a bit more job on the object where the properties are changed, but it's less job on the object listening for signals, since they can be sure that they have to do something when the signal handler is invoked. - - - -Why Having This Feature Thing ? -------------------------------- - -You will see in the code that some features are quite isolated from the rest of the code. First, there's a `GvFeature` object, that is the parent of all features. Then, features just need to inherit this object, connect to some signals from the core, and that's it. - -Isolating features is simply a way to keeps things cleanly separated, and to allow to disable some code at compile time, without having to cripple the code with `#ifdef`. It's possible thanks to the fact that features just react to signals. The core of the code itself is blissfully ignorant of the existence of these features, and never explictly invokes it. - -Features are created once at init, destroyed once at cleanup, and that's the only place where you will see `#ifdef`. They live in a world of their own. - -Such a strong isolation has some benefits: easier debug and maintenance, mainly. And it's nice to be able to disable it at compile-time, if ever people want to integrate the application in an environment where some of these features don't make sense (like on embedded devices). - -It also forces a better overall design. However, it can be a pain in the ass when a new feature shows up, and doesn't quite fit in, and the whole thing needs to be reworked, and all the existing features need to be updated to match the changes... - -Ultimately, with some improvments, these features could be loaded dynamically, and from this point they could be called plugins. And then, it's very common to have plugins in GNU/Linux media player, right ? So, these features can be seen as a poor's man plugin system. - - - -Station List: Shuffle Implementation ------------------------------------- - -Things I've tried and didn't work. - -One idea was that the player would have two StationList objects. One would be ordered, the other would be shuffled. With that, the 'shuffle problem' is taken out of the StationList object (which is therefore esier to implement) and is then solved outside of it. Mainly in the player, I thought. - -In practice, it adds quite a lot of complexity, because these two lists must be kept in sync (from a more genereal point of view, from the moment you duplicate data, you need to keep it in sync, and that's why duplicating data is always something to avoid). Furthermore, the station list is a global variable, that can be accessed by anyone. How to handle duplication then ? - -We could have both list (ordered and shuffled) global. But it would be a mess for the rest of the code. Always wondering which one you must deal with, and what if you want to add a new station ? So the code is responsible for adding it to both list ? And therefore, the code is responsible for keeping lists in sync ? - -Of course not, the sync between both lists must be automatic, but if both are global, it means that they both must watch each other's signals to keep in sync. Or another object must watch both of them and keep them in sync. This doesn't sound sweet to my ears. - -Another possibility is to have only the ordered station list public, and the shuffled one private to the player, and then the player would be left with the responsability to keep the shuffled list in sync, somehow. Hmmm, I don't like that too much either. - -OK, so let's forget about that. If the shuffle problem is not to be solved outside of the list, then let's solve it within the list. We could have a 'shuffle' property added to the station list, and that's all. The code set it to true or false, and doesn't bother anymore. - -It kind of works, but the StationList API becomes confusing. Because if you look at it as it is, you will notice that some functions are expected to support the shuffle property (obviously, `next` and `prev` will return a different value depending on the shuffle property), while other actually don't care about the shuffle property (`append`, `prepend` only deal with the ordered list). - -So, completely hiding the 'shuffle' from the outside world is also not a very good solutions. At some point, when you use the API, you start to find it confusing. Even if you set the shuffle property, some functions keep on dealing with an ordered list internally. It's magic, and we don't like magic. - -Actually, from the user point of view, if you enable shuffle, the list still appears ordered in the ui. It just affects the previous and next actions. And the best is to see this behavior appearing in the API. - -So in the end, the best implementation of the shuffle I came with is a 50/50: both the Player object and the StationList object know about it, and both do their job handling it. It appears explicitely in the StationList API, and only makes sense for `next` and `prev`. The Player is the 'owner' of the shuffle setting, and feeds it to StationList when calling methods that require it. - -In the end, this implementation is the most simple, and leaves little place for magic. I've been happy with it for a while now. diff -Nru goodvibes-0.3.6/docs/wiki.old/GObject-Introduction.md goodvibes-0.4.2/docs/wiki.old/GObject-Introduction.md --- goodvibes-0.3.6/docs/wiki.old/GObject-Introduction.md 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/docs/wiki.old/GObject-Introduction.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,162 +0,0 @@ -For developers passing by and who need to learn about GObject, here's my feedback. - -1. [How Do I Learn GObject ?](#how-do-i-learn-gobject-) -2. [Good Practices](#good-practices) -3. [Quick FAQ](#quick-faq) -4. [Been There, Done That](#been-there-done-that) - - - -How Do I Learn GObject ? ------------------------- - -First, you need to bookmark the official documentation. It's the best place to start, but also a good place to go back afterward. Things that don't make sense at the first reading will become clear as you go further. - -- [GObject Reference Manual](https://developer.gnome.org/gobject/stable/) - -Second, there's one essential article that nicely sums up the GObject construction process, and raise some important points around it. This article you will have to read again and again. - -- [A gentle introduction to gobject construction](https://blogs.gnome.org/desrt/2012/02/26/a-gentle-introduction-to-gobject-construction/) - -At last, you need some good examples. You will find it first within the GObject library itself, but you will need more. I recommend the main GObject based libraries, and applications where development is very active. You will find sometimes that the code is very up-to-date with the latest best practices, so it's good to look in different codes. Warm up your git, sharpen your grep, and there you go ! - -- [GLib](https://git.gnome.org/glib) -- [GTK+](https://git.gnome.org/gtk+) -- [GStreamer](https://github.com/GStreamer) -- [Rhythmbox](https://git.gnome.org/rhythmbox) -- [Totem](https://git.gnome.org/totem) - - - -Good Practices --------------- - -#### Follow The Conventions - -The first place to learn about good practices is the GObject conventions page. It's more than good practice actually. GObject expects you to follow a few conventions, so that code generation tools (`glib-mkenum`) and other stuff can actually work. Don't try to avoid that. - -- [GObject Conventions](https://developer.gnome.org/gobject/stable/gtype-conventions.html) - -#### Use `G_DECLARE_*` And `G_DEFINE_*` - -Do not clutter the header file with too much boilerplate, as it's often seen in some old GObject-based code. - -- [G_DECLARE_FINAL_DERIVABLE_TYPE](https://blogs.gnome.org/desrt/2015/01/27/g_declare_finalderivable_type/) - -#### Do The Minimum In `_init()` - -There should be almost nothing in the `init()` function. Most of the time, it just boils down to setting up the private pointer, if any. - -For all the rest, it's better to implement it in the `constructed()` method. - -- [A gentle introduction to gobject construction](https://blogs.gnome.org/desrt/2012/02/26/a-gentle-introduction-to-gobject-construction/) - -#### Always Use A Private Pointer - -You will notice that in here, I never put anything in the object structure. I ALWAYS use a private structure. - -Using a private structure is particularly useful for derivable objects, since for these objects, the object structure *must be* defined in the header (public) to allow inheritance. And of course, you want to keep your private data private, so it makes sense to define in within the implementation, therefore using a private structure. - -But when the object is not derivable, and therefore the object structure *should be* defined in the implementation, what's the point of having a private struct ? Answer: consistency, and less hassle when the objects change from final to derivable, or the other way around. - -- [Changing quickly between a final and derivable GObject class](https://blogs.gnome.org/swilmet/2015/10/10/changing-quickly-between-a-final-and-derivable-gobject-class/) - -Also, I *always* use a pointer named `priv` to access it. It's just a convention, but a very common one, and doing it everywhere makes the whole code consistent. - -#### Best Way To Set Properties - -The correct way to set an object pointer. It's not as trivial as it seems. - -- [Use g_set_object() to simplify (and safetyify) GObject property setters](https://tecnocode.co.uk/2014/12/19/use-g_set_object-to-simplify-and-safetyify-gobject-property-setters/) - - - -Quick FAQ ---------- - -#### How To Change A Construct-Only Property Via Inheritance - -This questions is asked on StackOverflow: - -- - -Unfortunately, the answer given by Emmanuele Bassi is wrong: setting the property in the `constructed()` virtual method won't work. - -Now that I've been dealing with GObject for a while, I see 3 ways to do that: - -- hack around with the `constructor()` method, as suggested in . -- don't use construct-only properties, use construct properties. Then you can modify it in `constructed()`. -- set the desired values within a wrapper, typically `my_inherated_object_new()`. If you only create your objects with these wrappers, it's fine. Notice that this is not binding friendly. - -I personally settled for the third solution within Goodvibes. - -#### How To Implement A Singleton - -This is discussed here and there on the Net. - -- [GObject API Reference](https://developer.gnome.org/gobject/unstable/gobject-The-Base-Object-Type.html#GObjectClass) -- [How to make a GObject singleton](https://blogs.gnome.org/xclaesse/2010/02/11/how-to-make-a-gobject-singleton/) - -#### How To Have Protected Fields - -GObject doesn't provide any solution to have protected fields. I managed to do without up to now, but just in case, here's a workaround. Basically, it's just about defining the private structure in the header (therefore making it public), and naming it 'protected' instead of 'private'. - -- [GObject and protected fields – simple hack](http://codica.pl/2008/12/21/gobject-and-protected-fields-simple-hack/) - -#### Any Design Patterns Out There ? - -For design pattern examples, the best is to hunt for it directly in the source code of some big projects. Additionally, here are some discussions about it. - -- -- [GObject design pattern: attached class extension](https://blogs.gnome.org/swilmet/2017/08/09/gobject-design-pattern-attached-class-extension/) - - - -Been there, done that ---------------------- - -#### Should I Set A Property Asynchronously ? - -Sometimes, setting a property is just about setting a variable. But at other times, it might trigger quite a bit of code execution. - -For example, I have an 'enable' property, and when I set it to true, it really enables the whole object, and possibly a lot of things happens. - -For some technical reasons, I had to actually delay the execution of the enable/disable code, with `g_idle_add()`. And, as you can expect, I changed the value of my property only *after* this asynchronous code was executed. Only at that moment the 'notify' signal was sent. - -This seems OK at a first glance. But in practice, there's a problem. The code that sets the property may not want to receive the notify signal, and therefore use `g_signal_handler_block()` before setting the property, and `g_signal_handler_unblock()` after setting it. - -If I set the property asynchronously, and therefore send the notify signal afterward, the code that set the property will receive the notify signal, even if it tried to block it. So it creates a bit of an unexpected behavior for the code setting the property. - -So... Should I set a property asynchronously ? The answer is NO. - -For this particular problem of the 'enable' property, I solved it by having two properties: -- `enabled`, readwrite, which reflects how the object is *configured*. Therefore this property is set synchronously. -- `state`, readable only, which gives the current state of the object, and go from *disabled* to *enabling* to *enabled*. This property is tied to `enabled`, but its value changes aynchronously. - -With two properties, one can connect to the `enabled` property to know how the object is configured, and one can connect to the `state` property to know the real object state. - -#### Should I Define A Base Class For My Object Hierarchy ? - -For example, GStreamer has its own `GstObject`. And at some point, I thought it was cool, and furthermore it seemed that it would solve some of the problems I faced. So I defined my own `GvObject` for a while. I then removed it quickly enough. Here's my feedback from that experience. - -First questions that arises: should all my objects inherit from GvObject ? Or only those who have a solid reason for that ? - -At first, I went for the latter, because I thought that if an object has no reason to inherit GvObject, then it should remain as lightweight and simple as possible, and inherit GObject. - -So I ended up with a mix of objects that were either GObject derived, either GvObject derived. It's a bit of a mess suddenly, because the separation between both, and the reasons for choosing the right parent, was all very unclear. - -Then, serialization kicked in, and I had another dilemna. If the serialization API targets GvObject, then GObject derived objects were left out, and couldn't be serialized. On the other hand, if the API targeted GObject, I couldn't take advantage of some of the specific features GvObject, that were actually very helpful for serializing. - -Which made me change my mind: if I define a GvObject base-class, then I should embrace it completely, and have every object inherit it. It looked nice and consistent now, but I lost a bit of the initial lightness in the process, and I was wondering if it was worth it. - -But still, I was happy because now the serialization was easier to implement, since I embedded some convenient stuff for it within my base class GvObject. - -But then, another problem kicked in. The UI part is implemented by inheriting GTK widgets. How will I serialize this GObject derived objects, now that the serialization API targets the GvObject type ? My only solution here was to rewrite the UI, use composition instead of inheritance, so that my UI objects could be derived from GvObject and be serializable. - -I didn't do that though. Instead, I came back to GObject for the base class. For all the problems that I solved with GvObject, I thought again and solved them differently, and in a better way. - -After all that, I draw some conclusions for myself: - -- think twice before defining a base class for your object hierarchy. It has its good points, for sure, but also its drawbacks. -- if you work with GObject-based libraries, be aware that the base class you define can't help for objects from those libraries, or that you inherit from those libraries. Your lower denominator for the whole set of classes you deal with will always be GObject. So, does you base type really helps, or does it get in the way ? -- ask yourself if you can't solve your problem with an interface instead. Interface are more flexible. Even if you use objects from other libraries, you can still inherit them, and implement an interface in the child. diff -Nru goodvibes-0.3.6/docs/wiki.old/Timeless-Wisdom.md goodvibes-0.4.2/docs/wiki.old/Timeless-Wisdom.md --- goodvibes-0.3.6/docs/wiki.old/Timeless-Wisdom.md 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/docs/wiki.old/Timeless-Wisdom.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -Some timeless wisdom that needs to be repeated again and again. - - - -> Smart data structures and dumb code works a lot better than the other way around. - -Eric S. Raymond - The Cathedral and the Bazaar - -> It is simple to make things complex, but complex to make things simple. - -Meyer's 3rd Law - -> It seems that perfection is attained not when there is nothing more to add, but when there is nothing more to remove. - -Antoine de Saint-Exupéry - Wind, Sand and Stars - 1939 diff -Nru goodvibes-0.3.6/docs/wiki.old/Ui-Design-Choices.md goodvibes-0.4.2/docs/wiki.old/Ui-Design-Choices.md --- goodvibes-0.3.6/docs/wiki.old/Ui-Design-Choices.md 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/docs/wiki.old/Ui-Design-Choices.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -Design choices I made along the way, and why. Just for my own remembering. - -1. [How much margin and spacing for the UI ?](#how-much-margin-and-spacing-for-the-ui-) -2. [Why not using GtkDialog to handle preferences ?](#why-not-using-gtkdialog-to-handle-preferences-) -3. [Should I use the GObject property details in the UI ?](#should-i-use-the-gobject-property-details-in-the-ui-) -4. [GTK+ Bookmarks](#gtk-bookmarks) - - - -How much margin and spacing for the UI ? ----------------------------------------- - -When designing the UI in Glade, there's no margins by default, so the whole thing looks ugly at this point. Margins, spacings, paddings and such must be set, and it's up to me to decide how much. So I wonder: how much ? - -I have no idea, and don't especially care, so I let someone else decide for me. I just followed the guidelines provided by GNOME. - -- [GNOME HUman Interface Guidelines](https://developer.gnome.org/hig/stable/) - - - -Why not using GtkDialog to handle preferences ? ------------------------------------------------ - -Mainly, it's because a dialog requires a transient parent, aka another window that must be the parent. Ever had this warning in your console ? - - Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged. - -But Goodvibes is mainly a status icon, and doesn't really have a main window to speak of. - -Loosely speaking, we could use the popup window as the transient parent, since it always exists. It's hidden most of the time, but it exists. But it looks a bit hacky to me. I don't really know why GTK+ needs a transient parent, and what it expects from this parent, but I'm almost sure the popup window is not up to the expectation. - -So in the end, I find it cleaner to use a window rather than a dialog. - - - -Should I use the GObject property details in the UI ? ------------------------------------------------------ - -Short answer: No. - -It might be tempting though, simply to avoid duplicating strings. - -Indeed, in the preferences dialog, often a setting is mapped to an object property. Given that a property already has a nick (that could be mapped to the setting label) and a blurb (aka a description that could be mapped to the setting tooltip), why should we define these strings again in the glade file ? Why don't we just set labels and tooltips from the property nick and blurb in the C code ? - -It's tempting. Even more after reading this piece of the doc: - -- - -However, I have good reasons not to do so, both for the nicks and blurbs (although in the following, I'll only talk about nicks, for clarity). - -First, there's the context. Let's suppose you have a property that decides what action should be associated with a middle-click. In your code, an ideal nick for the property would be "Mouse Middle Click". However, assuming that in the UI you have a "Mouse" section for the settings related to the mouse, then you don't want to repeat the word "Mouse". The ideal name for the setting would -then be "Middle Click". - -So, because of a different context, the best name for a property in the code, and the best name for the corresponding setting in the UI, might be different. - -Second, there's more problems when translation kicks in. Because then, the property nicks must be translatable, and if I want to be consistent, then **ALL** the properties should have a translatable nick. It means that those properties which don't appear in the UI will be translated for nothing. Useless work for translators, isnt't it ? Or should I only translates the nicks that appear in the UI ? But then how do I maintain this mess ? What will happen, in the end, is that I'll have nicks marked as translatable, but don't appear in the UI, while others appear in the UI but are not marked as translatable... - -The REAL problem, here, is that there will be no warnings for these missing translations. So there will always be missing translations in each new release. - -So, here are my two main issues: context, and translations. - -In the end, my choice is to use nicks and blurbs only as hints for developpers passing by. For the UI, I'll define everything in Glade, or in the related C file. It solves the context issue, and also the translation issue, since Glade automatically mark strings as translatable, so I don't have to bother. - -More interesting reading: - -- - - - -GTK+ Bookmarks --------------- - -- [GTK+ Development Blog](https://blog.gtk.org/) -- [Those “realize” & “map” widget signals](https://blogs.gnome.org/jnelson/2010/10/13/those-realize-map-widget-signals/) -- [Another Container for Gtk+ 3.12 | GtkActionBar](http://worldofgnome.org/another-container-for-gtk-3-12-gtkactionbar/) -- Composite Widgets - - [Announcing Composite Widget Templates](https://blogs.gnome.org/tvb/2013/04/09/announcing-composite-widget-templates/) - - [Embeding GtkBuilder UI definitions into GObject classes!](https://blogs.gnome.org/xjuan/2012/07/13/embeding-gtkbuilder-ui-definitions-into-gobject-classes/) -- [GTK+: Aligning / Justification in text widgets](https://www.murrayc.com/permalink/2015/03/02/gtk-aligning-justification-in-text-widgets/) diff -Nru goodvibes-0.3.6/.gitignore goodvibes-0.4.2/.gitignore --- goodvibes-0.3.6/.gitignore 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/.gitignore 2018-11-10 06:04:58.000000000 +0000 @@ -1,74 +1,3 @@ -# For all directories -.deps -*.o *~ - -# Binaries and libraries -/src/goodvibes -/src/goodvibes-client -/libcaphe/caphe/libcaphe.a -/libcaphe/tests/caphe-test - -# Generated files -/AUTHORS - -# Generated makefiles -/Makefile* -/data/Makefile* -/libcaphe/Makefile* -/libcaphe/caphe/Makefile* -/libcaphe/tests/Makefile* -/po/Makefile* -/src/Makefile* - -# Generated source files -*enum-types.[ch] - -# Data -/data/*.1 -/data/*.service -/data/*.service.in -/data/*.desktop -/data/*.desktop.in -/data/*.gschema.xml -/data/*.gschema.valid -/data/*.enums.xml -/data/gschemas.compiled - -# M4 macros -/m4/* -!/m4/gv-*.m4 - -# Autotools stuff -.dirstamp -/INSTALL -/aclocal.m4 -/ar-lib -/autom4te.cache/ -/compile -/config.guess -/config.log -/config.rpath -/config.status -/config.sub -/configure -/depcomp -/install-sh -/missing - -# Documentation +/build /docs/goodvibes.readthedocs.io/_build - -# I18n stuff -/ABOUT-NLS -/po/*.gmo -/po/*.header -/po/*.mo -/po/*.sed -/po/*.sin -/po/Makefile.in.in -/po/Makevars.template -/po/POTFILES -/po/Rules-quot -/po/stamp-it -/po/stamp-po diff -Nru goodvibes-0.3.6/.gitlab-ci/build.sh goodvibes-0.4.2/.gitlab-ci/build.sh --- goodvibes-0.3.6/.gitlab-ci/build.sh 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/.gitlab-ci/build.sh 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,35 @@ +#!/bin/bash + +set -e +set -u + +CPPFLAGS="\ + -std=gnu99 \ + -Wall \ + -Wextra \ + -Wshadow \ + -Werror" + +# As long as we use GtkStatusIcon, we need no-deprecated-declarations +CPPFLAGS="$CPPFLAGS -Wno-deprecated-declarations" + +# For some casts to GFunc, we get a warning. Typically: +# +# error: cast between incompatible function types from +# ‘void (*)(void *)’ to ‘void (*)(void *, void *)’ +# g_list_foreach(core_objects, (GFunc) g_object_unref, NULL); +# ^ +# gcc prefers no-cast-function-type +# clang prefers no-bad-function-cast +# It's unclear if an agreement will be reached. +if [ "${CC:-}" == "clang" ]; then + CPPFLAGS="$CPPFLAGS -Wno-bad-function-cast" +else + CPPFLAGS="$CPPFLAGS -Wno-cast-function-type" +fi + +export CPPFLAGS + +meson build $@ +ninja -C build +ninja -C build test diff -Nru goodvibes-0.3.6/.gitlab-ci/docker-build-image.sh goodvibes-0.4.2/.gitlab-ci/docker-build-image.sh --- goodvibes-0.3.6/.gitlab-ci/docker-build-image.sh 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/.gitlab-ci/docker-build-image.sh 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e +set -u + +fail() { echo >&2 "$@"; exit 1; } + +[ $# -eq 1 ] || fail "Usage: $(basename $0) " + +DOCKERFILE=$1 +[ -e $DOCKERFILE ] || fail "File '$DOCKERFILE' does not exist" + +FROM=$(grep '^FROM' $DOCKERFILE | sed 's/^FROM *//') +[ "$FROM" ] || fail "Failed to parse dockerfile" + +TAG=registry.gitlab.com/goodvibes/goodvibes/$FROM + +docker build \ + --tag $TAG \ + --file $DOCKERFILE \ + . + +cat << EOF + +-------- + +Now you might just want to push the image: +docker push $TAG + +EOF diff -Nru goodvibes-0.3.6/.gitlab-ci/Dockerfile.debian goodvibes-0.4.2/.gitlab-ci/Dockerfile.debian --- goodvibes-0.3.6/.gitlab-ci/Dockerfile.debian 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/.gitlab-ci/Dockerfile.debian 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,29 @@ +FROM debian:buster + +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive \ + apt-get install --yes --no-install-recommends \ + clang \ + gcc \ + gettext \ + libglib2.0-dev \ + libgstreamer1.0-dev \ + libgstreamer-plugins-base1.0-dev \ + libgtk-3-dev \ + libkeybinder-3.0-dev \ + libsoup2.4-dev \ + locales \ + meson \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* + +RUN useradd \ + --create-home \ + --shell /bin/bash \ + --uid 4321 \ + builder + +USER builder +WORKDIR /home/builder + +ENV LANG C.UTF-8 diff -Nru goodvibes-0.3.6/.gitlab-ci/Dockerfile.fedora goodvibes-0.4.2/.gitlab-ci/Dockerfile.fedora --- goodvibes-0.3.6/.gitlab-ci/Dockerfile.fedora 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/.gitlab-ci/Dockerfile.fedora 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,29 @@ +FROM fedora:28 + +RUN dnf -y install \ + clang \ + findutils \ + gcc \ + gettext-devel \ + glib2-devel \ + gstreamer1-devel \ + gstreamer1-plugins-base-devel \ + gtk3-devel \ + keybinder3-devel \ + libsoup-devel \ + meson \ + pkgconfig \ + tar \ + xz \ + && dnf clean all + +RUN useradd \ + --create-home \ + --shell /bin/bash \ + --uid 4321 \ + builder + +USER builder +WORKDIR /home/builder + +ENV LANG C.UTF-8 diff -Nru goodvibes-0.3.6/.gitlab-ci/docker-run-image.sh goodvibes-0.4.2/.gitlab-ci/docker-run-image.sh --- goodvibes-0.3.6/.gitlab-ci/docker-run-image.sh 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/.gitlab-ci/docker-run-image.sh 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,22 @@ +#!/bin/bash +# This script is for developers, not CI. + +set -e +set -u + +fail() { echo >&2 "$@"; exit 1; } + +[ $# -eq 1 ] || fail "Usage: $(basename $0) " + +IMAGE=$1 + +docker run \ + --rm \ + --tty \ + --interactive \ + --hostname gvbuilder \ + --user root:root \ + --volume $(pwd):/home/builder/goodvibes \ + --workdir /home/builder/goodvibes \ + $IMAGE \ + bash diff -Nru goodvibes-0.3.6/.gitlab-ci.yml goodvibes-0.4.2/.gitlab-ci.yml --- goodvibes-0.3.6/.gitlab-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/.gitlab-ci.yml 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,44 @@ +debian-gcc: + image: registry.gitlab.com/goodvibes/goodvibes/debian:buster + stage: build + script: + - bash -x ./.gitlab-ci/build.sh + +debian-clang: + image: registry.gitlab.com/goodvibes/goodvibes/debian:buster + stage: build + only: [ tags ] + variables: + CC: clang + script: + - bash -x ./.gitlab-ci/build.sh + +fedora-gcc: + image: registry.gitlab.com/goodvibes/goodvibes/fedora:28 + stage: build + only: [ tags ] + script: + - bash -x ./.gitlab-ci/build.sh + +fedora-clang: + image: registry.gitlab.com/goodvibes/goodvibes/fedora:28 + stage: build + only: [ tags ] + variables: + CC: clang + script: + - bash -x ./.gitlab-ci/build.sh + +debian-gcc-no-ui: + image: registry.gitlab.com/goodvibes/goodvibes/debian:buster + stage: build + only: [ tags ] + script: + - bash -x ./.gitlab-ci/build.sh -Dui-enabled=false + +debian-gcc-no-feat-hotkeys: + image: registry.gitlab.com/goodvibes/goodvibes/debian:buster + stage: build + only: [ tags ] + script: + - bash -x ./.gitlab-ci/build.sh -Dfeat-hotkeys=false diff -Nru goodvibes-0.3.6/goodvibes-launcher.sh goodvibes-0.4.2/goodvibes-launcher.sh --- goodvibes-0.3.6/goodvibes-launcher.sh 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/goodvibes-launcher.sh 2018-11-10 06:04:58.000000000 +0000 @@ -2,32 +2,27 @@ # The launcher is for people who want to run Goodvibes from the source tree, # without installing it. GLib and GTK+ need to access some shared resources, -# so we need to instruct them where to look for it. +# so we need to tell them to look for it in-tree. -GOODVIBES=src/goodvibes +fail() { echo >&2 "$@"; exit 1; } -fail() { - echo >&2 $@ - exit 1 -} +BUILDDIR=${BUILDDIR:-build} +GOODVIBES=$BUILDDIR/src/goodvibes -[ -x $GOODVIBES ] || fail "'$GOODVIBES' not found, did you build it?" +[ -d $BUILDDIR ] || fail "Build directory '$BUILDDIR' does not exit" +[ -x $GOODVIBES ] || fail "Executable '$GOODVIBES' not found" # XDG_DATA_DIRS is needed for: -# - GTK+ to load local icons from './data/icons' -if [ "$XDG_DATA_DIRS" ]; then - if grep -F -q -v './data/:' <<< "$XDG_DATA_DIRS"; then - XDG_DATA_DIRS="./data/:$XDG_DATA_DIRS" - fi -else - XDG_DATA_DIRS='./data/:/usr/local/share/:/usr/share/' -fi +# - GTK+ to load local icons from '$BUILDDIR/data/icons' +[ "$XDG_DATA_DIRS" ] \ + && XDG_DATA_DIRS="$BUILDDIR/data:$XDG_DATA_DIRS" \ + || XDG_DATA_DIRS="$BUILDDIR/data:/usr/local/share:/usr/share" export XDG_DATA_DIRS # GSCHEMA_SETTINGS_DIR is needed for: -# - GLib to load local settings schemas from './data' +# - GLib to load local settings schemas from '$BUILDDIR/data' # If you don't define it, you'll be hit by something like that: -# [GLib-GIO] Settings schema 'com.elboulangero.Goodvibes.Core' is not installed -export GSETTINGS_SCHEMA_DIR='./data/' +# [GLib-GIO] Settings schema '...Goodvibes.Core' is not installed +export GSETTINGS_SCHEMA_DIR="$BUILDDIR/data/" $GOODVIBES $@ diff -Nru goodvibes-0.3.6/HACKING.md goodvibes-0.4.2/HACKING.md --- goodvibes-0.3.6/HACKING.md 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/HACKING.md 2018-11-10 06:04:58.000000000 +0000 @@ -22,65 +22,47 @@ Download -------- -To get the latest source, clone the repository from GitHub. +To get the latest source, clone the repository from GitLab. - git clone https://github.com/elboulangero/goodvibes.git + git clone https://gitlab.com/goodvibes/goodvibes.git Additional repositories are available: - # Debian packaging files - git clone https://github.com/elboulangero/goodvibes-debian.git - # Dockerfile (build environment used by Shippable) - git clone https://github.com/elboulangero/goodvibes-docker.git + # Debian packaging files + git clone https://gitlab.com/goodvibes/goodvibes-debian.git Compilation ----------- -Goodvibes uses the `autotools` as a build system. The procedure to compile is -the usual one. +Goodvibes is built using [Meson][] and [Ninja][]. The build commands are: - ./autogen.sh && \ - ./configure && \ - make + meson build + cd build + ninja -If you want the build to be more verbose, invoke `./configure` as such. +Goodvibes build is quite modular. Features that require an external library can +be disabled at build time. To see all the options available, enter the build +directory and run: - ./configure --disable-silent-rules + meson configure -Goodvibes build is quite modular. Features that require an external library are -compiled only if the required dependencies are found on your system. Otherwise -they're excluded from the build. +For example, to disable the hotkeys feature: -You can change this behavior though. You can force a full-featured build, that -will fail if some of the required dependencies are missing. + meson configure -Dfeat-hotkeys=false - ./configure --enable-all +To disable compilation of the user interface (also disable every ui-related +features): -Or you can do the opposite, and force a minimal build with none of the optional -features enabled. + meson configure -Dui=false - ./configure --disable-all +Additionally, it's possible to run a few tests: -On top of that, you can explicitly enable or disable any optional features, -using the `--enable-FEATURE` or `--disable-FEATURE` options (and replacing -*FEATURE* with a feature's name). Such parameters take precedence over the -`--enable-all` and `--disable-all` options. + meson test -For example, to have a minimal build with only the UI enabled: - - ./configure --disable-all --enable-ui - -To have a full-featured build but disable notifications: - - ./configure --enable-all --disable-notifications - -Notice that disabling the UI will also disable all the UI-related features. - -For more details, have a look at the file [configure.ac](configure.ac) or run: - - ./configure -h +[meson]: http://mesonbuild.com +[ninja]: https://ninja-build.org/ @@ -92,35 +74,41 @@ If you want to run Goodvibes from the source tree, without installing it, use the launcher script. - ./goodvibes-launcher.sh + ./goodvibes-launcher.sh + +The script assumes that the build directory is named `build`. -Why do you need a script ? Some libraries expect shared resources to be -installed in standard locations. To be more accurate: +Why do you need a script? Some libraries expect shared resources to be +installed in some standard locations. To be more accurate: -- GLib expects settings schemas to be installed under - `/usr/share/glib-2.0/schemas/` or similar. -- GTK+ expects icons to be installed under `/usr/share/icons` or similar. +- GLib expects schemas to be installed at `/usr/share/glib-2.0/schemas/` or + similar. +- GTK+ expects icons to be installed at `/usr/share/icons` or similar. -It's possible to customize this behavior with environment variables though. -Have a look at the script for details. +It's possible to customize this behavior with environment variables though, and +that's what the launcher script does. Have a look at it for details. + +Also, don't expect any kind of desktop integration to work when you run from +the source tree. Ie, the desktop won't find any desktop file installed in the +standard location (`/usr/share/applications`), and various things might not +work: notifications, icon display here or there, etc. #### From a non-standard directory If for some reason you install Goodvibes in a non-standard directory (`/opt` or `/home/user` or whatever), you will be hit by the same problems mentioned -above: the shared resource won't be found at run-time. So please refer to the +above: the shared resources won't be found at run-time. So please refer to the launcher script to see which environment variables you need to set before running Goodvibes. #### Command-line options -To get a brief overview of the command-line options available, invoke with -`-h`. +To get a brief overview of the command-line options available, use `--help`. The option you will use the most is `-l` to change the log level. Here is a typical line: - ./src/goodvibes -l dbg + goodvibes -l dbg Colors are enabled by default, but you can disable it with `-c` if it hurts your eyes. Colors are automatically disabled when logs are redirected to a @@ -138,9 +126,9 @@ - [Running GStreamer Applications][] - [Running GTK+ Applications][] -Hardcore GTK+ debugging can be done with [GtkInspector][]: +Hardcore GTK+ debugging can be done with the [GtkInspector][]: - ./src/goodvibes --gtk-debug=interactive + goodvibes --gtk-debug=interactive [glib message output and debugging functions]: https://developer.gnome.org/glib/stable/glib-Message-Logging.html [running glib applications]: https://developer.gnome.org/glib/stable/glib-running.html @@ -148,6 +136,17 @@ [running gtk+ applications]: https://developer.gnome.org/gtk3/stable/gtk-running.html [gtkinspector]: https://wiki.gnome.org/Projects/GTK+/Inspector +#### Change language + +For testing, it can be convenient to change the language. For that, use the +`LANGUAGE` environment variable. + + LANGUAGE=fr goodvibes + +Note that gettext will look for the message files in the path given to +`bindtextdomain(3)`, so make sure that this path contains the message files. +This is logged when Goodvibes starts. + Additional Tools @@ -158,17 +157,17 @@ guess - `gsettings`. This is useful to witness Goodvibes reading and writing its configuration, and also to get or set some values. - gsettings monitor com.elboulangero.Goodvibes.Core - gsettings list-recursively com.elboulangero.Goodvibes.Core + gsettings monitor io.gitlab.Goodvibes.Core + gsettings list-recursively io.gitlab.Goodvibes.Core [DConf][] is the backend for GSettings. It's possible to play directly with the `dconf` command, therefore by-passing completely GSettings. - dconf watch /com/elboulangero/Goodvibes/ - dconf reset -f /com/elboulangero/Goodvibes/ + dconf watch /io/gitlab/Goodvibes/ + dconf reset -f /io/gitlab/Goodvibes/ [gsettings]: https://developer.gnome.org/gio/stable/GSettings.html -[dconf]: https://wiki.gnome.org/Projects +[dconf]: https://wiki.gnome.org/Projects/dconf @@ -181,22 +180,17 @@ The code is neatly split into different parts: -- `additions`: this is where I extend some of the libraries I use, where I add - some functions that I wish would exist already. -- `framework`: the name says it all. +- `framework`: the basic stuff we need. - `core`: the core of Goodvibes, basically enough to have the software up and running, without the ui. - `ui`: the GTK+ user interface. - `feat`: features that can be enable/disabled at compile-time. I guess it's quite similar to the plugins you often find in music players on GNU/Linux. Except that I didn't dare to call it plugin, for plugins are usually - something discovered and loaded at run-time, not compile-time. + something discovered and loaded at run-time, not at compile-time. - `libcaphe`: a library to handle system sleep inhibition. Actually GTK+ can already do that through GtkApplication, so one day this will go away. -I suggest to have a look at [configure.ac](configure.ac) and -[src/Makefile.am](src/Makefile.am) for more details. - How To Code That @@ -204,11 +198,11 @@ #### Adding a new setting -Settings are mapped directly to object properties. You must ensure that: +Settings are mapped directly to GObject properties. You must ensure that: -- the object must be a global instance, part of the `core`, `ui` or `feat` +- The object must be a global instance, part of the `core`, `ui` or `feat` system. -- the object must implement the `GvConfigurable` interface. +- The object must implement the `GvConfigurable` interface. You must bind the property to a setting using `g_settings_bind()`. This **must NOT be done** at construct-time, but later on in the `configure()` function @@ -216,27 +210,28 @@ You must understand that the startup procedure is made in two steps: -- first, every objects are created. No errors are expected at this stage. -- second, every objects are configured. Serious things start to happen, there - might be errors, and it's important to be ready to report it to the user. +1. Every objects are *created*. No errors are expected at this stage. +2. Every objects are *configured*. Serious things start to happen, there might + be errors, and it's important to be ready to report it to the user. That's + why the configure step is run *after* everything is created. #### Reporting an error to the user Here's how to report an error to the user from an object: -- the object must have been registered using the function - `gv_framework_register()`. -- the object must implement the `GvErrorable` interface. +- The object must have been registered using the function + `gv_framework_register_object()`. +- The object must implement the `GvErrorable` interface. Then, it's just a matter of invoking the function `gv_errorable_emit_error()`. A few things to notice: -- you shouldn't call this function too early (aka during construction), as the +- You shouldn't call this function too early (aka during construction), as the system is not ready yet. -- the user message **must be** translatable as it's intended for *users*. +- The user message **must be** translatable as it's intended for *users*. - It's up to you to drop an additional log (`WARNING()` should be used). -- the log message **must NOT be** translatable as it's intended for +- The log message **must NOT be** translatable as it's intended for *developers*. @@ -252,11 +247,11 @@ The code is currently indented using [Artistic Style][]. There's a script to automatically indent the whole thing: - ./scripts/code/indent.sh all + ./scripts/code/indent.sh all You can (and should) also indent your staged changes before commiting: - ./scripts/code/indent.sh staged + ./scripts/code/indent.sh staged [artistic style]: http://astyle.sourceforge.net/ @@ -272,17 +267,17 @@ - `WISHED` Things I wish, but will probably never do. - `TODO` Things that should be done pretty soon. -- `FIXME` For things obviously broken. +- `FIXME` Things obviously broken. Always try to make it a one-liner if possible, or at least describe the problem in one line, then add more details on the following lines. Stick to these conventions, and then getting a list of things is easy: - # TODO list - ack 'TODO' - # List everything - ack '// ' + # TODO list + ack 'TODO' + # List everything + ack '// ' Here are some links that discuss codetags: @@ -292,9 +287,9 @@ #### GObject C Files Layout If you find yourself writing a new file, therefore creating a new object, fear -not ! There's a script that generates all the boilerplate. +not! There's a script that generates all the boilerplate. - ./scripts/code/gv-object-make.sh + ./scripts/code/gv-object-make.sh Have a look at the structure of the C file created, and please notice a few things. @@ -305,9 +300,9 @@ Functions are grouped in sections, titled by a comment such as: - /* - * Section name - */ + /* + * Section name + */ Most of the time, these sections are always the same, because implementing a GObject always boils down to the same thing, more or less: GObject inherited @@ -324,25 +319,26 @@ Contribution ------------ -Contributing is better done through GitHub, so please follow the usual GitHub -workflow: +Contributing is better done through GitLab, please follow the usual workflow: -- have your account setup -- fork the project -- work on your own version -- discuss the changes, and eventually submit a merge request +- Have your account setup +- Fork the project +- Create a branch for your work +- Work +- Create a merge request If you hack around for your own use-case, and think that other users could -benefit from your hacks, feel free to share it and discuss it on GitHub. +benefit from your hacks, feel free to share it and discuss it on GitLab. -If we decide that your hacks should be integrated upstream, then you will have -to transform it in proper commits, make sure it fits into the current design, -that it respects the coding style and so on. +If we decide that your hacks should be integrated in Goodvibes proper, then you +will have to make sure it looks good, with meaningful commits that fit into the +existing design, proper commit messages, respect for the coding style, and so +on. Please note that my first goal for Goodvibes is to ensure a long-term maintenance. There are more than enough software with a short lifetime around, and I don't want to add another to the list. It means I want the code to be clean, readable, maintainable. Clean design and zero hacks are my goals. Dirty hacks are OK to solve an outstanding problem quickly, or to demonstrate a -possible solution. But they are not OK for long-term maintenance, and -therefore won't make it upstream. +possible solution. But they are not OK for long-term maintenance, and therefore +won't make it upstream. diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe.c goodvibes-0.4.2/libcaphe/caphe/caphe.c --- goodvibes-0.3.6/libcaphe/caphe/caphe.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "caphe-cup.h" - -void -caphe_cleanup(void) -{ - g_object_add_weak_pointer(G_OBJECT(caphe_cup_default_instance), - (gpointer *) &caphe_cup_default_instance); - g_object_unref(caphe_cup_default_instance); - g_assert_null(caphe_cup_default_instance); -} - -void -caphe_init(void) -{ - /* Dummy */ -} diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-cup.c goodvibes-0.4.2/libcaphe/caphe/caphe-cup.c --- goodvibes-0.3.6/libcaphe/caphe/caphe-cup.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-cup.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,502 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include -#include - -#include "caphe-trace.h" -#include "caphe-inhibitor.h" -#include "caphe-inhibitor-list.h" -#include "caphe-cup.h" - -/* - * Signals - */ - -enum { - SIGNAL_INHIBIT_FAILURE, - /* Number of signals */ - SIGNAL_N -}; - -static guint signals[SIGNAL_N]; - -/* - * Properties - */ - -enum { - /* Reserved */ - PROP_0, - /* Construct-only properties */ - PROP_APPLICATION_NAME, - /* Properties */ - PROP_INHIBITOR, - /* Total number of properties */ - LAST_PROP -}; - -static GParamSpec *properties[LAST_PROP]; - -/* - * GObject definitions - */ - -typedef struct { - /* If NULL, means an unhibibit request. - * If non NULL, means an inhibit request. - */ - gchar *reason; -} CapheRequest; - -struct _CapheCupPrivate { - /* List of inhibitors */ - CapheInhibitorList *inhibitor_list; - gboolean ready; - - /* Application name */ - gchar *application_name; - - /* Current state */ - CapheInhibitor *current_inhibitor; - gchar *current_reason; - /* Pending request */ - CapheRequest *pending_request; - /* Pending processing */ - guint when_idle_process_id; -}; - -typedef struct _CapheCupPrivate CapheCupPrivate; - -struct _CapheCup { - /* Parent instance structure */ - GObject parent_instance; - /* Private data */ - CapheCupPrivate *priv; -}; - -G_DEFINE_TYPE_WITH_PRIVATE(CapheCup, caphe_cup, G_TYPE_OBJECT) - -/* - * Helpers - */ - -CapheRequest * -caphe_request_new(const gchar *reason) -{ - CapheRequest *self; - - self = g_new0(CapheRequest, 1); - self->reason = g_strdup(reason); - - return self; -} - -void -caphe_request_free(CapheRequest *self) -{ - if (self == NULL) - return; - - g_free(self->reason); - g_free(self); -} - -/* - * Private methods - */ - -static void caphe_cup_set_inhibitor(CapheCup *self, CapheInhibitor *inhibitor); - -static void -caphe_cup_process(CapheCup *self) -{ - CapheCupPrivate *priv = self->priv; - - /* As long as we're not ready, we can't do anything */ - if (priv->ready == FALSE) - return; - - /* If there's nothing pending, do nothing */ - if (priv->pending_request == NULL) - return; - - /* We can start processing the pending request. - * In case we're trying to inhibit while already inhibited - * (it's possible in case the user wants to change the reason), - * we must slip an unhibit request in between. - */ - if (priv->current_reason && priv->pending_request->reason) { - g_debug("Slipping uninhibit request between two inhibit requests"); - - /* Uninhibit */ - if (priv->current_inhibitor) { - caphe_inhibitor_uninhibit(priv->current_inhibitor); - priv->current_inhibitor = NULL; - g_free(priv->current_reason); - priv->current_reason = NULL; - } - } - - /* Process now */ - if (priv->pending_request->reason) { - CapheInhibitor **inhibitors; - gboolean success; - - g_debug("Inhibition: processing request"); - - for (inhibitors = caphe_inhibitor_list_get_inhibitors(priv->inhibitor_list); - *inhibitors; inhibitors++) { - CapheInhibitor *inhibitor = *inhibitors; - GError *error = NULL; - - /* Ignore inhibitors that are not available */ - if (caphe_inhibitor_get_available(inhibitor) == FALSE) - continue; - - /* Attempt inhibition */ - success = caphe_inhibitor_inhibit(inhibitor, - priv->application_name, - priv->pending_request->reason, - &error); - if (success == FALSE) { - g_warning("Error while inhibiting: %s", error->message); - g_clear_error(&error); - continue; - } - - /* Save new status */ - caphe_cup_set_inhibitor(self, inhibitor); - g_free(priv->current_reason); - priv->current_reason = g_strdup(priv->pending_request->reason); - - /* Done */ - break; - } - - if (success == FALSE) { - g_signal_emit(self, signals[SIGNAL_INHIBIT_FAILURE], 0); - } - - /* Consume request */ - caphe_request_free(priv->pending_request); - priv->pending_request = NULL; - - } else { - g_debug("Uninhibition: processing request"); - - /* Uninhibit */ - if (priv->current_inhibitor) { - caphe_inhibitor_uninhibit(priv->current_inhibitor); - caphe_cup_set_inhibitor(self, NULL); - g_free(priv->current_reason); - priv->current_reason = NULL; - } - - /* Consume request */ - caphe_request_free(priv->pending_request); - priv->pending_request = NULL; - } -} - -/* - * Signal handlers - */ - -static void -on_inhibitor_list_ready(CapheInhibitorList *inhibitor_list G_GNUC_UNUSED, - CapheCup *self) -{ - CapheCupPrivate *priv = self->priv; - - /* We're ready, let's remember that */ - priv->ready = TRUE; - - /* Process */ - caphe_cup_process(self); -} - -/* - * Public - */ - -gboolean -caphe_cup_is_inhibited(CapheCup *self) -{ - CapheCupPrivate *priv = self->priv; - - return priv->current_inhibitor != NULL; -} - -static gboolean -when_idle_process(CapheCup *self) -{ - CapheCupPrivate *priv = self->priv; - - caphe_cup_process(self); - - priv->when_idle_process_id = 0; - - return G_SOURCE_REMOVE; -} - -void -caphe_cup_uninhibit(CapheCup *self) -{ - CapheCupPrivate *priv = self->priv; - - /* We might ignore the request in the following case: - * - we're already uninhibited - * - we're sure there's nothing happening at the moment - */ - if (priv->current_inhibitor == NULL && - priv->pending_request == NULL) - return; - - /* Otherwise, create a request */ - caphe_request_free(priv->pending_request); - priv->pending_request = caphe_request_new(NULL); - g_debug("Uninhibition: request created and pending"); - - /* Schedule process */ - if (priv->when_idle_process_id == 0) - priv->when_idle_process_id = g_idle_add((GSourceFunc) when_idle_process, self); -} - -void -caphe_cup_inhibit(CapheCup *self, const gchar *reason) -{ - CapheCupPrivate *priv = self->priv; - - g_return_if_fail(reason != NULL); - - /* We might ignore the request in the following case: - * - we're already inhibited with the same reason - * - we're sure there's nothing happening at the moment - * ... - */ - if (priv->current_inhibitor && - !g_strcmp0(reason, priv->current_reason) && - priv->pending_request == NULL) - return; - - /* Otherwise, create a request */ - caphe_request_free(priv->pending_request); - priv->pending_request = caphe_request_new(reason); - g_debug("Inhibition: request created and pending"); - - /* Schedule process */ - if (priv->when_idle_process_id == 0) - priv->when_idle_process_id = g_idle_add((GSourceFunc) when_idle_process, self); -} - -CapheCup * -caphe_cup_new(void) -{ - return g_object_new(CAPHE_TYPE_CUP, NULL); -} - -/* - * Property accessors - */ - -void -caphe_cup_set_application_name(CapheCup *self, const gchar *application_name) -{ - CapheCupPrivate *priv = self->priv; - - if (!g_strcmp0(priv->application_name, application_name)) - return; - - g_free(priv->application_name); - priv->application_name = g_strdup(application_name); - g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_APPLICATION_NAME]); -} - -CapheInhibitor * -caphe_cup_get_inhibitor(CapheCup *self) -{ - return self->priv->current_inhibitor; -} - -static void -caphe_cup_set_inhibitor(CapheCup *self, CapheInhibitor *inhibitor) -{ - CapheCupPrivate *priv = self->priv; - - if (g_set_object(&priv->current_inhibitor, inhibitor)) - g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_INHIBITOR]); -} - -static void -caphe_cup_get_property(GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - CapheCup *self = CAPHE_CUP(object); - - switch (property_id) { - case PROP_INHIBITOR: - g_value_set_object(value, caphe_cup_get_inhibitor(self)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void -caphe_cup_set_property(GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - CapheCup *self = CAPHE_CUP(object); - - switch (property_id) { - case PROP_APPLICATION_NAME: - caphe_cup_set_application_name(self, g_value_get_string(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -/* - * GObject methods - */ - -static void -caphe_cup_finalize(GObject *object) -{ - CapheCup *self = CAPHE_CUP(object); - CapheCupPrivate *priv = self->priv; - - TRACE("%p", self); - - if (priv->when_idle_process_id) - g_source_remove(priv->when_idle_process_id); - - caphe_request_free(priv->pending_request); - - g_free(priv->application_name); - - /* Unref current status */ - g_clear_object(&priv->current_inhibitor); - g_free(priv->current_reason); - - /* Destroy inhibitor list */ - g_clear_object(&priv->inhibitor_list); - - /* Chain up */ - if (G_OBJECT_CLASS(caphe_cup_parent_class)->finalize) - G_OBJECT_CLASS(caphe_cup_parent_class)->finalize(object); -} - -static void -caphe_cup_constructed(GObject *object) -{ - CapheCup *self = CAPHE_CUP(object); - CapheCupPrivate *priv = self->priv; - - TRACE("%p", self); - - /* Create inhibitor list */ - priv->inhibitor_list = caphe_inhibitor_list_new(); - g_signal_connect_object(priv->inhibitor_list, "ready", - G_CALLBACK(on_inhibitor_list_ready), - self, 0); - - /* Chain up */ - if (G_OBJECT_CLASS(caphe_cup_parent_class)->constructed) - G_OBJECT_CLASS(caphe_cup_parent_class)->constructed(object); -} - -static void -caphe_cup_init(CapheCup *self) -{ - CapheCupPrivate *priv = caphe_cup_get_instance_private(self); - const gchar *app_name; - - TRACE("%p", self); - - /* Default values */ - app_name = g_get_application_name(); - if (app_name == NULL) - app_name = "Unknown"; - priv->application_name = g_strdup(app_name); - - /* Set private pointer */ - self->priv = priv; -} - -static void -caphe_cup_class_init(CapheCupClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - - TRACE("%p", class); - - /* Override GObject methods */ - object_class->finalize = caphe_cup_finalize; - object_class->constructed = caphe_cup_constructed; - - /* Install properties */ - object_class->get_property = caphe_cup_get_property; - object_class->set_property = caphe_cup_set_property; - - properties[PROP_APPLICATION_NAME] = - g_param_spec_string("application-name", "Application name", NULL, - NULL, - G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE); - - properties[PROP_INHIBITOR] = - g_param_spec_object("inhibitor", "Current inhibitor", NULL, - CAPHE_TYPE_INHIBITOR, - G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); - - g_object_class_install_properties(object_class, LAST_PROP, properties); - - /* Signals */ - signals[SIGNAL_INHIBIT_FAILURE] = - g_signal_new("inhibit-failure", G_TYPE_FROM_CLASS(class), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -/* - * Convenience functions - */ - -CapheCup *caphe_cup_default_instance; - -CapheCup * -caphe_cup_get_default(void) -{ - if (caphe_cup_default_instance == NULL) - caphe_cup_default_instance = caphe_cup_new(); - - return caphe_cup_default_instance; -} diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-cup.h goodvibes-0.4.2/libcaphe/caphe/caphe-cup.h --- goodvibes-0.3.6/libcaphe/caphe/caphe-cup.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-cup.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __LIBCAPHE_CAPHE_CUP_H__ -#define __LIBCAPHE_CAPHE_CUP_H__ - -#include - -#include "caphe-inhibitor.h" - -/* GObject declarations */ - -#define CAPHE_TYPE_CUP caphe_cup_get_type() - -G_DECLARE_FINAL_TYPE(CapheCup, caphe_cup, CAPHE, CUP, GObject) - -/* Global instance (private, don't access) */ - -extern CapheCup *caphe_cup_default_instance; - -/* Methods */ - -CapheCup *caphe_cup_get_default(void); - -void caphe_cup_inhibit (CapheCup *self, const gchar *reason); -void caphe_cup_uninhibit (CapheCup *self); -gboolean caphe_cup_is_inhibited(CapheCup *self); - -/* Property accessors */ - -void caphe_cup_set_application_name(CapheCup *self, const gchar *name); -CapheInhibitor *caphe_cup_get_inhibitor (CapheCup *self); - -#endif /* __LIBCAPHE_CAPHE_CUP_H__ */ diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-dbus-inhibitor.c goodvibes-0.4.2/libcaphe/caphe/caphe-dbus-inhibitor.c --- goodvibes-0.3.6/libcaphe/caphe/caphe-dbus-inhibitor.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-dbus-inhibitor.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,372 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include -#include - -#include "caphe-trace.h" -#include "caphe-login-dbus-invokator.h" -#include "caphe-portal-dbus-invokator.h" -#include "caphe-power-dbus-invokator.h" -#include "caphe-session-dbus-invokator.h" -#include "caphe-dbus-invokator.h" -#include "caphe-dbus-proxy.h" -#include "caphe-dbus-inhibitor.h" - -/* - * Properties - */ - -enum { - /* Reserved */ - PROP_0, - /* Number of installable properties */ - LAST_INSTALLABLE_PROP, - /* Overriden properties */ - PROP_NAME, - PROP_AVAILABLE, - /* Total number of properties */ - LAST_PROP -}; - -static GParamSpec *properties[LAST_PROP]; - -/* - * GObject definitions - */ - -struct _CapheDbusInhibitorPrivate { - /* Properties */ - gchar *name; - /* Internal */ - CapheDbusProxy *proxy; - GType invokator_type; - CapheDbusInvokator *invokator; -}; - -typedef struct _CapheDbusInhibitorPrivate CapheDbusInhibitorPrivate; - -struct _CapheDbusInhibitor { - /* Parent instance structure */ - GObject parent_instance; - /* Private data */ - CapheDbusInhibitorPrivate *priv; -}; - -static void caphe_inhibitor_interface_init(CapheInhibitorInterface *iface); - -G_DEFINE_TYPE_WITH_CODE(CapheDbusInhibitor, caphe_dbus_inhibitor, G_TYPE_OBJECT, - G_ADD_PRIVATE(CapheDbusInhibitor) - G_IMPLEMENT_INTERFACE(CAPHE_TYPE_INHIBITOR, - caphe_inhibitor_interface_init)) - -/* - * Signal handlers - */ - -static void -on_caphe_dbus_proxy_notify_proxy(CapheDbusProxy *caphe_proxy, - GParamSpec *pspec G_GNUC_UNUSED, - CapheDbusInhibitor *self) -{ - CapheDbusInhibitorPrivate *priv = self->priv; - GDBusProxy *dbus_proxy = caphe_dbus_proxy_get_proxy(caphe_proxy); - - /* If the proxy disappeared, we must dispose of the invokator. - * Otherwise, we must create an invokator. - */ - if (dbus_proxy == NULL) { - g_clear_object(&priv->invokator); - - } else { - g_assert(priv->invokator == NULL); - priv->invokator = caphe_dbus_invokator_new(priv->invokator_type, dbus_proxy); - } - - /* Notify that availability changed */ - g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_AVAILABLE]); -} - -/* - * Inhibitor methods - */ - -static gboolean -caphe_dbus_inhibitor_is_inhibited(CapheInhibitor *inhibitor) -{ - CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(inhibitor); - CapheDbusInhibitorPrivate *priv = self->priv; - - if (priv->invokator == NULL) - return FALSE; - - return caphe_dbus_invokator_is_inhibited(priv->invokator); -} - -static void -caphe_dbus_inhibitor_uninhibit(CapheInhibitor *inhibitor) -{ - CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(inhibitor); - CapheDbusInhibitorPrivate *priv = self->priv; - - g_return_if_fail(priv->invokator != NULL); - - caphe_dbus_invokator_uninhibit(priv->invokator); -} - -static gboolean -caphe_dbus_inhibitor_inhibit(CapheInhibitor *inhibitor, const gchar *application, - const gchar *reason, GError **error) -{ - CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(inhibitor); - CapheDbusInhibitorPrivate *priv = self->priv; - - g_return_val_if_fail(application != NULL, FALSE); - g_return_val_if_fail(reason != NULL, FALSE); - g_return_val_if_fail(priv->invokator != NULL, FALSE); - - return caphe_dbus_invokator_inhibit(priv->invokator, application, reason, error); -} - -/* - * Inhibitor property accessors - */ - -static const gchar * -caphe_dbus_inhibitor_get_name(CapheInhibitor *inhibitor) -{ - CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(inhibitor); - CapheDbusInhibitorPrivate *priv = self->priv; - - return priv->name; -} - -static void -caphe_dbus_inhibitor_set_name(CapheInhibitor *inhibitor, const gchar *name) -{ - CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(inhibitor); - CapheDbusInhibitorPrivate *priv = self->priv; - - /* Construct-only property */ - g_assert_null(priv->name); - g_assert_nonnull(name); - priv->name = g_strdup(name); -} - -static gboolean -caphe_dbus_inhibitor_get_available(CapheInhibitor *inhibitor) -{ - CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(inhibitor); - CapheDbusInhibitorPrivate *priv = self->priv; - - return priv->invokator ? TRUE : FALSE; -} - -static void -caphe_dbus_inhibitor_get_property(GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - CapheInhibitor *inhibitor = CAPHE_INHIBITOR(object); - - switch (property_id) { - /* Inhibitor */ - case PROP_NAME: - g_value_set_string(value, caphe_dbus_inhibitor_get_name(inhibitor)); - break; - case PROP_AVAILABLE: - g_value_set_boolean(value, caphe_dbus_inhibitor_get_available(inhibitor)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void -caphe_dbus_inhibitor_set_property(GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - CapheInhibitor *inhibitor = CAPHE_INHIBITOR(object); - - switch (property_id) { - case PROP_NAME: - caphe_dbus_inhibitor_set_name(inhibitor, g_value_get_string(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -/* - * Public methods - */ - -CapheInhibitor * -caphe_dbus_inhibitor_new(const gchar *name) -{ - return g_object_new(CAPHE_TYPE_DBUS_INHIBITOR, - "name", name, - NULL); -} - -/* - * GObject methods - */ - -static void -caphe_dbus_inhibitor_finalize(GObject *object) -{ - CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(object); - CapheDbusInhibitorPrivate *priv = self->priv; - - TRACE("%p", object); - - if (priv->invokator) - g_object_unref(priv->invokator); - - if (priv->proxy) - g_object_unref(priv->proxy); - - g_free(priv->name); - - /* Chain up */ - if (G_OBJECT_CLASS(caphe_dbus_inhibitor_parent_class)->finalize) - G_OBJECT_CLASS(caphe_dbus_inhibitor_parent_class)->finalize(object); -} - -static void -caphe_dbus_inhibitor_constructed(GObject *object) -{ - CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(object); - CapheDbusInhibitorPrivate *priv = self->priv; - - TRACE("%p", object); - - /* Create the dbus proxy */ - if (!g_strcmp0(priv->name, "gnome-session-manager")) { - priv->invokator_type = CAPHE_TYPE_SESSION_DBUS_INVOKATOR; - priv->proxy = caphe_dbus_proxy_new(G_BUS_TYPE_SESSION, - "org.gnome.SessionManager", - "/org/gnome/SessionManager", - "org.gnome.SessionManager"); - - } else if (!g_strcmp0(priv->name, "xfce-session-manager")) { - priv->invokator_type = CAPHE_TYPE_SESSION_DBUS_INVOKATOR; - priv->proxy = caphe_dbus_proxy_new(G_BUS_TYPE_SESSION, - "org.xfce.SessionManager", - "/org/xfce/SessionManager", - "org.xfce.SessionManager"); - - } else if (!g_strcmp0(priv->name, "xdg-portal")) { - priv->invokator_type = CAPHE_TYPE_PORTAL_DBUS_INVOKATOR; - priv->proxy = caphe_dbus_proxy_new(G_BUS_TYPE_SESSION, - "org.freedesktop.portal.Desktop", - "/org/freedesktop/portal/desktop", - "org.freedesktop.portal.Inhibit"); - - } else if (!g_strcmp0(priv->name, "xdg-power-management")) { - /* Also provided by the following names: - * - org.xfce.PowerManager - * - org.kde.Solid.PowerManagement - */ - priv->invokator_type = CAPHE_TYPE_POWER_DBUS_INVOKATOR; - priv->proxy = caphe_dbus_proxy_new(G_BUS_TYPE_SESSION, - "org.freedesktop.PowerManagement", - "/org/freedesktop/PowerManagement/Inhibit", - "org.freedesktop.PowerManagement.Inhibit"); - - } else if (!g_strcmp0(priv->name, "xdg-login1")) { - priv->invokator_type = CAPHE_TYPE_LOGIN_DBUS_INVOKATOR; - priv->proxy = caphe_dbus_proxy_new(G_BUS_TYPE_SYSTEM, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager"); - } else { - g_error("Invalid inhibitor name '%s'", priv->name); - /* Program execution stops here */ - - } - - /* Connect to the 'proxy' signal to be notified as soon as the proxy - * is created. The signal is ensured to be sent once at init time. - */ - g_signal_connect_object(priv->proxy, "notify::proxy", - G_CALLBACK(on_caphe_dbus_proxy_notify_proxy), - self, 0); - - /* Chain up */ - if (G_OBJECT_CLASS(caphe_dbus_inhibitor_parent_class)->constructed) - G_OBJECT_CLASS(caphe_dbus_inhibitor_parent_class)->constructed(object); -} - -static void -caphe_dbus_inhibitor_init(CapheDbusInhibitor *self) -{ - CapheDbusInhibitorPrivate *priv = caphe_dbus_inhibitor_get_instance_private(self); - - TRACE("%p", self); - - /* Set private pointer */ - self->priv = priv; -} - -static void -caphe_dbus_inhibitor_class_init(CapheDbusInhibitorClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - - TRACE("%p", class); - - /* Override GObject methods */ - object_class->finalize = caphe_dbus_inhibitor_finalize; - object_class->constructed = caphe_dbus_inhibitor_constructed; - - /* Install properties */ - object_class->get_property = caphe_dbus_inhibitor_get_property; - object_class->set_property = caphe_dbus_inhibitor_set_property; - - /* Override Inhibitor properties */ - g_object_class_override_property(object_class, PROP_NAME, "name"); - properties[PROP_NAME] = - g_object_class_find_property(object_class, "name"); - - g_object_class_override_property(object_class, PROP_AVAILABLE, "available"); - properties[PROP_AVAILABLE] = - g_object_class_find_property(object_class, "available"); -} - -static void -caphe_inhibitor_interface_init(CapheInhibitorInterface *iface) -{ - /* Implement methods */ - iface->inhibit = caphe_dbus_inhibitor_inhibit; - iface->uninhibit = caphe_dbus_inhibitor_uninhibit; - iface->is_inhibited = caphe_dbus_inhibitor_is_inhibited; - iface->get_name = caphe_dbus_inhibitor_get_name; - iface->get_available = caphe_dbus_inhibitor_get_available; -} diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-dbus-inhibitor.h goodvibes-0.4.2/libcaphe/caphe/caphe-dbus-inhibitor.h --- goodvibes-0.3.6/libcaphe/caphe/caphe-dbus-inhibitor.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-dbus-inhibitor.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __LIBCAPHE_CAPHE_DBUS_INHIBITOR_H__ -#define __LIBCAPHE_CAPHE_DBUS_INHIBITOR_H__ - -#include - -#include "caphe-inhibitor.h" - -/* GObject declarations */ - -#define CAPHE_TYPE_DBUS_INHIBITOR caphe_dbus_inhibitor_get_type() - -G_DECLARE_FINAL_TYPE(CapheDbusInhibitor, caphe_dbus_inhibitor, CAPHE, DBUS_INHIBITOR, GObject) - -/* Property accessors */ - -CapheInhibitor *caphe_dbus_inhibitor_new(const gchar *service_id); - -#endif /* __LIBCAPHE_CAPHE_DBUS_INHIBITOR_H__ */ diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-dbus-invokator.c goodvibes-0.4.2/libcaphe/caphe/caphe-dbus-invokator.c --- goodvibes-0.3.6/libcaphe/caphe/caphe-dbus-invokator.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-dbus-invokator.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,207 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include -#include - -#include "caphe-trace.h" -#include "caphe-dbus-invokator.h" - -/* - * Properties - */ - -enum { - /* Reserved */ - PROP_0, - /* Construct-only properties */ - PROP_PROXY, - /* Total number of properties */ - LAST_PROP -}; - -static GParamSpec *properties[LAST_PROP]; - -/* - * GObject definitions - */ - -struct _CapheDbusInvokatorPrivate { - /* Properties */ - GDBusProxy *proxy; -}; - -typedef struct _CapheDbusInvokatorPrivate CapheDbusInvokatorPrivate; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(CapheDbusInvokator, caphe_dbus_invokator, G_TYPE_OBJECT) - -/* - * Property accessors - */ - -GDBusProxy * -caphe_dbus_invokator_get_proxy(CapheDbusInvokator *self) -{ - CapheDbusInvokatorPrivate *priv = caphe_dbus_invokator_get_instance_private(self); - - return priv->proxy; -} - -static void -caphe_dbus_invokator_set_proxy(CapheDbusInvokator *self, GDBusProxy *proxy) -{ - CapheDbusInvokatorPrivate *priv = caphe_dbus_invokator_get_instance_private(self); - - /* Construct-only property */ - g_assert_null(priv->proxy); - g_assert_nonnull(proxy); - - priv->proxy = g_object_ref(proxy); -} - -static void -caphe_dbus_invokator_get_property(GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - CapheDbusInvokator *self = CAPHE_DBUS_INVOKATOR(object); - - switch (property_id) { - case PROP_PROXY: - g_value_set_object(value, caphe_dbus_invokator_get_proxy(self)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void -caphe_dbus_invokator_set_property(GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - CapheDbusInvokator *self = CAPHE_DBUS_INVOKATOR(object); - - switch (property_id) { - case PROP_PROXY: - caphe_dbus_invokator_set_proxy(self, g_value_get_object(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -/* - * Public methods - */ - -gboolean -caphe_dbus_invokator_is_inhibited(CapheDbusInvokator *self) -{ - g_return_val_if_fail(CAPHE_IS_DBUS_INVOKATOR(self), FALSE); - - return CAPHE_DBUS_INVOKATOR_GET_CLASS(self)->is_inhibited(self); -} - -void -caphe_dbus_invokator_uninhibit(CapheDbusInvokator *self) -{ - g_return_if_fail(CAPHE_IS_DBUS_INVOKATOR(self)); - - return CAPHE_DBUS_INVOKATOR_GET_CLASS(self)->uninhibit(self); -} - -gboolean -caphe_dbus_invokator_inhibit(CapheDbusInvokator *self, const gchar *application, - const gchar *reason, GError **error) -{ - g_return_val_if_fail(CAPHE_IS_DBUS_INVOKATOR(self), FALSE); - - return CAPHE_DBUS_INVOKATOR_GET_CLASS(self)->inhibit(self, application, reason, error); -} - -CapheDbusInvokator * -caphe_dbus_invokator_new(GType invokator_type, GDBusProxy *proxy) -{ - g_return_val_if_fail(g_type_is_a(invokator_type, CAPHE_TYPE_DBUS_INVOKATOR), NULL); - - return g_object_new(invokator_type, "proxy", proxy, NULL); -} - -/* - * GObject methods - */ - -static void -caphe_dbus_invokator_finalize(GObject *object) -{ - CapheDbusInvokator *self = CAPHE_DBUS_INVOKATOR(object); - CapheDbusInvokatorPrivate *priv = caphe_dbus_invokator_get_instance_private(self); - - TRACE("%p", self); - - /* Free resources */ - g_object_unref(priv->proxy); - - /* Chain up */ - if (G_OBJECT_CLASS(caphe_dbus_invokator_parent_class)->finalize) - G_OBJECT_CLASS(caphe_dbus_invokator_parent_class)->finalize(object); -} - -static void -caphe_dbus_invokator_init(CapheDbusInvokator *self) -{ - CapheDbusInvokatorPrivate *priv = caphe_dbus_invokator_get_instance_private(self); - - TRACE("%p", self); - - /* Construct-only properties, initialized later on */ - priv->proxy = NULL; -} - -static void -caphe_dbus_invokator_class_init(CapheDbusInvokatorClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - - TRACE("%p", class); - - /* Override GObject methods */ - object_class->finalize = caphe_dbus_invokator_finalize; - - /* Install properties */ - object_class->get_property = caphe_dbus_invokator_get_property; - object_class->set_property = caphe_dbus_invokator_set_property; - - properties[PROP_PROXY] = - g_param_spec_object("proxy", "Proxy", NULL, - G_TYPE_DBUS_PROXY, - G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties(object_class, LAST_PROP, properties); -} diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-dbus-invokator.h goodvibes-0.4.2/libcaphe/caphe/caphe-dbus-invokator.h --- goodvibes-0.3.6/libcaphe/caphe/caphe-dbus-invokator.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-dbus-invokator.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __LIBCAPHE_CAPHE_DBUS_INVOKATOR_H__ -#define __LIBCAPHE_CAPHE_DBUS_INVOKATOR_H__ - -#include -#include - -/* GObject declarations */ - -#define CAPHE_TYPE_DBUS_INVOKATOR caphe_dbus_invokator_get_type() - -G_DECLARE_DERIVABLE_TYPE(CapheDbusInvokator, caphe_dbus_invokator, CAPHE, DBUS_INVOKATOR, GObject) - -struct _CapheDbusInvokatorClass { - /* Parent class */ - GObjectClass parent_class; - - /* Virtual Methods */ - gboolean (*inhibit) (CapheDbusInvokator *self, - const gchar *application, - const gchar *reason, - GError **error); - void (*uninhibit) (CapheDbusInvokator *self); - gboolean (*is_inhibited)(CapheDbusInvokator *self); -}; - -/* Methods */ - -CapheDbusInvokator *caphe_dbus_invokator_new(GType invokator_type, GDBusProxy *proxy); - -gboolean caphe_dbus_invokator_inhibit (CapheDbusInvokator *self, - const gchar *application, - const gchar *reason, - GError **error); -void caphe_dbus_invokator_uninhibit (CapheDbusInvokator *self); -gboolean caphe_dbus_invokator_is_inhibited(CapheDbusInvokator *self); - -/* Public property accessors */ - -GDBusProxy *caphe_dbus_invokator_get_proxy (CapheDbusInvokator *self); - -#endif /* __LIBCAPHE_CAPHE_DBUS_INVOKATOR_H__ */ diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-dbus-proxy.c goodvibes-0.4.2/libcaphe/caphe/caphe-dbus-proxy.c --- goodvibes-0.3.6/libcaphe/caphe/caphe-dbus-proxy.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-dbus-proxy.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,385 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include - -#include -#include - -#include "caphe-trace.h" -#include "caphe-dbus-proxy.h" - -#define debug(self, fmt, ...) \ - g_debug("[%s]: " fmt, strrchr(self->priv->well_known_name, '.') + 1, ##__VA_ARGS__) - -#define warning(self, fmt, ...) \ - g_warning("[%s]: " fmt, strrchr(self->priv->well_known_name, '.') + 1, ##__VA_ARGS__) - -/* - * Properties - */ - -enum { - /* Reserved */ - PROP_0, - /* Construct-only properties */ - PROP_BUS_TYPE, - PROP_WELL_KNOWN_NAME, - PROP_OBJECT_PATH, - PROP_INTERFACE_NAME, - /* Readable properties */ - PROP_PROXY, - /* Total number of properties */ - LAST_PROP -}; - -static GParamSpec *properties[LAST_PROP]; - -/* - * GObject definitions - */ - -struct _CapheDbusProxyPrivate { - /* Properties */ - GBusType bus_type; - gchar *well_known_name; - gchar *object_path; - gchar *interface_name; - /* Internal */ - guint watch_id; - GDBusProxy *proxy; -}; - -typedef struct _CapheDbusProxyPrivate CapheDbusProxyPrivate; - -struct _CapheDbusProxy { - /* Parent instance structure */ - GObject parent_instance; - /* Private data */ - CapheDbusProxyPrivate *priv; -}; - -G_DEFINE_TYPE_WITH_PRIVATE(CapheDbusProxy, caphe_dbus_proxy, G_TYPE_OBJECT) - -/* - * Property setters - */ - -static void -caphe_dbus_proxy_set_proxy(CapheDbusProxy *self, GDBusProxy *proxy) -{ - CapheDbusProxyPrivate *priv = self->priv; - - g_set_object(&priv->proxy, proxy); - g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_PROXY]); -} - -/* - * Callbacks - */ - -static void -on_proxy_created(GDBusConnection *connection G_GNUC_UNUSED, - GAsyncResult *result, - CapheDbusProxy *self) -{ - GDBusProxy *proxy; - GError *error = NULL; - - debug(self, "Proxy created"); - - proxy = g_dbus_proxy_new_finish(result, &error); - if (error) { - warning(self, "%s", error->message); - g_error_free(error); - } - - caphe_dbus_proxy_set_proxy(self, proxy); -} - -static void -on_name_vanished(GDBusConnection *connection G_GNUC_UNUSED, - const gchar *name, - CapheDbusProxy *self) -{ - debug(self, "Name '%s' vanished", name); - - caphe_dbus_proxy_set_proxy(self, NULL); -} - -static void -on_name_appeared(GDBusConnection *connection, - const gchar *name, - const gchar *name_owner, - CapheDbusProxy *self) -{ - CapheDbusProxyPrivate *priv = self->priv; - - debug(self, "Name '%s' appeared (owner %s)", name, name_owner); - - g_dbus_proxy_new(connection, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - NULL, - priv->well_known_name, - priv->object_path, - priv->interface_name, - NULL, - (GAsyncReadyCallback) on_proxy_created, - self); -} - -/* - * Property accessors - */ - -GDBusProxy * -caphe_dbus_proxy_get_proxy(CapheDbusProxy *self) -{ - CapheDbusProxyPrivate *priv = self->priv; - - return priv->proxy; -} - -static void -caphe_dbus_proxy_set_bus_type(CapheDbusProxy *self, GBusType bus_type) -{ - CapheDbusProxyPrivate *priv = self->priv; - - /* Construct-only property */ - g_assert(priv->bus_type == G_BUS_TYPE_NONE); - g_assert(bus_type != G_BUS_TYPE_NONE); - - priv->bus_type = bus_type; -} - -static void -caphe_dbus_proxy_set_well_known_name(CapheDbusProxy *self, const gchar *name) -{ - CapheDbusProxyPrivate *priv = self->priv; - - /* Construct-only property */ - g_assert_null(priv->well_known_name); - g_assert_nonnull(name); - - priv->well_known_name = g_strdup(name); -} - -static void -caphe_dbus_proxy_set_object_path(CapheDbusProxy *self, const gchar *object_path) -{ - CapheDbusProxyPrivate *priv = self->priv; - - /* Construct-only property */ - g_assert_null(priv->object_path); - g_assert_nonnull(object_path); - - priv->object_path = g_strdup(object_path); -} - -static void -caphe_dbus_proxy_set_interface_name(CapheDbusProxy *self, const gchar *interface_name) -{ - CapheDbusProxyPrivate *priv = self->priv; - - /* Construct-only property */ - g_assert_null(priv->interface_name); - g_assert_nonnull(interface_name); - - priv->interface_name = g_strdup(interface_name); -} - -static void -caphe_dbus_proxy_get_property(GObject *object, - guint property_id, - GValue *value G_GNUC_UNUSED, - GParamSpec *pspec) -{ - CapheDbusProxy *self = CAPHE_DBUS_PROXY(object); - - switch (property_id) { - case PROP_PROXY: - g_value_set_object(value, caphe_dbus_proxy_get_proxy(self)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void -caphe_dbus_proxy_set_property(GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - CapheDbusProxy *self = CAPHE_DBUS_PROXY(object); - - switch (property_id) { - case PROP_BUS_TYPE: - caphe_dbus_proxy_set_bus_type(self, g_value_get_enum(value)); - break; - case PROP_WELL_KNOWN_NAME: - caphe_dbus_proxy_set_well_known_name(self, g_value_get_string(value)); - break; - case PROP_OBJECT_PATH: - caphe_dbus_proxy_set_object_path(self, g_value_get_string(value)); - break; - case PROP_INTERFACE_NAME: - caphe_dbus_proxy_set_interface_name(self, g_value_get_string(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -/* - * Public methods - */ - -CapheDbusProxy * -caphe_dbus_proxy_new(GBusType bus_type, const gchar *well_known_name, - const gchar *object_path, const gchar *interface_name) -{ - return g_object_new(CAPHE_TYPE_DBUS_PROXY, - "bus-type", bus_type, - "well-known-name", well_known_name, - "object-path", object_path, - "interface-name", interface_name, - NULL); -} - -/* - * GObject methods - */ - -static void -caphe_dbus_proxy_finalize(GObject *object) -{ - CapheDbusProxy *self = CAPHE_DBUS_PROXY(object); - CapheDbusProxyPrivate *priv = self->priv; - - TRACE("%p", object); - - if (priv->watch_id) - g_bus_unwatch_name(priv->watch_id); - - if (priv->proxy) - g_object_unref(priv->proxy); - - g_free(priv->well_known_name); - g_free(priv->object_path); - g_free(priv->interface_name); - - /* Chain up */ - if (G_OBJECT_CLASS(caphe_dbus_proxy_parent_class)->finalize) - G_OBJECT_CLASS(caphe_dbus_proxy_parent_class)->finalize(object); -} - -static void -caphe_dbus_proxy_constructed(GObject *object) -{ - CapheDbusProxy *self = CAPHE_DBUS_PROXY(object); - CapheDbusProxyPrivate *priv = self->priv; - - TRACE("%p", object); - - debug(self, "Starting to watch '%s'", priv->well_known_name); - - priv->watch_id = g_bus_watch_name(priv->bus_type, - priv->well_known_name, - G_BUS_NAME_WATCHER_FLAGS_NONE, - (GBusNameAppearedCallback) on_name_appeared, - (GBusNameVanishedCallback) on_name_vanished, - self, - NULL); - - /* Chain up */ - if (G_OBJECT_CLASS(caphe_dbus_proxy_parent_class)->constructed) - G_OBJECT_CLASS(caphe_dbus_proxy_parent_class)->constructed(object); -} - -static void -caphe_dbus_proxy_init(CapheDbusProxy *self) -{ - CapheDbusProxyPrivate *priv = caphe_dbus_proxy_get_instance_private(self); - - TRACE("%p", self); - - /* Construct-only properties, initialized later on */ - priv->bus_type = G_BUS_TYPE_NONE; - priv->well_known_name = NULL; - priv->object_path = NULL; - priv->interface_name = NULL; - - /* Save private pointer */ - self->priv = priv; -} - -static void -caphe_dbus_proxy_class_init(CapheDbusProxyClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - - TRACE("%p", class); - - /* Override GObject methods */ - object_class->finalize = caphe_dbus_proxy_finalize; - object_class->constructed = caphe_dbus_proxy_constructed; - - /* Install properties */ - object_class->get_property = caphe_dbus_proxy_get_property; - object_class->set_property = caphe_dbus_proxy_set_property; - - properties[PROP_BUS_TYPE] = - g_param_spec_enum("bus-type", "Bus type", NULL, - G_TYPE_BUS_TYPE, G_BUS_TYPE_NONE, - G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY); - - properties[PROP_WELL_KNOWN_NAME] = - g_param_spec_string("well-known-name", "Well-known bus name", NULL, - NULL, - G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY); - - properties[PROP_OBJECT_PATH] = - g_param_spec_string("object-path", "Object path", NULL, - NULL, - G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY); - - properties[PROP_INTERFACE_NAME] = - g_param_spec_string("interface-name", "Interface name", NULL, - NULL, - G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY); - - properties[PROP_PROXY] = - g_param_spec_object("proxy", "Proxy", NULL, - G_TYPE_DBUS_PROXY, - G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); - - g_object_class_install_properties(object_class, LAST_PROP, properties); -} diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-dbus-proxy.h goodvibes-0.4.2/libcaphe/caphe/caphe-dbus-proxy.h --- goodvibes-0.3.6/libcaphe/caphe/caphe-dbus-proxy.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-dbus-proxy.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __LIBCAPHE_CAPHE_DBUS_PROXY_H__ -#define __LIBCAPHE_CAPHE_DBUS_PROXY_H__ - -#include -#include - -/* GObject declarations */ - -#define CAPHE_TYPE_DBUS_PROXY caphe_dbus_proxy_get_type() - -G_DECLARE_FINAL_TYPE(CapheDbusProxy, caphe_dbus_proxy, CAPHE, DBUS_PROXY, GObject) - -/* Public methods */ - -CapheDbusProxy *caphe_dbus_proxy_new(GBusType bus_type, const gchar *well_known_name, - const gchar *object_path, const gchar *interface_name); - -/* Property accessors */ - -GDBusProxy *caphe_dbus_proxy_get_proxy(CapheDbusProxy *self); - -#endif /* __LIBCAPHE_CAPHE_DBUS_PROXY_H__ */ diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe.h goodvibes-0.4.2/libcaphe/caphe/caphe.h --- goodvibes-0.3.6/libcaphe/caphe/caphe.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __LIBCAPHE_CAPHE_H__ -#define __LIBCAPHE_CAPHE_H__ - -#include "caphe-cup.h" - -void caphe_init (void); -void caphe_cleanup(void); - -#endif /* __LIBCAPHE_CAPHE_H__ */ diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-inhibitor.c goodvibes-0.4.2/libcaphe/caphe/caphe-inhibitor.c --- goodvibes-0.3.6/libcaphe/caphe/caphe-inhibitor.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-inhibitor.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "caphe-trace.h" -#include "caphe-inhibitor.h" - -/* - * GObject definitions - */ - -G_DEFINE_INTERFACE(CapheInhibitor, caphe_inhibitor, G_TYPE_OBJECT) - -/* - * Methods - */ - -gboolean -caphe_inhibitor_is_inhibited(CapheInhibitor *self) -{ - g_return_val_if_fail(CAPHE_IS_INHIBITOR(self), FALSE); - - return CAPHE_INHIBITOR_GET_IFACE(self)->is_inhibited(self); -} - -void -caphe_inhibitor_uninhibit(CapheInhibitor *self) -{ - g_return_if_fail(CAPHE_IS_INHIBITOR(self)); - - return CAPHE_INHIBITOR_GET_IFACE(self)->uninhibit(self); -} - -gboolean -caphe_inhibitor_inhibit(CapheInhibitor *self, const gchar *application, - const gchar *reason, GError **error) -{ - g_return_val_if_fail(CAPHE_IS_INHIBITOR(self), FALSE); - - return CAPHE_INHIBITOR_GET_IFACE(self)->inhibit(self, application, reason, error); -} - -/* - * Property accessors - */ - -const gchar * -caphe_inhibitor_get_name(CapheInhibitor *self) -{ - g_return_val_if_fail(CAPHE_IS_INHIBITOR(self), FALSE); - - return CAPHE_INHIBITOR_GET_IFACE(self)->get_name(self); -} - -gboolean -caphe_inhibitor_get_available(CapheInhibitor *self) -{ - g_return_val_if_fail(CAPHE_IS_INHIBITOR(self), FALSE); - - return CAPHE_INHIBITOR_GET_IFACE(self)->get_available(self); -} - -/* - * GObject methods - */ - -static void -caphe_inhibitor_default_init(CapheInhibitorInterface *iface) -{ - TRACE("%p", iface); - - g_object_interface_install_property - (iface, g_param_spec_string("name", "Name", NULL, NULL, - G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); - - g_object_interface_install_property - (iface, g_param_spec_boolean("available", "Available", NULL, FALSE, - G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); -} diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-inhibitor.h goodvibes-0.4.2/libcaphe/caphe/caphe-inhibitor.h --- goodvibes-0.3.6/libcaphe/caphe/caphe-inhibitor.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-inhibitor.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __LIBCAPHE_CAPHE_INHIBITOR_H__ -#define __LIBCAPHE_CAPHE_INHIBITOR_H__ - -#include - -/* GObject declarations */ - -#define CAPHE_TYPE_INHIBITOR caphe_inhibitor_get_type() - -G_DECLARE_INTERFACE(CapheInhibitor, caphe_inhibitor, CAPHE, INHIBITOR, GObject) - -struct _CapheInhibitorInterface { - /* Parent class */ - GTypeInterface parent_iface; - - /* Virtual Methods */ - gboolean (*inhibit) (CapheInhibitor *self, - const gchar *application, - const gchar *reason, - GError **error); - void (*uninhibit) (CapheInhibitor *self); - gboolean (*is_inhibited)(CapheInhibitor *self); - - /* Virtual property accessors */ - const gchar *(*get_name) (CapheInhibitor *self); - gboolean (*get_available)(CapheInhibitor *self); -}; - -/* Methods */ - -gboolean caphe_inhibitor_inhibit (CapheInhibitor *self, - const gchar *application, - const gchar *reason, - GError **error); -void caphe_inhibitor_uninhibit (CapheInhibitor *self); -gboolean caphe_inhibitor_is_inhibited(CapheInhibitor *self); - -/* Property accessors */ - -const gchar *caphe_inhibitor_get_name (CapheInhibitor *self); -gboolean caphe_inhibitor_get_available(CapheInhibitor *self); - -#endif /* __LIBCAPHE_CAPHE_INHIBITOR_H__ */ diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-inhibitor-list.c goodvibes-0.4.2/libcaphe/caphe/caphe-inhibitor-list.c --- goodvibes-0.3.6/libcaphe/caphe/caphe-inhibitor-list.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-inhibitor-list.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,254 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include -#include - -#include "caphe-trace.h" -#include "caphe-inhibitor.h" -#include "caphe-dbus-inhibitor.h" - -#include "caphe-inhibitor-list.h" - -/* Inhibitors we know of. This list is ordered by priority. */ - -enum { - CAPHE_GNOME_SESSION_MANAGER_IDX, - CAPHE_XFCE_SESSION_MANAGER_IDX, - CAPHE_XDG_PORTAL_IDX, - CAPHE_XDG_POWER_MANAGEMENT_IDX, - CAPHE_XDG_LOGIN1_IDX, - CAPHE_N_INHIBITORS, -}; - -static const gchar *caphe_inhibitor_ids[] = { - "gnome-session-manager", - "xfce-session-manager", - "xdg-portal", - "xdg-power-management", - "xdg-login1", - NULL -}; - -/* - * Signals - */ - -enum { - SIGNAL_READY, - /* Number of signals */ - SIGNAL_N -}; - -static guint signals[SIGNAL_N]; - -/* - * GObject definitions - */ - -struct _CapheInhibitorListPrivate { - /* List of inhibitors */ - CapheInhibitor *inhibitors[CAPHE_N_INHIBITORS]; - - /* For init-time */ - gboolean inhibitors_ready[CAPHE_N_INHIBITORS]; - gboolean ready; -}; - -typedef struct _CapheInhibitorListPrivate CapheInhibitorListPrivate; - -struct _CapheInhibitorList { - /* Parent instance structure */ - GObject parent_instance; - /* Private data */ - CapheInhibitorListPrivate *priv; -}; - -G_DEFINE_TYPE_WITH_PRIVATE(CapheInhibitorList, caphe_inhibitor_list, G_TYPE_OBJECT) - -/* - * Helpers - */ - -static gint -get_inhibitor_index(CapheInhibitor *inhibitors[], CapheInhibitor *inhibitor) -{ - gint i; - - for (i = 0; i < CAPHE_N_INHIBITORS; i++) { - if (inhibitors[i] == inhibitor) - return i; - } - - return -1; -} - -const gchar * -get_inhibitor_id(CapheInhibitor *inhibitors[], CapheInhibitor *inhibitor) -{ - gint i; - - for (i = 0; i < CAPHE_N_INHIBITORS; i++) { - if (inhibitors[i] == inhibitor) - return caphe_inhibitor_ids[i]; - } - - return "unknown"; -} - -/* - * Signal handlers - */ - -static void -on_inhibitor_notify_available(CapheInhibitor *inhibitor, - GParamSpec *pspec G_GNUC_UNUSED, - CapheInhibitorList *self) -{ - CapheInhibitorListPrivate *priv = self->priv; - gboolean available = caphe_inhibitor_get_available(inhibitor); - - /* Log */ - g_debug("Inhibitor '%s' availability changed: %s", - get_inhibitor_id(priv->inhibitors, inhibitor), - available ? "true" : "false"); - - /* We watch this signals only to know when all the inhibitors are ready */ - if (priv->ready == TRUE) - return; - - gint index; - - /* Update ready list */ - index = get_inhibitor_index(priv->inhibitors, inhibitor); - priv->inhibitors_ready[index] = TRUE; - - /* Check if every inhibitors are ready */ - for (index = 0; index < CAPHE_N_INHIBITORS; index++) { - if (priv->inhibitors_ready[index] == FALSE) - return; - } - - /* We're ready */ - g_debug("All inhibitors ready"); - priv->ready = TRUE; - - g_signal_emit(self, signals[SIGNAL_READY], 0); -} - -/* - * Public methods - */ - -CapheInhibitor ** -caphe_inhibitor_list_get_inhibitors(CapheInhibitorList *self) -{ - CapheInhibitorListPrivate *priv = self->priv; - - return priv->inhibitors; -} - -CapheInhibitorList * -caphe_inhibitor_list_new(void) -{ - return g_object_new(CAPHE_TYPE_INHIBITOR_LIST, NULL); -} - -/* - * GObject methods - */ - -static void -caphe_inhibitor_list_finalize(GObject *object) -{ - CapheInhibitorList *self = CAPHE_INHIBITOR_LIST(object); - CapheInhibitorListPrivate *priv = self->priv; - guint i; - - TRACE("%p", self); - - /* Disconnect and unref inhibitors */ - for (i = 0; i < CAPHE_N_INHIBITORS; i++) { - g_signal_handlers_disconnect_by_data(priv->inhibitors[i], self); - g_object_unref(priv->inhibitors[i]); - } - - /* Chain up */ - if (G_OBJECT_CLASS(caphe_inhibitor_list_parent_class)->finalize) - G_OBJECT_CLASS(caphe_inhibitor_list_parent_class)->finalize(object); -} - -static void -caphe_inhibitor_list_constructed(GObject *object) -{ - CapheInhibitorList *self = CAPHE_INHIBITOR_LIST(object); - CapheInhibitorListPrivate *priv = self->priv; - guint i; - - TRACE("%p", self); - - /* Create inhibitors */ - for (i = 0; i < CAPHE_N_INHIBITORS; i++) { - priv->inhibitors[i] = caphe_dbus_inhibitor_new(caphe_inhibitor_ids[i]); - - g_signal_connect_object(priv->inhibitors[i], "notify::available", - G_CALLBACK(on_inhibitor_notify_available), - self, 0); - } - - /* Chain up */ - if (G_OBJECT_CLASS(caphe_inhibitor_list_parent_class)->constructed) - G_OBJECT_CLASS(caphe_inhibitor_list_parent_class)->constructed(object); -} - -static void -caphe_inhibitor_list_init(CapheInhibitorList *self) -{ - CapheInhibitorListPrivate *priv = caphe_inhibitor_list_get_instance_private(self); - - TRACE("%p", self); - - /* Init some stuff */ - priv->ready = FALSE; - - /* Set private pointer */ - self->priv = priv; -} - -static void -caphe_inhibitor_list_class_init(CapheInhibitorListClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - - TRACE("%p", class); - - /* Override GObject methods */ - object_class->finalize = caphe_inhibitor_list_finalize; - object_class->constructed = caphe_inhibitor_list_constructed; - - /* Signals */ - signals[SIGNAL_READY] = - g_signal_new("ready", G_TYPE_FROM_CLASS(class), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); -} diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-inhibitor-list.h goodvibes-0.4.2/libcaphe/caphe/caphe-inhibitor-list.h --- goodvibes-0.3.6/libcaphe/caphe/caphe-inhibitor-list.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-inhibitor-list.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __LIBCAPHE_CAPHE_INHIBITOR_LIST_H__ -#define __LIBCAPHE_CAPHE_INHIBITOR_LIST_H__ - -#include - -#include "caphe-inhibitor.h" - -/* GObject declarations */ - -#define CAPHE_TYPE_INHIBITOR_LIST caphe_inhibitor_list_get_type() - -G_DECLARE_FINAL_TYPE(CapheInhibitorList, caphe_inhibitor_list, CAPHE, INHIBITOR_LIST, GObject) - -/* Methods */ - -CapheInhibitorList *caphe_inhibitor_list_new (void); -CapheInhibitor **caphe_inhibitor_list_get_inhibitors(CapheInhibitorList *self); - -#endif /* __LIBCAPHE_CAPHE_INHIBITOR_LIST_H__ */ diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-login-dbus-invokator.c goodvibes-0.4.2/libcaphe/caphe/caphe-login-dbus-invokator.c --- goodvibes-0.3.6/libcaphe/caphe/caphe-login-dbus-invokator.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-login-dbus-invokator.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,195 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include -#include -#include - -#include "caphe-trace.h" -#include "caphe-dbus-invokator.h" -#include "caphe-login-dbus-invokator.h" - -/* - * Debug macros - */ - -#define debug(proxy, fmt, ...) \ - g_debug("[%s]: " fmt, \ - proxy ? g_dbus_proxy_get_name(proxy) : "SessionManager", \ - ##__VA_ARGS__) - -/* - * GObject definitions - */ - -struct _CapheLoginDbusInvokatorPrivate { - gint32 fd; -}; - -typedef struct _CapheLoginDbusInvokatorPrivate CapheLoginDbusInvokatorPrivate; - -struct _CapheLoginDbusInvokator { - /* Parent instance structure */ - CapheDbusInvokator parent_instance; - /* Private data */ - CapheLoginDbusInvokatorPrivate *priv; -}; - -G_DEFINE_TYPE_WITH_PRIVATE(CapheLoginDbusInvokator, caphe_login_dbus_invokator, - CAPHE_TYPE_DBUS_INVOKATOR) - -/* - * DbusInvokator methods - */ - -static gboolean -caphe_login_dbus_invokator_is_inhibited(CapheDbusInvokator *dbus_invokator) -{ - CapheLoginDbusInvokator *self = CAPHE_LOGIN_DBUS_INVOKATOR(dbus_invokator); - CapheLoginDbusInvokatorPrivate *priv = self->priv; - - return priv->fd != -1; -} - -static void -caphe_login_dbus_invokator_uninhibit(CapheDbusInvokator *dbus_invokator) -{ - CapheLoginDbusInvokator *self = CAPHE_LOGIN_DBUS_INVOKATOR(dbus_invokator); - CapheLoginDbusInvokatorPrivate *priv = self->priv; - GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); - - if (priv->fd < 0) { - debug(proxy, "Already uninhibited (no fd)"); - return; - } - - close(priv->fd); - priv->fd = -1; - - debug(proxy, "Uninhibited"); -} - -static gboolean -caphe_login_dbus_invokator_inhibit(CapheDbusInvokator *dbus_invokator, - const gchar *application, const gchar *reason, - GError **error) -{ - CapheLoginDbusInvokator *self = CAPHE_LOGIN_DBUS_INVOKATOR(dbus_invokator); - CapheLoginDbusInvokatorPrivate *priv = self->priv; - GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); - GUnixFDList *fd_list = NULL; - gint32 fd_index; - GVariant *res; - - if (priv->fd >= 0) { - debug(proxy, "Already inhibited (fd: %d)", priv->fd); - return TRUE; - } - - if (proxy == NULL) { - debug(proxy, "No proxy"); - return FALSE; - } - - /* - * Documentation at: - * https://www.freedesktop.org/wiki/Software/systemd/inhibit/ - */ - res = g_dbus_proxy_call_with_unix_fd_list_sync(proxy, - "Inhibit", - g_variant_new( - "(ssss)", - "sleep", - application, - reason, - "block"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, /* in_fd_list */ - &fd_list, /* out_fd_list */ - NULL, /* cancellable */ - error); - - if (res == NULL) - return FALSE; - - g_variant_get(res, "(h)", &fd_index); - g_variant_unref(res); - debug(proxy, "Fd index: %d", fd_index); - - priv->fd = g_unix_fd_list_get(fd_list, fd_index, NULL); - g_object_unref(fd_list); - debug(proxy, "Inhibited (fd: %d)", priv->fd); - - return TRUE; -} - -/* - * GObject methods - */ - -static void -caphe_login_dbus_invokator_finalize(GObject *object) -{ - CapheDbusInvokator *dbus_invokator = CAPHE_DBUS_INVOKATOR(object); - - TRACE("%p", object); - - /* Ensure uninhibition */ - caphe_login_dbus_invokator_uninhibit(dbus_invokator); - - if (G_OBJECT_CLASS(caphe_login_dbus_invokator_parent_class)->finalize) - G_OBJECT_CLASS(caphe_login_dbus_invokator_parent_class)->finalize(object); -} - -static void -caphe_login_dbus_invokator_init(CapheLoginDbusInvokator *self) -{ - CapheLoginDbusInvokatorPrivate *priv = - caphe_login_dbus_invokator_get_instance_private(self); - - TRACE("%p", self); - - /* Initialize inhibit file descriptor */ - priv->fd = -1; - - /* Initialize private pointer */ - self->priv = priv; -} - -static void -caphe_login_dbus_invokator_class_init(CapheLoginDbusInvokatorClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - CapheDbusInvokatorClass *dbus_invokator_class = CAPHE_DBUS_INVOKATOR_CLASS(class); - - TRACE("%p", class); - - /* GObject methods */ - object_class->finalize = caphe_login_dbus_invokator_finalize; - - /* Implement methods */ - dbus_invokator_class->inhibit = caphe_login_dbus_invokator_inhibit; - dbus_invokator_class->uninhibit = caphe_login_dbus_invokator_uninhibit; - dbus_invokator_class->is_inhibited = caphe_login_dbus_invokator_is_inhibited; -} diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-login-dbus-invokator.h goodvibes-0.4.2/libcaphe/caphe/caphe-login-dbus-invokator.h --- goodvibes-0.3.6/libcaphe/caphe/caphe-login-dbus-invokator.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-login-dbus-invokator.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __LIBCAPHE_CAPHE_LOGIN_DBUS_INVOKATOR_H__ -#define __LIBCAPHE_CAPHE_LOGIN_DBUS_INVOKATOR_H__ - -#include - -#include "caphe-dbus-invokator.h" - -/* GObject declarations */ - -#define CAPHE_TYPE_LOGIN_DBUS_INVOKATOR caphe_login_dbus_invokator_get_type() - -G_DECLARE_FINAL_TYPE(CapheLoginDbusInvokator, caphe_login_dbus_invokator, - CAPHE, LOGIN_DBUS_INVOKATOR, CapheDbusInvokator) - -/* Methods */ - -CapheDbusInvokator *caphe_login_dbus_invokator_new(void); - -#endif /* __LIBCAPHE_CAPHE_LOGIN_DBUS_INVOKATOR_H__ */ diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-portal-dbus-invokator.c goodvibes-0.4.2/libcaphe/caphe/caphe-portal-dbus-invokator.c --- goodvibes-0.3.6/libcaphe/caphe/caphe-portal-dbus-invokator.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-portal-dbus-invokator.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,198 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include -#include - -#include "caphe-trace.h" -#include "caphe-dbus-invokator.h" -#include "caphe-portal-dbus-invokator.h" - -/* - * Debug macros - */ - -#define debug(proxy, fmt, ...) \ - g_debug("[%s]: " fmt, \ - proxy ? g_dbus_proxy_get_name(proxy) : "Portal", \ - ##__VA_ARGS__) - -/* - * GObject definitions - */ - -struct _CaphePortalDbusInvokatorPrivate { - char *handle; -}; - -typedef struct _CaphePortalDbusInvokatorPrivate CaphePortalDbusInvokatorPrivate; - -struct _CaphePortalDbusInvokator { - /* Parent instance structure */ - CapheDbusInvokator parent_instance; - /* Private data */ - CaphePortalDbusInvokatorPrivate *priv; -}; - -G_DEFINE_TYPE_WITH_PRIVATE(CaphePortalDbusInvokator, caphe_portal_dbus_invokator, - CAPHE_TYPE_DBUS_INVOKATOR) - -/* - * DbusInvokator methods - */ - -static gboolean -caphe_portal_dbus_invokator_is_inhibited(CapheDbusInvokator *dbus_invokator) -{ - CaphePortalDbusInvokator *self = CAPHE_PORTAL_DBUS_INVOKATOR(dbus_invokator); - CaphePortalDbusInvokatorPrivate *priv = self->priv; - - return priv->handle != NULL; -} - -static void -caphe_portal_dbus_invokator_uninhibit(CapheDbusInvokator *dbus_invokator) -{ - CaphePortalDbusInvokator *self = CAPHE_PORTAL_DBUS_INVOKATOR(dbus_invokator); - CaphePortalDbusInvokatorPrivate *priv = self->priv; - GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); - - if (priv->handle == NULL) { - debug(proxy, "Not inhibited (no handle)"); - return; - } - - if (proxy == NULL) { - debug(proxy, "No proxy"); - return; - } - - g_dbus_connection_call(g_dbus_proxy_get_connection(proxy), - "org.freedesktop.portal.Desktop", - priv->handle, - "org.freedesktop.portal.Request", - "Close", - g_variant_new("()"), - G_VARIANT_TYPE_UNIT, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, NULL, NULL); - - g_free(priv->handle); - priv->handle = NULL; - - debug(proxy, "Uninhibited"); -} - -static gboolean -caphe_portal_dbus_invokator_inhibit(CapheDbusInvokator *dbus_invokator, - const gchar *application G_GNUC_UNUSED, - const gchar *reason, GError **error) -{ - CaphePortalDbusInvokator *self = CAPHE_PORTAL_DBUS_INVOKATOR(dbus_invokator); - CaphePortalDbusInvokatorPrivate *priv = self->priv; - GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); - GVariant *res; - - if (priv->handle) { - debug(proxy, "Already inhibited (handle: %s)", priv->handle); - return TRUE; - } - - if (proxy == NULL) { - debug(proxy, "No proxy"); - return FALSE; - } - - GVariantBuilder options; - g_variant_builder_init(&options, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add(&options, "{sv}", "reason", g_variant_new_string(reason)); - res = g_dbus_proxy_call_sync(proxy, - "Inhibit", - g_variant_new("(su@a{sv})", - "", /* window */ - 4, - g_variant_builder_end(&options)), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - error); - - if (res == NULL) - return FALSE; - - g_variant_get(res, "(o)", &priv->handle); - g_variant_unref(res); - - debug(proxy, "Inhibited (handle: %s)", priv->handle); - - return TRUE; -} - -/* - * GObject methods - */ - -static void -caphe_portal_dbus_invokator_finalize(GObject *object) -{ - CapheDbusInvokator *dbus_invokator = CAPHE_DBUS_INVOKATOR(object); - - TRACE("%p", object); - - /* Ensure uninhibition */ - caphe_portal_dbus_invokator_uninhibit(dbus_invokator); - - /* Chain up */ - if (G_OBJECT_CLASS(caphe_portal_dbus_invokator_parent_class)->finalize) - G_OBJECT_CLASS(caphe_portal_dbus_invokator_parent_class)->finalize(object); -} - -static void -caphe_portal_dbus_invokator_init(CaphePortalDbusInvokator *self) -{ - CaphePortalDbusInvokatorPrivate *priv = - caphe_portal_dbus_invokator_get_instance_private(self); - - TRACE("%p", self); - - /* Initialize private pointer */ - self->priv = priv; -} - -static void -caphe_portal_dbus_invokator_class_init(CaphePortalDbusInvokatorClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - CapheDbusInvokatorClass *dbus_invokator_class = CAPHE_DBUS_INVOKATOR_CLASS(class); - - TRACE("%p", class); - - /* GObject methods */ - object_class->finalize = caphe_portal_dbus_invokator_finalize; - - /* Implement methods */ - dbus_invokator_class->inhibit = caphe_portal_dbus_invokator_inhibit; - dbus_invokator_class->uninhibit = caphe_portal_dbus_invokator_uninhibit; - dbus_invokator_class->is_inhibited = caphe_portal_dbus_invokator_is_inhibited; -} diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-portal-dbus-invokator.h goodvibes-0.4.2/libcaphe/caphe/caphe-portal-dbus-invokator.h --- goodvibes-0.3.6/libcaphe/caphe/caphe-portal-dbus-invokator.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-portal-dbus-invokator.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __LIBCAPHE_CAPHE_PORTAL_DBUS_INVOKATOR_H__ -#define __LIBCAPHE_CAPHE_PORTAL_DBUS_INVOKATOR_H__ - -#include - -#include "caphe-dbus-invokator.h" - -/* GObject declarations */ - -#define CAPHE_TYPE_PORTAL_DBUS_INVOKATOR caphe_portal_dbus_invokator_get_type() - -G_DECLARE_FINAL_TYPE(CaphePortalDbusInvokator, caphe_portal_dbus_invokator, - CAPHE, PORTAL_DBUS_INVOKATOR, CapheDbusInvokator) - -/* Methods */ - -CapheDbusInvokator *caphe_portal_dbus_invokator_new(void); - -#endif /* __LIBCAPHE_CAPHE_PORTAL_DBUS_INVOKATOR_H__ */ diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-power-dbus-invokator.c goodvibes-0.4.2/libcaphe/caphe/caphe-power-dbus-invokator.c --- goodvibes-0.3.6/libcaphe/caphe/caphe-power-dbus-invokator.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-power-dbus-invokator.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,191 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include -#include - -#include "caphe-trace.h" -#include "caphe-dbus-invokator.h" -#include "caphe-power-dbus-invokator.h" - -/* - * Debug macros - */ - - -#define debug(proxy, fmt, ...) \ - g_debug("[%s]: " fmt, \ - proxy ? g_dbus_proxy_get_name(proxy) : "PowerManagement", \ - ##__VA_ARGS__) - -/* - * GObject definitions - */ - -struct _CaphePowerDbusInvokatorPrivate { - guint32 cookie; -}; - -typedef struct _CaphePowerDbusInvokatorPrivate CaphePowerDbusInvokatorPrivate; - -struct _CaphePowerDbusInvokator { - /* Parent instance structure */ - CapheDbusInvokator parent_instance; - /* Private data */ - CaphePowerDbusInvokatorPrivate *priv; -}; - -G_DEFINE_TYPE_WITH_PRIVATE(CaphePowerDbusInvokator, caphe_power_dbus_invokator, - CAPHE_TYPE_DBUS_INVOKATOR) - -/* - * DbusInvokator methods - */ - -static gboolean -caphe_power_dbus_invokator_is_inhibited(CapheDbusInvokator *dbus_invokator) -{ - CaphePowerDbusInvokator *self = CAPHE_POWER_DBUS_INVOKATOR(dbus_invokator); - CaphePowerDbusInvokatorPrivate *priv = self->priv; - - return priv->cookie != 0; -} - -static void -caphe_power_dbus_invokator_uninhibit(CapheDbusInvokator *dbus_invokator) -{ - CaphePowerDbusInvokator *self = CAPHE_POWER_DBUS_INVOKATOR(dbus_invokator); - CaphePowerDbusInvokatorPrivate *priv = self->priv; - GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); - - if (priv->cookie == 0) { - debug(proxy, "Not inhibited (no cookie)"); - return; - } - - if (proxy == NULL) { - debug(proxy, "No proxy"); - return; - } - - g_dbus_proxy_call(proxy, - "UnInhibit", - g_variant_new("(u)", - priv->cookie), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, NULL, NULL); - - priv->cookie = 0; - - debug(proxy, "Uninhibited"); -} - -static gboolean -caphe_power_dbus_invokator_inhibit(CapheDbusInvokator *dbus_invokator, - const gchar *application, const gchar *reason, - GError **error) -{ - CaphePowerDbusInvokator *self = CAPHE_POWER_DBUS_INVOKATOR(dbus_invokator); - CaphePowerDbusInvokatorPrivate *priv = self->priv; - GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); - GVariant *res; - - if (priv->cookie != 0) { - debug(proxy, "Already inhibited (cookie: %u)", priv->cookie); - return TRUE; - } - - if (proxy == NULL) { - debug(proxy, "No proxy"); - return FALSE; - } - - res = g_dbus_proxy_call_sync(proxy, - "Inhibit", - g_variant_new("(ss)", - application, - reason), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - error); - - if (res == NULL) - return FALSE; - - g_variant_get(res, "(u)", &priv->cookie); - g_variant_unref(res); - - debug(proxy, "Inhibited (cookie: %u)", priv->cookie); - - return TRUE; -} - -/* - * GObject methods - */ - -static void -caphe_power_dbus_invokator_finalize(GObject *object) -{ - CapheDbusInvokator *dbus_invokator = CAPHE_DBUS_INVOKATOR(object); - - TRACE("%p", object); - - /* Ensure uninhibition */ - caphe_power_dbus_invokator_uninhibit(dbus_invokator); - - /* Chain up */ - if (G_OBJECT_CLASS(caphe_power_dbus_invokator_parent_class)->finalize) - G_OBJECT_CLASS(caphe_power_dbus_invokator_parent_class)->finalize(object); -} - -static void -caphe_power_dbus_invokator_init(CaphePowerDbusInvokator *self) -{ - CaphePowerDbusInvokatorPrivate *priv = - caphe_power_dbus_invokator_get_instance_private(self); - - TRACE("%p", self); - - /* Initialize private pointer */ - self->priv = priv; -} - -static void -caphe_power_dbus_invokator_class_init(CaphePowerDbusInvokatorClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - CapheDbusInvokatorClass *dbus_invokator_class = CAPHE_DBUS_INVOKATOR_CLASS(class); - - TRACE("%p", class); - - /* GObject methods */ - object_class->finalize = caphe_power_dbus_invokator_finalize; - - /* Implement methods */ - dbus_invokator_class->inhibit = caphe_power_dbus_invokator_inhibit; - dbus_invokator_class->uninhibit = caphe_power_dbus_invokator_uninhibit; - dbus_invokator_class->is_inhibited = caphe_power_dbus_invokator_is_inhibited; -} diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-power-dbus-invokator.h goodvibes-0.4.2/libcaphe/caphe/caphe-power-dbus-invokator.h --- goodvibes-0.3.6/libcaphe/caphe/caphe-power-dbus-invokator.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-power-dbus-invokator.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __LIBCAPHE_CAPHE_POWER_DBUS_INVOKATOR_H__ -#define __LIBCAPHE_CAPHE_POWER_DBUS_INVOKATOR_H__ - -#include - -#include "caphe-dbus-invokator.h" - -/* GObject declarations */ - -#define CAPHE_TYPE_POWER_DBUS_INVOKATOR caphe_power_dbus_invokator_get_type() - -G_DECLARE_FINAL_TYPE(CaphePowerDbusInvokator, caphe_power_dbus_invokator, - CAPHE, POWER_DBUS_INVOKATOR, CapheDbusInvokator) - -/* Methods */ - -CapheDbusInvokator *caphe_power_dbus_invokator_new(void); - -#endif /* __LIBCAPHE_CAPHE_POWER_DBUS_INVOKATOR_H__ */ diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-session-dbus-invokator.c goodvibes-0.4.2/libcaphe/caphe/caphe-session-dbus-invokator.c --- goodvibes-0.3.6/libcaphe/caphe/caphe-session-dbus-invokator.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-session-dbus-invokator.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,206 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include -#include - -#include "caphe-trace.h" -#include "caphe-dbus-invokator.h" -#include "caphe-session-dbus-invokator.h" - -/* - * Debug macros - */ - -#define debug(proxy, fmt, ...) \ - g_debug("[%s]: " fmt, \ - proxy ? g_dbus_proxy_get_name(proxy) : "SessionManager", \ - ##__VA_ARGS__) - -/* - * GObject definitions - */ - -struct _CapheSessionDbusInvokatorPrivate { - guint32 cookie; -}; - -typedef struct _CapheSessionDbusInvokatorPrivate CapheSessionDbusInvokatorPrivate; - -struct _CapheSessionDbusInvokator { - /* Parent instance structure */ - CapheDbusInvokator parent_instance; - /* Private data */ - CapheSessionDbusInvokatorPrivate *priv; -}; - -G_DEFINE_TYPE_WITH_PRIVATE(CapheSessionDbusInvokator, caphe_session_dbus_invokator, - CAPHE_TYPE_DBUS_INVOKATOR) - -/* - * DbusInvokator methods - */ - -static gboolean -caphe_session_dbus_invokator_is_inhibited(CapheDbusInvokator *dbus_invokator) -{ - CapheSessionDbusInvokator *self = CAPHE_SESSION_DBUS_INVOKATOR(dbus_invokator); - CapheSessionDbusInvokatorPrivate *priv = self->priv; - - return priv->cookie != 0; -} - -static void -caphe_session_dbus_invokator_uninhibit(CapheDbusInvokator *dbus_invokator) -{ - CapheSessionDbusInvokator *self = CAPHE_SESSION_DBUS_INVOKATOR(dbus_invokator); - CapheSessionDbusInvokatorPrivate *priv = self->priv; - GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); - - if (priv->cookie == 0) { - debug(proxy, "Not inhibited (no cookie)"); - return; - } - - if (proxy == NULL) { - debug(proxy, "No proxy"); - return; - } - - g_dbus_proxy_call(proxy, - "Uninhibit", - g_variant_new("(u)", - priv->cookie), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, NULL, NULL); - - priv->cookie = 0; - - debug(proxy, "Uninhibited"); -} - -static gboolean -caphe_session_dbus_invokator_inhibit(CapheDbusInvokator *dbus_invokator, - const gchar *application, const gchar *reason, - GError **error) -{ - CapheSessionDbusInvokator *self = CAPHE_SESSION_DBUS_INVOKATOR(dbus_invokator); - CapheSessionDbusInvokatorPrivate *priv = self->priv; - GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); - GVariant *res; - - if (priv->cookie != 0) { - debug(proxy, "Already inhibited (cookie: %u)", priv->cookie); - return TRUE; - } - - if (proxy == NULL) { - debug(proxy, "No proxy"); - return FALSE; - } - - /* - * From org.gnome.SessionManager.xml, the 4 arguments to pass are: - * - app_id The application identifier - * - toplevel_xid The toplevel X window identifier - * - reason The reason for the inhibit - * - flags Flags that specify what should be inhibited - * - * The flags parameter must include at least one of the following: - * - 1 Inhibit logging out - * - 2 Inhibit user switching - * - 4 Inhibit suspending the session or computer - * - 8 Inhibit the session being marked as idle - * - 16 Inhibit auto-mounting removable media for the session - */ - res = g_dbus_proxy_call_sync(proxy, - "Inhibit", - g_variant_new("(susu)", - application, - 0, - reason, - 4), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - error); - - if (res == NULL) - return FALSE; - - g_variant_get(res, "(u)", &priv->cookie); - g_variant_unref(res); - - debug(proxy, "Inhibited (cookie: %u)", priv->cookie); - - return TRUE; -} - -/* - * GObject methods - */ - -static void -caphe_session_dbus_invokator_finalize(GObject *object) -{ - CapheDbusInvokator *dbus_invokator = CAPHE_DBUS_INVOKATOR(object); - - TRACE("%p", object); - - /* Ensure uninhibition */ - caphe_session_dbus_invokator_uninhibit(dbus_invokator); - - /* Chain up */ - if (G_OBJECT_CLASS(caphe_session_dbus_invokator_parent_class)->finalize) - G_OBJECT_CLASS(caphe_session_dbus_invokator_parent_class)->finalize(object); -} - -static void -caphe_session_dbus_invokator_init(CapheSessionDbusInvokator *self) -{ - CapheSessionDbusInvokatorPrivate *priv = - caphe_session_dbus_invokator_get_instance_private(self); - - TRACE("%p", self); - - /* Initialize private pointer */ - self->priv = priv; -} - -static void -caphe_session_dbus_invokator_class_init(CapheSessionDbusInvokatorClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - CapheDbusInvokatorClass *dbus_invokator_class = CAPHE_DBUS_INVOKATOR_CLASS(class); - - TRACE("%p", class); - - /* GObject methods */ - object_class->finalize = caphe_session_dbus_invokator_finalize; - - /* Implement methods */ - dbus_invokator_class->inhibit = caphe_session_dbus_invokator_inhibit; - dbus_invokator_class->uninhibit = caphe_session_dbus_invokator_uninhibit; - dbus_invokator_class->is_inhibited = caphe_session_dbus_invokator_is_inhibited; -} diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-session-dbus-invokator.h goodvibes-0.4.2/libcaphe/caphe/caphe-session-dbus-invokator.h --- goodvibes-0.3.6/libcaphe/caphe/caphe-session-dbus-invokator.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-session-dbus-invokator.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __LIBCAPHE_CAPHE_SESSION_DBUS_INVOKATOR_H__ -#define __LIBCAPHE_CAPHE_SESSION_DBUS_INVOKATOR_H__ - -#include - -#include "caphe-dbus-invokator.h" - -/* GObject declarations */ - -#define CAPHE_TYPE_SESSION_DBUS_INVOKATOR caphe_session_dbus_invokator_get_type() - -G_DECLARE_FINAL_TYPE(CapheSessionDbusInvokator, caphe_session_dbus_invokator, - CAPHE, SESSION_DBUS_INVOKATOR, CapheDbusInvokator) - -/* Methods */ - -CapheDbusInvokator *caphe_session_dbus_invokator_new(void); - -#endif /* __LIBCAPHE_CAPHE_SESSION_DBUS_INVOKATOR_H__ */ diff -Nru goodvibes-0.3.6/libcaphe/caphe/caphe-trace.h goodvibes-0.4.2/libcaphe/caphe/caphe-trace.h --- goodvibes-0.3.6/libcaphe/caphe/caphe-trace.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/caphe-trace.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __LIBCAPHE_CAPHE_TRACE_H__ -#define __LIBCAPHE_CAPHE_TRACE_H__ - -#include - -#ifdef ENABLE_TRACE -#define CAPHE_TRACE_ENABLED 1 -#else -#define CAPHE_TRACE_ENABLED 0 -#endif - -#define TRACE(fmt, ...) \ - do { \ - if (CAPHE_TRACE_ENABLED) \ - g_debug("-> %s(" fmt ")", __func__, ##__VA_ARGS__); \ - } while (0) - -#endif /* __LIBCAPHE_CAPHE_TRACE_H__ */ diff -Nru goodvibes-0.3.6/libcaphe/caphe/Makefile.am goodvibes-0.4.2/libcaphe/caphe/Makefile.am --- goodvibes-0.3.6/libcaphe/caphe/Makefile.am 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/caphe/Makefile.am 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -# Process this file with automake to produce Makefile.in - -# ----------------------------------------------------- # -# Libcaphe # -# ----------------------------------------------------- # - -libcaphe_sources = \ - caphe.c caphe.h \ - caphe-cup.c caphe-cup.h \ - caphe-dbus-inhibitor.c caphe-dbus-inhibitor.h \ - caphe-dbus-invokator.c caphe-dbus-invokator.h \ - caphe-dbus-proxy.c caphe-dbus-proxy.h \ - caphe-inhibitor.c caphe-inhibitor.h \ - caphe-inhibitor-list.c caphe-inhibitor-list.h \ - caphe-login-dbus-invokator.c caphe-login-dbus-invokator.h \ - caphe-portal-dbus-invokator.c caphe-portal-dbus-invokator.h \ - caphe-power-dbus-invokator.c caphe-power-dbus-invokator.h \ - caphe-session-dbus-invokator.c caphe-session-dbus-invokator.h \ - caphe-trace.h - -libcaphe_cflags = \ - -DG_LOG_DOMAIN=\"Caphe\" \ - $(GLIB_CFLAGS) - -#libcaphe_cflags += -DENABLE_TRACE - -# ----------------------------------------------------- # -# Static Library # -# ----------------------------------------------------- # - -noinst_LIBRARIES = libcaphe.a - -libcaphe_a_SOURCES = $(libcaphe_sources) -libcaphe_a_CFLAGS = $(libcaphe_cflags) diff -Nru goodvibes-0.3.6/libcaphe/COPYING goodvibes-0.4.2/libcaphe/COPYING --- goodvibes-0.3.6/libcaphe/COPYING 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/COPYING 1970-01-01 00:00:00.000000000 +0000 @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff -Nru goodvibes-0.3.6/libcaphe/Makefile.am goodvibes-0.4.2/libcaphe/Makefile.am --- goodvibes-0.3.6/libcaphe/Makefile.am 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/Makefile.am 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -SUBDIRS = caphe tests diff -Nru goodvibes-0.3.6/libcaphe/README.md goodvibes-0.4.2/libcaphe/README.md --- goodvibes-0.3.6/libcaphe/README.md 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -Libcaphe -======== - -Libcaphe is a little library that inhibits sleep/suspend. - -You use it in your application if you want to prevent the system from going to -sleep. A typical use-case is for audio/video players, who might want to inhibit -sleep while playing. - -The code is inspired by [Caffeine-ng](https://gitlab.com/hobarrera/caffeine-ng). - -Libcaphe will work if one of the following D-Bus services is present on your -system: - -- org.gnome.SessionManager -- org.xfce.SessionManager -- org.freedesktop.PowerManagement -- org.freedesktop.login1 - -Notice that the prefered way to inhibit for GTK+ applications is to use -`gtk_application_inhibit()`. I use this library mainly to support old systems -that rely on `org.freedesktop.PowerManagement`, which has been deprecated a -while ago, but is still widely used. - - - -License -------- - -Copyright (C) 2016-2017 Arnaud Rebillout . - -Libcaphe is distributed under the GNU General Public License, either version 3, -or (at your option) any later version. See [LICENSE](LICENSE) for more details. - - - -About the name --------------- - -"Cà phê" is the Vietnamese for coffee. - -At the moment of this writing, Vietnam is the second largest producer in the -world after Brazil, and I thought the world ought to know :) diff -Nru goodvibes-0.3.6/libcaphe/tests/main.c goodvibes-0.4.2/libcaphe/tests/main.c --- goodvibes-0.3.6/libcaphe/tests/main.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/tests/main.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,188 +0,0 @@ -/* - * Libcaphe - * - * Copyright (C) 2016-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * Compilation: - * packages="glib-2.0 gio-2.0 gio-unix-2.0" - * gcc $(pkg-config --cflags --libs $packages) *.c -o main - * gcc $(pkg-config --cflags --libs $packages) -DENABLE_TRACE *.c -o main - * - * Execution: - * G_MESSAGES_DEBUG=all ./main - */ - -#include -#include - -#include -#include -#include - -#include "caphe/caphe.h" - -#define INHIBIT_REASON "Ice-coffee with milk" - -#define print(fmt, ...) g_print(fmt "\n", ##__VA_ARGS__) - -static GMainLoop *main_loop; - -static void -on_caphe_notify_inhibitor(CapheCup *caphe, - GParamSpec *pspec G_GNUC_UNUSED, - gpointer user_data G_GNUC_UNUSED) -{ - CapheInhibitor *inhibitor = caphe_cup_get_inhibitor(caphe); - - if (inhibitor) - print("Inhibited with inhibitor: %s", caphe_inhibitor_get_name(inhibitor)); - else - print("Uninhibited"); -} - -static gboolean -on_stress_step_4(CapheCup *caphe) -{ - if (!caphe_cup_is_inhibited(caphe)) - g_error("Should be inhibited !"); - - return G_SOURCE_REMOVE; -} - -static gboolean -on_stress_step_3(CapheCup *caphe) -{ - if (!caphe_cup_is_inhibited(caphe)) - g_error("Should be inhibited !"); - - print("Sending inhibit request for a different reason"); - caphe_cup_inhibit(caphe, "Expresso"); - - print("Waiting 1 sec. Expect inhibited."); - g_timeout_add_seconds(1, (GSourceFunc) on_stress_step_4, caphe); - - return G_SOURCE_REMOVE; -} - -static gboolean -on_stress_step_2(CapheCup *caphe) -{ - if (caphe_cup_is_inhibited(caphe)) - g_error("Shouldn't be inhibited !"); - - print("Sending batch of requests."); - caphe_cup_uninhibit(caphe); - caphe_cup_inhibit(caphe, INHIBIT_REASON); - caphe_cup_inhibit(caphe, INHIBIT_REASON "dfdf"); - caphe_cup_uninhibit(caphe); - caphe_cup_inhibit(caphe, INHIBIT_REASON); - - print("Waiting 1 sec. Expect inhibited."); - g_timeout_add_seconds(1, (GSourceFunc) on_stress_step_3, caphe); - - return G_SOURCE_REMOVE; -} - -static gboolean -when_idle_stress(CapheCup *caphe) -{ - print("Sending 1st batch of requests."); - caphe_cup_inhibit(caphe, INHIBIT_REASON); - caphe_cup_inhibit(caphe, INHIBIT_REASON); - caphe_cup_uninhibit(caphe); - caphe_cup_inhibit(caphe, INHIBIT_REASON); - caphe_cup_uninhibit(caphe); - - print("Waiting 1 second. Expect uninhibited."); - g_timeout_add_seconds(1, (GSourceFunc) on_stress_step_2, caphe); - - return G_SOURCE_REMOVE; -} - -static gboolean -when_idle_inhibit(CapheCup *caphe) -{ - print("Inhibiting..."); - caphe_cup_inhibit(caphe, INHIBIT_REASON); - - return G_SOURCE_REMOVE; -} - -static gboolean -sigint_handler(gpointer user_data G_GNUC_UNUSED) -{ - g_main_loop_quit(main_loop); - - return FALSE; -} - -static void -print_usage(const char *progname) -{ - print("Usage: %s ", progname); -} - -int -main(int argc, char *argv[]) -{ - CapheCup *caphe; - GSourceFunc idle_func; - - /* Process input arguments */ - if (argc == 1 || argc > 2) { - print_usage(argv[0]); - exit(EXIT_FAILURE); - } - - if (!g_strcmp0(argv[1], "inhibit")) - idle_func = (GSourceFunc) when_idle_inhibit; - else if (!g_strcmp0(argv[1], "stress")) - idle_func = (GSourceFunc) when_idle_stress; - else { - print_usage(argv[0]); - exit(EXIT_FAILURE); - } - - /* Init */ - caphe_init(); - caphe = caphe_cup_get_default(); - g_signal_connect(caphe, "notify::inhibitor", G_CALLBACK(on_caphe_notify_inhibitor), NULL); - - /* Add idle function. Priorities to try: - * - G_PRIORITY_LOW - * - G_PRIORITY_HIGH - */ - g_idle_add_full(G_PRIORITY_LOW, idle_func, caphe, NULL); - - /* Be ready to catch interruptions */ - g_unix_signal_add(SIGINT, sigint_handler, NULL); - - /* Main loop */ - print("-- Running the main loop --"); - main_loop = g_main_loop_new(NULL, FALSE); - g_main_loop_run(main_loop); - - /* Cleanup */ - print("-- Main loop exited --"); - g_main_loop_unref(main_loop); - caphe_cleanup(); - - return EXIT_SUCCESS; -} diff -Nru goodvibes-0.3.6/libcaphe/tests/Makefile.am goodvibes-0.4.2/libcaphe/tests/Makefile.am --- goodvibes-0.3.6/libcaphe/tests/Makefile.am 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/libcaphe/tests/Makefile.am 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -noinst_PROGRAMS = caphe-test - -caphe_test_SOURCES = \ - main.c - -caphe_test_CPPFLAGS = \ - $(GLIB_CFLAGS) \ - -I.. - -caphe_test_LDADD = \ - ../caphe/libcaphe.a \ - $(GLIB_LIBS) - diff -Nru goodvibes-0.3.6/m4/gv-add-global-var.m4 goodvibes-0.4.2/m4/gv-add-global-var.m4 --- goodvibes-0.3.6/m4/gv-add-global-var.m4 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/m4/gv-add-global-var.m4 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -# gv-add-global-var.m4 -# -# Copyright (C) 2015-2017 Arnaud Rebillout -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# GV_ADD_GLOBAL_VAR(VARIABLE, VALUE) -# ------------------------------------------------------- -# Create a variable at a very global scope. It can be used everywhere: -# - in the configure.ac -# - in C files (AC_DEFINE) -# - in output files (AC_SUBST) -AC_DEFUN([GV_ADD_GLOBAL_VAR], [ - $1=$2 - AC_DEFINE($1,$2,$3) - AC_SUBST($1) -]) diff -Nru goodvibes-0.3.6/m4/gv-feature.m4 goodvibes-0.4.2/m4/gv-feature.m4 --- goodvibes-0.3.6/m4/gv-feature.m4 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/m4/gv-feature.m4 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -# gv-feature.m4 -# -# Copyright (C) 2015-2017 Arnaud Rebillout -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# GV_FEATURE_ENABLE(FEATURE, FEATURE-NAME, DEFAULT-VALUE) -# ------------------------------------------------------- -# Allow user to decide whether an optional feature should be built. -# This macro simply sets the variable 'enable_FEATURE' to: -# - 'yes' if the feature was enabled by user. -# - 'no' if the feature was disabled by user. -# - 'DEFAULT-VALUE' if the feature was not set by user. -# Possible values are: 'yes', 'no', 'auto'. -# 'auto' makes sense only if GV_FEATURE_PKG_CHECK() -# is invoked afterward. -# Moreover, this macro outputs a line to report what's going on. -AC_DEFUN([GV_FEATURE_ENABLE], [ - AC_MSG_CHECKING([whether to enable $2]) - AC_ARG_ENABLE([$1], AS_HELP_STRING([--enable-translit($1, [_], [-])], [Enable $2])) - AS_IF([test "$enable_$1" = ""], [enable_$1=$3]) - AC_MSG_RESULT([$enable_$1]) -]) - -# GV_FEATURE_PKG_CHECK(FEATURE, VARIABLE-PREFIX, MODULES) -# ------------------------------------------------------- -# Check modules needed for a given feature. -# Assume the existence of the variable 'enable_FEATURE', -# which value dictates the behavior of this macro: -# - 'auto' invoke PKG_CHECK_EXISTS() and modify the variable -# 'enable_FEATURE' depending on the result. -# - 'yes' invoke PKG_CHECK_MODULES(). -# - * do nothing. -# Moreover, this macro outputs lines to report what's going on -# (this is done by the underlying PKG_CHECK calls). -AC_DEFUN([GV_FEATURE_PKG_CHECK], [ - AS_IF([test "$enable_$1" = "auto"], [ - AC_MSG_CHECKING([for $2 existence]) - PKG_CHECK_EXISTS([$3], [enable_$1=yes], [enable_$1=no]) - AC_MSG_RESULT([$enable_$1]) - ]) - AS_IF([test "$enable_$1" = "yes"], [ - PKG_CHECK_MODULES([$2], [$3]) - ]) -]) diff -Nru goodvibes-0.3.6/MAINTAINING.md goodvibes-0.4.2/MAINTAINING.md --- goodvibes-0.3.6/MAINTAINING.md 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/MAINTAINING.md 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,190 @@ +MAINTAINING +=========== + + + +Updating translations +--------------------- + +Before every release, it's time to update everything regarding translations, so +that translators have a chance to do their homework ! + +First, ensure that the file `po/POTFILES` is still up to date. This is still a +manual process, but it wouldn't be that hard to write a little script. + +Then, and before modifying the po files on our side, synchronize with Weblate +and lock it. We can do it either via the web interface, either via the client. + + # Lock Weblate translation + wlc lock + # Make Weblate push its changes to the git repo + wlc push + # Pull changes from the git repo to your local copy + git pull + +Then, update the *translation template*, aka. `po/goodvibes.pot`, along with +the *message catalogs*, aka. the po files. + + # Update the pot file and the po files + [ -d build ] || meson build + ninja -C build goodvibes-pot + ninja -C build goodvibes-update-po + + # Commit changes + git add po/*.{po,pot} + git commit -m"i18n: Update goodvibes.pot and po files" + + # Push changes to upstream repository + git push + +At last, we can unlock Weblate and update it. + + # Tell Weblate to pull changes (not needed if Weblate follows your repo automatically) + wlc pull + # Unlock translations + wlc unlock + +For more details, refer to the weblate workflow as described at: +. + + + +Releasing +--------- + +#### Translation bits + +Be sure to update everything related to **translation** (see above). + +Only then you can go on with: + +- Update the translator list in the *About* dialog. +- Update the translator list in the documentation. +- Write down changes in the `NEWS` file. + +In bash, it translates to something like that: + + ./scripts/translators.sh code + vi src/ui/gv-about-dialog.c + git commit -am"ui: Update translation credits" + ./scripts/translators.sh doc + vi docs/goodvibes.readthedocs.io/credits.rst + git commit -am"doc: Update translation credits" + vi NEWS + git commit -am"news: Update translations" + +Then: + +- Ensure `NEWS` is up-to-date (check Git history and GitLab milestones). +- Bump the version in `meson.build`. +- Git commit, git tag, git push. + +In bash, here you go: + + vi NEWS + v=0.3.5 + sed -i -E "s/version: '([0-9.]*)'/version: '$v'/" meson.build + git add NEWS meson.build + git commit -m "Bump version to ${v:?}" + git tag "v${v:?}" + git push && git push --tags + +Done. + + + +Packaging +--------- + +After releasing, update the Debian packaging files in the `goodvibes-debian` +repository. Basically, just bump the changelog, there's nothing else to do. + + DEBFULLNAME=$(git config user.name) \ + DEBEMAIL=$(git config user.email) \ + dch --distribution $(dpkg-parsechangelog --show-field Distribution) \ + --newversion ${v:?}-0ebo1 + +Git commit, git push. Done. + + git add debian/changelog + git commit -m "Version ${v:?}" + git push + +Then, just fire the script `debian/build-all.sh`. + + export DEBFULLNAME=$(git config user.name) + export DEBEMAIL=$(git config user.email) + ./debian/build-all.sh + +This script is tied to my config and won't work out of the box on someone else +system. But heck, if you're not me, you're not supposed to release anything +anyway, so move on! + +At last, a few `dput` commands will finish the damn job. Done with packaging. + + + +Artwork +------- + +Both the svg source files and the png files are versioned. To rebuild the png +files, run: + + ./scripts/rebuild-images.sh icons + + + +Integrations +------------ + +This is just for myself to remember what additional services are used for +Goodvibes development, and how it integrates with GitLab. + +#### GitLab CI + +Up to date documentation should be available on the *Registry* page: + + +The configuration is mostly in-tree: +- `.gitlab-ci.yml` describes the different pipelines +- `.gitlab-ci` contains Dockerfiles and associated scripts. + +The docker images need to be updated from time to time. The procedure to update +an image is roughly: + + DIST=debian + cd .gitlab-ci + + # Work on the image + vi Dockerfile.${DIST:?} + # Build the image + ./docker-build-image.sh Dockerfile.${DIST:?} + # Log in the registry + docker login registry.gitlab.com + # Push the image + docker push registry.gitlab.com/goodvibes/goodvibes/${DIST:?} + +#### GitHub Mirror + +Very well documented at: . +In short: + +1. Create a GitHub token. +2. Configure GitLab to push automatically, using the token to authenticate. + +This mirror is just there for a while, so that active GitHub users (if any) +have time to notice the change. + +#### WebLate + +Weblate needs to be notified of new commits, so there's a webhook. + +Additionally, Weblate needs write permission on the repository. This is +achieved by adding the [Weblate push user](https://gitlab.com/weblate) as a +member of the project. I configured it as a `Developer`, however developers +can't write to protected branches by default, so there's a bit of additional +config. + +#### ReadTheDocs + +Just needs to be notified of changes, so there's only a webhook. diff -Nru goodvibes-0.3.6/Makefile.am goodvibes-0.4.2/Makefile.am --- goodvibes-0.3.6/Makefile.am 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/Makefile.am 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -SUBDIRS = \ - data \ - libcaphe\ - po \ - src - -EXTRA_DIST = \ - autogen.sh \ - HACKING.md \ - README.md \ - RELEASING.md - -distclean-local: - find . -name '*~' -print0 | \ - xargs --no-run-if-empty -0 rm -vf - -indent: - ./scripts/code/indent.sh all - -icons: - ./scripts/images.sh icons diff -Nru goodvibes-0.3.6/meson.build goodvibes-0.4.2/meson.build --- goodvibes-0.3.6/meson.build 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/meson.build 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,127 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +project('goodvibes', 'c', + version: '0.4.2', + license: 'GPLv3+', + default_options: [ + 'buildtype=debugoptimized', + 'c_args=-Wshadow', + 'c_std=gnu99', + 'warning_level=2', # -Wextra + ] +) + +# Paths + +prefix = get_option('prefix') +assert(prefix.startswith('/'), 'Prefix is not absolute: "@0@"'.format(prefix)) + +bindir = join_paths(prefix, get_option('bindir')) +datadir = join_paths(prefix, get_option('datadir')) +localedir = join_paths(prefix, get_option('localedir')) +mandir = join_paths(prefix, get_option('mandir')) + +# Modules + +gnome = import('gnome') +i18n = import('i18n') + +# Project settings + +gv_binary = meson.project_name() +gv_version = meson.project_version() +gv_name_lowercase = 'goodvibes' +gv_name_camelcase = 'Goodvibes' +gv_name_uppercase = 'GOODVIBES' +gv_application_id = 'io.gitlab.Goodvibes' +gv_application_path = '/io/gitlab/Goodvibes' +gv_icon_name = gv_application_id +gv_homepage = 'https://gitlab.com/goodvibes/goodvibes' +gv_copyright = 'Copyright (C) 2015-2018' +gv_author_name = 'Arnaud Rebillout' +gv_author_email = 'elboulangero@gmail.com' + +# Goodvibes Core + +cc = meson.get_compiler('c') +math_dep = cc.find_library('m') + +glib_req = '>= 2.44' +glib_dep = dependency('glib-2.0', version: glib_req) +gobject_dep = dependency('gobject-2.0', version: glib_req) +gio_dep = dependency('gio-2.0', version: glib_req) +gio_unix_dep = dependency('gio-unix-2.0', version: glib_req) + +gst_req = '>= 1.4.4' +gst_dep = dependency('gstreamer-1.0', version: gst_req) +gst_base_dep = dependency('gstreamer-base-1.0', version: gst_req) +gst_audio_dep = dependency('gstreamer-audio-1.0', version: gst_req) + +libsoup_req = '>= 2.42' +libsoup_dep = dependency('libsoup-2.4', version: libsoup_req) + +gv_feat_console_output = get_option('feat-console-output') +gv_feat_dbus_server = get_option('feat-dbus-server') +gv_feat_inhibitor = get_option('feat-inhibitor') + +# Goodvibes UI + +gv_ui_enabled = get_option('ui-enabled') +if gv_ui_enabled + gv_feat_hotkeys = get_option('feat-hotkeys') + gv_feat_notifications = get_option('feat-notifications') +else + gv_feat_hotkeys = false + gv_feat_notifications = false +endif + +if gv_ui_enabled + gtk_req = '>= 3.12.0' + gtk_dep = dependency('gtk+-3.0', version: gtk_req) +endif + +if gv_feat_hotkeys + keybinder_req = '>= 0.3' + keybinder_dep = dependency('keybinder-3.0', version: keybinder_req) +endif + +# Subdirectories + +subdir('data') +subdir('src') +subdir('po') + +# Post-install + +meson.add_install_script('scripts/meson/post-install', datadir) + +# Summary + +summary = [ + '', + '--------------------------------', + '', + ' @0@ - @1@'.format(meson.project_name(), meson.project_version()), + '', + ' Core', + ' Console output: @0@'.format(gv_feat_console_output), + ' D-Bus server : @0@'.format(gv_feat_dbus_server), + ' Inhibitor : @0@'.format(gv_feat_inhibitor), + '', + ' UI', + ' Enabled : @0@'.format(gv_ui_enabled), + ' Hotkeys : @0@'.format(gv_feat_hotkeys), + ' Notifications : @0@'.format(gv_feat_notifications), + '', + '--------------------------------', + '', +] + +message('\n'.join(summary)) + +# Install the git pre-commit hook + +git_hook = run_command(join_paths(meson.source_root(), 'scripts/install-git-hook.sh')) +if git_hook.returncode() == 0 + message(git_hook.stdout().strip()) +endif diff -Nru goodvibes-0.3.6/meson_options.txt goodvibes-0.4.2/meson_options.txt --- goodvibes-0.3.6/meson_options.txt 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/meson_options.txt 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +option('ui-enabled', type: 'boolean', value: true, + description: 'Enable the graphical user interface (depends on GTK)') + +option('feat-console-output', type: 'boolean', value: true, + description: 'Enable the console-output feature') + +option('feat-dbus-server', type: 'boolean', value: true, + description: 'Enable the dbus-server feature') + +option('feat-inhibitor', type: 'boolean', value: true, + description: 'Enable the inhibitor feature') + +option('feat-hotkeys', type: 'boolean', value: true, + description: 'Enable the hotkeys feature (requires ui, depends on keybinder)') + +option('feat-notifications', type: 'boolean', value: true, + description: 'Enable the notifications feature (requires ui)') diff -Nru goodvibes-0.3.6/NEWS goodvibes-0.4.2/NEWS --- goodvibes-0.3.6/NEWS 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/NEWS 2018-11-10 06:04:58.000000000 +0000 @@ -1,3 +1,65 @@ +0.4.2 (2018-11-10) - Paris / L'Imperatrice +------------------------------------------ + +Fixes + * Segfault on application shutdown + + + +0.4.1 (2018-11-10) - Parfum Theremine / L'Imperatrice +----------------------------------------------------- + +Outstanding! + * Ready for Flatpak! + +General + * Change application id to 'io.gitlab.Goodvibes'. + * Rename icon files according to the app id (flatpak requirement). + * Stations are now saved in $XDG_DATA_HOME (was $XDG_CONFIG_HOME). + * Use GResource to handle glade files. #54 + +Fixes + * Support lowercase keys in pls playlists. #88 + * Add meson post-install script. + +Translations + * New translations: Spanish. + + + +0.4 (2018-08-18) - Sphynx / La Femme +------------------------------------ + +Outstanding! + * Project moved to GitLab, good-bye GitHub. + * CI is now handled by GitLab, good-bye Shippable. + * Build system switched to Meson, good-bye Autotools. #53 + +General + * Add an appstream file (ie. appdata). #47 + +Fixes + * Desktop file: exec now accepts url (thx Elías Alejandro Año Mendoza). + +Translations + * Updated translations: Dutch, German. + + + +0.3.7 (2018-05-08) - Marilou Reggae (Gainsbourg Cover) / Alain Bashung +---------------------------------------------------------------------- + +General + * Update default station list. + +Fixes + * Fix notification crash on Cinnamon. #79 + +Translations + * Updated translations: Czech, French, German, Norwegian. + + + 0.3.6 (2018-03-31) - Birthmark / Deftones ----------------------------------------- diff -Nru goodvibes-0.3.6/po/cs.po goodvibes-0.4.2/po/cs.po --- goodvibes-0.3.6/po/cs.po 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/po/cs.po 2018-11-10 06:04:58.000000000 +0000 @@ -7,9 +7,9 @@ msgstr "" "Project-Id-Version: goodvibes 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-03-28 00:40+0700\n" -"PO-Revision-Date: 2017-01-21 16:02+0000\n" -"Last-Translator: Michal Čihař \n" +"POT-Creation-Date: 2018-11-09 19:25+0700\n" +"PO-Revision-Date: 2018-04-02 10:36+0000\n" +"Last-Translator: Lukáš Linhart \n" "Language-Team: Czech \n" "Language: cs\n" @@ -17,214 +17,228 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -"X-Generator: Weblate 2.11-dev\n" +"X-Generator: Weblate 2.20-dev\n" -#: data/com.elboulangero.Goodvibes.desktop.in:3 src/main.c:149 -msgid "Goodvibes Radio Player" -msgstr "Přehrávač rádia Goodvibes" +#: data/io.gitlab.Goodvibes.appdata.xml.in:4 +#: data/io.gitlab.Goodvibes.desktop.in:3 src/main.c:149 +msgid "Goodvibes" +msgstr "Goodvibes" -#: data/com.elboulangero.Goodvibes.desktop.in:4 -msgid "Radio Player" -msgstr "Přehrávač rádia" - -#: data/com.elboulangero.Goodvibes.desktop.in:5 +#: data/io.gitlab.Goodvibes.appdata.xml.in:5 +#: data/io.gitlab.Goodvibes.desktop.in:5 msgid "Play web radios" msgstr "Přehrát webové rádio" +#: data/io.gitlab.Goodvibes.appdata.xml.in:10 +msgid "Goodvibes is a simple internet radio player for GNU/Linux." +msgstr "" + +#: data/io.gitlab.Goodvibes.appdata.xml.in:13 +msgid "" +"It comes with every basic features you can expect from an audio player, such " +"as multimedia keys, notifications, system sleep inhibition, and MPRIS2 " +"support." +msgstr "" + +#: data/io.gitlab.Goodvibes.desktop.in:4 +msgid "Radio Player" +msgstr "Přehrávač rádia" + #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! -#: data/com.elboulangero.Goodvibes.desktop.in:7 +#: data/io.gitlab.Goodvibes.desktop.in:7 msgid "Audio;Radio;Player;" msgstr "Audio;Radio;Přehrávač;Zvuk;" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! -#: data/com.elboulangero.Goodvibes.desktop.in:11 -msgid "goodvibes" -msgstr "goodvibes" - -#: data/ui/app-menu.glade:6 data/ui/menubar.glade:8 -#: data/ui/status-icon-menu.glade:6 src/ui/gv-station-context-menu.c:35 -#: src/ui/gv-station-dialog.c:428 +#: data/io.gitlab.Goodvibes.desktop.in:11 +msgid "io.gitlab.Goodvibes" +msgstr "io.gitlab.Goodvibes" + +#: src/ui/resources/app-menu.glade:6 src/ui/resources/menubar.glade:8 +#: src/ui/resources/status-icon-menu.glade:6 +#: src/ui/gv-station-context-menu.c:35 src/ui/gv-station-dialog.c:424 msgid "Add Station" -msgstr "" +msgstr "Přidat stanici" -#: data/ui/app-menu.glade:13 data/ui/menubar.glade:15 -#: data/ui/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:633 +#: src/ui/resources/app-menu.glade:13 src/ui/resources/menubar.glade:15 +#: src/ui/resources/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:629 msgid "Preferences" msgstr "Nastavení" -#: data/ui/app-menu.glade:19 data/ui/menubar.glade:36 -#: data/ui/status-icon-menu.glade:18 +#: src/ui/resources/app-menu.glade:19 src/ui/resources/menubar.glade:36 +#: src/ui/resources/status-icon-menu.glade:18 msgid "Online Help" msgstr "Online nápověda" -#: data/ui/app-menu.glade:24 data/ui/menubar.glade:43 -#: data/ui/status-icon-menu.glade:22 +#: src/ui/resources/app-menu.glade:24 src/ui/resources/menubar.glade:43 +#: src/ui/resources/status-icon-menu.glade:22 msgid "About" msgstr "O programu" -#: data/ui/app-menu.glade:28 data/ui/menubar.glade:21 +#: src/ui/resources/app-menu.glade:28 src/ui/resources/menubar.glade:21 msgid "Close UI" msgstr "Zavřít rozhraní" -#: data/ui/app-menu.glade:33 data/ui/menubar.glade:26 -#: data/ui/status-icon-menu.glade:26 +#: src/ui/resources/app-menu.glade:33 src/ui/resources/menubar.glade:26 +#: src/ui/resources/status-icon-menu.glade:26 msgid "Quit" msgstr "Ukončit" -#: data/ui/main-window.glade:47 src/ui/gv-main-window.c:351 +#: src/ui/resources/main-window.glade:47 src/ui/gv-main-window.c:350 msgid "No station selected" msgstr "Nebyla zvolena žádná stanice" -#: data/ui/main-window.glade:63 src/ui/gv-main-window.c:374 +#: src/ui/resources/main-window.glade:63 src/ui/gv-main-window.c:373 msgid "Stopped" msgstr "Zastaveno" -#: data/ui/menubar.glade:5 +#: src/ui/resources/menubar.glade:5 msgid "Menu" -msgstr "" +msgstr "Menu" -#: data/ui/menubar.glade:33 +#: src/ui/resources/menubar.glade:33 msgid "Help" msgstr "Nápověda" -#: data/ui/prefs-window.glade:35 +#: src/ui/resources/prefs-window.glade:35 msgid "Autoplay on Startup" msgstr "Automaticky přehrávat při spuštění" -#: data/ui/prefs-window.glade:48 +#: src/ui/resources/prefs-window.glade:48 msgid "Custom Output Pipeline" msgstr "" -#: data/ui/prefs-window.glade:79 +#: src/ui/resources/prefs-window.glade:79 msgid "Apply" -msgstr "" +msgstr "Potvrdit" -#: data/ui/prefs-window.glade:102 +#: src/ui/resources/prefs-window.glade:102 msgid "Playback" -msgstr "" +msgstr "Přehrávání" -#: data/ui/prefs-window.glade:138 +#: src/ui/resources/prefs-window.glade:138 msgid "Prevent sleep while playing" msgstr "Zabránit uspání při přehrávání" -#: data/ui/prefs-window.glade:151 +#: src/ui/resources/prefs-window.glade:151 msgid "System" msgstr "Nastavení systému" -#: data/ui/prefs-window.glade:197 +#: src/ui/resources/prefs-window.glade:197 msgid "Native D-Bus Server" -msgstr "" +msgstr "Nativní D-Bus Server" -#: data/ui/prefs-window.glade:209 +#: src/ui/resources/prefs-window.glade:209 +#, fuzzy msgid "MPRIS2 D-Bus Server" -msgstr "" +msgstr "MPRIS2 D-Bus Server" -#: data/ui/prefs-window.glade:222 +#: src/ui/resources/prefs-window.glade:222 msgid "D-Bus" -msgstr "" +msgstr "D-Bus" -#: data/ui/prefs-window.glade:238 +#: src/ui/resources/prefs-window.glade:238 msgid "Misc" msgstr "Různé" -#: data/ui/prefs-window.glade:262 +#: src/ui/resources/prefs-window.glade:262 msgid "Autoset Window Height" -msgstr "" +msgstr "Automatická výška okna" -#: data/ui/prefs-window.glade:278 +#: src/ui/resources/prefs-window.glade:278 msgid "Theme Variant" -msgstr "" +msgstr "varianta motivu" -#: data/ui/prefs-window.glade:291 +#: src/ui/resources/prefs-window.glade:291 #, fuzzy msgid "System Default" msgstr "Nastavení systému" -#: data/ui/prefs-window.glade:292 +#: src/ui/resources/prefs-window.glade:292 msgid "Prefer Dark" -msgstr "" +msgstr "Upřednostnit tmavý motiv" -#: data/ui/prefs-window.glade:293 +#: src/ui/resources/prefs-window.glade:293 msgid "Prefer Light" -msgstr "" +msgstr "Upřednostnit světlý motiv" -#: data/ui/prefs-window.glade:310 +#: src/ui/resources/prefs-window.glade:310 msgid "Window" -msgstr "" +msgstr "Okno" -#: data/ui/prefs-window.glade:336 +#: src/ui/resources/prefs-window.glade:336 msgid "Send Notifications" -msgstr "" +msgstr "Poslat oznámení" -#: data/ui/prefs-window.glade:359 +#: src/ui/resources/prefs-window.glade:359 msgid "Notifications" -msgstr "" +msgstr "oznámení" -#: data/ui/prefs-window.glade:394 +#: src/ui/resources/prefs-window.glade:394 msgid "Console Output" -msgstr "" +msgstr "Konzolový výstup" -#: data/ui/prefs-window.glade:407 +#: src/ui/resources/prefs-window.glade:407 msgid "Console" -msgstr "" +msgstr "konzole" -#: data/ui/prefs-window.glade:426 +#: src/ui/resources/prefs-window.glade:426 msgid "Display" -msgstr "" +msgstr "Displej" -#: data/ui/prefs-window.glade:464 +#: src/ui/resources/prefs-window.glade:464 msgid "Multimedia Hotkeys" msgstr "" -#: data/ui/prefs-window.glade:477 +#: src/ui/resources/prefs-window.glade:477 msgid "Keyboard" msgstr "" -#: data/ui/prefs-window.glade:503 +#: src/ui/resources/prefs-window.glade:503 msgid "Middle Click" msgstr "" -#: data/ui/prefs-window.glade:516 +#: src/ui/resources/prefs-window.glade:516 msgid "Toggle Play/Pause" msgstr "" -#: data/ui/prefs-window.glade:517 +#: src/ui/resources/prefs-window.glade:517 msgid "Mute" msgstr "" -#: data/ui/prefs-window.glade:530 +#: src/ui/resources/prefs-window.glade:530 msgid "Scrolling" msgstr "" -#: data/ui/prefs-window.glade:543 +#: src/ui/resources/prefs-window.glade:543 msgid "Change Station" msgstr "" -#: data/ui/prefs-window.glade:544 +#: src/ui/resources/prefs-window.glade:544 msgid "Change Volume" msgstr "" -#: data/ui/prefs-window.glade:558 +#: src/ui/resources/prefs-window.glade:558 msgid "Mouse (Status Icon Mode)" msgstr "" -#: data/ui/prefs-window.glade:577 +#: src/ui/resources/prefs-window.glade:577 msgid "Controls" msgstr "" -#: data/ui/prefs-window.glade:598 +#: src/ui/resources/prefs-window.glade:598 msgid "Close" msgstr "" -#: data/ui/station-dialog.glade:12 src/ui/gv-main-window.c:262 +#: src/ui/resources/station-dialog.glade:12 src/ui/gv-main-window.c:261 msgid "Name" msgstr "" -#: data/ui/station-dialog.glade:34 src/ui/gv-main-window.c:263 +#: src/ui/resources/station-dialog.glade:34 src/ui/gv-main-window.c:262 msgid "URI" msgstr "" -#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1088 +#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1134 #, c-format msgid "%s: %s" msgstr "" @@ -238,126 +252,135 @@ msgid "'%s' is neither a known station or a valid URI" msgstr "" -#: src/core/gv-station-list.c:1089 +#: src/core/gv-station-list.c:1135 msgid "Failed to save station list" msgstr "" -#: src/ui/gv-main-window.c:260 +#: src/ui/gv-main-window.c:259 msgid "Station Information" msgstr "" -#: src/ui/gv-main-window.c:274 +#: src/ui/gv-main-window.c:273 msgid "User-agent" msgstr "" -#: src/ui/gv-main-window.c:278 +#: src/ui/gv-main-window.c:277 msgid "Bitrate" msgstr "" -#: src/ui/gv-main-window.c:291 +#: src/ui/gv-main-window.c:290 msgid "Metadata" msgstr "" -#: src/ui/gv-main-window.c:293 +#: src/ui/gv-main-window.c:292 msgid "Artist" msgstr "" -#: src/ui/gv-main-window.c:294 +#: src/ui/gv-main-window.c:293 msgid "Title" msgstr "" -#: src/ui/gv-main-window.c:295 +#: src/ui/gv-main-window.c:294 msgid "Album" msgstr "" -#: src/ui/gv-main-window.c:296 +#: src/ui/gv-main-window.c:295 msgid "Genre" msgstr "" -#: src/ui/gv-main-window.c:297 +#: src/ui/gv-main-window.c:296 msgid "Year" msgstr "" -#: src/ui/gv-main-window.c:298 +#: src/ui/gv-main-window.c:297 msgid "Comment" msgstr "" -#: src/ui/gv-main-window.c:364 src/ui/gv-main-window.c:392 +#: src/ui/gv-main-window.c:363 src/ui/gv-main-window.c:391 msgid "Playing" msgstr "" -#: src/ui/gv-main-window.c:367 +#: src/ui/gv-main-window.c:366 msgid "Connecting…" msgstr "" -#: src/ui/gv-main-window.c:370 +#: src/ui/gv-main-window.c:369 msgid "Buffering…" msgstr "" -#: src/ui/gv-prefs-window.c:282 +#: src/ui/gv-prefs-window.c:281 msgid "Feature disabled at compile-time." msgstr "" -#: src/ui/gv-prefs-window.c:428 +#. +#. * Setup settings and features. +#. * These function calls create a binding between a gtk widget and +#. * an internal object, initializes the widget value, and set the +#. * widgets tooltips (label + setting). +#. +#. Misc +#: src/ui/gv-prefs-window.c:424 msgid "Whether to start playback automatically on startup." msgstr "" -#: src/ui/gv-prefs-window.c:434 +#: src/ui/gv-prefs-window.c:430 msgid "Whether to use a custom output pipeline." msgstr "" -#: src/ui/gv-prefs-window.c:440 +#: src/ui/gv-prefs-window.c:436 msgid "" "The GStreamer output pipeline used for playback. Refer to theonline " "documentation for examples." msgstr "" -#: src/ui/gv-prefs-window.c:456 +#: src/ui/gv-prefs-window.c:452 msgid "Prevent the system from going to sleep while playing." msgstr "" -#: src/ui/gv-prefs-window.c:461 +#: src/ui/gv-prefs-window.c:457 msgid "Enable the native D-Bus server (needed for the command-line interface)." msgstr "" -#: src/ui/gv-prefs-window.c:467 +#: src/ui/gv-prefs-window.c:463 msgid "Enable the MPRIS2 D-Bus server." msgstr "" -#: src/ui/gv-prefs-window.c:473 +#. Display +#: src/ui/gv-prefs-window.c:469 msgid "Prefer a different variant of the theme (if available)." msgstr "" -#: src/ui/gv-prefs-window.c:480 +#: src/ui/gv-prefs-window.c:476 msgid "" "Automatically adjust the window height when a station is added or removed." msgstr "" -#: src/ui/gv-prefs-window.c:487 +#: src/ui/gv-prefs-window.c:483 msgid "Setting not available in status icon mode." msgstr "" -#: src/ui/gv-prefs-window.c:491 +#: src/ui/gv-prefs-window.c:487 msgid "Show notification when the status changes." msgstr "" -#: src/ui/gv-prefs-window.c:496 +#: src/ui/gv-prefs-window.c:492 msgid "Display information on the standard output." msgstr "" -#: src/ui/gv-prefs-window.c:502 +#. Controls +#: src/ui/gv-prefs-window.c:498 msgid "Bind mutimedia keys (play/pause/stop/previous/next)." msgstr "" -#: src/ui/gv-prefs-window.c:508 +#: src/ui/gv-prefs-window.c:504 msgid "Action triggered by a middle click on the status icon." msgstr "" -#: src/ui/gv-prefs-window.c:514 +#: src/ui/gv-prefs-window.c:510 msgid "Action triggered by mouse-scrolling on the status icon." msgstr "" -#: src/ui/gv-prefs-window.c:520 +#: src/ui/gv-prefs-window.c:516 msgid "Setting only available in status icon mode." msgstr "" @@ -365,62 +388,62 @@ msgid "Remove Station" msgstr "" -#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:428 +#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:424 msgid "Edit Station" msgstr "" -#: src/ui/gv-station-dialog.c:284 +#: src/ui/gv-station-dialog.c:281 msgid "Cancel" msgstr "" -#: src/ui/gv-station-dialog.c:285 +#: src/ui/gv-station-dialog.c:282 msgid "Save" msgstr "" -#: src/ui/gv-status-icon.c:130 +#: src/ui/gv-status-icon.c:131 msgid "stopped" msgstr "" -#: src/ui/gv-status-icon.c:133 +#: src/ui/gv-status-icon.c:134 msgid "connecting" msgstr "" -#: src/ui/gv-status-icon.c:136 +#: src/ui/gv-status-icon.c:137 msgid "buffering" msgstr "" -#: src/ui/gv-status-icon.c:139 +#: src/ui/gv-status-icon.c:140 msgid "playing" msgstr "" -#: src/ui/gv-status-icon.c:142 +#: src/ui/gv-status-icon.c:143 msgid "unknown state" msgstr "" -#: src/ui/gv-status-icon.c:149 +#: src/ui/gv-status-icon.c:150 msgid "muted" msgstr "" -#: src/ui/gv-status-icon.c:153 +#: src/ui/gv-status-icon.c:154 msgid "vol." msgstr "" -#: src/ui/gv-status-icon.c:160 +#: src/ui/gv-status-icon.c:161 msgid "No station" msgstr "" -#: src/ui/gv-status-icon.c:167 +#: src/ui/gv-status-icon.c:168 msgid "No metadata" msgstr "" -#: src/feat/gv-hotkeys.c:144 +#: src/feat/gv-hotkeys.c:145 #, c-format msgid "" "%s:\n" "%s" msgstr "" -#: src/feat/gv-hotkeys.c:145 +#: src/feat/gv-hotkeys.c:146 msgid "Failed to bind the following keys" msgstr "" @@ -428,32 +451,38 @@ msgid "Failed to inhibit system sleep" msgstr "" -#: src/feat/gv-notifications.c:93 +#: src/feat/gv-notifications.c:59 #, c-format msgid "Playing %s" msgstr "" -#: src/feat/gv-notifications.c:96 +#: src/feat/gv-notifications.c:62 #, c-format msgid "Playing <%s>" msgstr "" -#: src/feat/gv-notifications.c:137 -msgid "(Unknown title)" +#: src/feat/gv-notifications.c:65 +msgid "Playing Station" msgstr "" -#: src/feat/gv-notifications.c:263 -msgid "Playing Station" +#: src/feat/gv-notifications.c:103 +msgid "(Unknown title)" msgstr "" -#: src/feat/gv-notifications.c:266 +#: src/feat/gv-notifications.c:110 msgid "New Track" msgstr "" -#: src/feat/gv-notifications.c:269 +#: src/feat/gv-notifications.c:122 msgid "Error" msgstr "" +#~ msgid "goodvibes" +#~ msgstr "goodvibes" + +#~ msgid "Goodvibes Radio Player" +#~ msgstr "Přehrávač rádia Goodvibes" + #~ msgid "File" #~ msgstr "Soubor" diff -Nru goodvibes-0.3.6/po/de.po goodvibes-0.4.2/po/de.po --- goodvibes-0.3.6/po/de.po 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/po/de.po 2018-11-10 06:04:58.000000000 +0000 @@ -7,9 +7,9 @@ msgstr "" "Project-Id-Version: goodvibes 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-03-28 00:40+0700\n" -"PO-Revision-Date: 2018-02-15 20:57+0000\n" -"Last-Translator: Andreas Kleinert \n" +"POT-Creation-Date: 2018-11-09 19:25+0700\n" +"PO-Revision-Date: 2018-08-10 12:38+0000\n" +"Last-Translator: vinz \n" "Language-Team: German \n" "Language: de\n" @@ -17,216 +17,230 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.19\n" +"X-Generator: Weblate 3.2-dev\n" -#: data/com.elboulangero.Goodvibes.desktop.in:3 src/main.c:149 -msgid "Goodvibes Radio Player" -msgstr "Goodvibes Radio-Player" +#: data/io.gitlab.Goodvibes.appdata.xml.in:4 +#: data/io.gitlab.Goodvibes.desktop.in:3 src/main.c:149 +msgid "Goodvibes" +msgstr "Goodvibes" -#: data/com.elboulangero.Goodvibes.desktop.in:4 -msgid "Radio Player" -msgstr "Radio-Player" - -#: data/com.elboulangero.Goodvibes.desktop.in:5 +#: data/io.gitlab.Goodvibes.appdata.xml.in:5 +#: data/io.gitlab.Goodvibes.desktop.in:5 msgid "Play web radios" msgstr "Webradios abspielen" +#: data/io.gitlab.Goodvibes.appdata.xml.in:10 +msgid "Goodvibes is a simple internet radio player for GNU/Linux." +msgstr "" +"Goodvibes ist ein einfaches Internetradio-Abspielprogramm für GNU-Linux." + +#: data/io.gitlab.Goodvibes.appdata.xml.in:13 +msgid "" +"It comes with every basic features you can expect from an audio player, such " +"as multimedia keys, notifications, system sleep inhibition, and MPRIS2 " +"support." +msgstr "" +"Es enthält alle Funktionen, die man von einem Internetradio-Player erwartet, " +"wie: Multimediatastenunterstützung, Benachrichtigungen, " +"Systemruhestandsunterdrückung und MPRI2-Unterstützung." + +#: data/io.gitlab.Goodvibes.desktop.in:4 +msgid "Radio Player" +msgstr "Radio-AbspielprogrammRadio-Player" + #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! -#: data/com.elboulangero.Goodvibes.desktop.in:7 +#: data/io.gitlab.Goodvibes.desktop.in:7 msgid "Audio;Radio;Player;" msgstr "Audio;Radio;Player;Webradio;" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! -#: data/com.elboulangero.Goodvibes.desktop.in:11 -msgid "goodvibes" -msgstr "goodvibes" - -#: data/ui/app-menu.glade:6 data/ui/menubar.glade:8 -#: data/ui/status-icon-menu.glade:6 src/ui/gv-station-context-menu.c:35 -#: src/ui/gv-station-dialog.c:428 -#, fuzzy +#: data/io.gitlab.Goodvibes.desktop.in:11 +msgid "io.gitlab.Goodvibes" +msgstr "io.gitlab.Goodvibes" + +#: src/ui/resources/app-menu.glade:6 src/ui/resources/menubar.glade:8 +#: src/ui/resources/status-icon-menu.glade:6 +#: src/ui/gv-station-context-menu.c:35 src/ui/gv-station-dialog.c:424 msgid "Add Station" -msgstr "Neuen Radiosender hinzufügen …" +msgstr "Radiosender hinzufügen" -#: data/ui/app-menu.glade:13 data/ui/menubar.glade:15 -#: data/ui/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:633 +#: src/ui/resources/app-menu.glade:13 src/ui/resources/menubar.glade:15 +#: src/ui/resources/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:629 msgid "Preferences" msgstr "Einstellungen" -#: data/ui/app-menu.glade:19 data/ui/menubar.glade:36 -#: data/ui/status-icon-menu.glade:18 +#: src/ui/resources/app-menu.glade:19 src/ui/resources/menubar.glade:36 +#: src/ui/resources/status-icon-menu.glade:18 msgid "Online Help" msgstr "Online-Hilfe" -#: data/ui/app-menu.glade:24 data/ui/menubar.glade:43 -#: data/ui/status-icon-menu.glade:22 +#: src/ui/resources/app-menu.glade:24 src/ui/resources/menubar.glade:43 +#: src/ui/resources/status-icon-menu.glade:22 msgid "About" -msgstr "Über …" +msgstr "Über" -#: data/ui/app-menu.glade:28 data/ui/menubar.glade:21 +#: src/ui/resources/app-menu.glade:28 src/ui/resources/menubar.glade:21 msgid "Close UI" msgstr "Benutzeroberfläche schließen" -#: data/ui/app-menu.glade:33 data/ui/menubar.glade:26 -#: data/ui/status-icon-menu.glade:26 +#: src/ui/resources/app-menu.glade:33 src/ui/resources/menubar.glade:26 +#: src/ui/resources/status-icon-menu.glade:26 msgid "Quit" msgstr "Beenden" -#: data/ui/main-window.glade:47 src/ui/gv-main-window.c:351 +#: src/ui/resources/main-window.glade:47 src/ui/gv-main-window.c:350 msgid "No station selected" msgstr "Keinen Radiosender ausgewählt" -#: data/ui/main-window.glade:63 src/ui/gv-main-window.c:374 +#: src/ui/resources/main-window.glade:63 src/ui/gv-main-window.c:373 msgid "Stopped" msgstr "Angehalten" -#: data/ui/menubar.glade:5 +#: src/ui/resources/menubar.glade:5 msgid "Menu" msgstr "Menü" -#: data/ui/menubar.glade:33 +#: src/ui/resources/menubar.glade:33 msgid "Help" msgstr "Hilfe" -#: data/ui/prefs-window.glade:35 +#: src/ui/resources/prefs-window.glade:35 msgid "Autoplay on Startup" msgstr "Automatisch beim Start abspielen" -#: data/ui/prefs-window.glade:48 +#: src/ui/resources/prefs-window.glade:48 msgid "Custom Output Pipeline" msgstr "Benutzerdefinierte Ausgangspipeline" -#: data/ui/prefs-window.glade:79 +#: src/ui/resources/prefs-window.glade:79 msgid "Apply" msgstr "Übernehmen" -#: data/ui/prefs-window.glade:102 +#: src/ui/resources/prefs-window.glade:102 msgid "Playback" msgstr "Wiedergabe" -#: data/ui/prefs-window.glade:138 +#: src/ui/resources/prefs-window.glade:138 msgid "Prevent sleep while playing" msgstr "Ruhemodus währen der Wiedergabe verhindern" -#: data/ui/prefs-window.glade:151 +#: src/ui/resources/prefs-window.glade:151 msgid "System" msgstr "System" -#: data/ui/prefs-window.glade:197 +#: src/ui/resources/prefs-window.glade:197 msgid "Native D-Bus Server" msgstr "Nativer D-Bus-Server" -#: data/ui/prefs-window.glade:209 +#: src/ui/resources/prefs-window.glade:209 msgid "MPRIS2 D-Bus Server" msgstr "MPRIS2 D-Bus-Server" -#: data/ui/prefs-window.glade:222 +#: src/ui/resources/prefs-window.glade:222 msgid "D-Bus" msgstr "D-Bus" -#: data/ui/prefs-window.glade:238 +#: src/ui/resources/prefs-window.glade:238 msgid "Misc" msgstr "Sonstiges" -#: data/ui/prefs-window.glade:262 +#: src/ui/resources/prefs-window.glade:262 msgid "Autoset Window Height" msgstr "Fensterhöhe automatisch festlegen" -#: data/ui/prefs-window.glade:278 +#: src/ui/resources/prefs-window.glade:278 msgid "Theme Variant" -msgstr "" +msgstr "Thema Variante" -#: data/ui/prefs-window.glade:291 -#, fuzzy +#: src/ui/resources/prefs-window.glade:291 msgid "System Default" -msgstr "System" +msgstr "Systemstandard" -#: data/ui/prefs-window.glade:292 +#: src/ui/resources/prefs-window.glade:292 msgid "Prefer Dark" -msgstr "" +msgstr "Lieber Dunkel" -#: data/ui/prefs-window.glade:293 +#: src/ui/resources/prefs-window.glade:293 msgid "Prefer Light" -msgstr "" +msgstr "Lieber Licht" -#: data/ui/prefs-window.glade:310 +#: src/ui/resources/prefs-window.glade:310 msgid "Window" -msgstr "" +msgstr "Fenster" -#: data/ui/prefs-window.glade:336 -#, fuzzy +#: src/ui/resources/prefs-window.glade:336 msgid "Send Notifications" -msgstr "Benachrichtigungen" +msgstr "Benachrichtigungen senden" -#: data/ui/prefs-window.glade:359 +#: src/ui/resources/prefs-window.glade:359 msgid "Notifications" msgstr "Benachrichtigungen" -#: data/ui/prefs-window.glade:394 +#: src/ui/resources/prefs-window.glade:394 msgid "Console Output" msgstr "Konsolenausgabe" -#: data/ui/prefs-window.glade:407 +#: src/ui/resources/prefs-window.glade:407 msgid "Console" msgstr "Konsole" -#: data/ui/prefs-window.glade:426 +#: src/ui/resources/prefs-window.glade:426 msgid "Display" msgstr "Anzeige" -#: data/ui/prefs-window.glade:464 +#: src/ui/resources/prefs-window.glade:464 msgid "Multimedia Hotkeys" msgstr "Multimedia-Tasten" -#: data/ui/prefs-window.glade:477 +#: src/ui/resources/prefs-window.glade:477 msgid "Keyboard" msgstr "Tastatur" -#: data/ui/prefs-window.glade:503 +#: src/ui/resources/prefs-window.glade:503 msgid "Middle Click" msgstr "Mittelklick" -#: data/ui/prefs-window.glade:516 +#: src/ui/resources/prefs-window.glade:516 msgid "Toggle Play/Pause" msgstr "Wiedergabe/Pause umschalten" -#: data/ui/prefs-window.glade:517 +#: src/ui/resources/prefs-window.glade:517 msgid "Mute" msgstr "Stummschaltung" -#: data/ui/prefs-window.glade:530 +#: src/ui/resources/prefs-window.glade:530 msgid "Scrolling" msgstr "Blättern" -#: data/ui/prefs-window.glade:543 +#: src/ui/resources/prefs-window.glade:543 msgid "Change Station" msgstr "Radiosender wechseln" -#: data/ui/prefs-window.glade:544 +#: src/ui/resources/prefs-window.glade:544 msgid "Change Volume" msgstr "Lautstärke ändern" -#: data/ui/prefs-window.glade:558 +#: src/ui/resources/prefs-window.glade:558 msgid "Mouse (Status Icon Mode)" msgstr "Maus (Statussymbol-Modus)" -#: data/ui/prefs-window.glade:577 +#: src/ui/resources/prefs-window.glade:577 msgid "Controls" msgstr "Bedienelemente" -#: data/ui/prefs-window.glade:598 +#: src/ui/resources/prefs-window.glade:598 msgid "Close" msgstr "Schließen" -#: data/ui/station-dialog.glade:12 src/ui/gv-main-window.c:262 +#: src/ui/resources/station-dialog.glade:12 src/ui/gv-main-window.c:261 msgid "Name" msgstr "Name" -#: data/ui/station-dialog.glade:34 src/ui/gv-main-window.c:263 +#: src/ui/resources/station-dialog.glade:34 src/ui/gv-main-window.c:262 msgid "URI" msgstr "Adresse" -#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1088 +#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1134 #, c-format msgid "%s: %s" msgstr "%s:%s" @@ -236,201 +250,206 @@ msgstr "Pipeline-Beschreibung konnte nicht analysiert werden" #: src/core/gv-player.c:819 -#, fuzzy, c-format +#, c-format msgid "'%s' is neither a known station or a valid URI" -msgstr "" -"„%s” ist weder eine bekannte Station noch eine gültige Internetadresse." +msgstr "'%s' ist weder eine bekannte Station noch eine gültige Internetadresse" -#: src/core/gv-station-list.c:1089 +#: src/core/gv-station-list.c:1135 msgid "Failed to save station list" msgstr "Senderliste konnte nicht gespeichert werden" -#: src/ui/gv-main-window.c:260 +#: src/ui/gv-main-window.c:259 msgid "Station Information" msgstr "Senderinformationen" -#: src/ui/gv-main-window.c:274 +#: src/ui/gv-main-window.c:273 msgid "User-agent" msgstr "Benutzer-Kennung" -#: src/ui/gv-main-window.c:278 +#: src/ui/gv-main-window.c:277 msgid "Bitrate" msgstr "Bitrate" -#: src/ui/gv-main-window.c:291 +#: src/ui/gv-main-window.c:290 msgid "Metadata" msgstr "Metadaten" -#: src/ui/gv-main-window.c:293 +#: src/ui/gv-main-window.c:292 msgid "Artist" msgstr "Künstler" -#: src/ui/gv-main-window.c:294 +#: src/ui/gv-main-window.c:293 msgid "Title" msgstr "Titel" -#: src/ui/gv-main-window.c:295 +#: src/ui/gv-main-window.c:294 msgid "Album" msgstr "Album" -#: src/ui/gv-main-window.c:296 +#: src/ui/gv-main-window.c:295 msgid "Genre" msgstr "Genre" -#: src/ui/gv-main-window.c:297 +#: src/ui/gv-main-window.c:296 msgid "Year" msgstr "Jahr" -#: src/ui/gv-main-window.c:298 +#: src/ui/gv-main-window.c:297 msgid "Comment" msgstr "Kommentar" -#: src/ui/gv-main-window.c:364 src/ui/gv-main-window.c:392 +#: src/ui/gv-main-window.c:363 src/ui/gv-main-window.c:391 msgid "Playing" msgstr "Wiedergabe" -#: src/ui/gv-main-window.c:367 -#, fuzzy +#: src/ui/gv-main-window.c:366 msgid "Connecting…" -msgstr "Verbindung wird hergestellt" +msgstr "Verbindung wird hergestellt…" -#: src/ui/gv-main-window.c:370 -#, fuzzy +#: src/ui/gv-main-window.c:369 msgid "Buffering…" -msgstr "Wird zwischengespeichert" +msgstr "Wird zwischengespeichert…" -#: src/ui/gv-prefs-window.c:282 +#: src/ui/gv-prefs-window.c:281 msgid "Feature disabled at compile-time." msgstr "Funktion zur Kompilierungszeit deaktiviert." -#: src/ui/gv-prefs-window.c:428 +#. +#. * Setup settings and features. +#. * These function calls create a binding between a gtk widget and +#. * an internal object, initializes the widget value, and set the +#. * widgets tooltips (label + setting). +#. +#. Misc +#: src/ui/gv-prefs-window.c:424 msgid "Whether to start playback automatically on startup." msgstr "" "Gibt an, ob die Wiedergabe beim Start automatisch gestartet werden soll." -#: src/ui/gv-prefs-window.c:434 +#: src/ui/gv-prefs-window.c:430 msgid "Whether to use a custom output pipeline." msgstr "" "Gibt an, ob eine benutzerdefinierte Ausgabepipeline verwendet werden soll." -#: src/ui/gv-prefs-window.c:440 +#: src/ui/gv-prefs-window.c:436 msgid "" "The GStreamer output pipeline used for playback. Refer to theonline " "documentation for examples." msgstr "" +"Die für die Wiedergabe verwendete GStreamer-Ausgabepipeline. Beispiele " +"finden Sie in der Online-Dokumentation." -#: src/ui/gv-prefs-window.c:456 +#: src/ui/gv-prefs-window.c:452 msgid "Prevent the system from going to sleep while playing." msgstr "Verhindern, dass das System bei der Wiedergabe in den Ruhemodus geht." -#: src/ui/gv-prefs-window.c:461 +#: src/ui/gv-prefs-window.c:457 msgid "Enable the native D-Bus server (needed for the command-line interface)." msgstr "" "Aktivieren Sie den nativen D-Bus-Server (für die Befehlszeilenschnittstelle " "erforderlich)." -#: src/ui/gv-prefs-window.c:467 +#: src/ui/gv-prefs-window.c:463 msgid "Enable the MPRIS2 D-Bus server." msgstr "Den MPRIS2 D-Bus Server aktivieren" -#: src/ui/gv-prefs-window.c:473 +#. Display +#: src/ui/gv-prefs-window.c:469 msgid "Prefer a different variant of the theme (if available)." -msgstr "" +msgstr "Bevorzugen Sie eine andere Variante des Themas (falls verfügbar)." -#: src/ui/gv-prefs-window.c:480 +#: src/ui/gv-prefs-window.c:476 msgid "" "Automatically adjust the window height when a station is added or removed." msgstr "" "Fensterhöhe automatisch anpassen, wenn eine Station hinzugefügt oder " "entfernt wird." -#: src/ui/gv-prefs-window.c:487 +#: src/ui/gv-prefs-window.c:483 msgid "Setting not available in status icon mode." msgstr "Einstellung im Statussymbolmodus nicht verfügbar." -#: src/ui/gv-prefs-window.c:491 -#, fuzzy +#: src/ui/gv-prefs-window.c:487 msgid "Show notification when the status changes." -msgstr "Benachrichtigungen anzeigen, wenn sich der Status ändert" +msgstr "Benachrichtigung anzeigen, wenn sich der Status ändert." -#: src/ui/gv-prefs-window.c:496 +#: src/ui/gv-prefs-window.c:492 msgid "Display information on the standard output." msgstr "Informationen zur Standardausgabe anzeigen." -#: src/ui/gv-prefs-window.c:502 +#. Controls +#: src/ui/gv-prefs-window.c:498 msgid "Bind mutimedia keys (play/pause/stop/previous/next)." msgstr "" "Multimedia-Tasten verbinden (Wiedergabe/Pause/Stopp/Vorherige/Nächste)." -#: src/ui/gv-prefs-window.c:508 +#: src/ui/gv-prefs-window.c:504 msgid "Action triggered by a middle click on the status icon." msgstr "" "Aktion, die durch einen mittleren Klick auf das Statussymbol ausgelöst wird." -#: src/ui/gv-prefs-window.c:514 +#: src/ui/gv-prefs-window.c:510 msgid "Action triggered by mouse-scrolling on the status icon." msgstr "" "Aktion, die durch Blättern mit der Maus auf dem Statussymbol ausgelöst wird." -#: src/ui/gv-prefs-window.c:520 -#, fuzzy +#: src/ui/gv-prefs-window.c:516 msgid "Setting only available in status icon mode." -msgstr "Einstellung im Statussymbolmodus nicht verfügbar." +msgstr "Einstellung nur im Statussymbolmodus verfügbar." #: src/ui/gv-station-context-menu.c:36 -#, fuzzy msgid "Remove Station" msgstr "Radiosender entfernen" -#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:428 +#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:424 msgid "Edit Station" msgstr "Radiosender bearbeiten" -#: src/ui/gv-station-dialog.c:284 +#: src/ui/gv-station-dialog.c:281 msgid "Cancel" msgstr "Abbrechen" -#: src/ui/gv-station-dialog.c:285 +#: src/ui/gv-station-dialog.c:282 msgid "Save" msgstr "Speichern" -#: src/ui/gv-status-icon.c:130 +#: src/ui/gv-status-icon.c:131 msgid "stopped" msgstr "Angehalten" -#: src/ui/gv-status-icon.c:133 +#: src/ui/gv-status-icon.c:134 msgid "connecting" msgstr "Verbindung wird hergestellt" -#: src/ui/gv-status-icon.c:136 +#: src/ui/gv-status-icon.c:137 msgid "buffering" msgstr "Wird zwischengespeichert" -#: src/ui/gv-status-icon.c:139 +#: src/ui/gv-status-icon.c:140 msgid "playing" msgstr "Wird wiedergegeben" -#: src/ui/gv-status-icon.c:142 +#: src/ui/gv-status-icon.c:143 msgid "unknown state" msgstr "Unbekannter Status" -#: src/ui/gv-status-icon.c:149 +#: src/ui/gv-status-icon.c:150 msgid "muted" msgstr "Stummgeschaltet" -#: src/ui/gv-status-icon.c:153 +#: src/ui/gv-status-icon.c:154 msgid "vol." msgstr "Laut." -#: src/ui/gv-status-icon.c:160 +#: src/ui/gv-status-icon.c:161 msgid "No station" msgstr "Kein Radiosender" -#: src/ui/gv-status-icon.c:167 +#: src/ui/gv-status-icon.c:168 msgid "No metadata" msgstr "Keine Metadaten" -#: src/feat/gv-hotkeys.c:144 +#: src/feat/gv-hotkeys.c:145 #, c-format msgid "" "%s:\n" @@ -439,7 +458,7 @@ "%s:\n" "%s" -#: src/feat/gv-hotkeys.c:145 +#: src/feat/gv-hotkeys.c:146 msgid "Failed to bind the following keys" msgstr "Folgende Tasten konnten nicht gebunden werden" @@ -447,33 +466,38 @@ msgid "Failed to inhibit system sleep" msgstr "Fehler beim Verhindern des Systemschlafs" -#: src/feat/gv-notifications.c:93 -#, fuzzy, c-format +#: src/feat/gv-notifications.c:59 +#, c-format msgid "Playing %s" -msgstr "Wiedergabe" +msgstr "Spiele %s" -#: src/feat/gv-notifications.c:96 -#, fuzzy, c-format +#: src/feat/gv-notifications.c:62 +#, c-format msgid "Playing <%s>" -msgstr "Wiedergabe" +msgstr "Spiele <%s>" -#: src/feat/gv-notifications.c:137 -#, fuzzy -msgid "(Unknown title)" -msgstr "Unbekannter Status" - -#: src/feat/gv-notifications.c:263 +#: src/feat/gv-notifications.c:65 msgid "Playing Station" msgstr "Radiosender wiedergeben" -#: src/feat/gv-notifications.c:266 +#: src/feat/gv-notifications.c:103 +msgid "(Unknown title)" +msgstr "(Unbekannter Titel)" + +#: src/feat/gv-notifications.c:110 msgid "New Track" msgstr "Neuer Titel" -#: src/feat/gv-notifications.c:269 +#: src/feat/gv-notifications.c:122 msgid "Error" msgstr "Fehler" +#~ msgid "goodvibes" +#~ msgstr "goodvibes" + +#~ msgid "Goodvibes Radio Player" +#~ msgstr "Goodvibes Radio-Player" + #~ msgid "Window Behavior" #~ msgstr "Fensterverhalten" diff -Nru goodvibes-0.3.6/po/es.po goodvibes-0.4.2/po/es.po --- goodvibes-0.3.6/po/es.po 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/po/es.po 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,481 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the goodvibes package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: goodvibes\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-11-09 19:25+0700\n" +"PO-Revision-Date: 2018-09-27 18:38+0000\n" +"Last-Translator: benages \n" +"Language-Team: Spanish \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.2-dev\n" + +#: data/io.gitlab.Goodvibes.appdata.xml.in:4 +#: data/io.gitlab.Goodvibes.desktop.in:3 src/main.c:149 +msgid "Goodvibes" +msgstr "" + +#: data/io.gitlab.Goodvibes.appdata.xml.in:5 +#: data/io.gitlab.Goodvibes.desktop.in:5 +msgid "Play web radios" +msgstr "Escuchar radios online" + +#: data/io.gitlab.Goodvibes.appdata.xml.in:10 +msgid "Goodvibes is a simple internet radio player for GNU/Linux." +msgstr "" +"Goodvibes es un simple reproductor de radios de internet para GNU/Linux." + +#: data/io.gitlab.Goodvibes.appdata.xml.in:13 +#, fuzzy +msgid "" +"It comes with every basic features you can expect from an audio player, such " +"as multimedia keys, notifications, system sleep inhibition, and MPRIS2 " +"support." +msgstr "" +"Viene con todas las funciones que puede esperar de un reproductor de audio, " +"cómo teclas multimedia, notificaciones, desactivación del autoapagado del " +"ordenador y soporte MPRIS2." + +#: data/io.gitlab.Goodvibes.desktop.in:4 +msgid "Radio Player" +msgstr "Reproductor de Radio" + +#. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: data/io.gitlab.Goodvibes.desktop.in:7 +msgid "Audio;Radio;Player;" +msgstr "Audio;Radio;Reproductor;" + +#. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! +#: data/io.gitlab.Goodvibes.desktop.in:11 +msgid "io.gitlab.Goodvibes" +msgstr "io.gitlab.Goodvibes" + +#: src/ui/resources/app-menu.glade:6 src/ui/resources/menubar.glade:8 +#: src/ui/resources/status-icon-menu.glade:6 +#: src/ui/gv-station-context-menu.c:35 src/ui/gv-station-dialog.c:424 +msgid "Add Station" +msgstr "Añadir estación" + +#: src/ui/resources/app-menu.glade:13 src/ui/resources/menubar.glade:15 +#: src/ui/resources/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:629 +msgid "Preferences" +msgstr "Preferencias" + +#: src/ui/resources/app-menu.glade:19 src/ui/resources/menubar.glade:36 +#: src/ui/resources/status-icon-menu.glade:18 +msgid "Online Help" +msgstr "Ayuda Online" + +#: src/ui/resources/app-menu.glade:24 src/ui/resources/menubar.glade:43 +#: src/ui/resources/status-icon-menu.glade:22 +msgid "About" +msgstr "Acerca de" + +#: src/ui/resources/app-menu.glade:28 src/ui/resources/menubar.glade:21 +msgid "Close UI" +msgstr "Cerrar GUI" + +#: src/ui/resources/app-menu.glade:33 src/ui/resources/menubar.glade:26 +#: src/ui/resources/status-icon-menu.glade:26 +msgid "Quit" +msgstr "Salir" + +#: src/ui/resources/main-window.glade:47 src/ui/gv-main-window.c:350 +msgid "No station selected" +msgstr "No hay ninguna estación seleccionada" + +#: src/ui/resources/main-window.glade:63 src/ui/gv-main-window.c:373 +msgid "Stopped" +msgstr "Parado" + +#: src/ui/resources/menubar.glade:5 +msgid "Menu" +msgstr "Menu" + +#: src/ui/resources/menubar.glade:33 +msgid "Help" +msgstr "Ayuda" + +#: src/ui/resources/prefs-window.glade:35 +msgid "Autoplay on Startup" +msgstr "Reproducir automáticamente al arrancar" + +#: src/ui/resources/prefs-window.glade:48 +msgid "Custom Output Pipeline" +msgstr "" + +#: src/ui/resources/prefs-window.glade:79 +msgid "Apply" +msgstr "Aplicar" + +#: src/ui/resources/prefs-window.glade:102 +msgid "Playback" +msgstr "Reproducción" + +#: src/ui/resources/prefs-window.glade:138 +msgid "Prevent sleep while playing" +msgstr "" + +#: src/ui/resources/prefs-window.glade:151 +msgid "System" +msgstr "Sistema" + +#: src/ui/resources/prefs-window.glade:197 +msgid "Native D-Bus Server" +msgstr "" + +#: src/ui/resources/prefs-window.glade:209 +msgid "MPRIS2 D-Bus Server" +msgstr "" + +#: src/ui/resources/prefs-window.glade:222 +msgid "D-Bus" +msgstr "" + +#: src/ui/resources/prefs-window.glade:238 +msgid "Misc" +msgstr "" + +#: src/ui/resources/prefs-window.glade:262 +msgid "Autoset Window Height" +msgstr "" + +#: src/ui/resources/prefs-window.glade:278 +msgid "Theme Variant" +msgstr "" + +#: src/ui/resources/prefs-window.glade:291 +msgid "System Default" +msgstr "" + +#: src/ui/resources/prefs-window.glade:292 +msgid "Prefer Dark" +msgstr "" + +#: src/ui/resources/prefs-window.glade:293 +msgid "Prefer Light" +msgstr "" + +#: src/ui/resources/prefs-window.glade:310 +msgid "Window" +msgstr "" + +#: src/ui/resources/prefs-window.glade:336 +msgid "Send Notifications" +msgstr "" + +#: src/ui/resources/prefs-window.glade:359 +msgid "Notifications" +msgstr "" + +#: src/ui/resources/prefs-window.glade:394 +msgid "Console Output" +msgstr "" + +#: src/ui/resources/prefs-window.glade:407 +msgid "Console" +msgstr "" + +#: src/ui/resources/prefs-window.glade:426 +msgid "Display" +msgstr "" + +#: src/ui/resources/prefs-window.glade:464 +msgid "Multimedia Hotkeys" +msgstr "" + +#: src/ui/resources/prefs-window.glade:477 +msgid "Keyboard" +msgstr "" + +#: src/ui/resources/prefs-window.glade:503 +msgid "Middle Click" +msgstr "" + +#: src/ui/resources/prefs-window.glade:516 +msgid "Toggle Play/Pause" +msgstr "" + +#: src/ui/resources/prefs-window.glade:517 +msgid "Mute" +msgstr "" + +#: src/ui/resources/prefs-window.glade:530 +msgid "Scrolling" +msgstr "" + +#: src/ui/resources/prefs-window.glade:543 +msgid "Change Station" +msgstr "" + +#: src/ui/resources/prefs-window.glade:544 +msgid "Change Volume" +msgstr "" + +#: src/ui/resources/prefs-window.glade:558 +msgid "Mouse (Status Icon Mode)" +msgstr "" + +#: src/ui/resources/prefs-window.glade:577 +msgid "Controls" +msgstr "" + +#: src/ui/resources/prefs-window.glade:598 +msgid "Close" +msgstr "" + +#: src/ui/resources/station-dialog.glade:12 src/ui/gv-main-window.c:261 +msgid "Name" +msgstr "" + +#: src/ui/resources/station-dialog.glade:34 src/ui/gv-main-window.c:262 +msgid "URI" +msgstr "" + +#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1134 +#, c-format +msgid "%s: %s" +msgstr "" + +#: src/core/gv-engine.c:268 +msgid "Failed to parse pipeline description" +msgstr "" + +#: src/core/gv-player.c:819 +#, c-format +msgid "'%s' is neither a known station or a valid URI" +msgstr "" + +#: src/core/gv-station-list.c:1135 +msgid "Failed to save station list" +msgstr "" + +#: src/ui/gv-main-window.c:259 +msgid "Station Information" +msgstr "" + +#: src/ui/gv-main-window.c:273 +msgid "User-agent" +msgstr "" + +#: src/ui/gv-main-window.c:277 +msgid "Bitrate" +msgstr "" + +#: src/ui/gv-main-window.c:290 +msgid "Metadata" +msgstr "" + +#: src/ui/gv-main-window.c:292 +msgid "Artist" +msgstr "" + +#: src/ui/gv-main-window.c:293 +msgid "Title" +msgstr "" + +#: src/ui/gv-main-window.c:294 +msgid "Album" +msgstr "" + +#: src/ui/gv-main-window.c:295 +msgid "Genre" +msgstr "" + +#: src/ui/gv-main-window.c:296 +msgid "Year" +msgstr "" + +#: src/ui/gv-main-window.c:297 +msgid "Comment" +msgstr "" + +#: src/ui/gv-main-window.c:363 src/ui/gv-main-window.c:391 +msgid "Playing" +msgstr "" + +#: src/ui/gv-main-window.c:366 +msgid "Connecting…" +msgstr "" + +#: src/ui/gv-main-window.c:369 +msgid "Buffering…" +msgstr "" + +#: src/ui/gv-prefs-window.c:281 +msgid "Feature disabled at compile-time." +msgstr "" + +#. +#. * Setup settings and features. +#. * These function calls create a binding between a gtk widget and +#. * an internal object, initializes the widget value, and set the +#. * widgets tooltips (label + setting). +#. +#. Misc +#: src/ui/gv-prefs-window.c:424 +msgid "Whether to start playback automatically on startup." +msgstr "" + +#: src/ui/gv-prefs-window.c:430 +msgid "Whether to use a custom output pipeline." +msgstr "" + +#: src/ui/gv-prefs-window.c:436 +msgid "" +"The GStreamer output pipeline used for playback. Refer to theonline " +"documentation for examples." +msgstr "" + +#: src/ui/gv-prefs-window.c:452 +msgid "Prevent the system from going to sleep while playing." +msgstr "" + +#: src/ui/gv-prefs-window.c:457 +msgid "Enable the native D-Bus server (needed for the command-line interface)." +msgstr "" + +#: src/ui/gv-prefs-window.c:463 +msgid "Enable the MPRIS2 D-Bus server." +msgstr "" + +#. Display +#: src/ui/gv-prefs-window.c:469 +msgid "Prefer a different variant of the theme (if available)." +msgstr "" + +#: src/ui/gv-prefs-window.c:476 +msgid "" +"Automatically adjust the window height when a station is added or removed." +msgstr "" + +#: src/ui/gv-prefs-window.c:483 +msgid "Setting not available in status icon mode." +msgstr "" + +#: src/ui/gv-prefs-window.c:487 +msgid "Show notification when the status changes." +msgstr "" + +#: src/ui/gv-prefs-window.c:492 +msgid "Display information on the standard output." +msgstr "" + +#. Controls +#: src/ui/gv-prefs-window.c:498 +msgid "Bind mutimedia keys (play/pause/stop/previous/next)." +msgstr "" + +#: src/ui/gv-prefs-window.c:504 +msgid "Action triggered by a middle click on the status icon." +msgstr "" + +#: src/ui/gv-prefs-window.c:510 +msgid "Action triggered by mouse-scrolling on the status icon." +msgstr "" + +#: src/ui/gv-prefs-window.c:516 +msgid "Setting only available in status icon mode." +msgstr "" + +#: src/ui/gv-station-context-menu.c:36 +msgid "Remove Station" +msgstr "" + +#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:424 +msgid "Edit Station" +msgstr "" + +#: src/ui/gv-station-dialog.c:281 +msgid "Cancel" +msgstr "" + +#: src/ui/gv-station-dialog.c:282 +msgid "Save" +msgstr "" + +#: src/ui/gv-status-icon.c:131 +msgid "stopped" +msgstr "" + +#: src/ui/gv-status-icon.c:134 +msgid "connecting" +msgstr "" + +#: src/ui/gv-status-icon.c:137 +msgid "buffering" +msgstr "" + +#: src/ui/gv-status-icon.c:140 +msgid "playing" +msgstr "" + +#: src/ui/gv-status-icon.c:143 +msgid "unknown state" +msgstr "" + +#: src/ui/gv-status-icon.c:150 +msgid "muted" +msgstr "" + +#: src/ui/gv-status-icon.c:154 +msgid "vol." +msgstr "" + +#: src/ui/gv-status-icon.c:161 +msgid "No station" +msgstr "" + +#: src/ui/gv-status-icon.c:168 +msgid "No metadata" +msgstr "" + +#: src/feat/gv-hotkeys.c:145 +#, c-format +msgid "" +"%s:\n" +"%s" +msgstr "" + +#: src/feat/gv-hotkeys.c:146 +msgid "Failed to bind the following keys" +msgstr "" + +#: src/feat/gv-inhibitor.c:111 +msgid "Failed to inhibit system sleep" +msgstr "" + +#: src/feat/gv-notifications.c:59 +#, c-format +msgid "Playing %s" +msgstr "" + +#: src/feat/gv-notifications.c:62 +#, c-format +msgid "Playing <%s>" +msgstr "" + +#: src/feat/gv-notifications.c:65 +msgid "Playing Station" +msgstr "" + +#: src/feat/gv-notifications.c:103 +msgid "(Unknown title)" +msgstr "" + +#: src/feat/gv-notifications.c:110 +msgid "New Track" +msgstr "" + +#: src/feat/gv-notifications.c:122 +msgid "Error" +msgstr "" diff -Nru goodvibes-0.3.6/po/fr.po goodvibes-0.4.2/po/fr.po --- goodvibes-0.3.6/po/fr.po 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/po/fr.po 2018-11-10 06:04:58.000000000 +0000 @@ -7,9 +7,9 @@ msgstr "" "Project-Id-Version: goodvibes 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-03-28 00:40+0700\n" -"PO-Revision-Date: 2018-03-21 12:48+0000\n" -"Last-Translator: Étienne Deparis \n" +"POT-Creation-Date: 2018-11-09 19:25+0700\n" +"PO-Revision-Date: 2018-05-22 07:26+0000\n" +"Last-Translator: Arnaud Rebillout \n" "Language-Team: French \n" "Language: fr\n" @@ -17,214 +17,226 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 2.20-dev\n" +"X-Generator: Weblate 3.0-dev\n" -#: data/com.elboulangero.Goodvibes.desktop.in:3 src/main.c:149 -msgid "Goodvibes Radio Player" -msgstr "Lecteur de radio Goodvibes" +#: data/io.gitlab.Goodvibes.appdata.xml.in:4 +#: data/io.gitlab.Goodvibes.desktop.in:3 src/main.c:149 +msgid "Goodvibes" +msgstr "Goodvibes" -#: data/com.elboulangero.Goodvibes.desktop.in:4 -msgid "Radio Player" -msgstr "Lecteur radio" - -#: data/com.elboulangero.Goodvibes.desktop.in:5 +#: data/io.gitlab.Goodvibes.appdata.xml.in:5 +#: data/io.gitlab.Goodvibes.desktop.in:5 msgid "Play web radios" msgstr "Écouter des radios web" +#: data/io.gitlab.Goodvibes.appdata.xml.in:10 +msgid "Goodvibes is a simple internet radio player for GNU/Linux." +msgstr "" + +#: data/io.gitlab.Goodvibes.appdata.xml.in:13 +msgid "" +"It comes with every basic features you can expect from an audio player, such " +"as multimedia keys, notifications, system sleep inhibition, and MPRIS2 " +"support." +msgstr "" + +#: data/io.gitlab.Goodvibes.desktop.in:4 +msgid "Radio Player" +msgstr "Lecteur radio" + #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! -#: data/com.elboulangero.Goodvibes.desktop.in:7 +#: data/io.gitlab.Goodvibes.desktop.in:7 msgid "Audio;Radio;Player;" msgstr "Audio;Radio;Player;" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! -#: data/com.elboulangero.Goodvibes.desktop.in:11 -msgid "goodvibes" -msgstr "goodvibes" - -#: data/ui/app-menu.glade:6 data/ui/menubar.glade:8 -#: data/ui/status-icon-menu.glade:6 src/ui/gv-station-context-menu.c:35 -#: src/ui/gv-station-dialog.c:428 +#: data/io.gitlab.Goodvibes.desktop.in:11 +msgid "io.gitlab.Goodvibes" +msgstr "io.gitlab.Goodvibes" + +#: src/ui/resources/app-menu.glade:6 src/ui/resources/menubar.glade:8 +#: src/ui/resources/status-icon-menu.glade:6 +#: src/ui/gv-station-context-menu.c:35 src/ui/gv-station-dialog.c:424 msgid "Add Station" msgstr "Ajouter une station" -#: data/ui/app-menu.glade:13 data/ui/menubar.glade:15 -#: data/ui/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:633 +#: src/ui/resources/app-menu.glade:13 src/ui/resources/menubar.glade:15 +#: src/ui/resources/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:629 msgid "Preferences" msgstr "Préférences" -#: data/ui/app-menu.glade:19 data/ui/menubar.glade:36 -#: data/ui/status-icon-menu.glade:18 +#: src/ui/resources/app-menu.glade:19 src/ui/resources/menubar.glade:36 +#: src/ui/resources/status-icon-menu.glade:18 msgid "Online Help" msgstr "Aide en ligne" -#: data/ui/app-menu.glade:24 data/ui/menubar.glade:43 -#: data/ui/status-icon-menu.glade:22 +#: src/ui/resources/app-menu.glade:24 src/ui/resources/menubar.glade:43 +#: src/ui/resources/status-icon-menu.glade:22 msgid "About" msgstr "À propos" -#: data/ui/app-menu.glade:28 data/ui/menubar.glade:21 +#: src/ui/resources/app-menu.glade:28 src/ui/resources/menubar.glade:21 msgid "Close UI" msgstr "Fermer l'interface" -#: data/ui/app-menu.glade:33 data/ui/menubar.glade:26 -#: data/ui/status-icon-menu.glade:26 +#: src/ui/resources/app-menu.glade:33 src/ui/resources/menubar.glade:26 +#: src/ui/resources/status-icon-menu.glade:26 msgid "Quit" msgstr "Quitter" -#: data/ui/main-window.glade:47 src/ui/gv-main-window.c:351 +#: src/ui/resources/main-window.glade:47 src/ui/gv-main-window.c:350 msgid "No station selected" msgstr "Aucune station sélectionnée" -#: data/ui/main-window.glade:63 src/ui/gv-main-window.c:374 +#: src/ui/resources/main-window.glade:63 src/ui/gv-main-window.c:373 msgid "Stopped" msgstr "Arrêté" -#: data/ui/menubar.glade:5 +#: src/ui/resources/menubar.glade:5 msgid "Menu" msgstr "Menu" -#: data/ui/menubar.glade:33 +#: src/ui/resources/menubar.glade:33 msgid "Help" msgstr "Aide" -#: data/ui/prefs-window.glade:35 +#: src/ui/resources/prefs-window.glade:35 msgid "Autoplay on Startup" msgstr "Lancer l'écoute au démarrage" -#: data/ui/prefs-window.glade:48 +#: src/ui/resources/prefs-window.glade:48 msgid "Custom Output Pipeline" msgstr "Chaîne de traitement de sortie personnalisée" -#: data/ui/prefs-window.glade:79 +#: src/ui/resources/prefs-window.glade:79 msgid "Apply" msgstr "Appliquer" -#: data/ui/prefs-window.glade:102 +#: src/ui/resources/prefs-window.glade:102 msgid "Playback" msgstr "Lecture" -#: data/ui/prefs-window.glade:138 +#: src/ui/resources/prefs-window.glade:138 msgid "Prevent sleep while playing" msgstr "Empêcher la mise en veille lors de l'écoute" -#: data/ui/prefs-window.glade:151 +#: src/ui/resources/prefs-window.glade:151 msgid "System" msgstr "Système" -#: data/ui/prefs-window.glade:197 +#: src/ui/resources/prefs-window.glade:197 msgid "Native D-Bus Server" msgstr "Serveur D-Bus natif" -#: data/ui/prefs-window.glade:209 +#: src/ui/resources/prefs-window.glade:209 msgid "MPRIS2 D-Bus Server" msgstr "Serveur D-Bus MPRIS2" -#: data/ui/prefs-window.glade:222 +#: src/ui/resources/prefs-window.glade:222 msgid "D-Bus" msgstr "D-Bus" -#: data/ui/prefs-window.glade:238 +#: src/ui/resources/prefs-window.glade:238 msgid "Misc" msgstr "Divers" -#: data/ui/prefs-window.glade:262 +#: src/ui/resources/prefs-window.glade:262 msgid "Autoset Window Height" msgstr "Fixer automatiquement la hauteur de la fenêtre" -#: data/ui/prefs-window.glade:278 +#: src/ui/resources/prefs-window.glade:278 msgid "Theme Variant" -msgstr "" +msgstr "Variante de thème" -#: data/ui/prefs-window.glade:291 -#, fuzzy +#: src/ui/resources/prefs-window.glade:291 msgid "System Default" -msgstr "Système" +msgstr "Valeur par défaut du système" -#: data/ui/prefs-window.glade:292 +#: src/ui/resources/prefs-window.glade:292 msgid "Prefer Dark" -msgstr "" +msgstr "Plutôt sombre" -#: data/ui/prefs-window.glade:293 +#: src/ui/resources/prefs-window.glade:293 msgid "Prefer Light" -msgstr "" +msgstr "Plutôt clair" -#: data/ui/prefs-window.glade:310 +#: src/ui/resources/prefs-window.glade:310 msgid "Window" -msgstr "" +msgstr "Fenêtre" -#: data/ui/prefs-window.glade:336 +#: src/ui/resources/prefs-window.glade:336 msgid "Send Notifications" msgstr "Afficher des notifications" -#: data/ui/prefs-window.glade:359 +#: src/ui/resources/prefs-window.glade:359 msgid "Notifications" msgstr "Notifications" -#: data/ui/prefs-window.glade:394 +#: src/ui/resources/prefs-window.glade:394 msgid "Console Output" msgstr "Sortie de la console" -#: data/ui/prefs-window.glade:407 +#: src/ui/resources/prefs-window.glade:407 msgid "Console" msgstr "Console" -#: data/ui/prefs-window.glade:426 +#: src/ui/resources/prefs-window.glade:426 msgid "Display" msgstr "Affichage" -#: data/ui/prefs-window.glade:464 +#: src/ui/resources/prefs-window.glade:464 msgid "Multimedia Hotkeys" msgstr "Touches Multimédia" -#: data/ui/prefs-window.glade:477 +#: src/ui/resources/prefs-window.glade:477 msgid "Keyboard" msgstr "Clavier" -#: data/ui/prefs-window.glade:503 +#: src/ui/resources/prefs-window.glade:503 msgid "Middle Click" msgstr "Clic milieu" -#: data/ui/prefs-window.glade:516 +#: src/ui/resources/prefs-window.glade:516 msgid "Toggle Play/Pause" msgstr "Lecture/Pause" -#: data/ui/prefs-window.glade:517 +#: src/ui/resources/prefs-window.glade:517 msgid "Mute" msgstr "Silence" -#: data/ui/prefs-window.glade:530 +#: src/ui/resources/prefs-window.glade:530 msgid "Scrolling" msgstr "Défilement" -#: data/ui/prefs-window.glade:543 +#: src/ui/resources/prefs-window.glade:543 msgid "Change Station" msgstr "Changer de station" -#: data/ui/prefs-window.glade:544 +#: src/ui/resources/prefs-window.glade:544 msgid "Change Volume" msgstr "Changer le volume" -#: data/ui/prefs-window.glade:558 +#: src/ui/resources/prefs-window.glade:558 msgid "Mouse (Status Icon Mode)" msgstr "Souris (en mode icône de statut)" -#: data/ui/prefs-window.glade:577 +#: src/ui/resources/prefs-window.glade:577 msgid "Controls" msgstr "Contrôles" -#: data/ui/prefs-window.glade:598 +#: src/ui/resources/prefs-window.glade:598 msgid "Close" msgstr "Fermer" -#: data/ui/station-dialog.glade:12 src/ui/gv-main-window.c:262 +#: src/ui/resources/station-dialog.glade:12 src/ui/gv-main-window.c:261 msgid "Name" msgstr "Nom" -#: data/ui/station-dialog.glade:34 src/ui/gv-main-window.c:263 +#: src/ui/resources/station-dialog.glade:34 src/ui/gv-main-window.c:262 msgid "URI" msgstr "Adresse (URI)" -#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1088 +#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1134 #, c-format msgid "%s: %s" msgstr "%s: %s" @@ -238,131 +250,142 @@ msgid "'%s' is neither a known station or a valid URI" msgstr "'%s' n'est ni une station connue, ni une URI valide" -#: src/core/gv-station-list.c:1089 +#: src/core/gv-station-list.c:1135 msgid "Failed to save station list" msgstr "Échec de l'enregistrement de la liste des stations" -#: src/ui/gv-main-window.c:260 +#: src/ui/gv-main-window.c:259 msgid "Station Information" msgstr "Information sur la station" -#: src/ui/gv-main-window.c:274 +#: src/ui/gv-main-window.c:273 msgid "User-agent" msgstr "Agent utilisateur" -#: src/ui/gv-main-window.c:278 +#: src/ui/gv-main-window.c:277 msgid "Bitrate" -msgstr "Bitrate" +msgstr "Débit" -#: src/ui/gv-main-window.c:291 +#: src/ui/gv-main-window.c:290 msgid "Metadata" msgstr "Métadonnée" -#: src/ui/gv-main-window.c:293 +#: src/ui/gv-main-window.c:292 msgid "Artist" msgstr "Artiste" -#: src/ui/gv-main-window.c:294 +#: src/ui/gv-main-window.c:293 msgid "Title" msgstr "Titre" -#: src/ui/gv-main-window.c:295 +#: src/ui/gv-main-window.c:294 msgid "Album" msgstr "Album" -#: src/ui/gv-main-window.c:296 +#: src/ui/gv-main-window.c:295 msgid "Genre" msgstr "Genre" -#: src/ui/gv-main-window.c:297 +#: src/ui/gv-main-window.c:296 msgid "Year" msgstr "Année" -#: src/ui/gv-main-window.c:298 +#: src/ui/gv-main-window.c:297 msgid "Comment" msgstr "Commentaire" -#: src/ui/gv-main-window.c:364 src/ui/gv-main-window.c:392 +#: src/ui/gv-main-window.c:363 src/ui/gv-main-window.c:391 msgid "Playing" msgstr "Lecture" -#: src/ui/gv-main-window.c:367 +#: src/ui/gv-main-window.c:366 msgid "Connecting…" msgstr "Connexion…" -#: src/ui/gv-main-window.c:370 +#: src/ui/gv-main-window.c:369 msgid "Buffering…" msgstr "Mise en mémoire tampon…" -#: src/ui/gv-prefs-window.c:282 +#: src/ui/gv-prefs-window.c:281 msgid "Feature disabled at compile-time." msgstr "Fonctionnalité désactivée lors de la compilation." -#: src/ui/gv-prefs-window.c:428 +#. +#. * Setup settings and features. +#. * These function calls create a binding between a gtk widget and +#. * an internal object, initializes the widget value, and set the +#. * widgets tooltips (label + setting). +#. +#. Misc +#: src/ui/gv-prefs-window.c:424 msgid "Whether to start playback automatically on startup." msgstr "Automatiquement reprendre la lecture au démarrage." -#: src/ui/gv-prefs-window.c:434 +#: src/ui/gv-prefs-window.c:430 msgid "Whether to use a custom output pipeline." msgstr "" "Nécessité d'utiliser une chaîne de traitements de sortie personnalisée." -#: src/ui/gv-prefs-window.c:440 +#: src/ui/gv-prefs-window.c:436 msgid "" "The GStreamer output pipeline used for playback. Refer to theonline " "documentation for examples." msgstr "" +"La chaîne de traitement GStreamer utilisée pour la lecture. Vous pouvez vous " +"référer à la documentation en ligne pour avoir des exemples." -#: src/ui/gv-prefs-window.c:456 +#: src/ui/gv-prefs-window.c:452 msgid "Prevent the system from going to sleep while playing." msgstr "Empêcher le système de se mettre en veille lors de la lecture." -#: src/ui/gv-prefs-window.c:461 +#: src/ui/gv-prefs-window.c:457 msgid "Enable the native D-Bus server (needed for the command-line interface)." msgstr "" "Activer le serveur natif D-Bus (requis par l'interface en ligne de commande)." -#: src/ui/gv-prefs-window.c:467 +#: src/ui/gv-prefs-window.c:463 msgid "Enable the MPRIS2 D-Bus server." msgstr "Activer le serveur D-BUS MPRIS2." -#: src/ui/gv-prefs-window.c:473 +#. Display +#: src/ui/gv-prefs-window.c:469 msgid "Prefer a different variant of the theme (if available)." -msgstr "" +msgstr "Choisir une variante du thème actuel (si disponible)." -#: src/ui/gv-prefs-window.c:480 +#: src/ui/gv-prefs-window.c:476 msgid "" "Automatically adjust the window height when a station is added or removed." msgstr "" "Ajuster automatiquement la hauteur de la fenêtre lorsqu'une station est " "ajoutée ou supprimée." -#: src/ui/gv-prefs-window.c:487 +#: src/ui/gv-prefs-window.c:483 msgid "Setting not available in status icon mode." msgstr "Paramètre non disponible en mode icône de statut." -#: src/ui/gv-prefs-window.c:491 +#: src/ui/gv-prefs-window.c:487 msgid "Show notification when the status changes." msgstr "Afficher une notification lorsque le statut change." -#: src/ui/gv-prefs-window.c:496 +#: src/ui/gv-prefs-window.c:492 msgid "Display information on the standard output." msgstr "Afficher les informations sur la sortie standard." -#: src/ui/gv-prefs-window.c:502 +#. Controls +#: src/ui/gv-prefs-window.c:498 msgid "Bind mutimedia keys (play/pause/stop/previous/next)." msgstr "Associer les touches multimédia (play/pause/stop/previous/next)." -#: src/ui/gv-prefs-window.c:508 +#: src/ui/gv-prefs-window.c:504 msgid "Action triggered by a middle click on the status icon." msgstr "Action effectuée lors d'un clic milieu sur l'icône de statut." -#: src/ui/gv-prefs-window.c:514 +#: src/ui/gv-prefs-window.c:510 msgid "Action triggered by mouse-scrolling on the status icon." msgstr "" "Action effectuée après utilisation de la molette sur l'icône de statut." -#: src/ui/gv-prefs-window.c:520 +#: src/ui/gv-prefs-window.c:516 msgid "Setting only available in status icon mode." msgstr "Paramètre disponible seulement en mode icône de statut." @@ -370,55 +393,55 @@ msgid "Remove Station" msgstr "Supprimer la station" -#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:428 +#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:424 msgid "Edit Station" msgstr "Éditer la station" -#: src/ui/gv-station-dialog.c:284 +#: src/ui/gv-station-dialog.c:281 msgid "Cancel" msgstr "Annuler" -#: src/ui/gv-station-dialog.c:285 +#: src/ui/gv-station-dialog.c:282 msgid "Save" msgstr "Enregistrer" -#: src/ui/gv-status-icon.c:130 +#: src/ui/gv-status-icon.c:131 msgid "stopped" msgstr "Stoppé" -#: src/ui/gv-status-icon.c:133 +#: src/ui/gv-status-icon.c:134 msgid "connecting" msgstr "connexion" -#: src/ui/gv-status-icon.c:136 +#: src/ui/gv-status-icon.c:137 msgid "buffering" msgstr "mise en mémoire tampon" -#: src/ui/gv-status-icon.c:139 +#: src/ui/gv-status-icon.c:140 msgid "playing" msgstr "lecture" -#: src/ui/gv-status-icon.c:142 +#: src/ui/gv-status-icon.c:143 msgid "unknown state" msgstr "état inconnu" -#: src/ui/gv-status-icon.c:149 +#: src/ui/gv-status-icon.c:150 msgid "muted" msgstr "coupé" -#: src/ui/gv-status-icon.c:153 +#: src/ui/gv-status-icon.c:154 msgid "vol." msgstr "vol." -#: src/ui/gv-status-icon.c:160 +#: src/ui/gv-status-icon.c:161 msgid "No station" msgstr "Aucune station" -#: src/ui/gv-status-icon.c:167 +#: src/ui/gv-status-icon.c:168 msgid "No metadata" msgstr "Aucune métadonnée" -#: src/feat/gv-hotkeys.c:144 +#: src/feat/gv-hotkeys.c:145 #, c-format msgid "" "%s:\n" @@ -427,7 +450,7 @@ "%s:\n" "%s" -#: src/feat/gv-hotkeys.c:145 +#: src/feat/gv-hotkeys.c:146 msgid "Failed to bind the following keys" msgstr "Échec lors de l'association des touches suivantes" @@ -435,32 +458,38 @@ msgid "Failed to inhibit system sleep" msgstr "Impossible d'empêcher la mise en veille du système" -#: src/feat/gv-notifications.c:93 +#: src/feat/gv-notifications.c:59 #, c-format msgid "Playing %s" msgstr "Lecture de %s" -#: src/feat/gv-notifications.c:96 +#: src/feat/gv-notifications.c:62 #, c-format msgid "Playing <%s>" msgstr "Lecture de <%s>" -#: src/feat/gv-notifications.c:137 -msgid "(Unknown title)" -msgstr "(Titre inconnu)" - -#: src/feat/gv-notifications.c:263 +#: src/feat/gv-notifications.c:65 msgid "Playing Station" msgstr "Lecture de la station" -#: src/feat/gv-notifications.c:266 +#: src/feat/gv-notifications.c:103 +msgid "(Unknown title)" +msgstr "(Titre inconnu)" + +#: src/feat/gv-notifications.c:110 msgid "New Track" msgstr "Nouvelle piste" -#: src/feat/gv-notifications.c:269 +#: src/feat/gv-notifications.c:122 msgid "Error" msgstr "Erreur" +#~ msgid "goodvibes" +#~ msgstr "goodvibes" + +#~ msgid "Goodvibes Radio Player" +#~ msgstr "Lecteur de radio Goodvibes" + #~ msgid "Window Behavior" #~ msgstr "Comportement de la fenêtre" diff -Nru goodvibes-0.3.6/po/goodvibes.pot goodvibes-0.4.2/po/goodvibes.pot --- goodvibes-0.3.6/po/goodvibes.pot 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/po/goodvibes.pot 2018-11-10 06:04:58.000000000 +0000 @@ -1,14 +1,14 @@ # SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the goodvibes package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: goodvibes 0.3.5\n" +"Project-Id-Version: goodvibes\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-03-28 00:40+0700\n" +"POT-Creation-Date: 2018-11-09 19:25+0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,211 +17,224 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: data/com.elboulangero.Goodvibes.desktop.in:3 src/main.c:149 -msgid "Goodvibes Radio Player" +#: data/io.gitlab.Goodvibes.appdata.xml.in:4 +#: data/io.gitlab.Goodvibes.desktop.in:3 src/main.c:149 +msgid "Goodvibes" msgstr "" -#: data/com.elboulangero.Goodvibes.desktop.in:4 -msgid "Radio Player" +#: data/io.gitlab.Goodvibes.appdata.xml.in:5 +#: data/io.gitlab.Goodvibes.desktop.in:5 +msgid "Play web radios" msgstr "" -#: data/com.elboulangero.Goodvibes.desktop.in:5 -msgid "Play web radios" +#: data/io.gitlab.Goodvibes.appdata.xml.in:10 +msgid "Goodvibes is a simple internet radio player for GNU/Linux." +msgstr "" + +#: data/io.gitlab.Goodvibes.appdata.xml.in:13 +msgid "" +"It comes with every basic features you can expect from an audio player, such " +"as multimedia keys, notifications, system sleep inhibition, and MPRIS2 " +"support." +msgstr "" + +#: data/io.gitlab.Goodvibes.desktop.in:4 +msgid "Radio Player" msgstr "" #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! -#: data/com.elboulangero.Goodvibes.desktop.in:7 +#: data/io.gitlab.Goodvibes.desktop.in:7 msgid "Audio;Radio;Player;" msgstr "" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! -#: data/com.elboulangero.Goodvibes.desktop.in:11 -msgid "goodvibes" +#: data/io.gitlab.Goodvibes.desktop.in:11 +msgid "io.gitlab.Goodvibes" msgstr "" -#: data/ui/app-menu.glade:6 data/ui/menubar.glade:8 -#: data/ui/status-icon-menu.glade:6 src/ui/gv-station-context-menu.c:35 -#: src/ui/gv-station-dialog.c:428 +#: src/ui/resources/app-menu.glade:6 src/ui/resources/menubar.glade:8 +#: src/ui/resources/status-icon-menu.glade:6 +#: src/ui/gv-station-context-menu.c:35 src/ui/gv-station-dialog.c:424 msgid "Add Station" msgstr "" -#: data/ui/app-menu.glade:13 data/ui/menubar.glade:15 -#: data/ui/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:633 +#: src/ui/resources/app-menu.glade:13 src/ui/resources/menubar.glade:15 +#: src/ui/resources/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:629 msgid "Preferences" msgstr "" -#: data/ui/app-menu.glade:19 data/ui/menubar.glade:36 -#: data/ui/status-icon-menu.glade:18 +#: src/ui/resources/app-menu.glade:19 src/ui/resources/menubar.glade:36 +#: src/ui/resources/status-icon-menu.glade:18 msgid "Online Help" msgstr "" -#: data/ui/app-menu.glade:24 data/ui/menubar.glade:43 -#: data/ui/status-icon-menu.glade:22 +#: src/ui/resources/app-menu.glade:24 src/ui/resources/menubar.glade:43 +#: src/ui/resources/status-icon-menu.glade:22 msgid "About" msgstr "" -#: data/ui/app-menu.glade:28 data/ui/menubar.glade:21 +#: src/ui/resources/app-menu.glade:28 src/ui/resources/menubar.glade:21 msgid "Close UI" msgstr "" -#: data/ui/app-menu.glade:33 data/ui/menubar.glade:26 -#: data/ui/status-icon-menu.glade:26 +#: src/ui/resources/app-menu.glade:33 src/ui/resources/menubar.glade:26 +#: src/ui/resources/status-icon-menu.glade:26 msgid "Quit" msgstr "" -#: data/ui/main-window.glade:47 src/ui/gv-main-window.c:351 +#: src/ui/resources/main-window.glade:47 src/ui/gv-main-window.c:350 msgid "No station selected" msgstr "" -#: data/ui/main-window.glade:63 src/ui/gv-main-window.c:374 +#: src/ui/resources/main-window.glade:63 src/ui/gv-main-window.c:373 msgid "Stopped" msgstr "" -#: data/ui/menubar.glade:5 +#: src/ui/resources/menubar.glade:5 msgid "Menu" msgstr "" -#: data/ui/menubar.glade:33 +#: src/ui/resources/menubar.glade:33 msgid "Help" msgstr "" -#: data/ui/prefs-window.glade:35 +#: src/ui/resources/prefs-window.glade:35 msgid "Autoplay on Startup" msgstr "" -#: data/ui/prefs-window.glade:48 +#: src/ui/resources/prefs-window.glade:48 msgid "Custom Output Pipeline" msgstr "" -#: data/ui/prefs-window.glade:79 +#: src/ui/resources/prefs-window.glade:79 msgid "Apply" msgstr "" -#: data/ui/prefs-window.glade:102 +#: src/ui/resources/prefs-window.glade:102 msgid "Playback" msgstr "" -#: data/ui/prefs-window.glade:138 +#: src/ui/resources/prefs-window.glade:138 msgid "Prevent sleep while playing" msgstr "" -#: data/ui/prefs-window.glade:151 +#: src/ui/resources/prefs-window.glade:151 msgid "System" msgstr "" -#: data/ui/prefs-window.glade:197 +#: src/ui/resources/prefs-window.glade:197 msgid "Native D-Bus Server" msgstr "" -#: data/ui/prefs-window.glade:209 +#: src/ui/resources/prefs-window.glade:209 msgid "MPRIS2 D-Bus Server" msgstr "" -#: data/ui/prefs-window.glade:222 +#: src/ui/resources/prefs-window.glade:222 msgid "D-Bus" msgstr "" -#: data/ui/prefs-window.glade:238 +#: src/ui/resources/prefs-window.glade:238 msgid "Misc" msgstr "" -#: data/ui/prefs-window.glade:262 +#: src/ui/resources/prefs-window.glade:262 msgid "Autoset Window Height" msgstr "" -#: data/ui/prefs-window.glade:278 +#: src/ui/resources/prefs-window.glade:278 msgid "Theme Variant" msgstr "" -#: data/ui/prefs-window.glade:291 +#: src/ui/resources/prefs-window.glade:291 msgid "System Default" msgstr "" -#: data/ui/prefs-window.glade:292 +#: src/ui/resources/prefs-window.glade:292 msgid "Prefer Dark" msgstr "" -#: data/ui/prefs-window.glade:293 +#: src/ui/resources/prefs-window.glade:293 msgid "Prefer Light" msgstr "" -#: data/ui/prefs-window.glade:310 +#: src/ui/resources/prefs-window.glade:310 msgid "Window" msgstr "" -#: data/ui/prefs-window.glade:336 +#: src/ui/resources/prefs-window.glade:336 msgid "Send Notifications" msgstr "" -#: data/ui/prefs-window.glade:359 +#: src/ui/resources/prefs-window.glade:359 msgid "Notifications" msgstr "" -#: data/ui/prefs-window.glade:394 +#: src/ui/resources/prefs-window.glade:394 msgid "Console Output" msgstr "" -#: data/ui/prefs-window.glade:407 +#: src/ui/resources/prefs-window.glade:407 msgid "Console" msgstr "" -#: data/ui/prefs-window.glade:426 +#: src/ui/resources/prefs-window.glade:426 msgid "Display" msgstr "" -#: data/ui/prefs-window.glade:464 +#: src/ui/resources/prefs-window.glade:464 msgid "Multimedia Hotkeys" msgstr "" -#: data/ui/prefs-window.glade:477 +#: src/ui/resources/prefs-window.glade:477 msgid "Keyboard" msgstr "" -#: data/ui/prefs-window.glade:503 +#: src/ui/resources/prefs-window.glade:503 msgid "Middle Click" msgstr "" -#: data/ui/prefs-window.glade:516 +#: src/ui/resources/prefs-window.glade:516 msgid "Toggle Play/Pause" msgstr "" -#: data/ui/prefs-window.glade:517 +#: src/ui/resources/prefs-window.glade:517 msgid "Mute" msgstr "" -#: data/ui/prefs-window.glade:530 +#: src/ui/resources/prefs-window.glade:530 msgid "Scrolling" msgstr "" -#: data/ui/prefs-window.glade:543 +#: src/ui/resources/prefs-window.glade:543 msgid "Change Station" msgstr "" -#: data/ui/prefs-window.glade:544 +#: src/ui/resources/prefs-window.glade:544 msgid "Change Volume" msgstr "" -#: data/ui/prefs-window.glade:558 +#: src/ui/resources/prefs-window.glade:558 msgid "Mouse (Status Icon Mode)" msgstr "" -#: data/ui/prefs-window.glade:577 +#: src/ui/resources/prefs-window.glade:577 msgid "Controls" msgstr "" -#: data/ui/prefs-window.glade:598 +#: src/ui/resources/prefs-window.glade:598 msgid "Close" msgstr "" -#: data/ui/station-dialog.glade:12 src/ui/gv-main-window.c:262 +#: src/ui/resources/station-dialog.glade:12 src/ui/gv-main-window.c:261 msgid "Name" msgstr "" -#: data/ui/station-dialog.glade:34 src/ui/gv-main-window.c:263 +#: src/ui/resources/station-dialog.glade:34 src/ui/gv-main-window.c:262 msgid "URI" msgstr "" -#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1088 +#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1134 #, c-format msgid "%s: %s" msgstr "" @@ -235,126 +248,135 @@ msgid "'%s' is neither a known station or a valid URI" msgstr "" -#: src/core/gv-station-list.c:1089 +#: src/core/gv-station-list.c:1135 msgid "Failed to save station list" msgstr "" -#: src/ui/gv-main-window.c:260 +#: src/ui/gv-main-window.c:259 msgid "Station Information" msgstr "" -#: src/ui/gv-main-window.c:274 +#: src/ui/gv-main-window.c:273 msgid "User-agent" msgstr "" -#: src/ui/gv-main-window.c:278 +#: src/ui/gv-main-window.c:277 msgid "Bitrate" msgstr "" -#: src/ui/gv-main-window.c:291 +#: src/ui/gv-main-window.c:290 msgid "Metadata" msgstr "" -#: src/ui/gv-main-window.c:293 +#: src/ui/gv-main-window.c:292 msgid "Artist" msgstr "" -#: src/ui/gv-main-window.c:294 +#: src/ui/gv-main-window.c:293 msgid "Title" msgstr "" -#: src/ui/gv-main-window.c:295 +#: src/ui/gv-main-window.c:294 msgid "Album" msgstr "" -#: src/ui/gv-main-window.c:296 +#: src/ui/gv-main-window.c:295 msgid "Genre" msgstr "" -#: src/ui/gv-main-window.c:297 +#: src/ui/gv-main-window.c:296 msgid "Year" msgstr "" -#: src/ui/gv-main-window.c:298 +#: src/ui/gv-main-window.c:297 msgid "Comment" msgstr "" -#: src/ui/gv-main-window.c:364 src/ui/gv-main-window.c:392 +#: src/ui/gv-main-window.c:363 src/ui/gv-main-window.c:391 msgid "Playing" msgstr "" -#: src/ui/gv-main-window.c:367 +#: src/ui/gv-main-window.c:366 msgid "Connecting…" msgstr "" -#: src/ui/gv-main-window.c:370 +#: src/ui/gv-main-window.c:369 msgid "Buffering…" msgstr "" -#: src/ui/gv-prefs-window.c:282 +#: src/ui/gv-prefs-window.c:281 msgid "Feature disabled at compile-time." msgstr "" -#: src/ui/gv-prefs-window.c:428 +#. +#. * Setup settings and features. +#. * These function calls create a binding between a gtk widget and +#. * an internal object, initializes the widget value, and set the +#. * widgets tooltips (label + setting). +#. +#. Misc +#: src/ui/gv-prefs-window.c:424 msgid "Whether to start playback automatically on startup." msgstr "" -#: src/ui/gv-prefs-window.c:434 +#: src/ui/gv-prefs-window.c:430 msgid "Whether to use a custom output pipeline." msgstr "" -#: src/ui/gv-prefs-window.c:440 +#: src/ui/gv-prefs-window.c:436 msgid "" "The GStreamer output pipeline used for playback. Refer to theonline " "documentation for examples." msgstr "" -#: src/ui/gv-prefs-window.c:456 +#: src/ui/gv-prefs-window.c:452 msgid "Prevent the system from going to sleep while playing." msgstr "" -#: src/ui/gv-prefs-window.c:461 +#: src/ui/gv-prefs-window.c:457 msgid "Enable the native D-Bus server (needed for the command-line interface)." msgstr "" -#: src/ui/gv-prefs-window.c:467 +#: src/ui/gv-prefs-window.c:463 msgid "Enable the MPRIS2 D-Bus server." msgstr "" -#: src/ui/gv-prefs-window.c:473 +#. Display +#: src/ui/gv-prefs-window.c:469 msgid "Prefer a different variant of the theme (if available)." msgstr "" -#: src/ui/gv-prefs-window.c:480 +#: src/ui/gv-prefs-window.c:476 msgid "" "Automatically adjust the window height when a station is added or removed." msgstr "" -#: src/ui/gv-prefs-window.c:487 +#: src/ui/gv-prefs-window.c:483 msgid "Setting not available in status icon mode." msgstr "" -#: src/ui/gv-prefs-window.c:491 +#: src/ui/gv-prefs-window.c:487 msgid "Show notification when the status changes." msgstr "" -#: src/ui/gv-prefs-window.c:496 +#: src/ui/gv-prefs-window.c:492 msgid "Display information on the standard output." msgstr "" -#: src/ui/gv-prefs-window.c:502 +#. Controls +#: src/ui/gv-prefs-window.c:498 msgid "Bind mutimedia keys (play/pause/stop/previous/next)." msgstr "" -#: src/ui/gv-prefs-window.c:508 +#: src/ui/gv-prefs-window.c:504 msgid "Action triggered by a middle click on the status icon." msgstr "" -#: src/ui/gv-prefs-window.c:514 +#: src/ui/gv-prefs-window.c:510 msgid "Action triggered by mouse-scrolling on the status icon." msgstr "" -#: src/ui/gv-prefs-window.c:520 +#: src/ui/gv-prefs-window.c:516 msgid "Setting only available in status icon mode." msgstr "" @@ -362,62 +384,62 @@ msgid "Remove Station" msgstr "" -#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:428 +#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:424 msgid "Edit Station" msgstr "" -#: src/ui/gv-station-dialog.c:284 +#: src/ui/gv-station-dialog.c:281 msgid "Cancel" msgstr "" -#: src/ui/gv-station-dialog.c:285 +#: src/ui/gv-station-dialog.c:282 msgid "Save" msgstr "" -#: src/ui/gv-status-icon.c:130 +#: src/ui/gv-status-icon.c:131 msgid "stopped" msgstr "" -#: src/ui/gv-status-icon.c:133 +#: src/ui/gv-status-icon.c:134 msgid "connecting" msgstr "" -#: src/ui/gv-status-icon.c:136 +#: src/ui/gv-status-icon.c:137 msgid "buffering" msgstr "" -#: src/ui/gv-status-icon.c:139 +#: src/ui/gv-status-icon.c:140 msgid "playing" msgstr "" -#: src/ui/gv-status-icon.c:142 +#: src/ui/gv-status-icon.c:143 msgid "unknown state" msgstr "" -#: src/ui/gv-status-icon.c:149 +#: src/ui/gv-status-icon.c:150 msgid "muted" msgstr "" -#: src/ui/gv-status-icon.c:153 +#: src/ui/gv-status-icon.c:154 msgid "vol." msgstr "" -#: src/ui/gv-status-icon.c:160 +#: src/ui/gv-status-icon.c:161 msgid "No station" msgstr "" -#: src/ui/gv-status-icon.c:167 +#: src/ui/gv-status-icon.c:168 msgid "No metadata" msgstr "" -#: src/feat/gv-hotkeys.c:144 +#: src/feat/gv-hotkeys.c:145 #, c-format msgid "" "%s:\n" "%s" msgstr "" -#: src/feat/gv-hotkeys.c:145 +#: src/feat/gv-hotkeys.c:146 msgid "Failed to bind the following keys" msgstr "" @@ -425,28 +447,28 @@ msgid "Failed to inhibit system sleep" msgstr "" -#: src/feat/gv-notifications.c:93 +#: src/feat/gv-notifications.c:59 #, c-format msgid "Playing %s" msgstr "" -#: src/feat/gv-notifications.c:96 +#: src/feat/gv-notifications.c:62 #, c-format msgid "Playing <%s>" msgstr "" -#: src/feat/gv-notifications.c:137 -msgid "(Unknown title)" +#: src/feat/gv-notifications.c:65 +msgid "Playing Station" msgstr "" -#: src/feat/gv-notifications.c:263 -msgid "Playing Station" +#: src/feat/gv-notifications.c:103 +msgid "(Unknown title)" msgstr "" -#: src/feat/gv-notifications.c:266 +#: src/feat/gv-notifications.c:110 msgid "New Track" msgstr "" -#: src/feat/gv-notifications.c:269 +#: src/feat/gv-notifications.c:122 msgid "Error" msgstr "" diff -Nru goodvibes-0.3.6/po/hu.po goodvibes-0.4.2/po/hu.po --- goodvibes-0.3.6/po/hu.po 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/po/hu.po 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,473 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the goodvibes package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: goodvibes\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-11-09 19:25+0700\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: data/io.gitlab.Goodvibes.appdata.xml.in:4 +#: data/io.gitlab.Goodvibes.desktop.in:3 src/main.c:149 +msgid "Goodvibes" +msgstr "" + +#: data/io.gitlab.Goodvibes.appdata.xml.in:5 +#: data/io.gitlab.Goodvibes.desktop.in:5 +msgid "Play web radios" +msgstr "" + +#: data/io.gitlab.Goodvibes.appdata.xml.in:10 +msgid "Goodvibes is a simple internet radio player for GNU/Linux." +msgstr "" + +#: data/io.gitlab.Goodvibes.appdata.xml.in:13 +msgid "" +"It comes with every basic features you can expect from an audio player, such " +"as multimedia keys, notifications, system sleep inhibition, and MPRIS2 " +"support." +msgstr "" + +#: data/io.gitlab.Goodvibes.desktop.in:4 +msgid "Radio Player" +msgstr "" + +#. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: data/io.gitlab.Goodvibes.desktop.in:7 +msgid "Audio;Radio;Player;" +msgstr "" + +#. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! +#: data/io.gitlab.Goodvibes.desktop.in:11 +msgid "io.gitlab.Goodvibes" +msgstr "io.gitlab.Goodvibes" + +#: src/ui/resources/app-menu.glade:6 src/ui/resources/menubar.glade:8 +#: src/ui/resources/status-icon-menu.glade:6 +#: src/ui/gv-station-context-menu.c:35 src/ui/gv-station-dialog.c:424 +msgid "Add Station" +msgstr "" + +#: src/ui/resources/app-menu.glade:13 src/ui/resources/menubar.glade:15 +#: src/ui/resources/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:629 +msgid "Preferences" +msgstr "" + +#: src/ui/resources/app-menu.glade:19 src/ui/resources/menubar.glade:36 +#: src/ui/resources/status-icon-menu.glade:18 +msgid "Online Help" +msgstr "" + +#: src/ui/resources/app-menu.glade:24 src/ui/resources/menubar.glade:43 +#: src/ui/resources/status-icon-menu.glade:22 +msgid "About" +msgstr "" + +#: src/ui/resources/app-menu.glade:28 src/ui/resources/menubar.glade:21 +msgid "Close UI" +msgstr "" + +#: src/ui/resources/app-menu.glade:33 src/ui/resources/menubar.glade:26 +#: src/ui/resources/status-icon-menu.glade:26 +msgid "Quit" +msgstr "" + +#: src/ui/resources/main-window.glade:47 src/ui/gv-main-window.c:350 +msgid "No station selected" +msgstr "" + +#: src/ui/resources/main-window.glade:63 src/ui/gv-main-window.c:373 +msgid "Stopped" +msgstr "" + +#: src/ui/resources/menubar.glade:5 +msgid "Menu" +msgstr "" + +#: src/ui/resources/menubar.glade:33 +msgid "Help" +msgstr "" + +#: src/ui/resources/prefs-window.glade:35 +msgid "Autoplay on Startup" +msgstr "" + +#: src/ui/resources/prefs-window.glade:48 +msgid "Custom Output Pipeline" +msgstr "" + +#: src/ui/resources/prefs-window.glade:79 +msgid "Apply" +msgstr "" + +#: src/ui/resources/prefs-window.glade:102 +msgid "Playback" +msgstr "" + +#: src/ui/resources/prefs-window.glade:138 +msgid "Prevent sleep while playing" +msgstr "" + +#: src/ui/resources/prefs-window.glade:151 +msgid "System" +msgstr "" + +#: src/ui/resources/prefs-window.glade:197 +msgid "Native D-Bus Server" +msgstr "" + +#: src/ui/resources/prefs-window.glade:209 +msgid "MPRIS2 D-Bus Server" +msgstr "" + +#: src/ui/resources/prefs-window.glade:222 +msgid "D-Bus" +msgstr "" + +#: src/ui/resources/prefs-window.glade:238 +msgid "Misc" +msgstr "" + +#: src/ui/resources/prefs-window.glade:262 +msgid "Autoset Window Height" +msgstr "" + +#: src/ui/resources/prefs-window.glade:278 +msgid "Theme Variant" +msgstr "" + +#: src/ui/resources/prefs-window.glade:291 +msgid "System Default" +msgstr "" + +#: src/ui/resources/prefs-window.glade:292 +msgid "Prefer Dark" +msgstr "" + +#: src/ui/resources/prefs-window.glade:293 +msgid "Prefer Light" +msgstr "" + +#: src/ui/resources/prefs-window.glade:310 +msgid "Window" +msgstr "" + +#: src/ui/resources/prefs-window.glade:336 +msgid "Send Notifications" +msgstr "" + +#: src/ui/resources/prefs-window.glade:359 +msgid "Notifications" +msgstr "" + +#: src/ui/resources/prefs-window.glade:394 +msgid "Console Output" +msgstr "" + +#: src/ui/resources/prefs-window.glade:407 +msgid "Console" +msgstr "" + +#: src/ui/resources/prefs-window.glade:426 +msgid "Display" +msgstr "" + +#: src/ui/resources/prefs-window.glade:464 +msgid "Multimedia Hotkeys" +msgstr "" + +#: src/ui/resources/prefs-window.glade:477 +msgid "Keyboard" +msgstr "" + +#: src/ui/resources/prefs-window.glade:503 +msgid "Middle Click" +msgstr "" + +#: src/ui/resources/prefs-window.glade:516 +msgid "Toggle Play/Pause" +msgstr "" + +#: src/ui/resources/prefs-window.glade:517 +msgid "Mute" +msgstr "" + +#: src/ui/resources/prefs-window.glade:530 +msgid "Scrolling" +msgstr "" + +#: src/ui/resources/prefs-window.glade:543 +msgid "Change Station" +msgstr "" + +#: src/ui/resources/prefs-window.glade:544 +msgid "Change Volume" +msgstr "" + +#: src/ui/resources/prefs-window.glade:558 +msgid "Mouse (Status Icon Mode)" +msgstr "" + +#: src/ui/resources/prefs-window.glade:577 +msgid "Controls" +msgstr "" + +#: src/ui/resources/prefs-window.glade:598 +msgid "Close" +msgstr "" + +#: src/ui/resources/station-dialog.glade:12 src/ui/gv-main-window.c:261 +msgid "Name" +msgstr "" + +#: src/ui/resources/station-dialog.glade:34 src/ui/gv-main-window.c:262 +msgid "URI" +msgstr "" + +#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1134 +#, c-format +msgid "%s: %s" +msgstr "" + +#: src/core/gv-engine.c:268 +msgid "Failed to parse pipeline description" +msgstr "" + +#: src/core/gv-player.c:819 +#, c-format +msgid "'%s' is neither a known station or a valid URI" +msgstr "" + +#: src/core/gv-station-list.c:1135 +msgid "Failed to save station list" +msgstr "" + +#: src/ui/gv-main-window.c:259 +msgid "Station Information" +msgstr "" + +#: src/ui/gv-main-window.c:273 +msgid "User-agent" +msgstr "" + +#: src/ui/gv-main-window.c:277 +msgid "Bitrate" +msgstr "" + +#: src/ui/gv-main-window.c:290 +msgid "Metadata" +msgstr "" + +#: src/ui/gv-main-window.c:292 +msgid "Artist" +msgstr "" + +#: src/ui/gv-main-window.c:293 +msgid "Title" +msgstr "" + +#: src/ui/gv-main-window.c:294 +msgid "Album" +msgstr "" + +#: src/ui/gv-main-window.c:295 +msgid "Genre" +msgstr "" + +#: src/ui/gv-main-window.c:296 +msgid "Year" +msgstr "" + +#: src/ui/gv-main-window.c:297 +msgid "Comment" +msgstr "" + +#: src/ui/gv-main-window.c:363 src/ui/gv-main-window.c:391 +msgid "Playing" +msgstr "" + +#: src/ui/gv-main-window.c:366 +msgid "Connecting…" +msgstr "" + +#: src/ui/gv-main-window.c:369 +msgid "Buffering…" +msgstr "" + +#: src/ui/gv-prefs-window.c:281 +msgid "Feature disabled at compile-time." +msgstr "" + +#. +#. * Setup settings and features. +#. * These function calls create a binding between a gtk widget and +#. * an internal object, initializes the widget value, and set the +#. * widgets tooltips (label + setting). +#. +#. Misc +#: src/ui/gv-prefs-window.c:424 +msgid "Whether to start playback automatically on startup." +msgstr "" + +#: src/ui/gv-prefs-window.c:430 +msgid "Whether to use a custom output pipeline." +msgstr "" + +#: src/ui/gv-prefs-window.c:436 +msgid "" +"The GStreamer output pipeline used for playback. Refer to theonline " +"documentation for examples." +msgstr "" + +#: src/ui/gv-prefs-window.c:452 +msgid "Prevent the system from going to sleep while playing." +msgstr "" + +#: src/ui/gv-prefs-window.c:457 +msgid "Enable the native D-Bus server (needed for the command-line interface)." +msgstr "" + +#: src/ui/gv-prefs-window.c:463 +msgid "Enable the MPRIS2 D-Bus server." +msgstr "" + +#. Display +#: src/ui/gv-prefs-window.c:469 +msgid "Prefer a different variant of the theme (if available)." +msgstr "" + +#: src/ui/gv-prefs-window.c:476 +msgid "" +"Automatically adjust the window height when a station is added or removed." +msgstr "" + +#: src/ui/gv-prefs-window.c:483 +msgid "Setting not available in status icon mode." +msgstr "" + +#: src/ui/gv-prefs-window.c:487 +msgid "Show notification when the status changes." +msgstr "" + +#: src/ui/gv-prefs-window.c:492 +msgid "Display information on the standard output." +msgstr "" + +#. Controls +#: src/ui/gv-prefs-window.c:498 +msgid "Bind mutimedia keys (play/pause/stop/previous/next)." +msgstr "" + +#: src/ui/gv-prefs-window.c:504 +msgid "Action triggered by a middle click on the status icon." +msgstr "" + +#: src/ui/gv-prefs-window.c:510 +msgid "Action triggered by mouse-scrolling on the status icon." +msgstr "" + +#: src/ui/gv-prefs-window.c:516 +msgid "Setting only available in status icon mode." +msgstr "" + +#: src/ui/gv-station-context-menu.c:36 +msgid "Remove Station" +msgstr "" + +#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:424 +msgid "Edit Station" +msgstr "" + +#: src/ui/gv-station-dialog.c:281 +msgid "Cancel" +msgstr "" + +#: src/ui/gv-station-dialog.c:282 +msgid "Save" +msgstr "" + +#: src/ui/gv-status-icon.c:131 +msgid "stopped" +msgstr "" + +#: src/ui/gv-status-icon.c:134 +msgid "connecting" +msgstr "" + +#: src/ui/gv-status-icon.c:137 +msgid "buffering" +msgstr "" + +#: src/ui/gv-status-icon.c:140 +msgid "playing" +msgstr "" + +#: src/ui/gv-status-icon.c:143 +msgid "unknown state" +msgstr "" + +#: src/ui/gv-status-icon.c:150 +msgid "muted" +msgstr "" + +#: src/ui/gv-status-icon.c:154 +msgid "vol." +msgstr "" + +#: src/ui/gv-status-icon.c:161 +msgid "No station" +msgstr "" + +#: src/ui/gv-status-icon.c:168 +msgid "No metadata" +msgstr "" + +#: src/feat/gv-hotkeys.c:145 +#, c-format +msgid "" +"%s:\n" +"%s" +msgstr "" + +#: src/feat/gv-hotkeys.c:146 +msgid "Failed to bind the following keys" +msgstr "" + +#: src/feat/gv-inhibitor.c:111 +msgid "Failed to inhibit system sleep" +msgstr "" + +#: src/feat/gv-notifications.c:59 +#, c-format +msgid "Playing %s" +msgstr "" + +#: src/feat/gv-notifications.c:62 +#, c-format +msgid "Playing <%s>" +msgstr "" + +#: src/feat/gv-notifications.c:65 +msgid "Playing Station" +msgstr "" + +#: src/feat/gv-notifications.c:103 +msgid "(Unknown title)" +msgstr "" + +#: src/feat/gv-notifications.c:110 +msgid "New Track" +msgstr "" + +#: src/feat/gv-notifications.c:122 +msgid "Error" +msgstr "" diff -Nru goodvibes-0.3.6/po/LINGUAS goodvibes-0.4.2/po/LINGUAS --- goodvibes-0.3.6/po/LINGUAS 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/po/LINGUAS 2018-11-10 06:04:58.000000000 +0000 @@ -4,3 +4,5 @@ nb_NO de ru +hu +es diff -Nru goodvibes-0.3.6/po/Makevars goodvibes-0.4.2/po/Makevars --- goodvibes-0.3.6/po/Makevars 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/po/Makevars 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -# Makefile variables for PO directory in any package using GNU gettext. - -# Usually the message domain is the same as the package name. -DOMAIN = $(PACKAGE) - -# These two variables depend on the location of this directory. -subdir = po -top_builddir = .. - -# These options get passed to xgettext. -XGETTEXT_OPTIONS = --from-code=UTF-8 --keyword=_ - -# This is the copyright holder that gets inserted into the header of the -# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding -# package. (Note that the msgstr strings, extracted from the package's -# sources, belong to the copyright holder of the package.) Translators are -# expected to transfer the copyright for their translations to this person -# or entity, or to disclaim their copyright. The empty string stands for -# the public domain; in this case the translators are expected to disclaim -# their copyright. -COPYRIGHT_HOLDER = $(PACKAGE_COPYRIGHT) $(PACKAGE_AUTHOR_NAME) $(PACKAGE_AUTHOR_EMAIL) - -# This tells whether or not to prepend "GNU " prefix to the package -# name that gets inserted into the header of the $(DOMAIN).pot file. -# Possible values are "yes", "no", or empty. If it is empty, try to -# detect it automatically by scanning the files in $(top_srcdir) for -# "GNU packagename" string. -PACKAGE_GNU = no - -# This is the email address or URL to which the translators shall report -# bugs in the untranslated strings: -# - Strings which are not entire sentences, see the maintainer guidelines -# in the GNU gettext documentation, section 'Preparing Strings'. -# - Strings which use unclear terms or require additional context to be -# understood. -# - Strings which make invalid assumptions about notation of date, time or -# money. -# - Pluralisation problems. -# - Incorrect English spelling. -# - Incorrect formatting. -# It can be your email address, or a mailing list address where translators -# can write to without being subscribed, or the URL of a web page through -# which the translators can contact you. -MSGID_BUGS_ADDRESS = - -# This is the list of locale categories, beyond LC_MESSAGES, for which the -# message catalogs shall be used. It is usually empty. -EXTRA_LOCALE_CATEGORIES = - -# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' -# context. Possible values are "yes" and "no". Set this to yes if the -# package uses functions taking also a message context, like pgettext(), or -# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. -USE_MSGCTXT = no - -# These options get passed to msgmerge. -# Useful options are in particular: -# --previous to keep previous msgids of translated messages, -# --quiet to reduce the verbosity. -MSGMERGE_OPTIONS = - -# These options get passed to msginit. -# If you want to disable line wrapping when writing PO files, add -# --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and -# MSGINIT_OPTIONS. -MSGINIT_OPTIONS = - -# This tells whether or not to regenerate a PO file when $(DOMAIN).pot -# has changed. Possible values are "yes" and "no". Set this to no if -# the POT file is checked in the repository and the version control -# program ignores timestamps. -PO_DEPENDS_ON_POT = no - -# This tells whether or not to forcibly update $(DOMAIN).pot and -# regenerate PO files on "make dist". Possible values are "yes" and -# "no". Set this to no if the POT file and PO files are maintained -# externally. -DIST_DEPENDS_ON_UPDATE_PO = no diff -Nru goodvibes-0.3.6/po/meson.build goodvibes-0.4.2/po/meson.build --- goodvibes-0.3.6/po/meson.build 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/po/meson.build 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +i18n.gettext(meson.project_name(), preset: 'glib') diff -Nru goodvibes-0.3.6/po/nb_NO.po goodvibes-0.4.2/po/nb_NO.po --- goodvibes-0.3.6/po/nb_NO.po 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/po/nb_NO.po 2018-11-10 06:04:58.000000000 +0000 @@ -7,8 +7,8 @@ msgstr "" "Project-Id-Version: goodvibes 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-03-28 00:40+0700\n" -"PO-Revision-Date: 2018-03-18 03:30+0000\n" +"POT-Creation-Date: 2018-11-09 19:25+0700\n" +"PO-Revision-Date: 2018-08-29 16:40+0000\n" "Last-Translator: Allan Nordhøy \n" "Language-Team: Norwegian Bokmål \n" @@ -17,214 +17,229 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.20-dev\n" +"X-Generator: Weblate 3.2-dev\n" -#: data/com.elboulangero.Goodvibes.desktop.in:3 src/main.c:149 -msgid "Goodvibes Radio Player" -msgstr "Goodvibes radioavspiller" +#: data/io.gitlab.Goodvibes.appdata.xml.in:4 +#: data/io.gitlab.Goodvibes.desktop.in:3 src/main.c:149 +msgid "Goodvibes" +msgstr "Goodvibes" -#: data/com.elboulangero.Goodvibes.desktop.in:4 -msgid "Radio Player" -msgstr "Radioavspiller" - -#: data/com.elboulangero.Goodvibes.desktop.in:5 +#: data/io.gitlab.Goodvibes.appdata.xml.in:5 +#: data/io.gitlab.Goodvibes.desktop.in:5 msgid "Play web radios" msgstr "Spill av nettradio" +#: data/io.gitlab.Goodvibes.appdata.xml.in:10 +msgid "Goodvibes is a simple internet radio player for GNU/Linux." +msgstr "Goodvibes er en enkel internettradiospiller for GNU/Linux." + +#: data/io.gitlab.Goodvibes.appdata.xml.in:13 +msgid "" +"It comes with every basic features you can expect from an audio player, such " +"as multimedia keys, notifications, system sleep inhibition, and MPRIS2 " +"support." +msgstr "" +"Den kommer med grunnleggende enkle funksjoner du kan forvente av en " +"lydspiller, som multimediataster, merknader, systemsøvnunngåelse, og MPRIS2-" +"støtte." + +#: data/io.gitlab.Goodvibes.desktop.in:4 +msgid "Radio Player" +msgstr "Radioavspiller" + #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! -#: data/com.elboulangero.Goodvibes.desktop.in:7 +#: data/io.gitlab.Goodvibes.desktop.in:7 msgid "Audio;Radio;Player;" msgstr "Lyd;Radio;Avspiller;Nettradio;" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! -#: data/com.elboulangero.Goodvibes.desktop.in:11 -msgid "goodvibes" -msgstr "goodvibes" - -#: data/ui/app-menu.glade:6 data/ui/menubar.glade:8 -#: data/ui/status-icon-menu.glade:6 src/ui/gv-station-context-menu.c:35 -#: src/ui/gv-station-dialog.c:428 +#: data/io.gitlab.Goodvibes.desktop.in:11 +msgid "io.gitlab.Goodvibes" +msgstr "io.gitlab.Goodvibes" + +#: src/ui/resources/app-menu.glade:6 src/ui/resources/menubar.glade:8 +#: src/ui/resources/status-icon-menu.glade:6 +#: src/ui/gv-station-context-menu.c:35 src/ui/gv-station-dialog.c:424 msgid "Add Station" msgstr "Legg til stasjon" -#: data/ui/app-menu.glade:13 data/ui/menubar.glade:15 -#: data/ui/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:633 +#: src/ui/resources/app-menu.glade:13 src/ui/resources/menubar.glade:15 +#: src/ui/resources/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:629 msgid "Preferences" msgstr "Innstillinger" -#: data/ui/app-menu.glade:19 data/ui/menubar.glade:36 -#: data/ui/status-icon-menu.glade:18 +#: src/ui/resources/app-menu.glade:19 src/ui/resources/menubar.glade:36 +#: src/ui/resources/status-icon-menu.glade:18 msgid "Online Help" msgstr "Nettbasert hjelp" -#: data/ui/app-menu.glade:24 data/ui/menubar.glade:43 -#: data/ui/status-icon-menu.glade:22 +#: src/ui/resources/app-menu.glade:24 src/ui/resources/menubar.glade:43 +#: src/ui/resources/status-icon-menu.glade:22 msgid "About" msgstr "Om" -#: data/ui/app-menu.glade:28 data/ui/menubar.glade:21 +#: src/ui/resources/app-menu.glade:28 src/ui/resources/menubar.glade:21 msgid "Close UI" msgstr "Lukk grensesnitt" -#: data/ui/app-menu.glade:33 data/ui/menubar.glade:26 -#: data/ui/status-icon-menu.glade:26 +#: src/ui/resources/app-menu.glade:33 src/ui/resources/menubar.glade:26 +#: src/ui/resources/status-icon-menu.glade:26 msgid "Quit" msgstr "Avslutt" -#: data/ui/main-window.glade:47 src/ui/gv-main-window.c:351 +#: src/ui/resources/main-window.glade:47 src/ui/gv-main-window.c:350 msgid "No station selected" msgstr "Ingen stasjon valgt" -#: data/ui/main-window.glade:63 src/ui/gv-main-window.c:374 +#: src/ui/resources/main-window.glade:63 src/ui/gv-main-window.c:373 msgid "Stopped" msgstr "Stoppet" -#: data/ui/menubar.glade:5 +#: src/ui/resources/menubar.glade:5 msgid "Menu" msgstr "Meny" -#: data/ui/menubar.glade:33 +#: src/ui/resources/menubar.glade:33 msgid "Help" msgstr "Hjelp" -#: data/ui/prefs-window.glade:35 +#: src/ui/resources/prefs-window.glade:35 msgid "Autoplay on Startup" msgstr "Spill av automatisk ved oppstart" -#: data/ui/prefs-window.glade:48 +#: src/ui/resources/prefs-window.glade:48 msgid "Custom Output Pipeline" msgstr "Egendefinert utdatakanal" -#: data/ui/prefs-window.glade:79 +#: src/ui/resources/prefs-window.glade:79 msgid "Apply" msgstr "Bruk" -#: data/ui/prefs-window.glade:102 +#: src/ui/resources/prefs-window.glade:102 msgid "Playback" msgstr "Avspilling" -#: data/ui/prefs-window.glade:138 +#: src/ui/resources/prefs-window.glade:138 msgid "Prevent sleep while playing" msgstr "Forhindre dvalgang under avspilling" -#: data/ui/prefs-window.glade:151 +#: src/ui/resources/prefs-window.glade:151 msgid "System" msgstr "System" -#: data/ui/prefs-window.glade:197 +#: src/ui/resources/prefs-window.glade:197 msgid "Native D-Bus Server" msgstr "Lokal D-Bus-tjener" -#: data/ui/prefs-window.glade:209 +#: src/ui/resources/prefs-window.glade:209 msgid "MPRIS2 D-Bus Server" msgstr "MPRIS2 D-Bus-tjener" -#: data/ui/prefs-window.glade:222 +#: src/ui/resources/prefs-window.glade:222 msgid "D-Bus" msgstr "D-Bus" -#: data/ui/prefs-window.glade:238 +#: src/ui/resources/prefs-window.glade:238 msgid "Misc" msgstr "Ymse" -#: data/ui/prefs-window.glade:262 +#: src/ui/resources/prefs-window.glade:262 msgid "Autoset Window Height" msgstr "Sett vindushøyde automatisk" -#: data/ui/prefs-window.glade:278 +#: src/ui/resources/prefs-window.glade:278 msgid "Theme Variant" -msgstr "" +msgstr "Tema Variant" -#: data/ui/prefs-window.glade:291 -#, fuzzy +#: src/ui/resources/prefs-window.glade:291 msgid "System Default" -msgstr "System" +msgstr "Systemforvalg" -#: data/ui/prefs-window.glade:292 +#: src/ui/resources/prefs-window.glade:292 msgid "Prefer Dark" -msgstr "" +msgstr "Foretrukket Mørk" -#: data/ui/prefs-window.glade:293 +#: src/ui/resources/prefs-window.glade:293 msgid "Prefer Light" -msgstr "" +msgstr "Foretrekker Lys" -#: data/ui/prefs-window.glade:310 +#: src/ui/resources/prefs-window.glade:310 msgid "Window" -msgstr "" +msgstr "Vindu" -#: data/ui/prefs-window.glade:336 +#: src/ui/resources/prefs-window.glade:336 msgid "Send Notifications" msgstr "Send merknader" -#: data/ui/prefs-window.glade:359 +#: src/ui/resources/prefs-window.glade:359 msgid "Notifications" msgstr "Merknader" -#: data/ui/prefs-window.glade:394 +#: src/ui/resources/prefs-window.glade:394 msgid "Console Output" msgstr "Konsollutdata" -#: data/ui/prefs-window.glade:407 +#: src/ui/resources/prefs-window.glade:407 msgid "Console" msgstr "Konsoll" -#: data/ui/prefs-window.glade:426 +#: src/ui/resources/prefs-window.glade:426 msgid "Display" msgstr "Vis" -#: data/ui/prefs-window.glade:464 +#: src/ui/resources/prefs-window.glade:464 msgid "Multimedia Hotkeys" msgstr "Multimediataster" -#: data/ui/prefs-window.glade:477 +#: src/ui/resources/prefs-window.glade:477 msgid "Keyboard" msgstr "Tastatur" -#: data/ui/prefs-window.glade:503 +#: src/ui/resources/prefs-window.glade:503 msgid "Middle Click" msgstr "Midtklikk" -#: data/ui/prefs-window.glade:516 +#: src/ui/resources/prefs-window.glade:516 msgid "Toggle Play/Pause" msgstr "Veksle Spill/Pause" -#: data/ui/prefs-window.glade:517 +#: src/ui/resources/prefs-window.glade:517 msgid "Mute" msgstr "Demp" -#: data/ui/prefs-window.glade:530 +#: src/ui/resources/prefs-window.glade:530 msgid "Scrolling" msgstr "Rulling" -#: data/ui/prefs-window.glade:543 +#: src/ui/resources/prefs-window.glade:543 msgid "Change Station" msgstr "Endre stasjon" -#: data/ui/prefs-window.glade:544 +#: src/ui/resources/prefs-window.glade:544 msgid "Change Volume" msgstr "Endre lydstyrke" -#: data/ui/prefs-window.glade:558 +#: src/ui/resources/prefs-window.glade:558 msgid "Mouse (Status Icon Mode)" msgstr "Mus (statusikonmodus)" -#: data/ui/prefs-window.glade:577 +#: src/ui/resources/prefs-window.glade:577 msgid "Controls" msgstr "Kontroller" -#: data/ui/prefs-window.glade:598 +#: src/ui/resources/prefs-window.glade:598 msgid "Close" msgstr "Lukk" -#: data/ui/station-dialog.glade:12 src/ui/gv-main-window.c:262 +#: src/ui/resources/station-dialog.glade:12 src/ui/gv-main-window.c:261 msgid "Name" msgstr "Navn" -#: data/ui/station-dialog.glade:34 src/ui/gv-main-window.c:263 +#: src/ui/resources/station-dialog.glade:34 src/ui/gv-main-window.c:262 msgid "URI" msgstr "URI" -#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1088 +#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1134 #, c-format msgid "%s: %s" msgstr "%s: %s" @@ -238,128 +253,139 @@ msgid "'%s' is neither a known station or a valid URI" msgstr "'%s' er hverken en kjent stasjon eller en gyldig URI" -#: src/core/gv-station-list.c:1089 +#: src/core/gv-station-list.c:1135 msgid "Failed to save station list" msgstr "Klarte ikke å lasgre stasjonsliste" -#: src/ui/gv-main-window.c:260 +#: src/ui/gv-main-window.c:259 msgid "Station Information" msgstr "Stasjonsinformasjon" -#: src/ui/gv-main-window.c:274 +#: src/ui/gv-main-window.c:273 msgid "User-agent" msgstr "Brukeragent" -#: src/ui/gv-main-window.c:278 +#: src/ui/gv-main-window.c:277 msgid "Bitrate" msgstr "Bitrate" -#: src/ui/gv-main-window.c:291 +#: src/ui/gv-main-window.c:290 msgid "Metadata" msgstr "Metadata" -#: src/ui/gv-main-window.c:293 +#: src/ui/gv-main-window.c:292 msgid "Artist" msgstr "Artist" -#: src/ui/gv-main-window.c:294 +#: src/ui/gv-main-window.c:293 msgid "Title" msgstr "Tittel" -#: src/ui/gv-main-window.c:295 +#: src/ui/gv-main-window.c:294 msgid "Album" msgstr "Album" -#: src/ui/gv-main-window.c:296 +#: src/ui/gv-main-window.c:295 msgid "Genre" msgstr "Sjanger" -#: src/ui/gv-main-window.c:297 +#: src/ui/gv-main-window.c:296 msgid "Year" msgstr "År" -#: src/ui/gv-main-window.c:298 +#: src/ui/gv-main-window.c:297 msgid "Comment" msgstr "Kommentar" -#: src/ui/gv-main-window.c:364 src/ui/gv-main-window.c:392 +#: src/ui/gv-main-window.c:363 src/ui/gv-main-window.c:391 msgid "Playing" msgstr "Spiller" -#: src/ui/gv-main-window.c:367 +#: src/ui/gv-main-window.c:366 msgid "Connecting…" msgstr "Kobler til…" -#: src/ui/gv-main-window.c:370 +#: src/ui/gv-main-window.c:369 msgid "Buffering…" msgstr "Mellomlagrer…" -#: src/ui/gv-prefs-window.c:282 +#: src/ui/gv-prefs-window.c:281 msgid "Feature disabled at compile-time." msgstr "Funksjon avskrudd ved kompilering." -#: src/ui/gv-prefs-window.c:428 +#. +#. * Setup settings and features. +#. * These function calls create a binding between a gtk widget and +#. * an internal object, initializes the widget value, and set the +#. * widgets tooltips (label + setting). +#. +#. Misc +#: src/ui/gv-prefs-window.c:424 msgid "Whether to start playback automatically on startup." msgstr "Hvorvidt avspilling skal startes automatisk ved oppstart." -#: src/ui/gv-prefs-window.c:434 +#: src/ui/gv-prefs-window.c:430 msgid "Whether to use a custom output pipeline." msgstr "Hvorvidt en egendefinert utdatakanal skal brukes." -#: src/ui/gv-prefs-window.c:440 +#: src/ui/gv-prefs-window.c:436 msgid "" "The GStreamer output pipeline used for playback. Refer to theonline " "documentation for examples." msgstr "" +"GStreamer utgangsrørledningen brukes til avspilling. Se referanse " +"dokumentasjon for eksempler." -#: src/ui/gv-prefs-window.c:456 +#: src/ui/gv-prefs-window.c:452 msgid "Prevent the system from going to sleep while playing." msgstr "Forhindre systemet fra dvalgang under avspilling." -#: src/ui/gv-prefs-window.c:461 +#: src/ui/gv-prefs-window.c:457 msgid "Enable the native D-Bus server (needed for the command-line interface)." msgstr "" "Skru på den lokale D-Bus-tjeneren (trengs for kommandolinjegresesnitt)." -#: src/ui/gv-prefs-window.c:467 +#: src/ui/gv-prefs-window.c:463 msgid "Enable the MPRIS2 D-Bus server." msgstr "Skru på MPRIS2 D-Bus-tjeneren." -#: src/ui/gv-prefs-window.c:473 +#. Display +#: src/ui/gv-prefs-window.c:469 msgid "Prefer a different variant of the theme (if available)." -msgstr "" +msgstr "Foretrekker en annen variant av temaet (hvis tilgjengelig)." -#: src/ui/gv-prefs-window.c:480 +#: src/ui/gv-prefs-window.c:476 msgid "" "Automatically adjust the window height when a station is added or removed." msgstr "" "Juster vindushøyden automatisk når en stasjon legges til eller fjernes." -#: src/ui/gv-prefs-window.c:487 +#: src/ui/gv-prefs-window.c:483 msgid "Setting not available in status icon mode." msgstr "Innstillingen er ikke tilgjengelig i statusikonsmodus." -#: src/ui/gv-prefs-window.c:491 +#: src/ui/gv-prefs-window.c:487 msgid "Show notification when the status changes." msgstr "Vis merknad når statusen endres." -#: src/ui/gv-prefs-window.c:496 +#: src/ui/gv-prefs-window.c:492 msgid "Display information on the standard output." msgstr "Vis informasjon i standardutdata." -#: src/ui/gv-prefs-window.c:502 +#. Controls +#: src/ui/gv-prefs-window.c:498 msgid "Bind mutimedia keys (play/pause/stop/previous/next)." msgstr "Tilknytt multimediataster (spill/pause/stopp/forrige/neste)." -#: src/ui/gv-prefs-window.c:508 +#: src/ui/gv-prefs-window.c:504 msgid "Action triggered by a middle click on the status icon." msgstr "Handling utløst av midtklikk på statusikonet." -#: src/ui/gv-prefs-window.c:514 +#: src/ui/gv-prefs-window.c:510 msgid "Action triggered by mouse-scrolling on the status icon." msgstr "Handling utløst av muserulling på statusikonet." -#: src/ui/gv-prefs-window.c:520 +#: src/ui/gv-prefs-window.c:516 msgid "Setting only available in status icon mode." msgstr "Innstillingen er kun tilgjengelig i statusikonsmodus." @@ -367,55 +393,55 @@ msgid "Remove Station" msgstr "Fjern stasjon" -#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:428 +#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:424 msgid "Edit Station" msgstr "Rediger stasjon" -#: src/ui/gv-station-dialog.c:284 +#: src/ui/gv-station-dialog.c:281 msgid "Cancel" msgstr "Avbryt" -#: src/ui/gv-station-dialog.c:285 +#: src/ui/gv-station-dialog.c:282 msgid "Save" msgstr "Lagre" -#: src/ui/gv-status-icon.c:130 +#: src/ui/gv-status-icon.c:131 msgid "stopped" msgstr "stoppet" -#: src/ui/gv-status-icon.c:133 +#: src/ui/gv-status-icon.c:134 msgid "connecting" msgstr "kobler til" -#: src/ui/gv-status-icon.c:136 +#: src/ui/gv-status-icon.c:137 msgid "buffering" msgstr "mellomlagrer" -#: src/ui/gv-status-icon.c:139 +#: src/ui/gv-status-icon.c:140 msgid "playing" msgstr "spiller" -#: src/ui/gv-status-icon.c:142 +#: src/ui/gv-status-icon.c:143 msgid "unknown state" msgstr "ukjent tilstand" -#: src/ui/gv-status-icon.c:149 +#: src/ui/gv-status-icon.c:150 msgid "muted" msgstr "dempet" -#: src/ui/gv-status-icon.c:153 +#: src/ui/gv-status-icon.c:154 msgid "vol." msgstr "lydst." -#: src/ui/gv-status-icon.c:160 +#: src/ui/gv-status-icon.c:161 msgid "No station" msgstr "Ingen stasjon" -#: src/ui/gv-status-icon.c:167 +#: src/ui/gv-status-icon.c:168 msgid "No metadata" msgstr "Ingen metadata" -#: src/feat/gv-hotkeys.c:144 +#: src/feat/gv-hotkeys.c:145 #, c-format msgid "" "%s:\n" @@ -424,7 +450,7 @@ "%s:\n" "%s" -#: src/feat/gv-hotkeys.c:145 +#: src/feat/gv-hotkeys.c:146 msgid "Failed to bind the following keys" msgstr "Klarte ikke å tilknytte følgende taster" @@ -432,32 +458,38 @@ msgid "Failed to inhibit system sleep" msgstr "Klarte ikke å forhindre systemdvalgang" -#: src/feat/gv-notifications.c:93 +#: src/feat/gv-notifications.c:59 #, c-format msgid "Playing %s" msgstr "Spiller %s" -#: src/feat/gv-notifications.c:96 +#: src/feat/gv-notifications.c:62 #, c-format msgid "Playing <%s>" msgstr "Spiller <%s>" -#: src/feat/gv-notifications.c:137 -msgid "(Unknown title)" -msgstr "(Ukjent tittel)" - -#: src/feat/gv-notifications.c:263 +#: src/feat/gv-notifications.c:65 msgid "Playing Station" msgstr "Spiller stasjon" -#: src/feat/gv-notifications.c:266 +#: src/feat/gv-notifications.c:103 +msgid "(Unknown title)" +msgstr "(Ukjent tittel)" + +#: src/feat/gv-notifications.c:110 msgid "New Track" msgstr "Nytt spor" -#: src/feat/gv-notifications.c:269 +#: src/feat/gv-notifications.c:122 msgid "Error" msgstr "Feil" +#~ msgid "goodvibes" +#~ msgstr "goodvibes" + +#~ msgid "Goodvibes Radio Player" +#~ msgstr "Goodvibes radioavspiller" + #~ msgid "Window Behavior" #~ msgstr "Vindusoppførsel" diff -Nru goodvibes-0.3.6/po/nl.po goodvibes-0.4.2/po/nl.po --- goodvibes-0.3.6/po/nl.po 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/po/nl.po 2018-11-10 06:04:58.000000000 +0000 @@ -7,8 +7,8 @@ msgstr "" "Project-Id-Version: goodvibes 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-03-28 00:40+0700\n" -"PO-Revision-Date: 2018-03-27 17:55+0000\n" +"POT-Creation-Date: 2018-11-09 19:25+0700\n" +"PO-Revision-Date: 2018-11-10 04:18+0000\n" "Last-Translator: Heimen Stoffels \n" "Language-Team: Dutch \n" @@ -17,213 +17,231 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.20-dev\n" +"X-Generator: Weblate 3.3-dev\n" -#: data/com.elboulangero.Goodvibes.desktop.in:3 src/main.c:149 -msgid "Goodvibes Radio Player" -msgstr "Goodvibes Radiospeler" +#: data/io.gitlab.Goodvibes.appdata.xml.in:4 +#: data/io.gitlab.Goodvibes.desktop.in:3 src/main.c:149 +msgid "Goodvibes" +msgstr "Goodvibes" -#: data/com.elboulangero.Goodvibes.desktop.in:4 -msgid "Radio Player" -msgstr "Radiospeler" - -#: data/com.elboulangero.Goodvibes.desktop.in:5 +#: data/io.gitlab.Goodvibes.appdata.xml.in:5 +#: data/io.gitlab.Goodvibes.desktop.in:5 msgid "Play web radios" msgstr "Internetradiostations afspelen" +#: data/io.gitlab.Goodvibes.appdata.xml.in:10 +msgid "Goodvibes is a simple internet radio player for GNU/Linux." +msgstr "" +"Goodvibes is een eenvoudige speler voor GNU/Linux voor het afspelen van " +"internetradiostations." + +#: data/io.gitlab.Goodvibes.appdata.xml.in:13 +msgid "" +"It comes with every basic features you can expect from an audio player, such " +"as multimedia keys, notifications, system sleep inhibition, and MPRIS2 " +"support." +msgstr "" +"Het bevat elke basisfunctie die je mag verwachten van een audiospeler, zoals " +"multimediatoetsen, meldingen, slaapstandonderdrukking en MPRIS2-" +"ondersteuning." + +#: data/io.gitlab.Goodvibes.desktop.in:4 +msgid "Radio Player" +msgstr "Radiospeler" + #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! -#: data/com.elboulangero.Goodvibes.desktop.in:7 +#: data/io.gitlab.Goodvibes.desktop.in:7 msgid "Audio;Radio;Player;" msgstr "Audio;Radio;Speler;" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! -#: data/com.elboulangero.Goodvibes.desktop.in:11 -msgid "goodvibes" -msgstr "goodvibes" - -#: data/ui/app-menu.glade:6 data/ui/menubar.glade:8 -#: data/ui/status-icon-menu.glade:6 src/ui/gv-station-context-menu.c:35 -#: src/ui/gv-station-dialog.c:428 +#: data/io.gitlab.Goodvibes.desktop.in:11 +msgid "io.gitlab.Goodvibes" +msgstr "io.gitlab.Goodvibes" + +#: src/ui/resources/app-menu.glade:6 src/ui/resources/menubar.glade:8 +#: src/ui/resources/status-icon-menu.glade:6 +#: src/ui/gv-station-context-menu.c:35 src/ui/gv-station-dialog.c:424 msgid "Add Station" msgstr "Station toevoegen" -#: data/ui/app-menu.glade:13 data/ui/menubar.glade:15 -#: data/ui/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:633 +#: src/ui/resources/app-menu.glade:13 src/ui/resources/menubar.glade:15 +#: src/ui/resources/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:629 msgid "Preferences" msgstr "Voorkeuren" -#: data/ui/app-menu.glade:19 data/ui/menubar.glade:36 -#: data/ui/status-icon-menu.glade:18 +#: src/ui/resources/app-menu.glade:19 src/ui/resources/menubar.glade:36 +#: src/ui/resources/status-icon-menu.glade:18 msgid "Online Help" msgstr "Online hulp" -#: data/ui/app-menu.glade:24 data/ui/menubar.glade:43 -#: data/ui/status-icon-menu.glade:22 +#: src/ui/resources/app-menu.glade:24 src/ui/resources/menubar.glade:43 +#: src/ui/resources/status-icon-menu.glade:22 msgid "About" msgstr "Over" -#: data/ui/app-menu.glade:28 data/ui/menubar.glade:21 +#: src/ui/resources/app-menu.glade:28 src/ui/resources/menubar.glade:21 msgid "Close UI" msgstr "UI sluiten" -#: data/ui/app-menu.glade:33 data/ui/menubar.glade:26 -#: data/ui/status-icon-menu.glade:26 +#: src/ui/resources/app-menu.glade:33 src/ui/resources/menubar.glade:26 +#: src/ui/resources/status-icon-menu.glade:26 msgid "Quit" msgstr "Afsluiten" -#: data/ui/main-window.glade:47 src/ui/gv-main-window.c:351 +#: src/ui/resources/main-window.glade:47 src/ui/gv-main-window.c:350 msgid "No station selected" msgstr "Geen station geselecteerd" -#: data/ui/main-window.glade:63 src/ui/gv-main-window.c:374 +#: src/ui/resources/main-window.glade:63 src/ui/gv-main-window.c:373 msgid "Stopped" msgstr "Gestopt" -#: data/ui/menubar.glade:5 +#: src/ui/resources/menubar.glade:5 msgid "Menu" msgstr "Menu" -#: data/ui/menubar.glade:33 +#: src/ui/resources/menubar.glade:33 msgid "Help" msgstr "Hulp" -#: data/ui/prefs-window.glade:35 +#: src/ui/resources/prefs-window.glade:35 msgid "Autoplay on Startup" msgstr "Automatisch afspelen na opstarten" -#: data/ui/prefs-window.glade:48 +#: src/ui/resources/prefs-window.glade:48 msgid "Custom Output Pipeline" msgstr "Aangepaste uitvoer-pijpleiding" -#: data/ui/prefs-window.glade:79 +#: src/ui/resources/prefs-window.glade:79 msgid "Apply" msgstr "Toepassen" -#: data/ui/prefs-window.glade:102 +#: src/ui/resources/prefs-window.glade:102 msgid "Playback" msgstr "Afspelen" -#: data/ui/prefs-window.glade:138 +#: src/ui/resources/prefs-window.glade:138 msgid "Prevent sleep while playing" msgstr "Slaapstand onderdrukken tijdens afspelen" -#: data/ui/prefs-window.glade:151 +#: src/ui/resources/prefs-window.glade:151 msgid "System" msgstr "Systeem" -#: data/ui/prefs-window.glade:197 +#: src/ui/resources/prefs-window.glade:197 msgid "Native D-Bus Server" msgstr "Systeem-D-Bus-server" -#: data/ui/prefs-window.glade:209 +#: src/ui/resources/prefs-window.glade:209 msgid "MPRIS2 D-Bus Server" msgstr "MPRIS D-Bus-server" -#: data/ui/prefs-window.glade:222 +#: src/ui/resources/prefs-window.glade:222 msgid "D-Bus" msgstr "D-Bus" -#: data/ui/prefs-window.glade:238 +#: src/ui/resources/prefs-window.glade:238 msgid "Misc" msgstr "Diversen" -#: data/ui/prefs-window.glade:262 +#: src/ui/resources/prefs-window.glade:262 msgid "Autoset Window Height" msgstr "Vensterhoogte automatisch instellen" -#: data/ui/prefs-window.glade:278 +#: src/ui/resources/prefs-window.glade:278 msgid "Theme Variant" msgstr "Themavariant" -#: data/ui/prefs-window.glade:291 +#: src/ui/resources/prefs-window.glade:291 msgid "System Default" msgstr "Systeemstandaard" -#: data/ui/prefs-window.glade:292 +#: src/ui/resources/prefs-window.glade:292 msgid "Prefer Dark" msgstr "Donker prefereren" -#: data/ui/prefs-window.glade:293 +#: src/ui/resources/prefs-window.glade:293 msgid "Prefer Light" msgstr "Licht prefereren" -#: data/ui/prefs-window.glade:310 +#: src/ui/resources/prefs-window.glade:310 msgid "Window" msgstr "Venster" -#: data/ui/prefs-window.glade:336 +#: src/ui/resources/prefs-window.glade:336 msgid "Send Notifications" msgstr "Meldingen versturen" -#: data/ui/prefs-window.glade:359 +#: src/ui/resources/prefs-window.glade:359 msgid "Notifications" msgstr "Meldingen" -#: data/ui/prefs-window.glade:394 +#: src/ui/resources/prefs-window.glade:394 msgid "Console Output" msgstr "Terminaluitvoer" -#: data/ui/prefs-window.glade:407 +#: src/ui/resources/prefs-window.glade:407 msgid "Console" msgstr "Terminal" -#: data/ui/prefs-window.glade:426 +#: src/ui/resources/prefs-window.glade:426 msgid "Display" msgstr "Weergave" -#: data/ui/prefs-window.glade:464 +#: src/ui/resources/prefs-window.glade:464 msgid "Multimedia Hotkeys" msgstr "Multimedia-sneltoetsen" -#: data/ui/prefs-window.glade:477 +#: src/ui/resources/prefs-window.glade:477 msgid "Keyboard" msgstr "Toetsenbord" -#: data/ui/prefs-window.glade:503 +#: src/ui/resources/prefs-window.glade:503 msgid "Middle Click" msgstr "Middelklik" -#: data/ui/prefs-window.glade:516 +#: src/ui/resources/prefs-window.glade:516 msgid "Toggle Play/Pause" msgstr "Schakelen tussen afspelen/pauzeren" -#: data/ui/prefs-window.glade:517 +#: src/ui/resources/prefs-window.glade:517 msgid "Mute" msgstr "Dempen" -#: data/ui/prefs-window.glade:530 +#: src/ui/resources/prefs-window.glade:530 msgid "Scrolling" msgstr "Scrollen" -#: data/ui/prefs-window.glade:543 +#: src/ui/resources/prefs-window.glade:543 msgid "Change Station" msgstr "Station wijzigen" -#: data/ui/prefs-window.glade:544 +#: src/ui/resources/prefs-window.glade:544 msgid "Change Volume" msgstr "Volume wijzigen" -#: data/ui/prefs-window.glade:558 +#: src/ui/resources/prefs-window.glade:558 msgid "Mouse (Status Icon Mode)" msgstr "Muis (systeemvakpictogram-modus)" -#: data/ui/prefs-window.glade:577 +#: src/ui/resources/prefs-window.glade:577 msgid "Controls" msgstr "Bediening" -#: data/ui/prefs-window.glade:598 +#: src/ui/resources/prefs-window.glade:598 msgid "Close" msgstr "Sluiten" -#: data/ui/station-dialog.glade:12 src/ui/gv-main-window.c:262 +#: src/ui/resources/station-dialog.glade:12 src/ui/gv-main-window.c:261 msgid "Name" msgstr "Naam" -#: data/ui/station-dialog.glade:34 src/ui/gv-main-window.c:263 +#: src/ui/resources/station-dialog.glade:34 src/ui/gv-main-window.c:262 msgid "URI" msgstr "URI" -#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1088 +#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1134 #, c-format msgid "%s: %s" msgstr "%s:%s" @@ -237,75 +255,82 @@ msgid "'%s' is neither a known station or a valid URI" msgstr "'%s' is een onbekend station of ongeldige URI" -#: src/core/gv-station-list.c:1089 +#: src/core/gv-station-list.c:1135 msgid "Failed to save station list" msgstr "Het opslaan van de stationslijst is mislukt" -#: src/ui/gv-main-window.c:260 +#: src/ui/gv-main-window.c:259 msgid "Station Information" msgstr "Stationsinformatie" -#: src/ui/gv-main-window.c:274 +#: src/ui/gv-main-window.c:273 msgid "User-agent" msgstr "Gebruikersagent" -#: src/ui/gv-main-window.c:278 +#: src/ui/gv-main-window.c:277 msgid "Bitrate" msgstr "Bitsnelheid" -#: src/ui/gv-main-window.c:291 +#: src/ui/gv-main-window.c:290 msgid "Metadata" msgstr "Metagegevens" -#: src/ui/gv-main-window.c:293 +#: src/ui/gv-main-window.c:292 msgid "Artist" msgstr "Artiest" -#: src/ui/gv-main-window.c:294 +#: src/ui/gv-main-window.c:293 msgid "Title" msgstr "Titel" -#: src/ui/gv-main-window.c:295 +#: src/ui/gv-main-window.c:294 msgid "Album" msgstr "Album" -#: src/ui/gv-main-window.c:296 +#: src/ui/gv-main-window.c:295 msgid "Genre" msgstr "Genre" -#: src/ui/gv-main-window.c:297 +#: src/ui/gv-main-window.c:296 msgid "Year" msgstr "Jaar" -#: src/ui/gv-main-window.c:298 +#: src/ui/gv-main-window.c:297 msgid "Comment" msgstr "Opmerking" -#: src/ui/gv-main-window.c:364 src/ui/gv-main-window.c:392 +#: src/ui/gv-main-window.c:363 src/ui/gv-main-window.c:391 msgid "Playing" msgstr "Bezig met afspelen" -#: src/ui/gv-main-window.c:367 +#: src/ui/gv-main-window.c:366 msgid "Connecting…" msgstr "Bezig met verbinden…" -#: src/ui/gv-main-window.c:370 +#: src/ui/gv-main-window.c:369 msgid "Buffering…" msgstr "Bezig met bufferen…" -#: src/ui/gv-prefs-window.c:282 +#: src/ui/gv-prefs-window.c:281 msgid "Feature disabled at compile-time." msgstr "Mogelijkheid is uitgeschakeld tijdens het compileren." -#: src/ui/gv-prefs-window.c:428 +#. +#. * Setup settings and features. +#. * These function calls create a binding between a gtk widget and +#. * an internal object, initializes the widget value, and set the +#. * widgets tooltips (label + setting). +#. +#. Misc +#: src/ui/gv-prefs-window.c:424 msgid "Whether to start playback automatically on startup." msgstr "Of de applicatie automatisch moet afspelen tijdens het opstarten." -#: src/ui/gv-prefs-window.c:434 +#: src/ui/gv-prefs-window.c:430 msgid "Whether to use a custom output pipeline." msgstr "Of een aangepaste uitvoer-pijpleiding moet worden gebruikt." -#: src/ui/gv-prefs-window.c:440 +#: src/ui/gv-prefs-window.c:436 msgid "" "The GStreamer output pipeline used for playback. Refer to theonline " "documentation for examples." @@ -313,59 +338,61 @@ "De voor afspelen gebruikte GStreamer-uitvoerpijplijn. Bekijk de online " "documentatie voor voorbeelden." -#: src/ui/gv-prefs-window.c:456 +#: src/ui/gv-prefs-window.c:452 msgid "Prevent the system from going to sleep while playing." msgstr "Voorkom dat het systeem in de slaapstand gaat tijdens het afspelen." -#: src/ui/gv-prefs-window.c:461 +#: src/ui/gv-prefs-window.c:457 msgid "Enable the native D-Bus server (needed for the command-line interface)." msgstr "" "Schakel de system-D-Bus-server in (benodigd voor de command-line interface)." -#: src/ui/gv-prefs-window.c:467 +#: src/ui/gv-prefs-window.c:463 msgid "Enable the MPRIS2 D-Bus server." msgstr "Schakel de MPRIS2 D-Bus-server in." -#: src/ui/gv-prefs-window.c:473 +#. Display +#: src/ui/gv-prefs-window.c:469 msgid "Prefer a different variant of the theme (if available)." msgstr "Andere themavariant prefereren (indien beschikbaar)." -#: src/ui/gv-prefs-window.c:480 +#: src/ui/gv-prefs-window.c:476 msgid "" "Automatically adjust the window height when a station is added or removed." msgstr "" "Vensterhoogte automatisch aanpassen als een station wordt toegevoegd of " "verwijderd." -#: src/ui/gv-prefs-window.c:487 +#: src/ui/gv-prefs-window.c:483 msgid "Setting not available in status icon mode." msgstr "De instelling is niet beschikbaar in systeemvakpictogram-modus." -#: src/ui/gv-prefs-window.c:491 +#: src/ui/gv-prefs-window.c:487 msgid "Show notification when the status changes." msgstr "Meldingen weergeven bij statuswijzigingen." -#: src/ui/gv-prefs-window.c:496 +#: src/ui/gv-prefs-window.c:492 msgid "Display information on the standard output." msgstr "Informatie weergeven over de standaard uitvoer." -#: src/ui/gv-prefs-window.c:502 +#. Controls +#: src/ui/gv-prefs-window.c:498 msgid "Bind mutimedia keys (play/pause/stop/previous/next)." msgstr "" "Multimedia-toetsen gebruiken (afspelen/pauzeren/stoppen/vorige/volgende)." -#: src/ui/gv-prefs-window.c:508 +#: src/ui/gv-prefs-window.c:504 msgid "Action triggered by a middle click on the status icon." msgstr "" "Actie die wordt getriggerd door een middelklik op het systeemvakpictogram." -#: src/ui/gv-prefs-window.c:514 +#: src/ui/gv-prefs-window.c:510 msgid "Action triggered by mouse-scrolling on the status icon." msgstr "" "Actie die wordt getriggerd door met de muis te scrollen over het " "systeemvakpictogram." -#: src/ui/gv-prefs-window.c:520 +#: src/ui/gv-prefs-window.c:516 msgid "Setting only available in status icon mode." msgstr "De instelling is alleen beschikbaar in systeemvakpictogram-modus." @@ -373,55 +400,55 @@ msgid "Remove Station" msgstr "Station verwijderen" -#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:428 +#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:424 msgid "Edit Station" msgstr "Station bewerken" -#: src/ui/gv-station-dialog.c:284 +#: src/ui/gv-station-dialog.c:281 msgid "Cancel" msgstr "Annuleren" -#: src/ui/gv-station-dialog.c:285 +#: src/ui/gv-station-dialog.c:282 msgid "Save" msgstr "Opslaan" -#: src/ui/gv-status-icon.c:130 +#: src/ui/gv-status-icon.c:131 msgid "stopped" msgstr "gestopt" -#: src/ui/gv-status-icon.c:133 +#: src/ui/gv-status-icon.c:134 msgid "connecting" msgstr "bezig met verbinden" -#: src/ui/gv-status-icon.c:136 +#: src/ui/gv-status-icon.c:137 msgid "buffering" msgstr "bezig met bufferen" -#: src/ui/gv-status-icon.c:139 +#: src/ui/gv-status-icon.c:140 msgid "playing" msgstr "bezig met afspelen" -#: src/ui/gv-status-icon.c:142 +#: src/ui/gv-status-icon.c:143 msgid "unknown state" msgstr "onbekende status" -#: src/ui/gv-status-icon.c:149 +#: src/ui/gv-status-icon.c:150 msgid "muted" msgstr "gedempt" -#: src/ui/gv-status-icon.c:153 +#: src/ui/gv-status-icon.c:154 msgid "vol." msgstr "vol." -#: src/ui/gv-status-icon.c:160 +#: src/ui/gv-status-icon.c:161 msgid "No station" msgstr "Geen station" -#: src/ui/gv-status-icon.c:167 +#: src/ui/gv-status-icon.c:168 msgid "No metadata" msgstr "Geen metagegevens" -#: src/feat/gv-hotkeys.c:144 +#: src/feat/gv-hotkeys.c:145 #, c-format msgid "" "%s:\n" @@ -430,7 +457,7 @@ "%s:\n" "%s" -#: src/feat/gv-hotkeys.c:145 +#: src/feat/gv-hotkeys.c:146 msgid "Failed to bind the following keys" msgstr "Het koppelen van de volgende toetsen is mislukt" @@ -438,32 +465,38 @@ msgid "Failed to inhibit system sleep" msgstr "Voorkomen van slaapmodus is mislukt" -#: src/feat/gv-notifications.c:93 +#: src/feat/gv-notifications.c:59 #, c-format msgid "Playing %s" msgstr "Bezig met afspelen van %s" -#: src/feat/gv-notifications.c:96 +#: src/feat/gv-notifications.c:62 #, c-format msgid "Playing <%s>" msgstr "Bezig met afspelen van <%s>" -#: src/feat/gv-notifications.c:137 -msgid "(Unknown title)" -msgstr "(onbekende titel)" - -#: src/feat/gv-notifications.c:263 +#: src/feat/gv-notifications.c:65 msgid "Playing Station" msgstr "Afspelend station" -#: src/feat/gv-notifications.c:266 +#: src/feat/gv-notifications.c:103 +msgid "(Unknown title)" +msgstr "(onbekende titel)" + +#: src/feat/gv-notifications.c:110 msgid "New Track" msgstr "Nieuw nummer" -#: src/feat/gv-notifications.c:269 +#: src/feat/gv-notifications.c:122 msgid "Error" msgstr "Fout" +#~ msgid "goodvibes" +#~ msgstr "goodvibes" + +#~ msgid "Goodvibes Radio Player" +#~ msgstr "Goodvibes Radiospeler" + #~ msgid "Window Behavior" #~ msgstr "Venstergedrag" diff -Nru goodvibes-0.3.6/po/POTFILES goodvibes-0.4.2/po/POTFILES --- goodvibes-0.3.6/po/POTFILES 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/po/POTFILES 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,25 @@ +# Integration files +data/io.gitlab.Goodvibes.appdata.xml.in +data/io.gitlab.Goodvibes.desktop.in + +# Glade ui files +src/ui/resources/app-menu.glade +src/ui/resources/main-window.glade +src/ui/resources/menubar.glade +src/ui/resources/prefs-window.glade +src/ui/resources/station-dialog.glade +src/ui/resources/status-icon-menu.glade + +# Source files +src/main.c +src/core/gv-engine.c +src/core/gv-player.c +src/core/gv-station-list.c +src/ui/gv-main-window.c +src/ui/gv-prefs-window.c +src/ui/gv-station-context-menu.c +src/ui/gv-station-dialog.c +src/ui/gv-status-icon.c +src/feat/gv-hotkeys.c +src/feat/gv-inhibitor.c +src/feat/gv-notifications.c diff -Nru goodvibes-0.3.6/po/POTFILES.in goodvibes-0.4.2/po/POTFILES.in --- goodvibes-0.3.6/po/POTFILES.in 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/po/POTFILES.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -# Desktop files -data/com.elboulangero.Goodvibes.desktop.in - -# Glade ui files -data/ui/app-menu.glade -data/ui/main-window.glade -data/ui/menubar.glade -data/ui/prefs-window.glade -data/ui/station-dialog.glade -data/ui/status-icon-menu.glade - -# Source files -src/main.c -src/core/gv-engine.c -src/core/gv-player.c -src/core/gv-station-list.c -src/ui/gv-main-window.c -src/ui/gv-prefs-window.c -src/ui/gv-station-context-menu.c -src/ui/gv-station-dialog.c -src/ui/gv-status-icon.c -src/feat/gv-hotkeys.c -src/feat/gv-inhibitor.c -src/feat/gv-notifications.c diff -Nru goodvibes-0.3.6/po/ru.po goodvibes-0.4.2/po/ru.po --- goodvibes-0.3.6/po/ru.po 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/po/ru.po 2018-11-10 06:04:58.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: goodvibes 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-03-28 00:40+0700\n" +"POT-Creation-Date: 2018-11-09 19:25+0700\n" "PO-Revision-Date: 2017-10-31 10:49+0000\n" "Last-Translator: Алексей Выскубов \n" "Language-Team: Russian =20) ? 1 : 2;\n" "X-Generator: Weblate 2.17\n" -#: data/com.elboulangero.Goodvibes.desktop.in:3 src/main.c:149 -msgid "Goodvibes Radio Player" -msgstr "Радио-проигрыватель Goodvibes" +#: data/io.gitlab.Goodvibes.appdata.xml.in:4 +#: data/io.gitlab.Goodvibes.desktop.in:3 src/main.c:149 +msgid "Goodvibes" +msgstr "Goodvibes" -#: data/com.elboulangero.Goodvibes.desktop.in:4 -msgid "Radio Player" -msgstr "Радио-проигрыватель" - -#: data/com.elboulangero.Goodvibes.desktop.in:5 +#: data/io.gitlab.Goodvibes.appdata.xml.in:5 +#: data/io.gitlab.Goodvibes.desktop.in:5 msgid "Play web radios" msgstr "Воспроизведение веб-радиостанций" +#: data/io.gitlab.Goodvibes.appdata.xml.in:10 +msgid "Goodvibes is a simple internet radio player for GNU/Linux." +msgstr "" + +#: data/io.gitlab.Goodvibes.appdata.xml.in:13 +msgid "" +"It comes with every basic features you can expect from an audio player, such " +"as multimedia keys, notifications, system sleep inhibition, and MPRIS2 " +"support." +msgstr "" + +#: data/io.gitlab.Goodvibes.desktop.in:4 +msgid "Radio Player" +msgstr "Радио-проигрыватель" + #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! -#: data/com.elboulangero.Goodvibes.desktop.in:7 +#: data/io.gitlab.Goodvibes.desktop.in:7 msgid "Audio;Radio;Player;" msgstr "Аудио;Радио;Проигрыватель;" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! -#: data/com.elboulangero.Goodvibes.desktop.in:11 -msgid "goodvibes" -msgstr "goodvibes" - -#: data/ui/app-menu.glade:6 data/ui/menubar.glade:8 -#: data/ui/status-icon-menu.glade:6 src/ui/gv-station-context-menu.c:35 -#: src/ui/gv-station-dialog.c:428 +#: data/io.gitlab.Goodvibes.desktop.in:11 +msgid "io.gitlab.Goodvibes" +msgstr "io.gitlab.Goodvibes" + +#: src/ui/resources/app-menu.glade:6 src/ui/resources/menubar.glade:8 +#: src/ui/resources/status-icon-menu.glade:6 +#: src/ui/gv-station-context-menu.c:35 src/ui/gv-station-dialog.c:424 #, fuzzy msgid "Add Station" msgstr "Добавить новую станцию" -#: data/ui/app-menu.glade:13 data/ui/menubar.glade:15 -#: data/ui/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:633 +#: src/ui/resources/app-menu.glade:13 src/ui/resources/menubar.glade:15 +#: src/ui/resources/status-icon-menu.glade:12 src/ui/gv-prefs-window.c:629 msgid "Preferences" msgstr "Параметры" -#: data/ui/app-menu.glade:19 data/ui/menubar.glade:36 -#: data/ui/status-icon-menu.glade:18 +#: src/ui/resources/app-menu.glade:19 src/ui/resources/menubar.glade:36 +#: src/ui/resources/status-icon-menu.glade:18 msgid "Online Help" msgstr "Онлайн-справка" -#: data/ui/app-menu.glade:24 data/ui/menubar.glade:43 -#: data/ui/status-icon-menu.glade:22 +#: src/ui/resources/app-menu.glade:24 src/ui/resources/menubar.glade:43 +#: src/ui/resources/status-icon-menu.glade:22 msgid "About" msgstr "О программе" -#: data/ui/app-menu.glade:28 data/ui/menubar.glade:21 +#: src/ui/resources/app-menu.glade:28 src/ui/resources/menubar.glade:21 msgid "Close UI" msgstr "Закрыть окно" -#: data/ui/app-menu.glade:33 data/ui/menubar.glade:26 -#: data/ui/status-icon-menu.glade:26 +#: src/ui/resources/app-menu.glade:33 src/ui/resources/menubar.glade:26 +#: src/ui/resources/status-icon-menu.glade:26 msgid "Quit" msgstr "Выход" -#: data/ui/main-window.glade:47 src/ui/gv-main-window.c:351 +#: src/ui/resources/main-window.glade:47 src/ui/gv-main-window.c:350 msgid "No station selected" msgstr "Не выбрана радиостанция" -#: data/ui/main-window.glade:63 src/ui/gv-main-window.c:374 +#: src/ui/resources/main-window.glade:63 src/ui/gv-main-window.c:373 msgid "Stopped" msgstr "Остановлено" -#: data/ui/menubar.glade:5 +#: src/ui/resources/menubar.glade:5 msgid "Menu" msgstr "" -#: data/ui/menubar.glade:33 +#: src/ui/resources/menubar.glade:33 msgid "Help" msgstr "Справка" -#: data/ui/prefs-window.glade:35 +#: src/ui/resources/prefs-window.glade:35 msgid "Autoplay on Startup" msgstr "Воспроизведение при Запуске" -#: data/ui/prefs-window.glade:48 +#: src/ui/resources/prefs-window.glade:48 msgid "Custom Output Pipeline" msgstr "" -#: data/ui/prefs-window.glade:79 +#: src/ui/resources/prefs-window.glade:79 msgid "Apply" msgstr "" -#: data/ui/prefs-window.glade:102 +#: src/ui/resources/prefs-window.glade:102 msgid "Playback" msgstr "" -#: data/ui/prefs-window.glade:138 +#: src/ui/resources/prefs-window.glade:138 msgid "Prevent sleep while playing" msgstr "Отключить спящий режим" -#: data/ui/prefs-window.glade:151 +#: src/ui/resources/prefs-window.glade:151 msgid "System" msgstr "Система" -#: data/ui/prefs-window.glade:197 +#: src/ui/resources/prefs-window.glade:197 msgid "Native D-Bus Server" msgstr "Родной сервер D-Bus" -#: data/ui/prefs-window.glade:209 +#: src/ui/resources/prefs-window.glade:209 msgid "MPRIS2 D-Bus Server" msgstr "MPRIS2 сервер D-Bus" -#: data/ui/prefs-window.glade:222 +#: src/ui/resources/prefs-window.glade:222 msgid "D-Bus" msgstr "Шина D-Bus" -#: data/ui/prefs-window.glade:238 +#: src/ui/resources/prefs-window.glade:238 msgid "Misc" msgstr "Разное" -#: data/ui/prefs-window.glade:262 +#: src/ui/resources/prefs-window.glade:262 msgid "Autoset Window Height" msgstr "" -#: data/ui/prefs-window.glade:278 +#: src/ui/resources/prefs-window.glade:278 msgid "Theme Variant" msgstr "" -#: data/ui/prefs-window.glade:291 +#: src/ui/resources/prefs-window.glade:291 #, fuzzy msgid "System Default" msgstr "Система" -#: data/ui/prefs-window.glade:292 +#: src/ui/resources/prefs-window.glade:292 msgid "Prefer Dark" msgstr "" -#: data/ui/prefs-window.glade:293 +#: src/ui/resources/prefs-window.glade:293 msgid "Prefer Light" msgstr "" -#: data/ui/prefs-window.glade:310 +#: src/ui/resources/prefs-window.glade:310 msgid "Window" msgstr "" -#: data/ui/prefs-window.glade:336 +#: src/ui/resources/prefs-window.glade:336 #, fuzzy msgid "Send Notifications" msgstr "Оповещения" -#: data/ui/prefs-window.glade:359 +#: src/ui/resources/prefs-window.glade:359 msgid "Notifications" msgstr "Оповещения" -#: data/ui/prefs-window.glade:394 +#: src/ui/resources/prefs-window.glade:394 msgid "Console Output" msgstr "Вывод консоли" -#: data/ui/prefs-window.glade:407 +#: src/ui/resources/prefs-window.glade:407 msgid "Console" msgstr "Консоль" -#: data/ui/prefs-window.glade:426 +#: src/ui/resources/prefs-window.glade:426 msgid "Display" msgstr "Интерфейс" -#: data/ui/prefs-window.glade:464 +#: src/ui/resources/prefs-window.glade:464 msgid "Multimedia Hotkeys" msgstr "Мультимедиа-клавиши" -#: data/ui/prefs-window.glade:477 +#: src/ui/resources/prefs-window.glade:477 msgid "Keyboard" msgstr "Клавиатура" -#: data/ui/prefs-window.glade:503 +#: src/ui/resources/prefs-window.glade:503 msgid "Middle Click" msgstr "Средняя кнопка" -#: data/ui/prefs-window.glade:516 +#: src/ui/resources/prefs-window.glade:516 msgid "Toggle Play/Pause" msgstr "Воспр./Пауза" -#: data/ui/prefs-window.glade:517 +#: src/ui/resources/prefs-window.glade:517 msgid "Mute" msgstr "Приглушить" -#: data/ui/prefs-window.glade:530 +#: src/ui/resources/prefs-window.glade:530 msgid "Scrolling" msgstr "Скроллинг" -#: data/ui/prefs-window.glade:543 +#: src/ui/resources/prefs-window.glade:543 msgid "Change Station" msgstr "Сменить станцию" -#: data/ui/prefs-window.glade:544 +#: src/ui/resources/prefs-window.glade:544 msgid "Change Volume" msgstr "Регулировка громкости" -#: data/ui/prefs-window.glade:558 +#: src/ui/resources/prefs-window.glade:558 msgid "Mouse (Status Icon Mode)" msgstr "Мышь (режим Status Icon)" -#: data/ui/prefs-window.glade:577 +#: src/ui/resources/prefs-window.glade:577 msgid "Controls" msgstr "Управление" -#: data/ui/prefs-window.glade:598 +#: src/ui/resources/prefs-window.glade:598 msgid "Close" msgstr "Закрыть" -#: data/ui/station-dialog.glade:12 src/ui/gv-main-window.c:262 +#: src/ui/resources/station-dialog.glade:12 src/ui/gv-main-window.c:261 msgid "Name" msgstr "Название" -#: data/ui/station-dialog.glade:34 src/ui/gv-main-window.c:263 +#: src/ui/resources/station-dialog.glade:34 src/ui/gv-main-window.c:262 msgid "URI" msgstr "URI" -#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1088 +#: src/core/gv-engine.c:267 src/core/gv-station-list.c:1134 #, c-format msgid "%s: %s" msgstr "" @@ -242,133 +255,142 @@ msgid "'%s' is neither a known station or a valid URI" msgstr "" -#: src/core/gv-station-list.c:1089 +#: src/core/gv-station-list.c:1135 msgid "Failed to save station list" msgstr "Невозможно сохранить список радиостанций" -#: src/ui/gv-main-window.c:260 +#: src/ui/gv-main-window.c:259 msgid "Station Information" msgstr "" -#: src/ui/gv-main-window.c:274 +#: src/ui/gv-main-window.c:273 msgid "User-agent" msgstr "" -#: src/ui/gv-main-window.c:278 +#: src/ui/gv-main-window.c:277 msgid "Bitrate" msgstr "" -#: src/ui/gv-main-window.c:291 +#: src/ui/gv-main-window.c:290 #, fuzzy msgid "Metadata" msgstr "Нет метаданных" -#: src/ui/gv-main-window.c:293 +#: src/ui/gv-main-window.c:292 msgid "Artist" msgstr "" -#: src/ui/gv-main-window.c:294 +#: src/ui/gv-main-window.c:293 msgid "Title" msgstr "" -#: src/ui/gv-main-window.c:295 +#: src/ui/gv-main-window.c:294 msgid "Album" msgstr "" -#: src/ui/gv-main-window.c:296 +#: src/ui/gv-main-window.c:295 msgid "Genre" msgstr "" -#: src/ui/gv-main-window.c:297 +#: src/ui/gv-main-window.c:296 msgid "Year" msgstr "" -#: src/ui/gv-main-window.c:298 +#: src/ui/gv-main-window.c:297 msgid "Comment" msgstr "" -#: src/ui/gv-main-window.c:364 src/ui/gv-main-window.c:392 +#: src/ui/gv-main-window.c:363 src/ui/gv-main-window.c:391 msgid "Playing" msgstr "Воспроизведение" -#: src/ui/gv-main-window.c:367 +#: src/ui/gv-main-window.c:366 #, fuzzy msgid "Connecting…" msgstr "соединение" -#: src/ui/gv-main-window.c:370 +#: src/ui/gv-main-window.c:369 #, fuzzy msgid "Buffering…" msgstr "буферизация" -#: src/ui/gv-prefs-window.c:282 +#: src/ui/gv-prefs-window.c:281 msgid "Feature disabled at compile-time." msgstr "Отключено при компиляции." -#: src/ui/gv-prefs-window.c:428 +#. +#. * Setup settings and features. +#. * These function calls create a binding between a gtk widget and +#. * an internal object, initializes the widget value, and set the +#. * widgets tooltips (label + setting). +#. +#. Misc +#: src/ui/gv-prefs-window.c:424 msgid "Whether to start playback automatically on startup." msgstr "Начинать ли воспроизведение автоматически при запуске." -#: src/ui/gv-prefs-window.c:434 +#: src/ui/gv-prefs-window.c:430 #, fuzzy msgid "Whether to use a custom output pipeline." msgstr "Использовать ли настраиваемый таймаут для оповещений." -#: src/ui/gv-prefs-window.c:440 +#: src/ui/gv-prefs-window.c:436 msgid "" "The GStreamer output pipeline used for playback. Refer to theonline " "documentation for examples." msgstr "" -#: src/ui/gv-prefs-window.c:456 +#: src/ui/gv-prefs-window.c:452 msgid "Prevent the system from going to sleep while playing." msgstr "Предотвратить переход системы в спящий режим во время воспроизведения." -#: src/ui/gv-prefs-window.c:461 +#: src/ui/gv-prefs-window.c:457 msgid "Enable the native D-Bus server (needed for the command-line interface)." msgstr "Включить родной сервер D-Bus (необходимо для работы в консоли)." -#: src/ui/gv-prefs-window.c:467 +#: src/ui/gv-prefs-window.c:463 msgid "Enable the MPRIS2 D-Bus server." msgstr "Включить MPRIS2 сервер D-Bus." -#: src/ui/gv-prefs-window.c:473 +#. Display +#: src/ui/gv-prefs-window.c:469 msgid "Prefer a different variant of the theme (if available)." msgstr "" -#: src/ui/gv-prefs-window.c:480 +#: src/ui/gv-prefs-window.c:476 msgid "" "Automatically adjust the window height when a station is added or removed." msgstr "" -#: src/ui/gv-prefs-window.c:487 +#: src/ui/gv-prefs-window.c:483 #, fuzzy msgid "Setting not available in status icon mode." msgstr "Приложение не было запущено в режиме значка статуса." -#: src/ui/gv-prefs-window.c:491 +#: src/ui/gv-prefs-window.c:487 #, fuzzy msgid "Show notification when the status changes." msgstr "Выводить оповещения при изменении статуса." -#: src/ui/gv-prefs-window.c:496 +#: src/ui/gv-prefs-window.c:492 msgid "Display information on the standard output." msgstr "Выводить информацию в консоль." -#: src/ui/gv-prefs-window.c:502 +#. Controls +#: src/ui/gv-prefs-window.c:498 msgid "Bind mutimedia keys (play/pause/stop/previous/next)." msgstr "" "Назначить мультимедиа-клавиши (воспроизведение/пауза/стоп/назад/вперёд)." -#: src/ui/gv-prefs-window.c:508 +#: src/ui/gv-prefs-window.c:504 msgid "Action triggered by a middle click on the status icon." msgstr "Действие, выполняемое средней кнопкой мыши по значку статуса." -#: src/ui/gv-prefs-window.c:514 +#: src/ui/gv-prefs-window.c:510 msgid "Action triggered by mouse-scrolling on the status icon." msgstr "Действие, выполняемое при проматывании мышью по значку статуса." -#: src/ui/gv-prefs-window.c:520 +#: src/ui/gv-prefs-window.c:516 #, fuzzy msgid "Setting only available in status icon mode." msgstr "Приложение не было запущено в режиме значка статуса." @@ -378,63 +400,63 @@ msgid "Remove Station" msgstr "Удалить станцию" -#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:428 +#: src/ui/gv-station-context-menu.c:37 src/ui/gv-station-dialog.c:424 #, fuzzy msgid "Edit Station" msgstr "Изменить станцию" -#: src/ui/gv-station-dialog.c:284 +#: src/ui/gv-station-dialog.c:281 msgid "Cancel" msgstr "Отмена" -#: src/ui/gv-station-dialog.c:285 +#: src/ui/gv-station-dialog.c:282 msgid "Save" msgstr "Сохранить" -#: src/ui/gv-status-icon.c:130 +#: src/ui/gv-status-icon.c:131 msgid "stopped" msgstr "остановлено" -#: src/ui/gv-status-icon.c:133 +#: src/ui/gv-status-icon.c:134 msgid "connecting" msgstr "соединение" -#: src/ui/gv-status-icon.c:136 +#: src/ui/gv-status-icon.c:137 msgid "buffering" msgstr "буферизация" -#: src/ui/gv-status-icon.c:139 +#: src/ui/gv-status-icon.c:140 msgid "playing" msgstr "воспроизведение" -#: src/ui/gv-status-icon.c:142 +#: src/ui/gv-status-icon.c:143 msgid "unknown state" msgstr "неизвестное состояние" -#: src/ui/gv-status-icon.c:149 +#: src/ui/gv-status-icon.c:150 msgid "muted" msgstr "приглушено" -#: src/ui/gv-status-icon.c:153 +#: src/ui/gv-status-icon.c:154 msgid "vol." msgstr "гром." -#: src/ui/gv-status-icon.c:160 +#: src/ui/gv-status-icon.c:161 msgid "No station" msgstr "Нет станции" -#: src/ui/gv-status-icon.c:167 +#: src/ui/gv-status-icon.c:168 msgid "No metadata" msgstr "Нет метаданных" -#: src/feat/gv-hotkeys.c:144 +#: src/feat/gv-hotkeys.c:145 #, c-format msgid "" "%s:\n" "%s" msgstr "" -#: src/feat/gv-hotkeys.c:145 +#: src/feat/gv-hotkeys.c:146 msgid "Failed to bind the following keys" msgstr "Не удалось назначить следующие клавиши" @@ -442,34 +464,40 @@ msgid "Failed to inhibit system sleep" msgstr "" -#: src/feat/gv-notifications.c:93 +#: src/feat/gv-notifications.c:59 #, fuzzy, c-format msgid "Playing %s" msgstr "Воспроизведение" -#: src/feat/gv-notifications.c:96 +#: src/feat/gv-notifications.c:62 #, fuzzy, c-format msgid "Playing <%s>" msgstr "Воспроизведение" -#: src/feat/gv-notifications.c:137 -#, fuzzy -msgid "(Unknown title)" -msgstr "неизвестное состояние" - -#: src/feat/gv-notifications.c:263 +#: src/feat/gv-notifications.c:65 #, fuzzy msgid "Playing Station" msgstr "Сменить станцию" -#: src/feat/gv-notifications.c:266 +#: src/feat/gv-notifications.c:103 +#, fuzzy +msgid "(Unknown title)" +msgstr "неизвестное состояние" + +#: src/feat/gv-notifications.c:110 msgid "New Track" msgstr "" -#: src/feat/gv-notifications.c:269 +#: src/feat/gv-notifications.c:122 msgid "Error" msgstr "" +#~ msgid "goodvibes" +#~ msgstr "goodvibes" + +#~ msgid "Goodvibes Radio Player" +#~ msgstr "Радио-проигрыватель Goodvibes" + #~ msgid "Emit Notifications" #~ msgstr "Показывать оповещения" diff -Nru goodvibes-0.3.6/README.md goodvibes-0.4.2/README.md --- goodvibes-0.3.6/README.md 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/README.md 2018-11-10 06:04:58.000000000 +0000 @@ -1,24 +1,17 @@ Goodvibes ========= -[![Tag](https://img.shields.io/github/tag/elboulangero/goodvibes.svg)](https://github.com/elboulangero/goodvibes/releases) -[![Build](https://img.shields.io/shippable/586380d4666b4b1000d180e8.svg)](https://app.shippable.com/github/elboulangero/goodvibes) -[![Translation](https://hosted.weblate.org/widgets/goodvibes/-/svg-badge.svg)](https://hosted.weblate.org/engage/goodvibes/?utm_source=widget) -[![License](https://img.shields.io/github/license/elboulangero/goodvibes.svg)](COPYING) - -

- Goodvibes logo -

+![Goodvibes Logo](https://gitlab.com/goodvibes/goodvibes/raw/master/data/icons/hicolor/256x256/apps/goodvibes.png) **Goodvibes** is an internet radio player for GNU/Linux. It aims to be light, simple, straightforward. - **Documentation** is available on [Read the Docs](https://goodvibes.readthedocs.io) +- **Development** is hosted on [GitLab](https://gitlab.com/goodvibes/goodvibes) - **Translation** takes place on [Weblate](https://hosted.weblate.org/projects/goodvibes) -- **Development** is hosted on [GitHub](https://github.com/elboulangero/goodvibes) - **Artwork** is made by [Hector Lahminèwskï](http://lahminewski-lab.net) -Goodvibes is released under the [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html), +Goodvibes is released under the [GPLv3+](https://www.gnu.org/licenses/gpl-3.0.html), and relies on major open-source building blocks such as [GLib][], [LibSoup][], [GStreamer][] and [GTK+][]. @@ -35,13 +28,13 @@ Compiling --------- -Goodvibes is written in C and builds with the Autotools. +Goodvibes is written in C and builds with Meson. At first, make sure you have all the dependencies installed. -*Note*: The following commands assume a Debian-like distribution. If you're +*Note*: The following commands are for a Debian-like distribution. If you're using another distribution, please adjust the package names and replace `apt` -by whatever yo use. +by whatever you use. ```bash # @@ -49,7 +42,7 @@ # # Build toolchain -sudo apt install autoconf autopoint build-essential git +sudo apt install build-essential git meson # Core dependencies sudo apt install libglib2.0-dev libsoup2.4-dev \ libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev @@ -74,17 +67,19 @@ ```bash # Grab the source -git clone https://github.com/elboulangero/goodvibes.git +git clone https://gitlab.com/goodvibes/goodvibes.git cd goodvibes # Build -./autogen.sh -./configure -make - -# Run from the source tree -./goodvibes-launcher.sh +meson build +ninja -C build # Install -sudo make install +sudo ninja -C build install +``` + +You can also run the application in-tree, without installing anything. + +```bash +./goodvibes-launcher.sh ``` diff -Nru goodvibes-0.3.6/RELEASING.md goodvibes-0.4.2/RELEASING.md --- goodvibes-0.3.6/RELEASING.md 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/RELEASING.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,130 +0,0 @@ -RELEASING -========= - - - -Updating translations ---------------------- - -Before every release, it's time to update everything regarding translations, so -that translators have a chance to do their homework ! - -First, ensure that the file `po/POTFILES.in` is still up to date. This is still -a manual process, but it wouldn't be that hard to write a little script. - -Then, and before modifying the po files on our side, synchronize with Weblate -and lock it. We can do it either via the web interface, either via the client. - - # Lock Weblate translation - wlc lock - # Push changes from Weblate to upstream repository - wlc push - # Pull changes from upstream repository to your local copy - git pull - -Then, update the *translation template*, aka. `po/goodvibes.pot`, along with -the *message catalogs*, aka. the po files. - - # Update translation files - make -C po update-po - git add po/*.{po,pot} - git commit -m"i18n: update goodvibes.pot and po files" - # Push changes to upstream repository - git push - -At last, we can unlock Weblate and update it. - - # Tell Weblate to pull changes (not needed if Weblate follows your repo automatically) - wlc pull - # Unlock translations - wlc unlock - -For more details, refer to the weblate workflow as described at: -. - - - - -Releasing ---------- - -#### Translation bits - -Be sure to update everything related to **translation** (see above). - -Only then you can go on with: - -- Update the translator list in the *About* dialog. -- Update the translator list in the documentation. -- Write down changes in the `NEWS` file. - -In bash, it translates to something like that: - - ./scripts/translators.sh code - vi src/ui/gv-about-dialog.c - git commit -am"ui: update translation credits" - ./scripts/translators.sh doc - vi docs/goodvibes.readthedocs.io/credits.rst - git commit -am"doc: update translation credits" - vi NEWS - git commit -am"Update translations in changelog" - -Then: - -- Ensure `NEWS` is up-to-date (check git history and GitHub milestones). -- Bump the version in `configure.ac`. -- Git commit, git tag, git push. - -In bash, here you go: - - vi NEWS - p=0.3.4 - v=0.3.5 - sed -i "s/${p:?}/${v:?}/" configure.ac - git add NEWS configure.ac - git commit -m "Bump version to ${v:?}" - git tag "v${v:?}" - git push && git push --tags - -Done. - - - -Packaging ---------- - -After releasing, update the Debian packaging files in the goodvibes-debian git -repository. Basically, just bump the changelog, there's nothing else to do. - - DEBFULLNAME=$(git config user.name) \ - DEBEMAIL=$(git config user.email) \ - dch --distribution $(dpkg-parsechangelog --show-field Distribution) \ - --newversion ${v:?}-ebo0 - -Git commit, git push. Done - - git add debian/changelog - git commit -m "Version ${v:?}" - git push - -Then, just fire the script `packaging.sh`, which will fetch everything from -GitHub and build everything that needs to be built. - - export DEBFULLNAME=$(git config user.name) - export DEBEMAIL=$(git config user.email) - ./scripts/packaging.sh ${v:?} - -This script is tied to my config and won't work out of the box on someone else -system. But heck, if you're not me, you're not supposed to release anything -anyway, so move on ! - -At last, a few `dput` commands will finish the damn job. Done with packaging. - - - - -Artwork -------- - -Both svg source files and png files are versioned. To update the png files, run -`make icons`. diff -Nru goodvibes-0.3.6/scripts/code/gv-object-make.sh goodvibes-0.4.2/scripts/code/gv-object-make.sh --- goodvibes-0.3.6/scripts/code/gv-object-make.sh 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/scripts/code/gv-object-make.sh 2018-11-10 06:04:58.000000000 +0000 @@ -175,4 +175,4 @@ # Done ! echo "Skeleton files '$dstdir/$dstfile.[ch]' created." -echo "Don't forget to add these new files to './src/Makefile.am'." +echo "Don't forget to add these new files to the meson build file'." diff -Nru goodvibes-0.3.6/scripts/code/gv-object-templates/gv-dummy.c goodvibes-0.4.2/scripts/code/gv-object-templates/gv-dummy.c --- goodvibes-0.3.6/scripts/code/gv-object-templates/gv-dummy.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/scripts/code/gv-object-templates/gv-dummy.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,10 +1,8 @@ #include #include -#include "additions/glib-object.h" - +#include "framework/glib-object-additions.h" #include "framework/log.h" - #include "core/gv-dummy.h" /* diff -Nru goodvibes-0.3.6/scripts/images.sh goodvibes-0.4.2/scripts/images.sh --- goodvibes-0.3.6/scripts/images.sh 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/scripts/images.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -#!/bin/bash -e - -CMD=$1 -SVGDIR=data/icons/src -ICONDIR=data/icons/hicolor -SITEDIR=docs/goodvibes.readthedocs.io - -usage() { - echo "Usage: $(basename $0) " - echo - echo "This script is used to re-build various images out of the svg sources" - echo - exit 0 -} - -fail() { - echo >&2 "$@" - exit 1 -} - -checkcmd() { - command -v $1 >/dev/null 2>&1 || fail "Command '$1' is not installed, aborting" -} - -checkdir() { - [ -d "$1" ] || fail "Directory '$1' does not exist, aborting" -} - -do_icons() { - checkdir $ICONDIR - - echo '--- Building small icons ---' - for size in 16 22 24 32 48; do - inkscape \ - --export-area-page \ - --export-width $size \ - --export-png $ICONDIR/${size}x${size}/apps/goodvibes.png \ - $SVGDIR/goodvibes-small.svg - done - - echo '--- Building large icons ---' - for size in 256 512; do - inkscape \ - --export-area-page \ - --export-width $size \ - --export-png $ICONDIR/${size}x${size}/apps/goodvibes.png \ - $SVGDIR/goodvibes-large.svg - done - - echo '--- Copying symbolic icons ---' - cp $SVGDIR/goodvibes-symbolic.svg $ICONDIR/symbolic/apps/goodvibes-symbolic.svg -} - -do_site() { - checkdir $SITEDIR - - echo '--- Building favicon ---' - tmpdir=$(mktemp --directory --tmpdir=$(pwd) favicon.XXXXXX) - trap "rm -fr $tmpdir" EXIT - for size in 16 24 32 48 64; do - inkscape \ - --export-area-page \ - --export-width $size \ - --export-png $tmpdir/$size.png \ - $SVGDIR/goodvibes-favicon.svg - done - convert $tmpdir/*.png $SITEDIR/images/favicon.ico - identify $SITEDIR/images/favicon.ico - - echo '--- Building goodvibes logo ---' - inkscape \ - --export-area-page \ - --export-width 192 \ - --export-png $SITEDIR/images/goodvibes.png \ - $SVGDIR/goodvibes-large.svg -} - -checkcmd convert -checkcmd identify -checkcmd inkscape -checkdir $SVGDIR - -case $CMD in - icons) - do_icons - ;; - - site) - do_site - ;; - - *) - usage - ;; -esac diff -Nru goodvibes-0.3.6/scripts/install-git-hook.sh goodvibes-0.4.2/scripts/install-git-hook.sh --- goodvibes-0.3.6/scripts/install-git-hook.sh 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/scripts/install-git-hook.sh 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e +set -u + +cd "$MESON_SOURCE_ROOT" + +[ -f .git/hooks/pre-commit.sample ] || exit 0 +[ ! -f .git/hooks/pre-commit ] || exit 0 + +install -m0755 .git/hooks/pre-commit.sample .git/hooks/pre-commit +echo 'Git pre-commit hook installed' diff -Nru goodvibes-0.3.6/scripts/meson/post-install goodvibes-0.4.2/scripts/meson/post-install --- goodvibes-0.3.6/scripts/meson/post-install 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/scripts/meson/post-install 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,25 @@ +#!/bin/sh + +set -e + +DATADIR="$1" + +# Package managers set this so we don't need to run +if [ "$DESTDIR" ]; then exit 0; fi + +cmdcheck() { command -v "$1" >/dev/null 2>&1; } + +if cmdcheck glib-compile-schemas; then + echo "Compiling GSettings schemas..." + glib-compile-schemas "$DATADIR/glib-2.0/schemas" +fi + +if cmdcheck gtk-update-icon-cache; then + echo "Updating icon cache..." + gtk-update-icon-cache -t -f "$DATADIR/icons/hicolor" +fi + +if cmdcheck update-desktop-database; then + echo "Updating desktop database..." + update-desktop-database "$DATADIR/applications" +fi diff -Nru goodvibes-0.3.6/scripts/meson/validate-ui-file goodvibes-0.4.2/scripts/meson/validate-ui-file --- goodvibes-0.3.6/scripts/meson/validate-ui-file 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/scripts/meson/validate-ui-file 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,17 @@ +#!/bin/sh + +set -e + +UIFILE="$1" + +SKIP=77 # the Meson test harness recognises exit code 77 as skip + +cmdcheck() { command -v "$1" >/dev/null 2>&1; } + +# Skip test if there's no graphics +[ "$DISPLAY" ] || exit $SKIP + +# Skip test if gtk-builder-tool is not installed +cmdcheck gtk-builder-tool || exit $SKIP + +gtk-builder-tool validate "$UIFILE" diff -Nru goodvibes-0.3.6/scripts/packaging.sh goodvibes-0.4.2/scripts/packaging.sh --- goodvibes-0.3.6/scripts/packaging.sh 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/scripts/packaging.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -#!/bin/bash -# -# References: -# -# -# - -set -e -set -u - -VERSION='' # $1 -DEBIAN_DISTS='stretch buster' -stretch=deb9 -buster=deb10 -UBUNTU_DISTS='xenial artful' -xenial=ubuntu16.04 -artful=ubuntu17.10 -ARCHIVE_BASEURL=https://github.com/elboulangero/goodvibes/archive -PACKAGE_URL=https://github.com/elboulangero/goodvibes-debian.git - -fail() { - echo >&2 $@ - exit 1 -} - -title() { - echo -e '\e[7m'">>> $@"'\e[0m' -} - -usage() { - cat << EOF -Usage: $(basename $0) - -Example: $(basename $0) '0.3.4' - -This script takes care of packaging Goodvibes for Debian and Ubuntu, -assuming that everything is ready: aka a new version of Goodvibes was -properly released, and the Debian packaging files have been updated, -and the whole thing's been pushed to GitHub. - -Actually, the script does not deal with the current source tree (and -therefore has no real reason to live here). Everything is downloaded -from GitHub. -EOF - exit 0 -} - -[ $# -gt 0 ] && VERSION=$1 -[ "$VERSION" ] || usage - -set -e -set -u - -WRKDIR=$(pwd)/packaging -mkdir $WRKDIR -cd $WRKDIR - -# Download everything - -title "Downloading source and packaging files for version '$VERSION' ..." - -URL=$ARCHIVE_BASEURL/v$VERSION.tar.gz -OUTPUT=goodvibes_$VERSION.orig.tar.gz -wget $URL -O $OUTPUT -tar -xf $OUTPUT - -cd goodvibes-$VERSION - -git clone $PACKAGE_URL tmp -mv tmp/debian . -rm -fr tmp - -DEBVERSION=$(dpkg-parsechangelog --show-field version) -[ "$VERSION" == "$(cut -d'-' -f1 <<< $DEBVERSION)" ] || \ - fail "Version '$VERSION' does not match Debian version '$DEBVERSION'" - -# Build the Debian binary packages - -PBUILDER_CACHE=/var/cache/pbuilder - -for dist in $DEBIAN_DISTS; do - chrootdir=$PBUILDER_CACHE/base-$dist.cow - [ -d $chrootdir ] || continue - - title "Building binary package for $dist ..." - - sed --in-place \ - "s/$VERSION-.*) .*;/$VERSION-0ebo1+${!dist}) $dist;/" \ - debian/changelog - - sudo cowbuilder update \ - --distribution $dist \ - --basepath $chrootdir - - pdebuild --pbuilder cowbuilder \ - --auto-debsign \ - --buildresult .. \ - -- \ - --basepath $chrootdir -done - -# Build the Ubuntu source packages - -for dist in $UBUNTU_DISTS; do - - title "Building source package for $dist ..." - - sed --in-place \ - "s/$VERSION-.*) .*;/$VERSION-0ebo1+${!dist}) $dist;/" \ - debian/changelog - - debuild -S -sa -done - -# Done - -title "Done, time to upload !" -dput --host-list diff -Nru goodvibes-0.3.6/scripts/rebuild-images.sh goodvibes-0.4.2/scripts/rebuild-images.sh --- goodvibes-0.3.6/scripts/rebuild-images.sh 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/scripts/rebuild-images.sh 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,101 @@ +#!/bin/bash + +set -e +set -u + +CMD="${1:-}" + +APPID=io.gitlab.Goodvibes + +SVGDIR=data/icons/src +ICONDIR=data/icons/hicolor +SITEDIR=docs/goodvibes.readthedocs.io + +usage() { + echo "Usage: $(basename $0) " + echo + echo "This script is used to re-build various images out of the svg sources" + echo + exit 0 +} + +fail() { + echo >&2 "$@" + exit 1 +} + +checkcmd() { + command -v $1 >/dev/null 2>&1 || fail "Command '$1' is not installed, aborting" +} + +checkdir() { + [ -d "$1" ] || fail "Directory '$1' does not exist, aborting" +} + +do_icons() { + checkdir $ICONDIR + + echo '--- Building small icons ---' + for size in 16 22 24 32 48; do + inkscape \ + --export-area-page \ + --export-width $size \ + --export-png $ICONDIR/${size}x${size}/apps/$APPID.png \ + $SVGDIR/goodvibes-small.svg + done + + echo '--- Building large icons ---' + for size in 256 512; do + inkscape \ + --export-area-page \ + --export-width $size \ + --export-png $ICONDIR/${size}x${size}/apps/$APPID.png \ + $SVGDIR/goodvibes-large.svg + done + + echo '--- Copying symbolic icons ---' + cp $SVGDIR/goodvibes-symbolic.svg $ICONDIR/symbolic/apps/$APPID-symbolic.svg +} + +do_site() { + checkdir $SITEDIR + + echo '--- Building favicon ---' + tmpdir=$(mktemp --directory --tmpdir=$(pwd) favicon.XXXXXX) + trap "rm -fr $tmpdir" EXIT + for size in 16 24 32 48 64; do + inkscape \ + --export-area-page \ + --export-width $size \ + --export-png $tmpdir/$size.png \ + $SVGDIR/goodvibes-favicon.svg + done + convert $tmpdir/*.png $SITEDIR/images/favicon.ico + identify $SITEDIR/images/favicon.ico + + echo '--- Building logo ---' + inkscape \ + --export-area-page \ + --export-width 192 \ + --export-png $SITEDIR/images/goodvibes.png \ + $SVGDIR/goodvibes-large.svg +} + +checkcmd convert +checkcmd identify +checkcmd inkscape +checkdir $SVGDIR + +case $CMD in + icons) + do_icons + ;; + + site) + do_site + ;; + + *) + usage + ;; +esac diff -Nru goodvibes-0.3.6/scripts/test/mpris2.sh goodvibes-0.4.2/scripts/test/mpris2.sh --- goodvibes-0.3.6/scripts/test/mpris2.sh 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/scripts/test/mpris2.sh 2018-11-10 06:04:58.000000000 +0000 @@ -17,8 +17,8 @@ echo "" echo "Examples:" echo " $0 call Player Play" - echo " $0 call TrackList GoTo objpath:\"/com/elboulangero/Goodvibes/TrackList/0x55be33e73a60\"" - echo " $0 call TrackList GetTracksMetadata array:objpath:\"/com/elboulangero/Goodvibes/TrackList/0x56502c272620\",\"/com/elboulangero/Goodvibes/TrackList/0x56502c272660\"" + echo " $0 call TrackList GoTo objpath:\"/io/gitlab/Goodvibes/TrackList/0x55be33e73a60\"" + echo " $0 call TrackList GetTracksMetadata array:objpath:\"/io/gitlab/Goodvibes/TrackList/0x56502c272620\",\"/io/gitlab/Goodvibes/TrackList/0x56502c272660\"" } iface_real() diff -Nru goodvibes-0.3.6/scripts/translators.sh goodvibes-0.4.2/scripts/translators.sh --- goodvibes-0.3.6/scripts/translators.sh 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/scripts/translators.sh 2018-11-10 06:04:58.000000000 +0000 @@ -18,18 +18,17 @@ } get_translators() { - # xargs here is used to trim whitespaces - # https://stackoverflow.com/a/12973694/776208 - for file in po/*.po; do lc=$(basename $file | cut -d'.' -f1) line=$(grep '^"Language-Team' $file) - lang=$(echo $line | cut -d':' -f2- | cut -d'<' -f1 | xargs) + value=$(echo $line | cut -d':' -f2- | sed 's/^ *//') + lang=$(echo $value | cut -d'<' -f1 | sed 's/ *$//') line=$(grep '^"Last-Translator' $file) - name=$(echo $line | cut -d':' -f2- | cut -d'<' -f1 | xargs) - email=$(echo $line | cut -d'<' -f2- | cut -d'>' -f1 | xargs) + value=$(echo $line | cut -d':' -f2- | sed 's/^ *//') + name=$(echo $value | cut -d'<' -f1 | sed 's/ *$//') + email=$(echo $value | cut -d'<' -f2- | cut -d'>' -f1) LCS+=("${lc:?}") LANGS+=("${lang:?}") diff -Nru goodvibes-0.3.6/.shippable.yml goodvibes-0.4.2/.shippable.yml --- goodvibes-0.3.6/.shippable.yml 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/.shippable.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -language: c - -branches: - only: - - master - -compiler: - - gcc - - clang - -env: - global: - - CPPFLAGS="-std=gnu99 -Wall -Wextra -Wshadow -Werror -Wno-deprecated-declarations" - matrix: - - IMAGE_NAME="elboulangero/goodvibes-debian" - - IMAGE_NAME="elboulangero/goodvibes-ubuntu" - - IMAGE_NAME="elboulangero/goodvibes-fedora" - -build: - pre_ci_boot: - image_name: $IMAGE_NAME - image_tag: latest - pull: true - - ci: - - ./autogen.sh && CPPFLAGS="$CPPFLAGS" ./configure --enable-all && make && make install - diff -Nru goodvibes-0.3.6/src/additions/glib.c goodvibes-0.4.2/src/additions/glib.c --- goodvibes-0.3.6/src/additions/glib.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/additions/glib.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,133 +0,0 @@ -/* - * Goodvibes Radio Player - * - * Copyright (C) 2015-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include - -/* - * Version Information - */ - -const gchar * -glib_get_runtime_version_string(void) -{ - static gchar *version_string; - - if (version_string == NULL) { - version_string = g_strdup_printf("GLib %u.%u.%u", - glib_major_version, - glib_minor_version, - glib_micro_version); - } - - return version_string; -} - -const gchar * -glib_get_compile_version_string(void) -{ - static gchar *version_string; - - if (version_string == NULL) { - version_string = g_strdup_printf("GLib %u.%u.%u", - GLIB_MAJOR_VERSION, - GLIB_MINOR_VERSION, - GLIB_MICRO_VERSION); - } - - return version_string; -} - -/* - * String Utilities Functions - */ - -gchar * -g_strjoin_null(const gchar *separator, unsigned int n_strings, ...) -{ - gchar *string, *s; - va_list args; - gsize len; - gsize separator_len; - gchar *ptr; - guint i; - - if (separator == NULL) - separator = ""; - - separator_len = strlen(separator); - - /* First part, getting length */ - len = 1; - va_start(args, n_strings); - for (i = 0; i < n_strings; i++) { - s = va_arg(args, gchar *); - if (s) { - if (len != 1) - len += separator_len; - len += strlen(s); - } - } - va_end(args); - - /* Second part, building string */ - string = g_new(gchar, len); - ptr = string; - va_start(args, n_strings); - for (i = 0; i < n_strings; i++) { - s = va_arg(args, gchar *); - if (s) { - if (ptr != string) - ptr = g_stpcpy(ptr, separator); - ptr = g_stpcpy(ptr, s); - } - } - va_end(args); - - if (ptr == string) - string[0] = '\0'; - - return string; -} - -/* - * GVariant - */ - -void -g_variant_builder_add_dictentry_array_string(GVariantBuilder *b, const gchar *key, ...) -{ - GVariantBuilder ab; - va_list ap; - gchar *s; - - g_variant_builder_init(&ab, G_VARIANT_TYPE_ARRAY); - - va_start(ap, key); - s = va_arg(ap, gchar *); - while (s) { - GVariant *tmp = g_variant_new_string(s); - g_variant_builder_add(&ab, "v", tmp); - s = va_arg(ap, gchar *); - } - - g_variant_builder_add(b, "{sv}", key, g_variant_builder_end(&ab)); -} diff -Nru goodvibes-0.3.6/src/additions/glib.h goodvibes-0.4.2/src/additions/glib.h --- goodvibes-0.3.6/src/additions/glib.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/additions/glib.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -/* - * Goodvibes Radio Player - * - * Copyright (C) 2015-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __GOODVIBES_ADDITIONS_GLIB_H__ -#define __GOODVIBES_ADDITIONS_GLIB_H__ - -#include - -/* - * Version Information - */ - -const gchar *glib_get_runtime_version_string(void); -const gchar *glib_get_compile_version_string(void); - -/* - * String Utilities Functions - */ - -gchar *g_strjoin_null(const gchar *separator, unsigned int n_strings, ...); - -/* - * GVariant - */ - -#define g_variant_builder_add_dictentry_string(b, key, val) \ - g_variant_builder_add(b, "{sv}", key, g_variant_new_string(val)) - -#define g_variant_builder_add_dictentry_object_path(b, key, val) \ - g_variant_builder_add(b, "{sv}", key, g_variant_new_object_path(val)) - -void g_variant_builder_add_dictentry_array_string(GVariantBuilder *b, - const gchar *key, - ...) G_GNUC_NULL_TERMINATED; - -#endif /* __GOODVIBES_ADDITIONS_GLIB_H__ */ diff -Nru goodvibes-0.3.6/src/additions/glib-object.c goodvibes-0.4.2/src/additions/glib-object.c --- goodvibes-0.3.6/src/additions/glib-object.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/additions/glib-object.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,172 +0,0 @@ -/* - * Goodvibes Radio Player - * - * Copyright (C) 2015-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "additions/glib-object.h" - -/* - * GType - */ - -gchar * -g_type_dup_name(GType type) -{ - return g_strdup(g_type_name(type)); -} - -gchar * -g_type_dup_name_no_prefix(GType type) -{ - const gchar *type_name; - const gchar *ptr; - - type_name = g_type_name(type); - - ptr = type_name; - if (*ptr != '\0') - ptr++; - - while (*ptr != '\0') { - if (g_ascii_isupper(*ptr)) - break; - ptr++; - } - - if (*ptr == '\0') - return g_strdup(type_name); - else - return g_strdup(ptr); - -} - -/* - * GObject - */ - -gboolean -g_object_get_boolean(GObject *object, const gchar *property_name) -{ - gboolean value; - - g_object_get(object, property_name, &value, NULL); - - return value; -} - -guint -g_object_get_uint(GObject *object, const gchar *property_name) -{ - guint value; - - g_object_get(object, property_name, &value, NULL); - - return value; -} - -gchar * -g_object_get_string(GObject *object, const gchar *property_name) -{ - gchar *value; - - g_object_get(object, property_name, &value, NULL); - - return value; -} - -const gchar * -g_object_get_property_desc(GObject *object, const gchar *property_name) -{ - GParamSpec *pspec; - const gchar *desc; - - pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(object), property_name); - g_assert_nonnull(pspec); - desc = g_param_spec_get_blurb(pspec); - g_assert_nonnull(desc); - - return desc; -} - -void -g_object_get_property_uint_bounds(GObject *object, const gchar *property_name, - guint *minimum, guint *maximum) -{ - GParamSpec *pspec; - GParamSpecUInt *pspec_uint; - - if (minimum) - *minimum = 0; - if (maximum) - *maximum = 0; - - pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(object), property_name); - g_assert_nonnull(pspec); - g_assert_true(G_IS_PARAM_SPEC_UINT(pspec)); - - pspec_uint = G_PARAM_SPEC_UINT(pspec); - if (minimum) - *minimum = pspec_uint->minimum; - if (maximum) - *maximum = pspec_uint->maximum; -} - -/* - * Signals - */ - -void -g_signal_handlers_connect_object(gpointer instance, GSignalHandler *handlers, - gpointer gobject, GConnectFlags connect_flags) -{ - GSignalHandler *handler; - - if (handlers == NULL) - return; - - for (handler = handlers; handler->name; handler++) - g_signal_connect_object(instance, handler->name, handler->callback, - gobject, connect_flags); -} - -void -g_signal_handlers_block(gpointer instance, GSignalHandler *handlers, gpointer data) -{ - GSignalHandler *handler; - - if (handlers == NULL) - return; - - for (handler = handlers; handler->name; handler++) - g_signal_handlers_block_by_func(instance, handler->callback, data); -} - -void -g_signal_handlers_unblock(gpointer instance, GSignalHandler *handlers, gpointer data) -{ - GSignalHandler *handler; - - if (handlers == NULL) - return; - - for (handler = handlers; handler->name; handler++) - g_signal_handlers_unblock_by_func(instance, handler->callback, data); -} diff -Nru goodvibes-0.3.6/src/additions/glib-object.h goodvibes-0.4.2/src/additions/glib-object.h --- goodvibes-0.3.6/src/additions/glib-object.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/additions/glib-object.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -/* - * Goodvibes Radio Player - * - * Copyright (C) 2015-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __GOODVIBES_ADDITIONS_GLIB_OBJECT_H__ -#define __GOODVIBES_ADDITIONS_GLIB_OBJECT_H__ - -#include - -/* - * GType - */ - -/* Duplicate type name, eventually without the prefix */ -gchar *g_type_dup_name(GType type); -gchar *g_type_dup_name_no_prefix(GType type); - -/* - * GObject - */ - -/* Duplicate type name, eventually without the prefix */ -#define g_object_dup_type_name(obj) \ - g_type_dup_name(G_OBJECT_TYPE(obj)) -#define g_object_dup_type_name_no_prefix(obj) \ - g_type_dup_name_no_prefix(G_OBJECT_TYPE(obj)) - -/* Chain up for finalize() */ -#define G_OBJECT_CHAINUP_FINALIZE(module_obj_name, obj) \ - G_OBJECT_CLASS(module_obj_name##_parent_class)->finalize(obj) - -/* Chain up for constructed() - beware, constructed() is not guaranteed to exist */ -#define G_OBJECT_CHAINUP_CONSTRUCTED(module_obj_name, obj) \ - do { \ - if (G_OBJECT_CLASS(module_obj_name##_parent_class)->constructed) \ - G_OBJECT_CLASS(module_obj_name##_parent_class)->constructed(obj); \ - } while (0) - -/* get() for fundamental types */ -gboolean g_object_get_boolean(GObject *object, const gchar *property_name); -guint g_object_get_uint (GObject *object, const gchar *property_name); -gchar *g_object_get_string (GObject *object, const gchar *property_name); - -const gchar *g_object_get_property_desc (GObject *object, const gchar *property_name); -void g_object_get_property_uint_bounds(GObject *object, const gchar *property_name, - guint *minimum, guint *maximum); - -/* - * Signals - */ - -struct _GSignalHandler { - const gchar *name; - GCallback callback; -}; - -typedef struct _GSignalHandler GSignalHandler; - -void g_signal_handlers_connect_object(gpointer instance, GSignalHandler *handlers, gpointer gobject, - GConnectFlags connect_flags); -void g_signal_handlers_block (gpointer instance, GSignalHandler *handlers, gpointer data); -void g_signal_handlers_unblock (gpointer instance, GSignalHandler *handlers, gpointer data); - -#endif /* __GOODVIBES_ADDITIONS_GLIB_OBJECT_H__ */ diff -Nru goodvibes-0.3.6/src/additions/gst.c goodvibes-0.4.2/src/additions/gst.c --- goodvibes-0.3.6/src/additions/gst.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/additions/gst.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -/* - * Goodvibes Radio Player - * - * Copyright (C) 2015-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -/* - * Gst - */ - -const gchar * -gst_get_runtime_version_string(void) -{ - static gchar *version_string; - - if (version_string == NULL) { - guint major; - guint minor; - guint micro; - guint nano; - - gst_version(&major, &minor, µ, &nano); - - version_string = g_strdup_printf("GStreamer %u.%u.%u.%u", - major, minor, micro, nano); - } - - return version_string; -} - -const gchar * -gst_get_compile_version_string(void) -{ - static gchar *version_string; - - if (version_string == NULL) { - version_string = g_strdup_printf("GStreamer %u.%u.%u.%u", - GST_VERSION_MAJOR, - GST_VERSION_MINOR, - GST_VERSION_MICRO, - GST_VERSION_NANO); - } - - return version_string; -} diff -Nru goodvibes-0.3.6/src/additions/gst.h goodvibes-0.4.2/src/additions/gst.h --- goodvibes-0.3.6/src/additions/gst.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/additions/gst.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* - * Goodvibes Radio Player - * - * Copyright (C) 2015-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __GOODVIBES_ADDITIONS_GST_H__ -#define __GOODVIBES_ADDITIONS_GST_H__ - -/* - * Gst - */ - -const gchar *gst_get_runtime_version_string(void); -const gchar *gst_get_compile_version_string(void); - -#endif /* __GOODVIBES_ADDITIONS_GST_H__ */ diff -Nru goodvibes-0.3.6/src/additions/gtk.c goodvibes-0.4.2/src/additions/gtk.c --- goodvibes-0.3.6/src/additions/gtk.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/additions/gtk.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -/* - * Goodvibes Radio Player - * - * Copyright (C) 2015-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include - -/* - * Version Information - */ - -const gchar * -gtk_get_runtime_version_string(void) -{ - static gchar *version_string; - - if (version_string == NULL) { - version_string = g_strdup_printf("GTK+ %u.%u.%u", - gtk_get_major_version(), - gtk_get_minor_version(), - gtk_get_micro_version()); - } - - return version_string; -} - -const gchar * -gtk_get_compile_version_string(void) -{ - static gchar *version_string; - - if (version_string == NULL) { - version_string = g_strdup_printf("GTK+ %u.%u.%u", - GTK_MAJOR_VERSION, - GTK_MINOR_VERSION, - GTK_MICRO_VERSION); - } - - return version_string; -} diff -Nru goodvibes-0.3.6/src/additions/gtk.h goodvibes-0.4.2/src/additions/gtk.h --- goodvibes-0.3.6/src/additions/gtk.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/additions/gtk.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -/* - * Goodvibes Radio Player - * - * Copyright (C) 2015-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __GOODVIBES_ADDITIONS_GTK_H__ -#define __GOODVIBES_ADDITIONS_GTK_H__ - -#include - -/* - * Version Information - */ - -const gchar *gtk_get_runtime_version_string(void); -const gchar *gtk_get_compile_version_string(void); - -/* - * GtkBuilder - */ - -#define gtk_builder_get_widget(builder, name) \ - GTK_WIDGET(gtk_builder_get_object(builder, name)) - -#define gtk_builder_get_object(builder, name) \ - G_OBJECT(gtk_builder_get_object(builder, name)) - -/* - * Convenient macros to save widgets from a GtkBuilder instance. - * If the widget is not found, it is considered as a programming error, - * therefore ending the execution of the program. - * This macro also ensures that the widget name in the ui file is the same - * as the one used in the C file, therefore enforcing a consistent naming - * across the code. - */ - -#define GTK_BUILDER_SAVE_WIDGET(builder, str, name) \ - do { \ - str->name = gtk_builder_get_widget(builder, #name); \ - g_assert(GTK_IS_WIDGET(str->name)); \ - } while (0) - -#define GTK_BUILDER_SAVE_OBJECT(builder, str, name) \ - do { \ - str->name = gtk_builder_get_object(builder, #name); \ - g_assert(G_IS_OBJECT(str->name)); \ - } while (0) - -/* - * GtkWidget - */ - -#define gtk_widget_set_margins(widget, margin) \ - do { \ - gtk_widget_set_margin_start(widget, margin); \ - gtk_widget_set_margin_end(widget, margin); \ - gtk_widget_set_margin_top(widget, margin); \ - gtk_widget_set_margin_bottom(widget, margin); \ - } while (0) - -#endif /* __GOODVIBES_ADDITIONS_GTK_H__ */ diff -Nru goodvibes-0.3.6/src/client.c goodvibes-0.4.2/src/client.c --- goodvibes-0.3.6/src/client.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/client.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -27,6 +27,8 @@ #include #include +#include "framework/config.h" + /* http://misc.flogisoft.com/bash/tip_colors_and_formatting */ #define ESC "\033" #define BOLD_CODE "[1m" @@ -64,9 +66,9 @@ NL(); TITLE ("Base commands"); - COMMAND("launch", "Launch " PACKAGE_CAMEL_NAME); - COMMAND("quit", "Quit " PACKAGE_CAMEL_NAME); - COMMAND("is-running", "Check whether " PACKAGE_CAMEL_NAME " is running"); + COMMAND("launch", "Launch " GV_NAME_CAPITAL); + COMMAND("quit", "Quit " GV_NAME_CAPITAL); + COMMAND("is-running", "Check whether " GV_NAME_CAPITAL " is running"); COMMAND("help", "Print this help message"); NL(); @@ -113,9 +115,9 @@ * DBus */ -#define DBUS_NAME PACKAGE_APPLICATION_ID -#define DBUS_PATH PACKAGE_APPLICATION_PATH -#define DBUS_ROOT_IFACE PACKAGE_APPLICATION_ID +#define DBUS_NAME GV_APPLICATION_ID +#define DBUS_PATH GV_APPLICATION_PATH +#define DBUS_ROOT_IFACE GV_APPLICATION_ID #define DBUS_PLAYER_IFACE DBUS_ROOT_IFACE ".Player" #define DBUS_STATIONS_IFACE DBUS_ROOT_IFACE ".Stations" @@ -150,7 +152,7 @@ if (error->domain == G_DBUS_ERROR && error->code == G_DBUS_ERROR_NAME_HAS_NO_OWNER) { /* Goodvibes is not running */ - print_err(PACKAGE_CAMEL_NAME " is not running !"); + print_err(GV_NAME_CAPITAL " is not running !"); } else { /* Other error, just dump the GError */ print_err("DBus call error: %s", error->message); @@ -751,7 +753,7 @@ /* Section */ capitalize_first_letters(argv[1]); section = argv[1]; - schema_id = g_strjoin(".", PACKAGE_APPLICATION_ID, section, NULL); + schema_id = g_strjoin(".", GV_APPLICATION_ID, section, NULL); argc -= 2; argv += 2; diff -Nru goodvibes-0.3.6/src/core/gst-additions.c goodvibes-0.4.2/src/core/gst-additions.c --- goodvibes-0.3.6/src/core/gst-additions.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/core/gst-additions.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Goodvibes Radio Player + * + * Copyright (C) 2015-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +/* + * Version Information + */ + +const gchar * +gst_get_runtime_version_string(void) +{ + static gchar *version_string; + + if (version_string == NULL) { + guint major; + guint minor; + guint micro; + guint nano; + + gst_version(&major, &minor, µ, &nano); + + version_string = g_strdup_printf("GStreamer %u.%u.%u.%u", + major, minor, micro, nano); + } + + return version_string; +} + +const gchar * +gst_get_compile_version_string(void) +{ + static gchar *version_string; + + if (version_string == NULL) { + version_string = g_strdup_printf("GStreamer %u.%u.%u.%u", + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + GST_VERSION_MICRO, + GST_VERSION_NANO); + } + + return version_string; +} diff -Nru goodvibes-0.3.6/src/core/gst-additions.h goodvibes-0.4.2/src/core/gst-additions.h --- goodvibes-0.3.6/src/core/gst-additions.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/core/gst-additions.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,32 @@ +/* + * Goodvibes Radio Player + * + * Copyright (C) 2015-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GOODVIBES_FRAMEWORK_GST_ADDITIONS_H__ +#define __GOODVIBES_FRAMEWORK_GST_ADDITIONS_H__ + +/* + * Gst + */ + +const gchar *gst_get_runtime_version_string(void); +const gchar *gst_get_compile_version_string(void); + +#endif /* __GOODVIBES_FRAMEWORK_GST_ADDITIONS_H__ */ diff -Nru goodvibes-0.3.6/src/core/gv-core.c goodvibes-0.4.2/src/core/gv-core.c --- goodvibes-0.3.6/src/core/gv-core.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-core.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -28,6 +28,8 @@ #include "core/gv-player.h" #include "core/gv-station-list.h" +#define CORE_SCHEMA_ID_SUFFIX "Core" + /* * Public variables */ @@ -54,7 +56,7 @@ #include -#include "additions/gst.h" +#include "core/gst-additions.h" void gv_core_audio_backend_cleanup(void) @@ -88,10 +90,22 @@ static gchar * make_user_agent(void) { - return g_strdup_printf("%s/%s (%s)", - PACKAGE_CAMEL_NAME, - PACKAGE_VERSION, - "Linux"); + const gchar *os = NULL; + gchar *agent; + + /* https://sourceforge.net/p/predef/wiki/OperatingSystems */ +#ifdef __gnu_linux__ + os = "GNU/Linux"; +#elif __linux__ + os = "Linux"; +#endif + + if (os) + agent = g_strdup_printf("%s/%s (%s)", GV_NAME_CAPITAL, PACKAGE_VERSION, os); + else + agent = g_strdup_printf("%s/%s", GV_NAME_CAPITAL, PACKAGE_VERSION); + + return agent; } /* @@ -130,8 +144,7 @@ { /* Destroy core objects */ core_objects = g_list_reverse(core_objects); - g_list_foreach(core_objects, (GFunc) g_object_unref, NULL); - g_list_free(core_objects); + g_list_free_full(core_objects, (GDestroyNotify) g_object_unref); /* Clear application pointer */ gv_core_application = NULL; @@ -153,7 +166,7 @@ gv_core_application = application; /* Create core objects */ - gv_core_settings = g_settings_new(PACKAGE_APPLICATION_ID ".Core"); + gv_core_settings = gv_get_settings(CORE_SCHEMA_ID_SUFFIX); core_objects = g_list_append(core_objects, gv_core_settings); gv_core_station_list = gv_station_list_new(); @@ -168,6 +181,6 @@ /* Register objects in the framework */ for (item = core_objects; item; item = item->next) { GObject *object = G_OBJECT(item->data); - gv_framework_register(object); + gv_framework_register_object(object); } } diff -Nru goodvibes-0.3.6/src/core/gv-core.h goodvibes-0.4.2/src/core/gv-core.h --- goodvibes-0.3.6/src/core/gv-core.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-core.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/core/gv-core-internal.h goodvibes-0.4.2/src/core/gv-core-internal.h --- goodvibes-0.3.6/src/core/gv-core-internal.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-core-internal.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/core/gv-engine.c goodvibes-0.4.2/src/core/gv-engine.c --- goodvibes-0.3.6/src/core/gv-engine.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-engine.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -24,9 +24,9 @@ #include #include -#include "additions/glib-object.h" -#include "additions/gst.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" +#include "core/gst-additions.h" #include "core/gv-core-enum-types.h" #include "core/gv-core-internal.h" #include "core/gv-metadata.h" @@ -1168,7 +1168,7 @@ properties[PROP_STATE] = g_param_spec_enum("state", "Playback state", NULL, - GV_ENGINE_STATE_ENUM_TYPE, + GV_TYPE_ENGINE_STATE, GV_ENGINE_STATE_STOPPED, GV_PARAM_DEFAULT_FLAGS | G_PARAM_READABLE); diff -Nru goodvibes-0.3.6/src/core/gv-engine.h goodvibes-0.4.2/src/core/gv-engine.h --- goodvibes-0.3.6/src/core/gv-engine.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-engine.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/core/gv-metadata.c goodvibes-0.4.2/src/core/gv-metadata.c --- goodvibes-0.3.6/src/core/gv-metadata.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-metadata.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -22,7 +22,7 @@ #include #include -#include "additions/glib-object.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-metadata.h" diff -Nru goodvibes-0.3.6/src/core/gv-metadata.h goodvibes-0.4.2/src/core/gv-metadata.h --- goodvibes-0.3.6/src/core/gv-metadata.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-metadata.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/core/gv-player.c goodvibes-0.4.2/src/core/gv-player.c --- goodvibes-0.3.6/src/core/gv-player.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-player.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -24,7 +24,7 @@ #include #include -#include "additions/glib-object.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-engine.h" #include "core/gv-core-enum-types.h" @@ -984,7 +984,7 @@ /* Player properties */ properties[PROP_STATE] = g_param_spec_enum("state", "Playback state", NULL, - GV_PLAYER_STATE_ENUM_TYPE, + GV_TYPE_PLAYER_STATE, GV_PLAYER_STATE_STOPPED, GV_PARAM_DEFAULT_FLAGS | G_PARAM_READABLE); diff -Nru goodvibes-0.3.6/src/core/gv-player.h goodvibes-0.4.2/src/core/gv-player.h --- goodvibes-0.3.6/src/core/gv-player.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-player.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/core/gv-playlist.c goodvibes-0.4.2/src/core/gv-playlist.c --- goodvibes-0.3.6/src/core/gv-playlist.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-playlist.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -34,7 +34,7 @@ #include #include -#include "additions/glib-object.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-playlist.h" @@ -156,14 +156,46 @@ * https://en.wikipedia.org/wiki/PLS_(file_format) */ +static guint +pls_get_n_items(GKeyFile *keyfile) +{ + const gchar *keys[] = { "NumberOfEntries", "numberofentries", + "NumberOfEvents", "numberofevents", + NULL }; + const gchar **ptr; + const gchar *key = NULL; + GError *err = NULL; + gint n_items; + + for (ptr = keys; *ptr; ptr++) { + if (g_key_file_has_key(keyfile, "playlist", *ptr, NULL)) { + key = *ptr; + break; + } + } + + if (key == NULL) { + WARNING("Failed to get the number of items in pls playlist"); + return 0; + } + + n_items = g_key_file_get_integer(keyfile, "playlist", key, &err); + if (err) { + WARNING("Failed to get key '%s': %s", key, err->message); + g_error_free(err); + return 0; + } + + return n_items; +} + static GSList * parse_playlist_pls(const gchar *text, gsize text_size) { GSList *list = NULL; GKeyFile *keyfile; GError *err = NULL; - gint i, n_items; - const gchar *n_items_key; + guint i, n_items; keyfile = g_key_file_new(); @@ -176,28 +208,16 @@ } /* Get the number of items */ - if (g_key_file_has_key(keyfile, "playlist", "NumberOfEntries", NULL)) { - n_items_key = "NumberOfEntries"; - } else if (g_key_file_has_key(keyfile, "playlist", "NumberOfEvents", NULL)) { - n_items_key = "NumberOfEvents"; - } else { - WARNING("Failed to get the nunmber of items in pls playlist"); - goto end; - } - - n_items = g_key_file_get_integer(keyfile, "playlist", n_items_key, &err); - if (err) { - WARNING("Failed to get key '%s': %s", n_items_key, err->message); - g_error_free(err); + n_items = pls_get_n_items(keyfile); + if (n_items == 0) goto end; - } /* Get all stream uris */ - for (i = 1; i <= n_items; i++) { + for (i = 0; i < n_items; i++) { gchar key[8]; gchar *str; - g_snprintf(key, sizeof key, "File%d", i); + g_snprintf(key, sizeof key, "File%u", i + 1); str = g_key_file_get_string(keyfile, "playlist", key, &err); if (err) { @@ -406,7 +426,7 @@ /* Was it parsed successfully ? */ if (priv->streams == NULL) { - WARNING("Faild to parse playlist"); + WARNING("Failed to parse playlist"); goto end; } diff -Nru goodvibes-0.3.6/src/core/gv-playlist.h goodvibes-0.4.2/src/core/gv-playlist.h --- goodvibes-0.3.6/src/core/gv-playlist.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-playlist.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/core/gv-station.c goodvibes-0.4.2/src/core/gv-station.c --- goodvibes-0.3.6/src/core/gv-station.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-station.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -22,7 +22,7 @@ #include #include -#include "additions/glib-object.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-core-internal.h" #include "core/gv-playlist.h" @@ -100,6 +100,12 @@ * Helpers */ +static gpointer +copy_func_strdup(gconstpointer src, gpointer data G_GNUC_UNUSED) +{ + return g_strdup(src); +} + static void gv_station_set_stream_uris(GvStation *self, GSList *list) { @@ -108,7 +114,7 @@ if (priv->stream_uris) g_slist_free_full(priv->stream_uris, g_free); - priv->stream_uris = g_slist_copy_deep(list, (GCopyFunc) g_strdup, NULL); + priv->stream_uris = g_slist_copy_deep(list, copy_func_strdup, NULL); g_object_notify(G_OBJECT(self), "stream-uris"); } diff -Nru goodvibes-0.3.6/src/core/gv-station.h goodvibes-0.4.2/src/core/gv-station.h --- goodvibes-0.3.6/src/core/gv-station.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-station.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/core/gv-station-list.c goodvibes-0.4.2/src/core/gv-station-list.c --- goodvibes-0.3.6/src/core/gv-station-list.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-station-list.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -19,11 +19,13 @@ * along with this program. If not, see . */ +#include #include #include +#include #include -#include "additions/glib-object.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-station-list.h" @@ -32,52 +34,74 @@ // It might be slow. The implementation never tried to be fast. /* - * FIP + * FIP * Just the best radios you'll ever listen to. */ -#define FIP_STATIONS \ +#define FIP_STATIONS \ "" \ " FIP Paris" \ - " http://direct.fipradio.fr/live/fip-midfi.mp3" \ + " https://direct.fipradio.fr/live/fip-midfi.mp3" \ "" \ "" \ " FIP Autour du Rock" \ - " http://direct.fipradio.fr/live/fip-webradio1.mp3" \ + " https://direct.fipradio.fr/live/fip-webradio1.mp3" \ "" \ "" \ " FIP Autour du Jazz" \ - " http://direct.fipradio.fr/live/fip-webradio2.mp3" \ + " https://direct.fipradio.fr/live/fip-webradio2.mp3" \ "" \ "" \ " FIP Autour du Groove" \ - " http://direct.fipradio.fr/live/fip-webradio3.mp3" \ + " https://direct.fipradio.fr/live/fip-webradio3.mp3" \ "" \ "" \ " FIP Autour du Monde" \ - " http://direct.fipradio.fr/live/fip-webradio4.mp3" \ + " https://direct.fipradio.fr/live/fip-webradio4.mp3" \ "" \ "" \ " FIP Tout nouveau, tout FIP" \ - " http://direct.fipradio.fr/live/fip-webradio5.mp3" \ + " https://direct.fipradio.fr/live/fip-webradio5.mp3" \ "" \ "" \ - " FIP Evenementielle" \ - " http://direct.fipradio.fr/live/fip-webradio6.mp3" \ + " FIP Autour du Reggae" \ + " https://direct.fipradio.fr/live/fip-webradio6.mp3" \ + "" \ + "" \ + " FIP Autour de l'Électro" \ + " https://direct.fipradio.fr/live/fip-webradio8.mp3" \ "" /* - * More of my favorite french radios. - * - Nova - * - Grenouille + * Nova + * Another killer radio from France. */ -#define FRENCH_STATIONS \ +#define NOVA_STATIONS \ "" \ " Nova" \ - " http://broadcast.infomaniak.net/radionova-high.mp3" \ + " http://novazz.ice.infomaniak.ch/novazz-128.mp3" \ + "" \ + "" \ + " Nova Vintage" \ + " http://nova-vnt.ice.infomaniak.ch/nova-vnt-128" \ + "" \ + "" \ + " Nova la Nuit" \ + " http://nova-ln.ice.infomaniak.ch/nova-ln-128" \ "" \ "" \ + " Nova V.F." \ + " http://nova-vf.ice.infomaniak.ch/nova-vf-128" \ + "" + +/* + * More of my favorite french radios. + * - Grenouille + */ + +#define FRENCH_STATIONS \ + "" \ " Radio Grenouille" \ " http://live.radiogrenouille.com/live" \ "" @@ -133,27 +157,30 @@ * Default station list, loaded if no station list file is found */ -#define DEFAULT_STATIONS_DEV \ +#define DEFAULT_STATIONS_DEV \ FIP_STATIONS \ + NOVA_STATIONS \ FRENCH_STATIONS \ TESTING_BROKEN_STATIONS \ TESTING_PLAYLIST_STATIONS \ - TESTING_MORE_STATIONS \ + TESTING_MORE_STATIONS -#define DEFAULT_STATIONS_PROD \ +#define DEFAULT_STATIONS_PROD \ FIP_STATIONS \ + NOVA_STATIONS \ FRENCH_STATIONS -#define DEFAULT_STATION_LIST \ +#define DEFAULT_STATION_LIST \ "" \ DEFAULT_STATIONS_PROD \ "" /* - * Save delay - how long do we wait to write configuration to file + * More defines... */ -#define SAVE_DELAY 1 +#define SAVE_DELAY 1 // how long to wait before writing changes to disk +#define STATION_LIST_FILE "stations.xml" // where to write the stations /* * Signals @@ -176,8 +203,8 @@ */ struct _GvStationListPrivate { - /* Load/save pathes */ - GSList *load_pathes; + /* Load/save paths */ + gchar **load_paths; gchar *save_path; /* Timeout id, > 0 if a save operation is scheduled */ guint save_source_id; @@ -203,6 +230,16 @@ G_IMPLEMENT_INTERFACE(GV_TYPE_ERRORABLE, NULL)) /* + * Helpers + */ + +static gpointer +copy_func_object_ref(gconstpointer src, gpointer data G_GNUC_UNUSED) +{ + return g_object_ref((gpointer) src); +} + +/* * Markup handling */ @@ -453,7 +490,7 @@ GvStationListIter *iter; iter = g_new0(GvStationListIter, 1); - iter->head = g_list_copy_deep(list, (GCopyFunc) g_object_ref, NULL); + iter->head = g_list_copy_deep(list, copy_func_object_ref, NULL); iter->item = iter->head; return iter; @@ -659,7 +696,7 @@ if (priv->shuffled) { g_list_free_full(priv->shuffled, g_object_unref); priv->shuffled = g_list_copy_deep_shuffle(priv->stations, - (GCopyFunc) g_object_ref, NULL); + copy_func_object_ref, NULL); } /* Emit a signal */ @@ -708,7 +745,7 @@ if (priv->shuffled) { g_list_free_full(priv->shuffled, g_object_unref); priv->shuffled = g_list_copy_deep_shuffle(priv->stations, - (GCopyFunc) g_object_ref, NULL); + copy_func_object_ref, NULL); } /* Emit a signal */ @@ -830,7 +867,7 @@ if (shuffle) { if (priv->shuffled == NULL) { priv->shuffled = g_list_copy_deep_shuffle(priv->stations, - (GCopyFunc) g_object_ref, NULL); + copy_func_object_ref, NULL); } stations = priv->shuffled; } else { @@ -896,7 +933,7 @@ if (shuffle) { if (priv->shuffled == NULL) { priv->shuffled = g_list_copy_deep_shuffle(priv->stations, - (GCopyFunc) g_object_ref, NULL); + copy_func_object_ref, NULL); } stations = priv->shuffled; } else { @@ -1066,18 +1103,27 @@ { GvStationListPrivate *priv = self->priv; GError *err = NULL; - gchar *text; + gchar *dirname = NULL; + gchar *text = NULL; /* Stringify data */ text = print_markup(priv->stations, &err); if (err) goto cleanup; + /* Create directory */ + dirname = g_path_get_dirname(priv->save_path); + if (g_mkdir_with_parents(dirname, S_IRWXU) != 0) { + WARNING("Failed to make directory '%s': %s", dirname, strerror(errno)); + goto cleanup; + } + /* Write to file */ - gv_file_write_sync(priv->save_path, text, &err); + g_file_set_contents(priv->save_path, text, -1, &err); cleanup: /* Cleanup */ + g_free(dirname); g_free(text); /* Handle error */ @@ -1096,22 +1142,28 @@ gv_station_list_load(GvStationList *self) { GvStationListPrivate *priv = self->priv; - GSList *item = NULL; - GList *sta_item; + const gchar *loaded_path = NULL; + guint i, n_paths; + GList *item; TRACE("%p", self); /* This should be called only once at startup */ g_assert_null(priv->stations); - /* Load from a list of pathes */ - for (item = priv->load_pathes; item; item = item->next) { + /* Load from a list of paths */ + n_paths = g_strv_length(priv->load_paths); + for (i = 0; i < n_paths; i++) { + const gchar *path = priv->load_paths[i]; GError *err = NULL; - const gchar *path = item->data; gchar *text; + /* Check if the file exists */ + if (!g_file_test(path, G_FILE_TEST_EXISTS)) + continue; + /* Attempt to read file */ - gv_file_read_sync(path, &text, &err); + g_file_get_contents(path, &text, NULL, &err); if (err) { WARNING("%s", err->message); g_clear_error(&err); @@ -1128,13 +1180,12 @@ } /* Success */ + loaded_path = path; break; } /* Check if we got something */ - if (item) { - const gchar *loaded_path = item->data; - + if (loaded_path) { INFO("Station list loaded from file '%s'", loaded_path); } else { GError *err = NULL; @@ -1152,8 +1203,8 @@ DEBUG("Station list has %u stations", gv_station_list_length(self)); /* Register a notify handler for each station */ - for (sta_item = priv->stations; sta_item; sta_item = sta_item->next) { - GvStation *station = sta_item->data; + for (item = priv->stations; item; item = item->next) { + GvStation *station = item->data; g_signal_connect_object(station, "notify", G_CALLBACK(on_station_notify), self, 0); } @@ -1180,6 +1231,78 @@ * GObject methods */ +static gchar ** +make_station_list_load_paths(void) +{ + const gchar *const *system_dirs; + const gchar *user_dir; + guint i, n_dirs; + gchar **dirs; + + system_dirs = gv_get_app_system_data_dirs(); + user_dir = gv_get_app_user_data_dir(); + + n_dirs = g_strv_length((gchar **) system_dirs) + 1; + dirs = g_malloc0_n(n_dirs + 1, sizeof(gchar *)); + dirs[0] = g_build_filename(user_dir, STATION_LIST_FILE, NULL); + for (i = 1; i < n_dirs; i++) { + const gchar *dir; + dir = system_dirs[i - 1]; + dirs[i] = g_build_filename(dir, STATION_LIST_FILE, NULL); + } + + return dirs; +} + +static gchar * +make_station_list_save_path(void) +{ + const gchar *user_dir; + gchar *dir; + + user_dir = gv_get_app_user_data_dir(); + dir = g_build_filename(user_dir, STATION_LIST_FILE, NULL); + + return dir; +} + +static void +move_station_list_file(const gchar *new_file) +{ + const gchar *user_config_dir; + gchar *old_file = NULL; + gchar *dirname = NULL; + + user_config_dir = gv_get_app_user_config_dir(); + old_file = g_build_filename(user_config_dir, "stations", NULL); + + if (!g_file_test(old_file, G_FILE_TEST_EXISTS)) + goto cleanup; + + INFO("Station list migration: '%s' > '%s'", old_file, new_file); + + dirname = g_path_get_dirname(new_file); + if (g_mkdir_with_parents(dirname, S_IRWXU) != 0) { + WARNING("Failed to make directory '%s': %s", + dirname, strerror(errno)); + goto cleanup; + } + g_free(dirname); + + if (g_rename(old_file, new_file) != 0) { + WARNING("Failed to rename file '%s' to '%s': %s", + old_file, new_file, strerror(errno)); + goto cleanup; + } + + dirname = g_path_get_dirname(old_file); + g_rmdir(dirname); + + cleanup: + g_free(dirname); + g_free(old_file); +} + static void gv_station_list_finalize(GObject *object) { @@ -1209,9 +1332,9 @@ } g_list_free(priv->stations); - /* Free pathes */ + /* Free paths */ g_free(priv->save_path); - g_slist_free_full(priv->load_pathes, g_free); + g_strfreev(priv->load_paths); /* Chain up */ G_OBJECT_CHAINUP_FINALIZE(gv_station_list, object); @@ -1223,10 +1346,12 @@ GvStationList *self = GV_STATION_LIST(object); GvStationListPrivate *priv = self->priv; - /* Initialize pathes */ - priv->load_pathes = gv_get_existing_path_list - (GV_DIR_USER_CONFIG | GV_DIR_SYSTEM_CONFIG, "stations"); - priv->save_path = g_build_filename(gv_get_user_config_dir(), "stations", NULL); + /* Initialize paths */ + priv->load_paths = make_station_list_load_paths(); + priv->save_path = make_station_list_save_path(); + + /* In version 4.1, the station file moved */ + move_station_list_file(priv->save_path); /* Chain up */ G_OBJECT_CHAINUP_CONSTRUCTED(gv_station_list, object); diff -Nru goodvibes-0.3.6/src/core/gv-station-list.h goodvibes-0.4.2/src/core/gv-station-list.h --- goodvibes-0.3.6/src/core/gv-station-list.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/core/gv-station-list.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/core/meson.build goodvibes-0.4.2/src/core/meson.build --- goodvibes-0.3.6/src/core/meson.build 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/core/meson.build 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Sources and dependencies + +core_sources = [ + 'gst-additions.c', + 'gv-core.c', + 'gv-engine.c', + 'gv-metadata.c', + 'gv-player.c', + 'gv-playlist.c', + 'gv-station.c', + 'gv-station-list.c', +] + +core_dependencies = [ + glib_dep, + gobject_dep, + gio_dep, + gst_dep, + gst_audio_dep, + gst_base_dep, + libsoup_dep, + gvframework_dep, +] + +core_enum_headers = [ 'gv-engine.h', 'gv-player.h' ] +core_enums = gnome.mkenums_simple('gv-core-enum-types', + sources: core_enum_headers +) +core_enum_h = core_enums[1] + +# Library definition + +gvcore = static_library('gvcore', + sources: [ core_enums, core_sources ], + dependencies: core_dependencies, + include_directories: root_inc, +) + +gvcore_dep = declare_dependency( + dependencies: core_dependencies, + sources: [ core_enum_h ], + link_with: gvcore, +) diff -Nru goodvibes-0.3.6/src/feat/gv-console-output.c goodvibes-0.4.2/src/feat/gv-console-output.c --- goodvibes-0.3.6/src/feat/gv-console-output.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-console-output.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -25,7 +25,7 @@ #include #include -#include "additions/glib.h" +#include "framework/glib-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" @@ -66,7 +66,7 @@ static void print_hello_line(void) { - PRINT("---- " PACKAGE_CAMEL_NAME " " PACKAGE_VERSION " ----"); + PRINT("---- " GV_NAME_CAPITAL " " PACKAGE_VERSION " ----"); PRINT("Hit Ctrl+C to quit..."); } @@ -186,7 +186,7 @@ GList *item; /* Disconnect signal handlers */ - for (item = gv_framework_object_list; item; item = item->next) { + for (item = gv_framework_get_objects(); item; item = item->next) { GObject *object = G_OBJECT(item->data); if (GV_IS_ERRORABLE(object) == FALSE) @@ -220,13 +220,12 @@ g_signal_connect_object(player, "notify", G_CALLBACK(on_player_notify), feature, 0); /* Connect to objects that emit 'error' */ - for (item = gv_framework_object_list; item; item = item->next) { + for (item = gv_framework_get_objects(); item; item = item->next) { GObject *object = G_OBJECT(item->data); if (GV_IS_ERRORABLE(object) == FALSE) continue; - WARNING("Object '%s' is errorable", G_OBJECT_TYPE_NAME(object)); g_signal_connect_object(object, "error", G_CALLBACK(on_errorable_error), feature, 0); } } diff -Nru goodvibes-0.3.6/src/feat/gv-console-output.h goodvibes-0.4.2/src/feat/gv-console-output.h --- goodvibes-0.3.6/src/feat/gv-console-output.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-console-output.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/feat/gv-dbus-server.c goodvibes-0.4.2/src/feat/gv-dbus-server.c --- goodvibes-0.3.6/src/feat/gv-dbus-server.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-dbus-server.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -23,7 +23,7 @@ #include #include -#include "additions/glib-object.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" diff -Nru goodvibes-0.3.6/src/feat/gv-dbus-server.h goodvibes-0.4.2/src/feat/gv-dbus-server.h --- goodvibes-0.3.6/src/feat/gv-dbus-server.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-dbus-server.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/feat/gv-dbus-server-mpris2.c goodvibes-0.4.2/src/feat/gv-dbus-server-mpris2.c --- goodvibes-0.3.6/src/feat/gv-dbus-server-mpris2.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-dbus-server-mpris2.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -26,21 +26,21 @@ #include #include -#include "additions/glib.h" -#include "additions/glib-object.h" +#include "framework/glib-additions.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" -#ifdef UI_ENABLED +#ifdef GV_UI_ENABLED #include "ui/gv-ui.h" #endif #include "feat/gv-dbus-server.h" #include "feat/gv-dbus-server-mpris2.h" -#define TRACKID_PATH PACKAGE_APPLICATION_PATH "/TrackList" -#define PLAYLISTID_PATH PACKAGE_APPLICATION_PATH "/Playlist" +#define TRACKID_PATH GV_APPLICATION_PATH "/TrackList" +#define PLAYLISTID_PATH GV_APPLICATION_PATH "/Playlist" -#define DBUS_NAME "org.mpris.MediaPlayer2." PACKAGE_CAMEL_NAME +#define DBUS_NAME "org.mpris.MediaPlayer2." GV_NAME_CAPITAL #define DBUS_PATH "/org/mpris/MediaPlayer2" #define DBUS_IFACE_ROOT "org.mpris.MediaPlayer2" #define DBUS_IFACE_PLAYER DBUS_IFACE_ROOT ".Player" @@ -457,7 +457,7 @@ GVariant *params G_GNUC_UNUSED, GError **error G_GNUC_UNUSED) { -#ifdef UI_ENABLED +#ifdef GV_UI_ENABLED gv_ui_present_main(); #endif return NULL; @@ -823,7 +823,7 @@ static GVariant * prop_get_can_raise(GvDbusServer *dbus_server G_GNUC_UNUSED) { -#ifdef UI_ENABLED +#ifdef GV_UI_ENABLED return g_variant_new_boolean(TRUE); #else return g_variant_new_boolean(FALSE); @@ -839,7 +839,7 @@ static GVariant * prop_get_desktop_entry(GvDbusServer *dbus_server G_GNUC_UNUSED) { - return g_variant_new_string(PACKAGE_APPLICATION_ID); + return g_variant_new_string(GV_APPLICATION_ID); } static GVariant * diff -Nru goodvibes-0.3.6/src/feat/gv-dbus-server-mpris2.h goodvibes-0.4.2/src/feat/gv-dbus-server-mpris2.h --- goodvibes-0.3.6/src/feat/gv-dbus-server-mpris2.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-dbus-server-mpris2.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/feat/gv-dbus-server-native.c goodvibes-0.4.2/src/feat/gv-dbus-server-native.c --- goodvibes-0.3.6/src/feat/gv-dbus-server-native.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-dbus-server-native.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -23,16 +23,16 @@ #include #include -#include "additions/glib.h" -#include "additions/glib-object.h" +#include "framework/glib-additions.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" #include "feat/gv-dbus-server.h" #include "feat/gv-dbus-server-native.h" -#define DBUS_PATH PACKAGE_APPLICATION_PATH -#define DBUS_IFACE_ROOT PACKAGE_APPLICATION_ID +#define DBUS_PATH GV_APPLICATION_PATH +#define DBUS_IFACE_ROOT GV_APPLICATION_ID #define DBUS_IFACE_PLAYER DBUS_IFACE_ROOT ".Player" #define DBUS_IFACE_STATIONS DBUS_IFACE_ROOT ".Stations" diff -Nru goodvibes-0.3.6/src/feat/gv-dbus-server-native.h goodvibes-0.4.2/src/feat/gv-dbus-server-native.h --- goodvibes-0.3.6/src/feat/gv-dbus-server-native.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-dbus-server-native.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/feat/gv-feat.c goodvibes-0.4.2/src/feat/gv-feat.c --- goodvibes-0.3.6/src/feat/gv-feat.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-feat.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -23,20 +23,20 @@ #include "framework/gv-framework.h" -#ifdef CONSOLE_OUTPUT_ENABLED +#ifdef GV_FEAT_CONSOLE_OUTPUT #include "feat/gv-console-output.h" #endif -#ifdef DBUS_SERVER_ENABLED +#ifdef GV_FEAT_DBUS_SERVER #include "feat/gv-dbus-server-native.h" #include "feat/gv-dbus-server-mpris2.h" #endif -#ifdef HOTKEYS_ENABLED +#ifdef GV_FEAT_HOTKEYS #include "feat/gv-hotkeys.h" #endif -#ifdef INHIBITOR_ENABLED +#ifdef GV_FEAT_INHIBITOR #include "feat/gv-inhibitor.h" #endif -#ifdef NOTIFICATIONS_ENABLED +#ifdef GV_FEAT_NOTIFICATIONS #include "feat/gv-notifications.h" #endif @@ -96,8 +96,7 @@ gv_feat_cleanup(void) { feat_objects = g_list_reverse(feat_objects); - g_list_foreach(feat_objects, (GFunc) g_object_unref, NULL); - g_list_free(feat_objects); + g_list_free_full(feat_objects, (GDestroyNotify) g_object_unref); } void @@ -116,26 +115,26 @@ * in the build system, see the `configure.ac` for more details. */ -#ifdef CONSOLE_OUTPUT_ENABLED +#ifdef GV_FEAT_CONSOLE_OUTPUT feature = gv_console_output_new(); feat_objects = g_list_append(feat_objects, feature); #endif -#ifdef DBUS_SERVER_ENABLED +#ifdef GV_FEAT_DBUS_SERVER feature = gv_dbus_server_native_new(); feat_objects = g_list_append(feat_objects, feature); feature = gv_dbus_server_mpris2_new(); feat_objects = g_list_append(feat_objects, feature); #endif -#ifdef INHIBITOR_ENABLED +#ifdef GV_FEAT_INHIBITOR feature = gv_inhibitor_new(); feat_objects = g_list_append(feat_objects, feature); #endif -#ifdef HOTKEYS_ENABLED +#ifdef GV_FEAT_HOTKEYS feature = gv_hotkeys_new(); feat_objects = g_list_append(feat_objects, feature); #endif -#ifdef NOTIFICATIONS_ENABLED +#ifdef GV_FEAT_NOTIFICATIONS feature = gv_notifications_new(); feat_objects = g_list_append(feat_objects, feature); #endif @@ -143,7 +142,7 @@ /* Register objects in the framework */ for (item = feat_objects; item; item = item->next) { feature = GV_FEATURE(item->data); - gv_framework_register(feature); + gv_framework_register_object(feature); /* Drop a line */ INFO("Feature compiled in: '%s'", gv_feature_get_name(feature)); diff -Nru goodvibes-0.3.6/src/feat/gv-feat.h goodvibes-0.4.2/src/feat/gv-feat.h --- goodvibes-0.3.6/src/feat/gv-feat.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-feat.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/feat/gv-hotkeys.c goodvibes-0.4.2/src/feat/gv-hotkeys.c --- goodvibes-0.3.6/src/feat/gv-hotkeys.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-hotkeys.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -23,6 +23,7 @@ #include #include +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" diff -Nru goodvibes-0.3.6/src/feat/gv-hotkeys.h goodvibes-0.4.2/src/feat/gv-hotkeys.h --- goodvibes-0.3.6/src/feat/gv-hotkeys.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-hotkeys.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/feat/gv-inhibitor.c goodvibes-0.4.2/src/feat/gv-inhibitor.c --- goodvibes-0.3.6/src/feat/gv-inhibitor.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-inhibitor.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -24,7 +24,7 @@ #include #include -#include "caphe/caphe.h" +#include "libcaphe/caphe.h" #include "framework/gv-framework.h" #include "core/gv-core.h" diff -Nru goodvibes-0.3.6/src/feat/gv-inhibitor.h goodvibes-0.4.2/src/feat/gv-inhibitor.h --- goodvibes-0.3.6/src/feat/gv-inhibitor.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-inhibitor.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/feat/gv-notifications.c goodvibes-0.4.2/src/feat/gv-notifications.c --- goodvibes-0.3.6/src/feat/gv-notifications.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-notifications.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -23,99 +23,65 @@ #include #include -#include "additions/glib.h" +#include "framework/glib-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" #include "feat/gv-notifications.h" -#define ICON_NAME PACKAGE_NAME - -/* Notice that other system icons are suitable: - * - "audio-x-generic" for sound notifications - * - "dialog-error" for errors - */ - /* * GObject definitions */ -struct _GvNotificationsPrivate { - /* Notifications */ - GNotification *notif_station; - GNotification *notif_metadata; - GNotification *notif_error; -}; - -typedef struct _GvNotificationsPrivate GvNotificationsPrivate; - struct _GvNotifications { /* Parent instance structure */ - GvFeature parent_instance; - /* Private data */ - GvNotificationsPrivate *priv; + GvFeature parent_instance; }; -G_DEFINE_TYPE_WITH_PRIVATE(GvNotifications, gv_notifications, GV_TYPE_FEATURE) +G_DEFINE_TYPE(GvNotifications, gv_notifications, GV_TYPE_FEATURE) /* * Helpers */ static GNotification * -make_notification(const gchar *title, const gchar *icon_name, GNotificationPriority priority) +make_station_notification(GvStation *station) { GNotification *notif; - GIcon *icon; - - notif = g_notification_new(title); - - icon = g_themed_icon_new(icon_name); - g_notification_set_icon(notif, icon); - g_object_unref(icon); - - g_notification_set_priority(notif, priority); - - return notif; -} - -static gboolean -update_notification_station(GNotification *notif, GvStation *station) -{ const gchar *str; - gchar *text; + gchar *body; if (station == NULL) - return FALSE; + return NULL; str = gv_station_get_name(station); if (str) { - text = g_strdup_printf(_("Playing %s"), str); + body = g_strdup_printf(_("Playing %s"), str); } else { str = gv_station_get_uri(station); - text = g_strdup_printf(_("Playing <%s>"), str); + body = g_strdup_printf(_("Playing <%s>"), str); } - g_notification_set_body(notif, text); + notif = g_notification_new(_("Playing Station")); + g_notification_set_body(notif, body); + g_free(body); - g_free(text); - - return TRUE; + return notif; } -static gboolean -update_notification_metadata(GNotification *notif, GvMetadata *metadata) +static GNotification * +make_metadata_notification(GvMetadata *metadata) { + GNotification *notif; const gchar *artist; const gchar *title; const gchar *album; const gchar *year; const gchar *genre; - gchar *album_year; - gchar *text; + gchar *body; if (metadata == NULL) - return FALSE; + return NULL; artist = gv_metadata_get_artist(metadata); title = gv_metadata_get_title(metadata); @@ -123,36 +89,40 @@ year = gv_metadata_get_year(metadata); genre = gv_metadata_get_genre(metadata); - /* If there's only the 'title' field, don't bother being smart, - * just display it as it. Actually, most radios fill only this field, - * and put everything in it (title + artist + some more stuff). - */ if (title && !artist && !album && !year && !genre) { - g_notification_set_body(notif, title); - return TRUE; - } - - /* Otherwise, each existing field is displayed on a line */ - if (title == NULL) - title = _("(Unknown title)"); + /* If there's only the 'title' field, don't bother being smart, + * just display it as it. Actually, most radios fill only this field, + * and put everything in it (title + artist + some more stuff). + */ + body = g_strdup(title); + } else { + /* Otherwise, each existing field is displayed on a line */ + gchar *album_year; - album_year = gv_metadata_make_album_year(metadata, FALSE); - text = g_strjoin_null("\n", 4, title, artist, album_year, genre); + if (title == NULL) + title = _("(Unknown title)"); - g_notification_set_body(notif, text); + album_year = gv_metadata_make_album_year(metadata, FALSE); + body = g_strjoin_null("\n", 4, title, artist, album_year, genre); + g_free(album_year); + } - g_free(text); - g_free(album_year); + notif = g_notification_new(_("New Track")); + g_notification_set_body(notif, body); + g_free(body); - return TRUE; + return notif; } -static gboolean -update_notification_error(GNotification *notif, const gchar *error_string) +static GNotification * +make_error_notification(const gchar *error_string) { + GNotification *notif; + + notif = g_notification_new(_("Error")); g_notification_set_body(notif, error_string); - return TRUE; + return notif; } /* @@ -161,16 +131,14 @@ static void on_player_notify(GvPlayer *player, - GParamSpec *pspec, - GvNotifications *self) + GParamSpec *pspec, + GvNotifications *self G_GNUC_UNUSED) { - GvNotificationsPrivate *priv = self->priv; const gchar *property_name = g_param_spec_get_name(pspec); GApplication *app = gv_core_application; if (!g_strcmp0(property_name, "state")) { - GNotification *notif = priv->notif_station; - gboolean must_notify = FALSE; + GNotification *notif; GvPlayerState state; GvStation *station; @@ -179,38 +147,40 @@ return; station = gv_player_get_station(player); - must_notify = update_notification_station(notif, station); - if (must_notify == FALSE) + notif = make_station_notification(station); + if (notif == NULL) return; g_application_send_notification(app, "station", notif); + g_object_unref(notif); } else if (!g_strcmp0(property_name, "metadata")) { - GNotification *notif = priv->notif_metadata; - gboolean must_notify = FALSE; + GNotification *notif; GvMetadata *metadata; metadata = gv_player_get_metadata(player); - must_notify = update_notification_metadata(notif, metadata); - if (must_notify == FALSE) + notif = make_metadata_notification(metadata); + if (notif == NULL) return; g_application_send_notification(app, "metadata", notif); + g_object_unref(notif); } } static void -on_errorable_error(GvErrorable *errorable, const gchar *error_string, +on_errorable_error(GvErrorable *errorable, + const gchar *error_string, GvNotifications *self) { - GvNotificationsPrivate *priv = self->priv; - GNotification *notif = priv->notif_error; GApplication *app = gv_core_application; + GNotification *notif; TRACE("%p, %s, %p", errorable, error_string, self); - update_notification_error(notif, error_string); + notif = make_error_notification(error_string); g_application_send_notification(app, "error", notif); + g_object_unref(notif); } /* @@ -220,12 +190,11 @@ static void gv_notifications_disable(GvFeature *feature) { - GvNotificationsPrivate *priv = GV_NOTIFICATIONS(feature)->priv; GvPlayer *player = gv_core_player; GList *item; /* Disconnect signal handlers */ - for (item = gv_framework_object_list; item; item = item->next) { + for (item = gv_framework_get_objects(); item; item = item->next) { GObject *object = G_OBJECT(item->data); if (GV_IS_ERRORABLE(object) == FALSE) @@ -236,14 +205,6 @@ g_signal_handlers_disconnect_by_data(player, feature); - /* Unref notifications */ - g_object_unref(priv->notif_station); - priv->notif_station = NULL; - g_object_unref(priv->notif_metadata); - priv->notif_metadata = NULL; - g_object_unref(priv->notif_error); - priv->notif_error = NULL; - /* Chain up */ GV_FEATURE_CHAINUP_DISABLE(gv_notifications, feature); } @@ -251,29 +212,17 @@ static void gv_notifications_enable(GvFeature *feature) { - GvNotificationsPrivate *priv = GV_NOTIFICATIONS(feature)->priv; GvPlayer *player = gv_core_player; GList *item; /* Chain up */ GV_FEATURE_CHAINUP_ENABLE(gv_notifications, feature); - /* Create notifications */ - g_assert_null(priv->notif_station); - priv->notif_station = make_notification(_("Playing Station"), ICON_NAME, - G_NOTIFICATION_PRIORITY_NORMAL); - g_assert_null(priv->notif_metadata); - priv->notif_metadata = make_notification(_("New Track"), ICON_NAME, - G_NOTIFICATION_PRIORITY_NORMAL); - g_assert_null(priv->notif_error); - priv->notif_error = make_notification(_("Error"), ICON_NAME, - G_NOTIFICATION_PRIORITY_NORMAL); - /* Connect to player 'notify' */ g_signal_connect_object(player, "notify", G_CALLBACK(on_player_notify), feature, 0); /* Connect to objects that emit 'error' */ - for (item = gv_framework_object_list; item; item = item->next) { + for (item = gv_framework_get_objects(); item; item = item->next) { GObject *object = G_OBJECT(item->data); if (GV_IS_ERRORABLE(object) == FALSE) @@ -301,9 +250,6 @@ gv_notifications_init(GvNotifications *self) { TRACE("%p", self); - - /* Initialize private pointer */ - self->priv = gv_notifications_get_instance_private(self); } static void diff -Nru goodvibes-0.3.6/src/feat/gv-notifications.h goodvibes-0.4.2/src/feat/gv-notifications.h --- goodvibes-0.3.6/src/feat/gv-notifications.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/feat/gv-notifications.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/feat/meson.build goodvibes-0.4.2/src/feat/meson.build --- goodvibes-0.3.6/src/feat/meson.build 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/feat/meson.build 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Sources and dependencies + +feat_sources = [ + 'gv-feat.c' +] + +feat_dependencies = [ + glib_dep, + gobject_dep, + gvframework_dep, +] + +if gv_feat_console_output + feat_sources += 'gv-console-output.c' +endif + +if gv_feat_dbus_server + feat_sources += [ + 'gv-dbus-server.c', + 'gv-dbus-server-native.c', + 'gv-dbus-server-mpris2.c' + ] + if gv_ui_enabled + feat_dependencies += gvui_dep + endif +endif + +if gv_feat_inhibitor + feat_sources += 'gv-inhibitor.c' + feat_dependencies += libcaphe_dep +endif + +if gv_feat_hotkeys + feat_sources += 'gv-hotkeys.c' + feat_dependencies += keybinder_dep +endif + +if gv_feat_notifications + feat_sources += 'gv-notifications.c' +endif + +# Library definition + +gvfeat = static_library('gvfeat', + sources: [ feat_sources ], + dependencies: feat_dependencies, + include_directories: root_inc, +) + +gvfeat_dep = declare_dependency( + dependencies: feat_dependencies, + link_with: gvfeat, +) diff -Nru goodvibes-0.3.6/src/framework/glib-additions.c goodvibes-0.4.2/src/framework/glib-additions.c --- goodvibes-0.3.6/src/framework/glib-additions.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/framework/glib-additions.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,133 @@ +/* + * Goodvibes Radio Player + * + * Copyright (C) 2015-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +/* + * Version Information + */ + +const gchar * +glib_get_runtime_version_string(void) +{ + static gchar *version_string; + + if (version_string == NULL) { + version_string = g_strdup_printf("GLib %u.%u.%u", + glib_major_version, + glib_minor_version, + glib_micro_version); + } + + return version_string; +} + +const gchar * +glib_get_compile_version_string(void) +{ + static gchar *version_string; + + if (version_string == NULL) { + version_string = g_strdup_printf("GLib %u.%u.%u", + GLIB_MAJOR_VERSION, + GLIB_MINOR_VERSION, + GLIB_MICRO_VERSION); + } + + return version_string; +} + +/* + * String Utilities Functions + */ + +gchar * +g_strjoin_null(const gchar *separator, unsigned int n_strings, ...) +{ + gchar *string, *s; + va_list args; + gsize len; + gsize separator_len; + gchar *ptr; + guint i; + + if (separator == NULL) + separator = ""; + + separator_len = strlen(separator); + + /* First part, getting length */ + len = 1; + va_start(args, n_strings); + for (i = 0; i < n_strings; i++) { + s = va_arg(args, gchar *); + if (s) { + if (len != 1) + len += separator_len; + len += strlen(s); + } + } + va_end(args); + + /* Second part, building string */ + string = g_new(gchar, len); + ptr = string; + va_start(args, n_strings); + for (i = 0; i < n_strings; i++) { + s = va_arg(args, gchar *); + if (s) { + if (ptr != string) + ptr = g_stpcpy(ptr, separator); + ptr = g_stpcpy(ptr, s); + } + } + va_end(args); + + if (ptr == string) + string[0] = '\0'; + + return string; +} + +/* + * GVariant + */ + +void +g_variant_builder_add_dictentry_array_string(GVariantBuilder *b, const gchar *key, ...) +{ + GVariantBuilder ab; + va_list ap; + gchar *s; + + g_variant_builder_init(&ab, G_VARIANT_TYPE_ARRAY); + + va_start(ap, key); + s = va_arg(ap, gchar *); + while (s) { + GVariant *tmp = g_variant_new_string(s); + g_variant_builder_add(&ab, "v", tmp); + s = va_arg(ap, gchar *); + } + + g_variant_builder_add(b, "{sv}", key, g_variant_builder_end(&ab)); +} diff -Nru goodvibes-0.3.6/src/framework/glib-additions.h goodvibes-0.4.2/src/framework/glib-additions.h --- goodvibes-0.3.6/src/framework/glib-additions.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/framework/glib-additions.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * Goodvibes Radio Player + * + * Copyright (C) 2015-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GOODVIBES_FRAMEWORK_GLIB_ADDITIONS_H__ +#define __GOODVIBES_FRAMEWORK_GLIB_ADDITIONS_H__ + +#include + +/* + * Version Information + */ + +const gchar *glib_get_runtime_version_string(void); +const gchar *glib_get_compile_version_string(void); + +/* + * String Utilities Functions + */ + +gchar *g_strjoin_null(const gchar *separator, unsigned int n_strings, ...); + +/* + * GVariant + */ + +#define g_variant_builder_add_dictentry_string(b, key, val) \ + g_variant_builder_add(b, "{sv}", key, g_variant_new_string(val)) + +#define g_variant_builder_add_dictentry_object_path(b, key, val) \ + g_variant_builder_add(b, "{sv}", key, g_variant_new_object_path(val)) + +void g_variant_builder_add_dictentry_array_string(GVariantBuilder *b, + const gchar *key, + ...) G_GNUC_NULL_TERMINATED; + +#endif /* __GOODVIBES_FRAMEWORK_GLIB_ADDITIONS_H__ */ diff -Nru goodvibes-0.3.6/src/framework/glib-object-additions.c goodvibes-0.4.2/src/framework/glib-object-additions.c --- goodvibes-0.3.6/src/framework/glib-object-additions.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/framework/glib-object-additions.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,172 @@ +/* + * Goodvibes Radio Player + * + * Copyright (C) 2015-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "glib-object-additions.h" + +/* + * GType + */ + +gchar * +g_type_dup_name(GType type) +{ + return g_strdup(g_type_name(type)); +} + +gchar * +g_type_dup_name_no_prefix(GType type) +{ + const gchar *type_name; + const gchar *ptr; + + type_name = g_type_name(type); + + ptr = type_name; + if (*ptr != '\0') + ptr++; + + while (*ptr != '\0') { + if (g_ascii_isupper(*ptr)) + break; + ptr++; + } + + if (*ptr == '\0') + return g_strdup(type_name); + else + return g_strdup(ptr); + +} + +/* + * GObject + */ + +gboolean +g_object_get_boolean(GObject *object, const gchar *property_name) +{ + gboolean value; + + g_object_get(object, property_name, &value, NULL); + + return value; +} + +guint +g_object_get_uint(GObject *object, const gchar *property_name) +{ + guint value; + + g_object_get(object, property_name, &value, NULL); + + return value; +} + +gchar * +g_object_get_string(GObject *object, const gchar *property_name) +{ + gchar *value; + + g_object_get(object, property_name, &value, NULL); + + return value; +} + +const gchar * +g_object_get_property_desc(GObject *object, const gchar *property_name) +{ + GParamSpec *pspec; + const gchar *desc; + + pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(object), property_name); + g_assert_nonnull(pspec); + desc = g_param_spec_get_blurb(pspec); + g_assert_nonnull(desc); + + return desc; +} + +void +g_object_get_property_uint_bounds(GObject *object, const gchar *property_name, + guint *minimum, guint *maximum) +{ + GParamSpec *pspec; + GParamSpecUInt *pspec_uint; + + if (minimum) + *minimum = 0; + if (maximum) + *maximum = 0; + + pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(object), property_name); + g_assert_nonnull(pspec); + g_assert_true(G_IS_PARAM_SPEC_UINT(pspec)); + + pspec_uint = G_PARAM_SPEC_UINT(pspec); + if (minimum) + *minimum = pspec_uint->minimum; + if (maximum) + *maximum = pspec_uint->maximum; +} + +/* + * Signals + */ + +void +g_signal_handlers_connect_object(gpointer instance, GSignalHandler *handlers, + gpointer gobject, GConnectFlags connect_flags) +{ + GSignalHandler *handler; + + if (handlers == NULL) + return; + + for (handler = handlers; handler->name; handler++) + g_signal_connect_object(instance, handler->name, handler->callback, + gobject, connect_flags); +} + +void +g_signal_handlers_block(gpointer instance, GSignalHandler *handlers, gpointer data) +{ + GSignalHandler *handler; + + if (handlers == NULL) + return; + + for (handler = handlers; handler->name; handler++) + g_signal_handlers_block_by_func(instance, handler->callback, data); +} + +void +g_signal_handlers_unblock(gpointer instance, GSignalHandler *handlers, gpointer data) +{ + GSignalHandler *handler; + + if (handlers == NULL) + return; + + for (handler = handlers; handler->name; handler++) + g_signal_handlers_unblock_by_func(instance, handler->callback, data); +} diff -Nru goodvibes-0.3.6/src/framework/glib-object-additions.h goodvibes-0.4.2/src/framework/glib-object-additions.h --- goodvibes-0.3.6/src/framework/glib-object-additions.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/framework/glib-object-additions.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,81 @@ +/* + * Goodvibes Radio Player + * + * Copyright (C) 2015-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GOODVIBES_FRAMEWORK_GLIB_OBJECT_ADDITIONS_H__ +#define __GOODVIBES_FRAMEWORK_GLIB_OBJECT_ADDITIONS_H__ + +#include + +/* + * GType + */ + +/* Duplicate type name, eventually without the prefix */ +gchar *g_type_dup_name(GType type); +gchar *g_type_dup_name_no_prefix(GType type); + +/* + * GObject + */ + +/* Duplicate type name, eventually without the prefix */ +#define g_object_dup_type_name(obj) \ + g_type_dup_name(G_OBJECT_TYPE(obj)) +#define g_object_dup_type_name_no_prefix(obj) \ + g_type_dup_name_no_prefix(G_OBJECT_TYPE(obj)) + +/* Chain up for finalize() */ +#define G_OBJECT_CHAINUP_FINALIZE(module_obj_name, obj) \ + G_OBJECT_CLASS(module_obj_name##_parent_class)->finalize(obj) + +/* Chain up for constructed() - beware, constructed() is not guaranteed to exist */ +#define G_OBJECT_CHAINUP_CONSTRUCTED(module_obj_name, obj) \ + do { \ + if (G_OBJECT_CLASS(module_obj_name##_parent_class)->constructed) \ + G_OBJECT_CLASS(module_obj_name##_parent_class)->constructed(obj); \ + } while (0) + +/* get() for fundamental types */ +gboolean g_object_get_boolean(GObject *object, const gchar *property_name); +guint g_object_get_uint (GObject *object, const gchar *property_name); +gchar *g_object_get_string (GObject *object, const gchar *property_name); + +const gchar *g_object_get_property_desc (GObject *object, const gchar *property_name); +void g_object_get_property_uint_bounds(GObject *object, const gchar *property_name, + guint *minimum, guint *maximum); + +/* + * Signals + */ + +struct _GSignalHandler { + const gchar *name; + GCallback callback; +}; + +typedef struct _GSignalHandler GSignalHandler; + +void g_signal_handlers_connect_object(gpointer instance, GSignalHandler *handlers, gpointer gobject, + GConnectFlags connect_flags); +void g_signal_handlers_block (gpointer instance, GSignalHandler *handlers, gpointer data); +void g_signal_handlers_unblock (gpointer instance, GSignalHandler *handlers, gpointer data); + +#endif /* __GOODVIBES_FRAMEWORK_GLIB_OBJECT_ADDITIONS_H__ */ diff -Nru goodvibes-0.3.6/src/framework/gv-configurable.c goodvibes-0.4.2/src/framework/gv-configurable.c --- goodvibes-0.3.6/src/framework/gv-configurable.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/gv-configurable.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -21,8 +21,8 @@ #include -#include "framework/log.h" -#include "framework/gv-configurable.h" +#include "gv-configurable.h" +#include "log.h" /* * GObject definitions diff -Nru goodvibes-0.3.6/src/framework/gv-configurable.h goodvibes-0.4.2/src/framework/gv-configurable.h --- goodvibes-0.3.6/src/framework/gv-configurable.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/gv-configurable.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/framework/gv-errorable.c goodvibes-0.4.2/src/framework/gv-errorable.c --- goodvibes-0.3.6/src/framework/gv-errorable.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/gv-errorable.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -21,8 +21,8 @@ #include -#include "framework/log.h" -#include "framework/gv-errorable.h" +#include "gv-errorable.h" +#include "log.h" /* * GObject definitions diff -Nru goodvibes-0.3.6/src/framework/gv-errorable.h goodvibes-0.4.2/src/framework/gv-errorable.h --- goodvibes-0.3.6/src/framework/gv-errorable.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/gv-errorable.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/framework/gv-feature.c goodvibes-0.4.2/src/framework/gv-feature.c --- goodvibes-0.3.6/src/framework/gv-feature.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/gv-feature.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -22,13 +22,15 @@ #include #include -#include "additions/glib.h" -#include "additions/glib-object.h" -#include "framework/log.h" -#include "framework/gv-configurable.h" -#include "framework/gv-feature.h" -#include "framework/gv-framework-enum-types.h" -#include "framework/gv-param-specs.h" +#include "config.h" +#include "glib-additions.h" +#include "glib-object-additions.h" +#include "gv-configurable.h" +#include "gv-feature.h" +#include "gv-framework-enum-types.h" +#include "gv-param-specs.h" +#include "log.h" +#include "utils.h" /* * Properties @@ -272,7 +274,7 @@ GvFeature *self = GV_FEATURE(object); GvFeatureClass *class = GV_FEATURE_GET_CLASS(self); GvFeaturePrivate *priv = gv_feature_get_instance_private(self); - gchar *schema_id; + gchar *schema_id_suffix; TRACE("%p", object); @@ -287,9 +289,9 @@ g_assert_nonnull(priv->name); /* Create settings */ - schema_id = g_strjoin(".", PACKAGE_APPLICATION_ID, "Feat", priv->name, NULL); - priv->settings = g_settings_new(schema_id); - g_free(schema_id); + schema_id_suffix = g_strjoin(".", "Feat", priv->name, NULL); + priv->settings = gv_get_settings(schema_id_suffix); + g_free(schema_id_suffix); } static void @@ -321,7 +323,7 @@ properties[PROP_FLAGS] = g_param_spec_flags("flags", "Feature flags", NULL, - GV_FEATURE_FLAGS_ENUM_TYPE, + GV_TYPE_FEATURE_FLAGS, GV_FEATURE_DEFAULT, GV_PARAM_DEFAULT_FLAGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); diff -Nru goodvibes-0.3.6/src/framework/gv-feature.h goodvibes-0.4.2/src/framework/gv-feature.h --- goodvibes-0.3.6/src/framework/gv-feature.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/gv-feature.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -25,8 +25,6 @@ #include #include -#include "additions/glib-object.h" - /* GObject declarations */ #define GV_TYPE_FEATURE gv_feature_get_type() diff -Nru goodvibes-0.3.6/src/framework/gv-file-helpers.c goodvibes-0.4.2/src/framework/gv-file-helpers.c --- goodvibes-0.3.6/src/framework/gv-file-helpers.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/gv-file-helpers.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,274 +0,0 @@ -/* - * Goodvibes Radio Player - * - * Copyright (C) 2015-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include - -#include - -#include "framework/log.h" -#include "framework/gv-file-helpers.h" - -/* - * File I/O - */ - -gboolean -gv_file_read_sync(const gchar *path, gchar **text, GError **err) -{ - g_assert(text); - - return g_file_get_contents(path, text, NULL, err); -} - -gboolean -gv_file_write_sync(const gchar *path, const gchar *text, GError **err) -{ - return g_file_set_contents(path, text, -1, err); -} - -/* - * Pathes - */ - -static gchar * -gv_get_current_dir(const gchar *subdir) -{ - gchar *dir; - gchar *current_dir; - - current_dir = g_get_current_dir(); - dir = g_build_filename(current_dir, subdir, NULL); - g_free(current_dir); - - return dir; -} - -const gchar * -gv_get_current_config_dir(void) -{ - static gchar *dir; - - if (dir == NULL) - dir = gv_get_current_dir("config"); - - return dir; -} - -const gchar * -gv_get_current_data_dir(void) -{ - static gchar *dir; - - if (dir == NULL) - dir = gv_get_current_dir("data"); - - return dir; -} - -const gchar * -gv_get_user_data_dir(void) -{ - static gchar *dir; - - if (dir == NULL) { - const gchar *user_dir; - gboolean created; - - user_dir = g_get_user_data_dir(); - dir = g_build_filename(user_dir, PACKAGE_NAME, NULL); - - created = g_mkdir_with_parents(dir, S_IRWXU); - if (created != 0) - WARNING("Failed to make user data dir '%s': %s", - dir, strerror(errno)); - } - - return dir; -} - -const gchar * -gv_get_user_config_dir(void) -{ - static gchar *dir; - - if (dir == NULL) { - const gchar *user_dir; - gboolean created; - - user_dir = g_get_user_config_dir(); - dir = g_build_filename(user_dir, PACKAGE_NAME, NULL); - - created = g_mkdir_with_parents(dir, S_IRWXU); - if (created != 0) - WARNING("Failed to make user config dir '%s': %s", - dir, strerror(errno)); - } - - return dir; -} - -const gchar *const * -gv_get_system_config_dirs(void) -{ - static gchar **dirs; - - if (dirs == NULL) { - const gchar *const *system_dirs; - guint i, n_dirs; - - system_dirs = g_get_system_config_dirs(); - for (i = 0, n_dirs = 0; system_dirs[i] != NULL; i++) - n_dirs++; - - dirs = g_malloc0_n(n_dirs + 1, sizeof(gchar *)); - for (i = 0; system_dirs[i] != NULL; i++) - dirs[i] = g_build_filename(system_dirs[i], PACKAGE_NAME, NULL); - } - - return (const gchar * const *) dirs; -} - -const gchar *const * -gv_get_system_data_dirs(void) -{ - static gchar **dirs; - - if (dirs == NULL) { - const gchar *const *system_dirs; - guint i, n_dirs; - - system_dirs = g_get_system_data_dirs(); - for (i = 0, n_dirs = 0; system_dirs[i] != NULL; i++) - n_dirs++; - - dirs = g_malloc0_n(n_dirs + 1, sizeof(gchar *)); - for (i = 0; system_dirs[i] != NULL; i++) - dirs[i] = g_build_filename(system_dirs[i], PACKAGE_NAME, NULL); - } - - return (const gchar * const *) dirs; -} - -GSList * -gv_get_path_list(GvDirType dir_type, const gchar *filename) -{ - GSList *list = NULL; - gchar *path; - - if (dir_type & GV_DIR_CURRENT_CONFIG) { - path = g_build_filename(gv_get_current_config_dir(), filename, NULL); - list = g_slist_append(list, path); - } - - if (dir_type & GV_DIR_CURRENT_DATA) { - path = g_build_filename(gv_get_current_data_dir(), filename, NULL); - list = g_slist_append(list, path); - } - - if (dir_type & GV_DIR_USER_CONFIG) { - path = g_build_filename(gv_get_user_config_dir(), filename, NULL); - list = g_slist_append(list, path); - } - - if (dir_type & GV_DIR_USER_DATA) { - path = g_build_filename(gv_get_user_data_dir(), filename, NULL); - list = g_slist_append(list, path); - } - - if (dir_type & GV_DIR_SYSTEM_CONFIG) { - const gchar *const *system_dirs; - guint i; - - system_dirs = gv_get_system_config_dirs(); - - for (i = 0; system_dirs[i] != NULL; i++) { - path = g_build_filename(system_dirs[i], filename, NULL); - list = g_slist_append(list, path); - } - } - - if (dir_type & GV_DIR_SYSTEM_DATA) { - const gchar *const *system_dirs; - guint i; - - system_dirs = gv_get_system_data_dirs(); - - for (i = 0; system_dirs[i] != NULL; i++) { - path = g_build_filename(system_dirs[i], filename, NULL); - list = g_slist_append(list, path); - } - } - - return list; -} - -GSList * -gv_get_existing_path_list(GvDirType dir_type, const gchar *filename) -{ - GSList *pathes, *item; - - pathes = gv_get_path_list(dir_type, filename); - item = pathes; - - while (item) { - GSList *next_item; - gchar *file; - - next_item = item->next; - - file = (gchar *) item->data; - if (!g_file_test(file, G_FILE_TEST_EXISTS)) { - pathes = g_slist_delete_link(pathes, item); - g_free(file); - } - - item = next_item; - } - - return pathes; -} - -gchar * -gv_get_first_existing_path(GvDirType dir_type, const gchar *filename) -{ - GSList *pathes, *item; - gchar *path = NULL; - - pathes = gv_get_path_list(dir_type, filename); - - for (item = pathes; item; item = item->next) { - const gchar *file; - - file = (const gchar *) item->data; - if (g_file_test(file, G_FILE_TEST_EXISTS)) { - path = g_strdup(file); - break; - } - } - - g_slist_free_full(pathes, g_free); - - return path; -} diff -Nru goodvibes-0.3.6/src/framework/gv-file-helpers.h goodvibes-0.4.2/src/framework/gv-file-helpers.h --- goodvibes-0.3.6/src/framework/gv-file-helpers.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/gv-file-helpers.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -/* - * Goodvibes Radio Player - * - * Copyright (C) 2015-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __GOODVIBES_FRAMEWORK_GV_FILE_HELPERS_H__ -#define __GOODVIBES_FRAMEWORK_GV_FILE_HELPERS_H__ - -#include - -/* File I/O */ - -gboolean gv_file_read_sync (const gchar *path, gchar **text, GError **err); -gboolean gv_file_write_sync(const gchar *path, const gchar *text, GError **err); - -/* Pathes */ - -const gchar *gv_get_current_config_dir(void); -const gchar *gv_get_current_data_dir (void); -const gchar *gv_get_user_config_dir (void); -const gchar *gv_get_user_data_dir (void); -const gchar *const *gv_get_system_config_dirs(void); -const gchar *const *gv_get_system_data_dirs (void); - -typedef enum { - GV_DIR_CURRENT_CONFIG = (1 << 0), - GV_DIR_CURRENT_DATA = (1 << 1), - GV_DIR_USER_CONFIG = (1 << 2), - GV_DIR_USER_DATA = (1 << 3), - GV_DIR_SYSTEM_CONFIG = (1 << 4), - GV_DIR_SYSTEM_DATA = (1 << 5), -} GvDirType; - -GSList *gv_get_path_list(GvDirType dir_type, const gchar *filename); -GSList *gv_get_existing_path_list(GvDirType dir_type, const gchar *filename); -gchar *gv_get_first_existing_path(GvDirType dir_type, const gchar *filename); - -#endif /* __GOODVIBES_FRAMEWORK_GV_FILE_HELPERS_H__ */ diff -Nru goodvibes-0.3.6/src/framework/gv-framework.c goodvibes-0.4.2/src/framework/gv-framework.c --- goodvibes-0.3.6/src/framework/gv-framework.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/gv-framework.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -25,21 +25,46 @@ #include #include -#include "framework/log.h" -#include "framework/gv-framework.h" +#include "log.h" -GList *gv_framework_object_list; +static gboolean initialized = FALSE; +/* + * Global object list + * + * This list contains all the global objects, ie. objects which lifetime + * last for the whole program duration. It must be populated during + * initialization, and accessed only after. + */ + +static GList *object_list; + +/* Return the list of global objects. This list must be treated as read-only by + * the caller, it's not supposed to be modified. + */ +GList * +gv_framework_get_objects(void) +{ + /* This should happen only after initialization is complete */ + g_assert(initialized == TRUE); + + return object_list; +} + +/* Register a global object. */ void -gv_framework_register(gpointer data) +gv_framework_register_object(gpointer data) { GObject *object = G_OBJECT(data); + /* This should happen only during initialization, never after */ + g_assert(initialized == FALSE); + /* Add to the object list (we don't take ownership) */ - gv_framework_object_list = g_list_prepend(gv_framework_object_list, object); + object_list = g_list_prepend(object_list, object); - /* Add a weak pointer */ - g_object_add_weak_pointer(object, (gpointer *) &(gv_framework_object_list->data)); + /* Add a weak pointer, for cleanup checks */ + g_object_add_weak_pointer(object, (gpointer *) &(object_list->data)); } void @@ -47,17 +72,28 @@ { GList *item; + g_assert(initialized == TRUE); + /* Objects in list should be empty, thanks to the magic of weak pointers */ - for (item = gv_framework_object_list; item; item = item->next) { + for (item = object_list; item; item = item->next) { GObject *object = G_OBJECT(item->data); - if (object != NULL) - WARNING("Object of type '%s' has not been finalized !", - G_OBJECT_TYPE_NAME(object)); + if (object == NULL) + continue; + + WARNING("Object of type '%s' has not been finalized !", + G_OBJECT_TYPE_NAME(object)); } /* Free list */ - g_list_free(gv_framework_object_list); + g_list_free(object_list); +} + +void +gv_framework_init_completed(void) +{ + g_assert(initialized == FALSE); + initialized = TRUE; } void diff -Nru goodvibes-0.3.6/src/framework/gv-framework.h goodvibes-0.4.2/src/framework/gv-framework.h --- goodvibes-0.3.6/src/framework/gv-framework.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/gv-framework.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -25,35 +25,23 @@ #include #include /* _() is defined here */ +#include "framework/config.h" /* generated by the build system */ + #include "framework/gv-configurable.h" #include "framework/gv-errorable.h" #include "framework/gv-feature.h" -#include "framework/gv-file-helpers.h" #include "framework/gv-framework-enum-types.h" #include "framework/gv-param-specs.h" - #include "framework/log.h" #include "framework/uri-schemes.h" +#include "framework/utils.h" #include "framework/vt-codes.h" -/* - * Global object list - * - * This list contains all the global objects. It is completely filled - * after initialization has been completed, and therefore should only - * be accessed after this point. In other words, it's probably an error - * to access this list in a 'constructed()' method, it's too early. - * - * Of course this list is 'read-only' and shouldn't be modified. - */ - -extern GList *gv_framework_object_list; - -/* Functions */ - -void gv_framework_init (void); -void gv_framework_cleanup (void); +void gv_framework_init (void); +void gv_framework_init_completed(void); +void gv_framework_cleanup (void); -void gv_framework_register(gpointer object); +void gv_framework_register_object(gpointer object); +GList *gv_framework_get_objects (void); #endif /* __GOODVIBES_FRAMEWORK_GV_FRAMEWORK_H__ */ diff -Nru goodvibes-0.3.6/src/framework/gv-param-specs.h goodvibes-0.4.2/src/framework/gv-param-specs.h --- goodvibes-0.3.6/src/framework/gv-param-specs.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/gv-param-specs.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/framework/log.c goodvibes-0.4.2/src/framework/log.c --- goodvibes-0.3.6/src/framework/log.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/log.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -28,7 +28,7 @@ #include #include -#include "framework/vt-codes.h" +#include "vt-codes.h" /* Additional log level for traces */ diff -Nru goodvibes-0.3.6/src/framework/log.h goodvibes-0.4.2/src/framework/log.h --- goodvibes-0.3.6/src/framework/log.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/log.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/framework/meson.build goodvibes-0.4.2/src/framework/meson.build --- goodvibes-0.3.6/src/framework/meson.build 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/framework/meson.build 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Configuration file + +config = configuration_data() +config.set_quoted('GETTEXT_PACKAGE', gv_name_lowercase) +config.set_quoted('GV_LOCALEDIR', localedir) +config.set_quoted('PACKAGE_NAME', gv_name_lowercase) +config.set_quoted('PACKAGE_VERSION', gv_version) +config.set_quoted('GV_NAME_CAPITAL', gv_name_camelcase) +config.set_quoted('GV_APPLICATION_ID', gv_application_id) +config.set_quoted('GV_APPLICATION_PATH', gv_application_path) +config.set_quoted('GV_ICON_NAME', gv_icon_name) +config.set_quoted('GV_HOMEPAGE', gv_homepage) +config.set_quoted('GV_COPYRIGHT', gv_copyright) +config.set_quoted('GV_AUTHOR_NAME', gv_author_name) +config.set_quoted('GV_AUTHOR_EMAIL', gv_author_email) + +config.set('GV_FEAT_CONSOLE_OUTPUT', gv_feat_console_output) +config.set('GV_FEAT_DBUS_SERVER', gv_feat_dbus_server) +config.set('GV_FEAT_INHIBITOR', gv_feat_inhibitor) +config.set('GV_UI_ENABLED', gv_ui_enabled) +config.set('GV_FEAT_HOTKEYS', gv_feat_hotkeys) +config.set('GV_FEAT_NOTIFICATIONS', gv_feat_notifications) + +configure_file( + output: 'config.h', + configuration: config, +) + +# Sources and dependencies + +framework_sources = [ + 'glib-additions.c', + 'glib-object-additions.c', + 'gv-configurable.c', + 'gv-errorable.c', + 'gv-feature.c', + 'gv-framework.c', + 'log.c', + 'uri-schemes.c', + 'utils.c', +] + +framework_dependencies = [ + glib_dep, + gobject_dep, + gio_dep, +] + +framework_enum_headers = [ 'gv-feature.h' ] +framework_enums = gnome.mkenums_simple('gv-framework-enum-types', + sources: framework_enum_headers +) +framework_enum_h = framework_enums[1] + +# Library definition + +gvframework = static_library('gvframework', + sources: [ framework_sources, framework_enums ], + dependencies: framework_dependencies, + include_directories: root_inc, +) + +gvframework_dep = declare_dependency( + dependencies: framework_dependencies, + sources: [ framework_enum_h ], + link_with: gvframework, +) diff -Nru goodvibes-0.3.6/src/framework/uri-schemes.c goodvibes-0.4.2/src/framework/uri-schemes.c --- goodvibes-0.3.6/src/framework/uri-schemes.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/uri-schemes.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/framework/uri-schemes.h goodvibes-0.4.2/src/framework/uri-schemes.h --- goodvibes-0.3.6/src/framework/uri-schemes.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/uri-schemes.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/framework/utils.c goodvibes-0.4.2/src/framework/utils.c --- goodvibes-0.3.6/src/framework/utils.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/framework/utils.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,190 @@ +/* + * Goodvibes Radio Player + * + * Copyright (C) 2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "config.h" +#include "log.h" + +#define GV_OLD_APPLICATION_ID "com.elboulangero.Goodvibes" + +/* + * Settings + */ + +static GSettings * +get_current_settings(const gchar *component) +{ + gchar *schema_id; + GSettings *settings; + + schema_id = g_strdup_printf("%s.%s", GV_APPLICATION_ID, component); + settings = g_settings_new(schema_id); + g_free(schema_id); + + return settings; +} + +static GSettings * +get_old_settings(const gchar *component) +{ + gchar *schema_id; + GSettingsSchema *schema; + GSettingsSchemaSource *source; + + source = g_settings_schema_source_get_default(); + if (source == NULL) + return NULL; + + schema_id = g_strdup_printf("%s.%s", GV_OLD_APPLICATION_ID, component); + schema = g_settings_schema_source_lookup(source, schema_id, TRUE); + g_free(schema_id); + + if (schema == NULL) + return NULL; + + return g_settings_new_full(schema, NULL, NULL); +} + +static void +merge_settings(const gchar *component, GSettings *from, GSettings *to) +{ + gint i; + gchar **keys; + gboolean changed; + GSettingsSchema *schema; + + g_object_get(from, "settings-schema", &schema, NULL); + keys = g_settings_schema_list_keys(schema); + changed = FALSE; + + for (i = 0; keys[i]; i++) { + const gchar *key; + GVariant *value; + + key = keys[i]; + value = g_settings_get_user_value(from, key); + if (value == NULL) + continue; + + INFO("Settings migration: %s: moving key '%s'", component, key); + g_settings_set_value(to, key, value); + g_settings_reset(from, key); + g_variant_unref(value); + changed = TRUE; + } + + if (changed) { + INFO("Settings migration: %s: syncing", component); + g_settings_sync(); + } + + g_strfreev(keys); + g_settings_schema_unref(schema); +} + +GSettings * +gv_get_settings(const gchar *component) +{ + GSettings *settings, *old_settings; + + settings = get_current_settings(component); + old_settings = get_old_settings(component); + + if (old_settings) { + merge_settings(component, old_settings, settings); + g_object_unref(old_settings); + } + + return settings; +} + +/* + * XDG + */ + +const gchar * +gv_get_app_user_config_dir(void) +{ + static gchar *dir; + + if (dir == NULL) { + const gchar *user_dir; + + user_dir = g_get_user_config_dir(); + dir = g_build_filename(user_dir, PACKAGE_NAME, NULL); + } + + return dir; +} + +const gchar * +gv_get_app_user_data_dir(void) +{ + static gchar *dir; + + if (dir == NULL) { + const gchar *user_dir; + + user_dir = g_get_user_data_dir(); + dir = g_build_filename(user_dir, PACKAGE_NAME, NULL); + } + + return dir; +} + +const gchar *const * +gv_get_app_system_config_dirs(void) +{ + static gchar **dirs; + + if (dirs == NULL) { + const gchar *const *system_dirs; + guint i, n_dirs; + + system_dirs = g_get_system_config_dirs(); + n_dirs = g_strv_length((gchar **) system_dirs); + dirs = g_malloc0_n(n_dirs + 1, sizeof(gchar *)); + for (i = 0; i < n_dirs; i++) + dirs[i] = g_build_filename(system_dirs[i], PACKAGE_NAME, NULL); + } + + return (const gchar * const *) dirs; +} + +const gchar *const * +gv_get_app_system_data_dirs(void) +{ + static gchar **dirs; + + if (dirs == NULL) { + const gchar *const *system_dirs; + guint i, n_dirs; + + system_dirs = g_get_system_data_dirs(); + n_dirs = g_strv_length((gchar **) system_dirs); + dirs = g_malloc0_n(n_dirs + 1, sizeof(gchar *)); + for (i = 0; i < n_dirs; i++) + dirs[i] = g_build_filename(system_dirs[i], PACKAGE_NAME, NULL); + } + + return (const gchar * const *) dirs; +} diff -Nru goodvibes-0.3.6/src/framework/utils.h goodvibes-0.4.2/src/framework/utils.h --- goodvibes-0.3.6/src/framework/utils.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/framework/utils.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,34 @@ +/* + * Goodvibes Radio Player + * + * Copyright (C) 2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GOODVIBES_FRAMEWORK_UTILS_H__ +#define __GOODVIBES_FRAMEWORK_UTILS_H__ + +#include + +GSettings *gv_get_settings(const gchar *component); + +const gchar *gv_get_app_user_config_dir(void); +const gchar *gv_get_app_user_data_dir(void); +const gchar *const *gv_get_app_system_config_dirs(void); +const gchar *const *gv_get_app_system_data_dirs(void); + +#endif /* __GOODVIBES_FRAMEWORK_UTILS_H__ */ diff -Nru goodvibes-0.3.6/src/framework/vt-codes.h goodvibes-0.4.2/src/framework/vt-codes.h --- goodvibes-0.3.6/src/framework/vt-codes.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/framework/vt-codes.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/gv-console-application.c goodvibes-0.4.2/src/gv-console-application.c --- goodvibes-0.3.6/src/gv-console-application.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/gv-console-application.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2017 Arnaud Rebillout + * Copyright (C) 2017-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -88,6 +88,7 @@ gv_framework_init(); gv_core_init(app); gv_feat_init(); + gv_framework_init_completed(); /* Configuration */ DEBUG_NO_CONTEXT("---- Configuring ----"); diff -Nru goodvibes-0.3.6/src/gv-console-application.h goodvibes-0.4.2/src/gv-console-application.h --- goodvibes-0.3.6/src/gv-console-application.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/gv-console-application.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2017 Arnaud Rebillout + * Copyright (C) 2017-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/gv-graphical-application.c goodvibes-0.4.2/src/gv-graphical-application.c --- goodvibes-0.3.6/src/gv-graphical-application.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/gv-graphical-application.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2017 Arnaud Rebillout + * Copyright (C) 2017-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -26,12 +26,14 @@ #include "framework/gv-framework.h" #include "core/gv-core.h" #include "ui/gv-ui.h" -#include "ui/gv-ui-helpers.h" #include "feat/gv-feat.h" #include "gv-graphical-application.h" #include "options.h" +#define APPMENU_RESOURCE_PATH GV_APPLICATION_PATH "/Ui/app-menu.glade" +#define MENUBAR_RESOURCE_PATH GV_APPLICATION_PATH "/Ui/menubar.glade" + /* * GObject definitions */ @@ -81,7 +83,7 @@ GVariant *parameters G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED) { - g_app_info_launch_default_for_uri(PACKAGE_HOMEPAGE, NULL, NULL); + g_app_info_launch_default_for_uri(GV_HOMEPAGE, NULL, NULL); } static void @@ -172,15 +174,10 @@ if (prefers_app_menu) { GtkBuilder *builder; GMenuModel *model; - gchar *uifile; - - gv_builder_load("app-menu.glade", &builder, &uifile); - DEBUG("App menu loaded from ui file '%s'", uifile); + builder = gtk_builder_new_from_resource(APPMENU_RESOURCE_PATH); model = G_MENU_MODEL(gtk_builder_get_object(builder, "app-menu")); gtk_application_set_app_menu(GTK_APPLICATION(app), model); - - g_free(uifile); g_object_unref(builder); } @@ -188,15 +185,10 @@ if (!prefers_app_menu) { GtkBuilder *builder; GMenuModel *model; - gchar *uifile; - - gv_builder_load("menubar.glade", &builder, &uifile); - DEBUG("Menubar loaded from ui file '%s'", uifile); + builder = gtk_builder_new_from_resource(MENUBAR_RESOURCE_PATH); model = G_MENU_MODEL(gtk_builder_get_object(builder, "menubar")); gtk_application_set_menubar(GTK_APPLICATION(app), model); - - g_free(uifile); g_object_unref(builder); } } @@ -207,6 +199,7 @@ gv_core_init(app); gv_ui_init(app, options.status_icon); gv_feat_init(); + gv_framework_init_completed(); /* Configuration */ DEBUG_NO_CONTEXT("---- Configuring ----"); diff -Nru goodvibes-0.3.6/src/gv-graphical-application.h goodvibes-0.4.2/src/gv-graphical-application.h --- goodvibes-0.3.6/src/gv-graphical-application.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/gv-graphical-application.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2017 Arnaud Rebillout + * Copyright (C) 2017-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/libcaphe/caphe.c goodvibes-0.4.2/src/libcaphe/caphe.c --- goodvibes-0.3.6/src/libcaphe/caphe.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "caphe-cup.h" + +void +caphe_cleanup(void) +{ + g_object_add_weak_pointer(G_OBJECT(caphe_cup_default_instance), + (gpointer *) &caphe_cup_default_instance); + g_object_unref(caphe_cup_default_instance); + g_assert_null(caphe_cup_default_instance); +} + +void +caphe_init(void) +{ + /* Dummy */ +} diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-cup.c goodvibes-0.4.2/src/libcaphe/caphe-cup.c --- goodvibes-0.3.6/src/libcaphe/caphe-cup.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-cup.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,502 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include + +#include "caphe-trace.h" +#include "caphe-inhibitor.h" +#include "caphe-inhibitor-list.h" +#include "caphe-cup.h" + +/* + * Signals + */ + +enum { + SIGNAL_INHIBIT_FAILURE, + /* Number of signals */ + SIGNAL_N +}; + +static guint signals[SIGNAL_N]; + +/* + * Properties + */ + +enum { + /* Reserved */ + PROP_0, + /* Construct-only properties */ + PROP_APPLICATION_NAME, + /* Properties */ + PROP_INHIBITOR, + /* Total number of properties */ + LAST_PROP +}; + +static GParamSpec *properties[LAST_PROP]; + +/* + * GObject definitions + */ + +typedef struct { + /* If NULL, means an unhibibit request. + * If non NULL, means an inhibit request. + */ + gchar *reason; +} CapheRequest; + +struct _CapheCupPrivate { + /* List of inhibitors */ + CapheInhibitorList *inhibitor_list; + gboolean ready; + + /* Application name */ + gchar *application_name; + + /* Current state */ + CapheInhibitor *current_inhibitor; + gchar *current_reason; + /* Pending request */ + CapheRequest *pending_request; + /* Pending processing */ + guint when_idle_process_id; +}; + +typedef struct _CapheCupPrivate CapheCupPrivate; + +struct _CapheCup { + /* Parent instance structure */ + GObject parent_instance; + /* Private data */ + CapheCupPrivate *priv; +}; + +G_DEFINE_TYPE_WITH_PRIVATE(CapheCup, caphe_cup, G_TYPE_OBJECT) + +/* + * Helpers + */ + +CapheRequest * +caphe_request_new(const gchar *reason) +{ + CapheRequest *self; + + self = g_new0(CapheRequest, 1); + self->reason = g_strdup(reason); + + return self; +} + +void +caphe_request_free(CapheRequest *self) +{ + if (self == NULL) + return; + + g_free(self->reason); + g_free(self); +} + +/* + * Private methods + */ + +static void caphe_cup_set_inhibitor(CapheCup *self, CapheInhibitor *inhibitor); + +static void +caphe_cup_process(CapheCup *self) +{ + CapheCupPrivate *priv = self->priv; + + /* As long as we're not ready, we can't do anything */ + if (priv->ready == FALSE) + return; + + /* If there's nothing pending, do nothing */ + if (priv->pending_request == NULL) + return; + + /* We can start processing the pending request. + * In case we're trying to inhibit while already inhibited + * (it's possible in case the user wants to change the reason), + * we must slip an unhibit request in between. + */ + if (priv->current_reason && priv->pending_request->reason) { + g_debug("Slipping uninhibit request between two inhibit requests"); + + /* Uninhibit */ + if (priv->current_inhibitor) { + caphe_inhibitor_uninhibit(priv->current_inhibitor); + priv->current_inhibitor = NULL; + g_free(priv->current_reason); + priv->current_reason = NULL; + } + } + + /* Process now */ + if (priv->pending_request->reason) { + CapheInhibitor **inhibitors; + gboolean success; + + g_debug("Inhibition: processing request"); + + for (inhibitors = caphe_inhibitor_list_get_inhibitors(priv->inhibitor_list); + *inhibitors; inhibitors++) { + CapheInhibitor *inhibitor = *inhibitors; + GError *error = NULL; + + /* Ignore inhibitors that are not available */ + if (caphe_inhibitor_get_available(inhibitor) == FALSE) + continue; + + /* Attempt inhibition */ + success = caphe_inhibitor_inhibit(inhibitor, + priv->application_name, + priv->pending_request->reason, + &error); + if (success == FALSE) { + g_warning("Error while inhibiting: %s", error->message); + g_clear_error(&error); + continue; + } + + /* Save new status */ + caphe_cup_set_inhibitor(self, inhibitor); + g_free(priv->current_reason); + priv->current_reason = g_strdup(priv->pending_request->reason); + + /* Done */ + break; + } + + if (success == FALSE) { + g_signal_emit(self, signals[SIGNAL_INHIBIT_FAILURE], 0); + } + + /* Consume request */ + caphe_request_free(priv->pending_request); + priv->pending_request = NULL; + + } else { + g_debug("Uninhibition: processing request"); + + /* Uninhibit */ + if (priv->current_inhibitor) { + caphe_inhibitor_uninhibit(priv->current_inhibitor); + caphe_cup_set_inhibitor(self, NULL); + g_free(priv->current_reason); + priv->current_reason = NULL; + } + + /* Consume request */ + caphe_request_free(priv->pending_request); + priv->pending_request = NULL; + } +} + +/* + * Signal handlers + */ + +static void +on_inhibitor_list_ready(CapheInhibitorList *inhibitor_list G_GNUC_UNUSED, + CapheCup *self) +{ + CapheCupPrivate *priv = self->priv; + + /* We're ready, let's remember that */ + priv->ready = TRUE; + + /* Process */ + caphe_cup_process(self); +} + +/* + * Public + */ + +gboolean +caphe_cup_is_inhibited(CapheCup *self) +{ + CapheCupPrivate *priv = self->priv; + + return priv->current_inhibitor != NULL; +} + +static gboolean +when_idle_process(CapheCup *self) +{ + CapheCupPrivate *priv = self->priv; + + caphe_cup_process(self); + + priv->when_idle_process_id = 0; + + return G_SOURCE_REMOVE; +} + +void +caphe_cup_uninhibit(CapheCup *self) +{ + CapheCupPrivate *priv = self->priv; + + /* We might ignore the request in the following case: + * - we're already uninhibited + * - we're sure there's nothing happening at the moment + */ + if (priv->current_inhibitor == NULL && + priv->pending_request == NULL) + return; + + /* Otherwise, create a request */ + caphe_request_free(priv->pending_request); + priv->pending_request = caphe_request_new(NULL); + g_debug("Uninhibition: request created and pending"); + + /* Schedule process */ + if (priv->when_idle_process_id == 0) + priv->when_idle_process_id = g_idle_add((GSourceFunc) when_idle_process, self); +} + +void +caphe_cup_inhibit(CapheCup *self, const gchar *reason) +{ + CapheCupPrivate *priv = self->priv; + + g_return_if_fail(reason != NULL); + + /* We might ignore the request in the following case: + * - we're already inhibited with the same reason + * - we're sure there's nothing happening at the moment + * ... + */ + if (priv->current_inhibitor && + !g_strcmp0(reason, priv->current_reason) && + priv->pending_request == NULL) + return; + + /* Otherwise, create a request */ + caphe_request_free(priv->pending_request); + priv->pending_request = caphe_request_new(reason); + g_debug("Inhibition: request created and pending"); + + /* Schedule process */ + if (priv->when_idle_process_id == 0) + priv->when_idle_process_id = g_idle_add((GSourceFunc) when_idle_process, self); +} + +CapheCup * +caphe_cup_new(void) +{ + return g_object_new(CAPHE_TYPE_CUP, NULL); +} + +/* + * Property accessors + */ + +void +caphe_cup_set_application_name(CapheCup *self, const gchar *application_name) +{ + CapheCupPrivate *priv = self->priv; + + if (!g_strcmp0(priv->application_name, application_name)) + return; + + g_free(priv->application_name); + priv->application_name = g_strdup(application_name); + g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_APPLICATION_NAME]); +} + +CapheInhibitor * +caphe_cup_get_inhibitor(CapheCup *self) +{ + return self->priv->current_inhibitor; +} + +static void +caphe_cup_set_inhibitor(CapheCup *self, CapheInhibitor *inhibitor) +{ + CapheCupPrivate *priv = self->priv; + + if (g_set_object(&priv->current_inhibitor, inhibitor)) + g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_INHIBITOR]); +} + +static void +caphe_cup_get_property(GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + CapheCup *self = CAPHE_CUP(object); + + switch (property_id) { + case PROP_INHIBITOR: + g_value_set_object(value, caphe_cup_get_inhibitor(self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +caphe_cup_set_property(GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + CapheCup *self = CAPHE_CUP(object); + + switch (property_id) { + case PROP_APPLICATION_NAME: + caphe_cup_set_application_name(self, g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +/* + * GObject methods + */ + +static void +caphe_cup_finalize(GObject *object) +{ + CapheCup *self = CAPHE_CUP(object); + CapheCupPrivate *priv = self->priv; + + TRACE("%p", self); + + if (priv->when_idle_process_id) + g_source_remove(priv->when_idle_process_id); + + caphe_request_free(priv->pending_request); + + g_free(priv->application_name); + + /* Unref current status */ + g_clear_object(&priv->current_inhibitor); + g_free(priv->current_reason); + + /* Destroy inhibitor list */ + g_clear_object(&priv->inhibitor_list); + + /* Chain up */ + if (G_OBJECT_CLASS(caphe_cup_parent_class)->finalize) + G_OBJECT_CLASS(caphe_cup_parent_class)->finalize(object); +} + +static void +caphe_cup_constructed(GObject *object) +{ + CapheCup *self = CAPHE_CUP(object); + CapheCupPrivate *priv = self->priv; + + TRACE("%p", self); + + /* Create inhibitor list */ + priv->inhibitor_list = caphe_inhibitor_list_new(); + g_signal_connect_object(priv->inhibitor_list, "ready", + G_CALLBACK(on_inhibitor_list_ready), + self, 0); + + /* Chain up */ + if (G_OBJECT_CLASS(caphe_cup_parent_class)->constructed) + G_OBJECT_CLASS(caphe_cup_parent_class)->constructed(object); +} + +static void +caphe_cup_init(CapheCup *self) +{ + CapheCupPrivate *priv = caphe_cup_get_instance_private(self); + const gchar *app_name; + + TRACE("%p", self); + + /* Default values */ + app_name = g_get_application_name(); + if (app_name == NULL) + app_name = "Unknown"; + priv->application_name = g_strdup(app_name); + + /* Set private pointer */ + self->priv = priv; +} + +static void +caphe_cup_class_init(CapheCupClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + + TRACE("%p", class); + + /* Override GObject methods */ + object_class->finalize = caphe_cup_finalize; + object_class->constructed = caphe_cup_constructed; + + /* Install properties */ + object_class->get_property = caphe_cup_get_property; + object_class->set_property = caphe_cup_set_property; + + properties[PROP_APPLICATION_NAME] = + g_param_spec_string("application-name", "Application name", NULL, + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE); + + properties[PROP_INHIBITOR] = + g_param_spec_object("inhibitor", "Current inhibitor", NULL, + CAPHE_TYPE_INHIBITOR, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); + + g_object_class_install_properties(object_class, LAST_PROP, properties); + + /* Signals */ + signals[SIGNAL_INHIBIT_FAILURE] = + g_signal_new("inhibit-failure", G_TYPE_FROM_CLASS(class), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); +} + +/* + * Convenience functions + */ + +CapheCup *caphe_cup_default_instance; + +CapheCup * +caphe_cup_get_default(void) +{ + if (caphe_cup_default_instance == NULL) + caphe_cup_default_instance = caphe_cup_new(); + + return caphe_cup_default_instance; +} diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-cup.h goodvibes-0.4.2/src/libcaphe/caphe-cup.h --- goodvibes-0.3.6/src/libcaphe/caphe-cup.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-cup.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __LIBCAPHE_CAPHE_CUP_H__ +#define __LIBCAPHE_CAPHE_CUP_H__ + +#include + +#include "caphe-inhibitor.h" + +/* GObject declarations */ + +#define CAPHE_TYPE_CUP caphe_cup_get_type() + +G_DECLARE_FINAL_TYPE(CapheCup, caphe_cup, CAPHE, CUP, GObject) + +/* Global instance (private, don't access) */ + +extern CapheCup *caphe_cup_default_instance; + +/* Methods */ + +CapheCup *caphe_cup_get_default(void); + +void caphe_cup_inhibit (CapheCup *self, const gchar *reason); +void caphe_cup_uninhibit (CapheCup *self); +gboolean caphe_cup_is_inhibited(CapheCup *self); + +/* Property accessors */ + +void caphe_cup_set_application_name(CapheCup *self, const gchar *name); +CapheInhibitor *caphe_cup_get_inhibitor (CapheCup *self); + +#endif /* __LIBCAPHE_CAPHE_CUP_H__ */ diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-dbus-inhibitor.c goodvibes-0.4.2/src/libcaphe/caphe-dbus-inhibitor.c --- goodvibes-0.3.6/src/libcaphe/caphe-dbus-inhibitor.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-dbus-inhibitor.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,372 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include + +#include "caphe-trace.h" +#include "caphe-login-dbus-invokator.h" +#include "caphe-portal-dbus-invokator.h" +#include "caphe-power-dbus-invokator.h" +#include "caphe-session-dbus-invokator.h" +#include "caphe-dbus-invokator.h" +#include "caphe-dbus-proxy.h" +#include "caphe-dbus-inhibitor.h" + +/* + * Properties + */ + +enum { + /* Reserved */ + PROP_0, + /* Number of installable properties */ + LAST_INSTALLABLE_PROP, + /* Overriden properties */ + PROP_NAME, + PROP_AVAILABLE, + /* Total number of properties */ + LAST_PROP +}; + +static GParamSpec *properties[LAST_PROP]; + +/* + * GObject definitions + */ + +struct _CapheDbusInhibitorPrivate { + /* Properties */ + gchar *name; + /* Internal */ + CapheDbusProxy *proxy; + GType invokator_type; + CapheDbusInvokator *invokator; +}; + +typedef struct _CapheDbusInhibitorPrivate CapheDbusInhibitorPrivate; + +struct _CapheDbusInhibitor { + /* Parent instance structure */ + GObject parent_instance; + /* Private data */ + CapheDbusInhibitorPrivate *priv; +}; + +static void caphe_inhibitor_interface_init(CapheInhibitorInterface *iface); + +G_DEFINE_TYPE_WITH_CODE(CapheDbusInhibitor, caphe_dbus_inhibitor, G_TYPE_OBJECT, + G_ADD_PRIVATE(CapheDbusInhibitor) + G_IMPLEMENT_INTERFACE(CAPHE_TYPE_INHIBITOR, + caphe_inhibitor_interface_init)) + +/* + * Signal handlers + */ + +static void +on_caphe_dbus_proxy_notify_proxy(CapheDbusProxy *caphe_proxy, + GParamSpec *pspec G_GNUC_UNUSED, + CapheDbusInhibitor *self) +{ + CapheDbusInhibitorPrivate *priv = self->priv; + GDBusProxy *dbus_proxy = caphe_dbus_proxy_get_proxy(caphe_proxy); + + /* If the proxy disappeared, we must dispose of the invokator. + * Otherwise, we must create an invokator. + */ + if (dbus_proxy == NULL) { + g_clear_object(&priv->invokator); + + } else { + g_assert(priv->invokator == NULL); + priv->invokator = caphe_dbus_invokator_new(priv->invokator_type, dbus_proxy); + } + + /* Notify that availability changed */ + g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_AVAILABLE]); +} + +/* + * Inhibitor methods + */ + +static gboolean +caphe_dbus_inhibitor_is_inhibited(CapheInhibitor *inhibitor) +{ + CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(inhibitor); + CapheDbusInhibitorPrivate *priv = self->priv; + + if (priv->invokator == NULL) + return FALSE; + + return caphe_dbus_invokator_is_inhibited(priv->invokator); +} + +static void +caphe_dbus_inhibitor_uninhibit(CapheInhibitor *inhibitor) +{ + CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(inhibitor); + CapheDbusInhibitorPrivate *priv = self->priv; + + g_return_if_fail(priv->invokator != NULL); + + caphe_dbus_invokator_uninhibit(priv->invokator); +} + +static gboolean +caphe_dbus_inhibitor_inhibit(CapheInhibitor *inhibitor, const gchar *application, + const gchar *reason, GError **error) +{ + CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(inhibitor); + CapheDbusInhibitorPrivate *priv = self->priv; + + g_return_val_if_fail(application != NULL, FALSE); + g_return_val_if_fail(reason != NULL, FALSE); + g_return_val_if_fail(priv->invokator != NULL, FALSE); + + return caphe_dbus_invokator_inhibit(priv->invokator, application, reason, error); +} + +/* + * Inhibitor property accessors + */ + +static const gchar * +caphe_dbus_inhibitor_get_name(CapheInhibitor *inhibitor) +{ + CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(inhibitor); + CapheDbusInhibitorPrivate *priv = self->priv; + + return priv->name; +} + +static void +caphe_dbus_inhibitor_set_name(CapheInhibitor *inhibitor, const gchar *name) +{ + CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(inhibitor); + CapheDbusInhibitorPrivate *priv = self->priv; + + /* Construct-only property */ + g_assert_null(priv->name); + g_assert_nonnull(name); + priv->name = g_strdup(name); +} + +static gboolean +caphe_dbus_inhibitor_get_available(CapheInhibitor *inhibitor) +{ + CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(inhibitor); + CapheDbusInhibitorPrivate *priv = self->priv; + + return priv->invokator ? TRUE : FALSE; +} + +static void +caphe_dbus_inhibitor_get_property(GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + CapheInhibitor *inhibitor = CAPHE_INHIBITOR(object); + + switch (property_id) { + /* Inhibitor */ + case PROP_NAME: + g_value_set_string(value, caphe_dbus_inhibitor_get_name(inhibitor)); + break; + case PROP_AVAILABLE: + g_value_set_boolean(value, caphe_dbus_inhibitor_get_available(inhibitor)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +caphe_dbus_inhibitor_set_property(GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + CapheInhibitor *inhibitor = CAPHE_INHIBITOR(object); + + switch (property_id) { + case PROP_NAME: + caphe_dbus_inhibitor_set_name(inhibitor, g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +/* + * Public methods + */ + +CapheInhibitor * +caphe_dbus_inhibitor_new(const gchar *name) +{ + return g_object_new(CAPHE_TYPE_DBUS_INHIBITOR, + "name", name, + NULL); +} + +/* + * GObject methods + */ + +static void +caphe_dbus_inhibitor_finalize(GObject *object) +{ + CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(object); + CapheDbusInhibitorPrivate *priv = self->priv; + + TRACE("%p", object); + + if (priv->invokator) + g_object_unref(priv->invokator); + + if (priv->proxy) + g_object_unref(priv->proxy); + + g_free(priv->name); + + /* Chain up */ + if (G_OBJECT_CLASS(caphe_dbus_inhibitor_parent_class)->finalize) + G_OBJECT_CLASS(caphe_dbus_inhibitor_parent_class)->finalize(object); +} + +static void +caphe_dbus_inhibitor_constructed(GObject *object) +{ + CapheDbusInhibitor *self = CAPHE_DBUS_INHIBITOR(object); + CapheDbusInhibitorPrivate *priv = self->priv; + + TRACE("%p", object); + + /* Create the dbus proxy */ + if (!g_strcmp0(priv->name, "gnome-session-manager")) { + priv->invokator_type = CAPHE_TYPE_SESSION_DBUS_INVOKATOR; + priv->proxy = caphe_dbus_proxy_new(G_BUS_TYPE_SESSION, + "org.gnome.SessionManager", + "/org/gnome/SessionManager", + "org.gnome.SessionManager"); + + } else if (!g_strcmp0(priv->name, "xfce-session-manager")) { + priv->invokator_type = CAPHE_TYPE_SESSION_DBUS_INVOKATOR; + priv->proxy = caphe_dbus_proxy_new(G_BUS_TYPE_SESSION, + "org.xfce.SessionManager", + "/org/xfce/SessionManager", + "org.xfce.SessionManager"); + + } else if (!g_strcmp0(priv->name, "xdg-portal")) { + priv->invokator_type = CAPHE_TYPE_PORTAL_DBUS_INVOKATOR; + priv->proxy = caphe_dbus_proxy_new(G_BUS_TYPE_SESSION, + "org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop", + "org.freedesktop.portal.Inhibit"); + + } else if (!g_strcmp0(priv->name, "xdg-power-management")) { + /* Also provided by the following names: + * - org.xfce.PowerManager + * - org.kde.Solid.PowerManagement + */ + priv->invokator_type = CAPHE_TYPE_POWER_DBUS_INVOKATOR; + priv->proxy = caphe_dbus_proxy_new(G_BUS_TYPE_SESSION, + "org.freedesktop.PowerManagement", + "/org/freedesktop/PowerManagement/Inhibit", + "org.freedesktop.PowerManagement.Inhibit"); + + } else if (!g_strcmp0(priv->name, "xdg-login1")) { + priv->invokator_type = CAPHE_TYPE_LOGIN_DBUS_INVOKATOR; + priv->proxy = caphe_dbus_proxy_new(G_BUS_TYPE_SYSTEM, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager"); + } else { + g_error("Invalid inhibitor name '%s'", priv->name); + /* Program execution stops here */ + + } + + /* Connect to the 'proxy' signal to be notified as soon as the proxy + * is created. The signal is ensured to be sent once at init time. + */ + g_signal_connect_object(priv->proxy, "notify::proxy", + G_CALLBACK(on_caphe_dbus_proxy_notify_proxy), + self, 0); + + /* Chain up */ + if (G_OBJECT_CLASS(caphe_dbus_inhibitor_parent_class)->constructed) + G_OBJECT_CLASS(caphe_dbus_inhibitor_parent_class)->constructed(object); +} + +static void +caphe_dbus_inhibitor_init(CapheDbusInhibitor *self) +{ + CapheDbusInhibitorPrivate *priv = caphe_dbus_inhibitor_get_instance_private(self); + + TRACE("%p", self); + + /* Set private pointer */ + self->priv = priv; +} + +static void +caphe_dbus_inhibitor_class_init(CapheDbusInhibitorClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + + TRACE("%p", class); + + /* Override GObject methods */ + object_class->finalize = caphe_dbus_inhibitor_finalize; + object_class->constructed = caphe_dbus_inhibitor_constructed; + + /* Install properties */ + object_class->get_property = caphe_dbus_inhibitor_get_property; + object_class->set_property = caphe_dbus_inhibitor_set_property; + + /* Override Inhibitor properties */ + g_object_class_override_property(object_class, PROP_NAME, "name"); + properties[PROP_NAME] = + g_object_class_find_property(object_class, "name"); + + g_object_class_override_property(object_class, PROP_AVAILABLE, "available"); + properties[PROP_AVAILABLE] = + g_object_class_find_property(object_class, "available"); +} + +static void +caphe_inhibitor_interface_init(CapheInhibitorInterface *iface) +{ + /* Implement methods */ + iface->inhibit = caphe_dbus_inhibitor_inhibit; + iface->uninhibit = caphe_dbus_inhibitor_uninhibit; + iface->is_inhibited = caphe_dbus_inhibitor_is_inhibited; + iface->get_name = caphe_dbus_inhibitor_get_name; + iface->get_available = caphe_dbus_inhibitor_get_available; +} diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-dbus-inhibitor.h goodvibes-0.4.2/src/libcaphe/caphe-dbus-inhibitor.h --- goodvibes-0.3.6/src/libcaphe/caphe-dbus-inhibitor.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-dbus-inhibitor.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __LIBCAPHE_CAPHE_DBUS_INHIBITOR_H__ +#define __LIBCAPHE_CAPHE_DBUS_INHIBITOR_H__ + +#include + +#include "caphe-inhibitor.h" + +/* GObject declarations */ + +#define CAPHE_TYPE_DBUS_INHIBITOR caphe_dbus_inhibitor_get_type() + +G_DECLARE_FINAL_TYPE(CapheDbusInhibitor, caphe_dbus_inhibitor, CAPHE, DBUS_INHIBITOR, GObject) + +/* Property accessors */ + +CapheInhibitor *caphe_dbus_inhibitor_new(const gchar *service_id); + +#endif /* __LIBCAPHE_CAPHE_DBUS_INHIBITOR_H__ */ diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-dbus-invokator.c goodvibes-0.4.2/src/libcaphe/caphe-dbus-invokator.c --- goodvibes-0.3.6/src/libcaphe/caphe-dbus-invokator.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-dbus-invokator.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,207 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include + +#include "caphe-trace.h" +#include "caphe-dbus-invokator.h" + +/* + * Properties + */ + +enum { + /* Reserved */ + PROP_0, + /* Construct-only properties */ + PROP_PROXY, + /* Total number of properties */ + LAST_PROP +}; + +static GParamSpec *properties[LAST_PROP]; + +/* + * GObject definitions + */ + +struct _CapheDbusInvokatorPrivate { + /* Properties */ + GDBusProxy *proxy; +}; + +typedef struct _CapheDbusInvokatorPrivate CapheDbusInvokatorPrivate; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(CapheDbusInvokator, caphe_dbus_invokator, G_TYPE_OBJECT) + +/* + * Property accessors + */ + +GDBusProxy * +caphe_dbus_invokator_get_proxy(CapheDbusInvokator *self) +{ + CapheDbusInvokatorPrivate *priv = caphe_dbus_invokator_get_instance_private(self); + + return priv->proxy; +} + +static void +caphe_dbus_invokator_set_proxy(CapheDbusInvokator *self, GDBusProxy *proxy) +{ + CapheDbusInvokatorPrivate *priv = caphe_dbus_invokator_get_instance_private(self); + + /* Construct-only property */ + g_assert_null(priv->proxy); + g_assert_nonnull(proxy); + + priv->proxy = g_object_ref(proxy); +} + +static void +caphe_dbus_invokator_get_property(GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + CapheDbusInvokator *self = CAPHE_DBUS_INVOKATOR(object); + + switch (property_id) { + case PROP_PROXY: + g_value_set_object(value, caphe_dbus_invokator_get_proxy(self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +caphe_dbus_invokator_set_property(GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + CapheDbusInvokator *self = CAPHE_DBUS_INVOKATOR(object); + + switch (property_id) { + case PROP_PROXY: + caphe_dbus_invokator_set_proxy(self, g_value_get_object(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +/* + * Public methods + */ + +gboolean +caphe_dbus_invokator_is_inhibited(CapheDbusInvokator *self) +{ + g_return_val_if_fail(CAPHE_IS_DBUS_INVOKATOR(self), FALSE); + + return CAPHE_DBUS_INVOKATOR_GET_CLASS(self)->is_inhibited(self); +} + +void +caphe_dbus_invokator_uninhibit(CapheDbusInvokator *self) +{ + g_return_if_fail(CAPHE_IS_DBUS_INVOKATOR(self)); + + return CAPHE_DBUS_INVOKATOR_GET_CLASS(self)->uninhibit(self); +} + +gboolean +caphe_dbus_invokator_inhibit(CapheDbusInvokator *self, const gchar *application, + const gchar *reason, GError **error) +{ + g_return_val_if_fail(CAPHE_IS_DBUS_INVOKATOR(self), FALSE); + + return CAPHE_DBUS_INVOKATOR_GET_CLASS(self)->inhibit(self, application, reason, error); +} + +CapheDbusInvokator * +caphe_dbus_invokator_new(GType invokator_type, GDBusProxy *proxy) +{ + g_return_val_if_fail(g_type_is_a(invokator_type, CAPHE_TYPE_DBUS_INVOKATOR), NULL); + + return g_object_new(invokator_type, "proxy", proxy, NULL); +} + +/* + * GObject methods + */ + +static void +caphe_dbus_invokator_finalize(GObject *object) +{ + CapheDbusInvokator *self = CAPHE_DBUS_INVOKATOR(object); + CapheDbusInvokatorPrivate *priv = caphe_dbus_invokator_get_instance_private(self); + + TRACE("%p", self); + + /* Free resources */ + g_object_unref(priv->proxy); + + /* Chain up */ + if (G_OBJECT_CLASS(caphe_dbus_invokator_parent_class)->finalize) + G_OBJECT_CLASS(caphe_dbus_invokator_parent_class)->finalize(object); +} + +static void +caphe_dbus_invokator_init(CapheDbusInvokator *self) +{ + CapheDbusInvokatorPrivate *priv = caphe_dbus_invokator_get_instance_private(self); + + TRACE("%p", self); + + /* Construct-only properties, initialized later on */ + priv->proxy = NULL; +} + +static void +caphe_dbus_invokator_class_init(CapheDbusInvokatorClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + + TRACE("%p", class); + + /* Override GObject methods */ + object_class->finalize = caphe_dbus_invokator_finalize; + + /* Install properties */ + object_class->get_property = caphe_dbus_invokator_get_property; + object_class->set_property = caphe_dbus_invokator_set_property; + + properties[PROP_PROXY] = + g_param_spec_object("proxy", "Proxy", NULL, + G_TYPE_DBUS_PROXY, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties(object_class, LAST_PROP, properties); +} diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-dbus-invokator.h goodvibes-0.4.2/src/libcaphe/caphe-dbus-invokator.h --- goodvibes-0.3.6/src/libcaphe/caphe-dbus-invokator.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-dbus-invokator.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __LIBCAPHE_CAPHE_DBUS_INVOKATOR_H__ +#define __LIBCAPHE_CAPHE_DBUS_INVOKATOR_H__ + +#include +#include + +/* GObject declarations */ + +#define CAPHE_TYPE_DBUS_INVOKATOR caphe_dbus_invokator_get_type() + +G_DECLARE_DERIVABLE_TYPE(CapheDbusInvokator, caphe_dbus_invokator, CAPHE, DBUS_INVOKATOR, GObject) + +struct _CapheDbusInvokatorClass { + /* Parent class */ + GObjectClass parent_class; + + /* Virtual Methods */ + gboolean (*inhibit) (CapheDbusInvokator *self, + const gchar *application, + const gchar *reason, + GError **error); + void (*uninhibit) (CapheDbusInvokator *self); + gboolean (*is_inhibited)(CapheDbusInvokator *self); +}; + +/* Methods */ + +CapheDbusInvokator *caphe_dbus_invokator_new(GType invokator_type, GDBusProxy *proxy); + +gboolean caphe_dbus_invokator_inhibit (CapheDbusInvokator *self, + const gchar *application, + const gchar *reason, + GError **error); +void caphe_dbus_invokator_uninhibit (CapheDbusInvokator *self); +gboolean caphe_dbus_invokator_is_inhibited(CapheDbusInvokator *self); + +/* Public property accessors */ + +GDBusProxy *caphe_dbus_invokator_get_proxy (CapheDbusInvokator *self); + +#endif /* __LIBCAPHE_CAPHE_DBUS_INVOKATOR_H__ */ diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-dbus-proxy.c goodvibes-0.4.2/src/libcaphe/caphe-dbus-proxy.c --- goodvibes-0.3.6/src/libcaphe/caphe-dbus-proxy.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-dbus-proxy.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,385 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include +#include + +#include "caphe-trace.h" +#include "caphe-dbus-proxy.h" + +#define debug(self, fmt, ...) \ + g_debug("[%s]: " fmt, strrchr(self->priv->well_known_name, '.') + 1, ##__VA_ARGS__) + +#define warning(self, fmt, ...) \ + g_warning("[%s]: " fmt, strrchr(self->priv->well_known_name, '.') + 1, ##__VA_ARGS__) + +/* + * Properties + */ + +enum { + /* Reserved */ + PROP_0, + /* Construct-only properties */ + PROP_BUS_TYPE, + PROP_WELL_KNOWN_NAME, + PROP_OBJECT_PATH, + PROP_INTERFACE_NAME, + /* Readable properties */ + PROP_PROXY, + /* Total number of properties */ + LAST_PROP +}; + +static GParamSpec *properties[LAST_PROP]; + +/* + * GObject definitions + */ + +struct _CapheDbusProxyPrivate { + /* Properties */ + GBusType bus_type; + gchar *well_known_name; + gchar *object_path; + gchar *interface_name; + /* Internal */ + guint watch_id; + GDBusProxy *proxy; +}; + +typedef struct _CapheDbusProxyPrivate CapheDbusProxyPrivate; + +struct _CapheDbusProxy { + /* Parent instance structure */ + GObject parent_instance; + /* Private data */ + CapheDbusProxyPrivate *priv; +}; + +G_DEFINE_TYPE_WITH_PRIVATE(CapheDbusProxy, caphe_dbus_proxy, G_TYPE_OBJECT) + +/* + * Property setters + */ + +static void +caphe_dbus_proxy_set_proxy(CapheDbusProxy *self, GDBusProxy *proxy) +{ + CapheDbusProxyPrivate *priv = self->priv; + + g_set_object(&priv->proxy, proxy); + g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_PROXY]); +} + +/* + * Callbacks + */ + +static void +on_proxy_created(GDBusConnection *connection G_GNUC_UNUSED, + GAsyncResult *result, + CapheDbusProxy *self) +{ + GDBusProxy *proxy; + GError *error = NULL; + + debug(self, "Proxy created"); + + proxy = g_dbus_proxy_new_finish(result, &error); + if (error) { + warning(self, "%s", error->message); + g_error_free(error); + } + + caphe_dbus_proxy_set_proxy(self, proxy); +} + +static void +on_name_vanished(GDBusConnection *connection G_GNUC_UNUSED, + const gchar *name, + CapheDbusProxy *self) +{ + debug(self, "Name '%s' vanished", name); + + caphe_dbus_proxy_set_proxy(self, NULL); +} + +static void +on_name_appeared(GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + CapheDbusProxy *self) +{ + CapheDbusProxyPrivate *priv = self->priv; + + debug(self, "Name '%s' appeared (owner %s)", name, name_owner); + + g_dbus_proxy_new(connection, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + priv->well_known_name, + priv->object_path, + priv->interface_name, + NULL, + (GAsyncReadyCallback) on_proxy_created, + self); +} + +/* + * Property accessors + */ + +GDBusProxy * +caphe_dbus_proxy_get_proxy(CapheDbusProxy *self) +{ + CapheDbusProxyPrivate *priv = self->priv; + + return priv->proxy; +} + +static void +caphe_dbus_proxy_set_bus_type(CapheDbusProxy *self, GBusType bus_type) +{ + CapheDbusProxyPrivate *priv = self->priv; + + /* Construct-only property */ + g_assert(priv->bus_type == G_BUS_TYPE_NONE); + g_assert(bus_type != G_BUS_TYPE_NONE); + + priv->bus_type = bus_type; +} + +static void +caphe_dbus_proxy_set_well_known_name(CapheDbusProxy *self, const gchar *name) +{ + CapheDbusProxyPrivate *priv = self->priv; + + /* Construct-only property */ + g_assert_null(priv->well_known_name); + g_assert_nonnull(name); + + priv->well_known_name = g_strdup(name); +} + +static void +caphe_dbus_proxy_set_object_path(CapheDbusProxy *self, const gchar *object_path) +{ + CapheDbusProxyPrivate *priv = self->priv; + + /* Construct-only property */ + g_assert_null(priv->object_path); + g_assert_nonnull(object_path); + + priv->object_path = g_strdup(object_path); +} + +static void +caphe_dbus_proxy_set_interface_name(CapheDbusProxy *self, const gchar *interface_name) +{ + CapheDbusProxyPrivate *priv = self->priv; + + /* Construct-only property */ + g_assert_null(priv->interface_name); + g_assert_nonnull(interface_name); + + priv->interface_name = g_strdup(interface_name); +} + +static void +caphe_dbus_proxy_get_property(GObject *object, + guint property_id, + GValue *value G_GNUC_UNUSED, + GParamSpec *pspec) +{ + CapheDbusProxy *self = CAPHE_DBUS_PROXY(object); + + switch (property_id) { + case PROP_PROXY: + g_value_set_object(value, caphe_dbus_proxy_get_proxy(self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +caphe_dbus_proxy_set_property(GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + CapheDbusProxy *self = CAPHE_DBUS_PROXY(object); + + switch (property_id) { + case PROP_BUS_TYPE: + caphe_dbus_proxy_set_bus_type(self, g_value_get_enum(value)); + break; + case PROP_WELL_KNOWN_NAME: + caphe_dbus_proxy_set_well_known_name(self, g_value_get_string(value)); + break; + case PROP_OBJECT_PATH: + caphe_dbus_proxy_set_object_path(self, g_value_get_string(value)); + break; + case PROP_INTERFACE_NAME: + caphe_dbus_proxy_set_interface_name(self, g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +/* + * Public methods + */ + +CapheDbusProxy * +caphe_dbus_proxy_new(GBusType bus_type, const gchar *well_known_name, + const gchar *object_path, const gchar *interface_name) +{ + return g_object_new(CAPHE_TYPE_DBUS_PROXY, + "bus-type", bus_type, + "well-known-name", well_known_name, + "object-path", object_path, + "interface-name", interface_name, + NULL); +} + +/* + * GObject methods + */ + +static void +caphe_dbus_proxy_finalize(GObject *object) +{ + CapheDbusProxy *self = CAPHE_DBUS_PROXY(object); + CapheDbusProxyPrivate *priv = self->priv; + + TRACE("%p", object); + + if (priv->watch_id) + g_bus_unwatch_name(priv->watch_id); + + if (priv->proxy) + g_object_unref(priv->proxy); + + g_free(priv->well_known_name); + g_free(priv->object_path); + g_free(priv->interface_name); + + /* Chain up */ + if (G_OBJECT_CLASS(caphe_dbus_proxy_parent_class)->finalize) + G_OBJECT_CLASS(caphe_dbus_proxy_parent_class)->finalize(object); +} + +static void +caphe_dbus_proxy_constructed(GObject *object) +{ + CapheDbusProxy *self = CAPHE_DBUS_PROXY(object); + CapheDbusProxyPrivate *priv = self->priv; + + TRACE("%p", object); + + debug(self, "Starting to watch '%s'", priv->well_known_name); + + priv->watch_id = g_bus_watch_name(priv->bus_type, + priv->well_known_name, + G_BUS_NAME_WATCHER_FLAGS_NONE, + (GBusNameAppearedCallback) on_name_appeared, + (GBusNameVanishedCallback) on_name_vanished, + self, + NULL); + + /* Chain up */ + if (G_OBJECT_CLASS(caphe_dbus_proxy_parent_class)->constructed) + G_OBJECT_CLASS(caphe_dbus_proxy_parent_class)->constructed(object); +} + +static void +caphe_dbus_proxy_init(CapheDbusProxy *self) +{ + CapheDbusProxyPrivate *priv = caphe_dbus_proxy_get_instance_private(self); + + TRACE("%p", self); + + /* Construct-only properties, initialized later on */ + priv->bus_type = G_BUS_TYPE_NONE; + priv->well_known_name = NULL; + priv->object_path = NULL; + priv->interface_name = NULL; + + /* Save private pointer */ + self->priv = priv; +} + +static void +caphe_dbus_proxy_class_init(CapheDbusProxyClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + + TRACE("%p", class); + + /* Override GObject methods */ + object_class->finalize = caphe_dbus_proxy_finalize; + object_class->constructed = caphe_dbus_proxy_constructed; + + /* Install properties */ + object_class->get_property = caphe_dbus_proxy_get_property; + object_class->set_property = caphe_dbus_proxy_set_property; + + properties[PROP_BUS_TYPE] = + g_param_spec_enum("bus-type", "Bus type", NULL, + G_TYPE_BUS_TYPE, G_BUS_TYPE_NONE, + G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY); + + properties[PROP_WELL_KNOWN_NAME] = + g_param_spec_string("well-known-name", "Well-known bus name", NULL, + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY); + + properties[PROP_OBJECT_PATH] = + g_param_spec_string("object-path", "Object path", NULL, + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY); + + properties[PROP_INTERFACE_NAME] = + g_param_spec_string("interface-name", "Interface name", NULL, + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY); + + properties[PROP_PROXY] = + g_param_spec_object("proxy", "Proxy", NULL, + G_TYPE_DBUS_PROXY, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); + + g_object_class_install_properties(object_class, LAST_PROP, properties); +} diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-dbus-proxy.h goodvibes-0.4.2/src/libcaphe/caphe-dbus-proxy.h --- goodvibes-0.3.6/src/libcaphe/caphe-dbus-proxy.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-dbus-proxy.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,43 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __LIBCAPHE_CAPHE_DBUS_PROXY_H__ +#define __LIBCAPHE_CAPHE_DBUS_PROXY_H__ + +#include +#include + +/* GObject declarations */ + +#define CAPHE_TYPE_DBUS_PROXY caphe_dbus_proxy_get_type() + +G_DECLARE_FINAL_TYPE(CapheDbusProxy, caphe_dbus_proxy, CAPHE, DBUS_PROXY, GObject) + +/* Public methods */ + +CapheDbusProxy *caphe_dbus_proxy_new(GBusType bus_type, const gchar *well_known_name, + const gchar *object_path, const gchar *interface_name); + +/* Property accessors */ + +GDBusProxy *caphe_dbus_proxy_get_proxy(CapheDbusProxy *self); + +#endif /* __LIBCAPHE_CAPHE_DBUS_PROXY_H__ */ diff -Nru goodvibes-0.3.6/src/libcaphe/caphe.h goodvibes-0.4.2/src/libcaphe/caphe.h --- goodvibes-0.3.6/src/libcaphe/caphe.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __LIBCAPHE_CAPHE_H__ +#define __LIBCAPHE_CAPHE_H__ + +#include "libcaphe/caphe-cup.h" + +void caphe_init (void); +void caphe_cleanup(void); + +#endif /* __LIBCAPHE_CAPHE_H__ */ diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-inhibitor.c goodvibes-0.4.2/src/libcaphe/caphe-inhibitor.c --- goodvibes-0.3.6/src/libcaphe/caphe-inhibitor.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-inhibitor.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,99 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "caphe-trace.h" +#include "caphe-inhibitor.h" + +/* + * GObject definitions + */ + +G_DEFINE_INTERFACE(CapheInhibitor, caphe_inhibitor, G_TYPE_OBJECT) + +/* + * Methods + */ + +gboolean +caphe_inhibitor_is_inhibited(CapheInhibitor *self) +{ + g_return_val_if_fail(CAPHE_IS_INHIBITOR(self), FALSE); + + return CAPHE_INHIBITOR_GET_IFACE(self)->is_inhibited(self); +} + +void +caphe_inhibitor_uninhibit(CapheInhibitor *self) +{ + g_return_if_fail(CAPHE_IS_INHIBITOR(self)); + + return CAPHE_INHIBITOR_GET_IFACE(self)->uninhibit(self); +} + +gboolean +caphe_inhibitor_inhibit(CapheInhibitor *self, const gchar *application, + const gchar *reason, GError **error) +{ + g_return_val_if_fail(CAPHE_IS_INHIBITOR(self), FALSE); + + return CAPHE_INHIBITOR_GET_IFACE(self)->inhibit(self, application, reason, error); +} + +/* + * Property accessors + */ + +const gchar * +caphe_inhibitor_get_name(CapheInhibitor *self) +{ + g_return_val_if_fail(CAPHE_IS_INHIBITOR(self), FALSE); + + return CAPHE_INHIBITOR_GET_IFACE(self)->get_name(self); +} + +gboolean +caphe_inhibitor_get_available(CapheInhibitor *self) +{ + g_return_val_if_fail(CAPHE_IS_INHIBITOR(self), FALSE); + + return CAPHE_INHIBITOR_GET_IFACE(self)->get_available(self); +} + +/* + * GObject methods + */ + +static void +caphe_inhibitor_default_init(CapheInhibitorInterface *iface) +{ + TRACE("%p", iface); + + g_object_interface_install_property + (iface, g_param_spec_string("name", "Name", NULL, NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_interface_install_property + (iface, g_param_spec_boolean("available", "Available", NULL, FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); +} diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-inhibitor.h goodvibes-0.4.2/src/libcaphe/caphe-inhibitor.h --- goodvibes-0.3.6/src/libcaphe/caphe-inhibitor.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-inhibitor.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,64 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __LIBCAPHE_CAPHE_INHIBITOR_H__ +#define __LIBCAPHE_CAPHE_INHIBITOR_H__ + +#include + +/* GObject declarations */ + +#define CAPHE_TYPE_INHIBITOR caphe_inhibitor_get_type() + +G_DECLARE_INTERFACE(CapheInhibitor, caphe_inhibitor, CAPHE, INHIBITOR, GObject) + +struct _CapheInhibitorInterface { + /* Parent class */ + GTypeInterface parent_iface; + + /* Virtual Methods */ + gboolean (*inhibit) (CapheInhibitor *self, + const gchar *application, + const gchar *reason, + GError **error); + void (*uninhibit) (CapheInhibitor *self); + gboolean (*is_inhibited)(CapheInhibitor *self); + + /* Virtual property accessors */ + const gchar *(*get_name) (CapheInhibitor *self); + gboolean (*get_available)(CapheInhibitor *self); +}; + +/* Methods */ + +gboolean caphe_inhibitor_inhibit (CapheInhibitor *self, + const gchar *application, + const gchar *reason, + GError **error); +void caphe_inhibitor_uninhibit (CapheInhibitor *self); +gboolean caphe_inhibitor_is_inhibited(CapheInhibitor *self); + +/* Property accessors */ + +const gchar *caphe_inhibitor_get_name (CapheInhibitor *self); +gboolean caphe_inhibitor_get_available(CapheInhibitor *self); + +#endif /* __LIBCAPHE_CAPHE_INHIBITOR_H__ */ diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-inhibitor-list.c goodvibes-0.4.2/src/libcaphe/caphe-inhibitor-list.c --- goodvibes-0.3.6/src/libcaphe/caphe-inhibitor-list.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-inhibitor-list.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,254 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include + +#include "caphe-trace.h" +#include "caphe-inhibitor.h" +#include "caphe-dbus-inhibitor.h" + +#include "caphe-inhibitor-list.h" + +/* Inhibitors we know of. This list is ordered by priority. */ + +enum { + CAPHE_GNOME_SESSION_MANAGER_IDX, + CAPHE_XFCE_SESSION_MANAGER_IDX, + CAPHE_XDG_PORTAL_IDX, + CAPHE_XDG_POWER_MANAGEMENT_IDX, + CAPHE_XDG_LOGIN1_IDX, + CAPHE_N_INHIBITORS, +}; + +static const gchar *caphe_inhibitor_ids[] = { + "gnome-session-manager", + "xfce-session-manager", + "xdg-portal", + "xdg-power-management", + "xdg-login1", + NULL +}; + +/* + * Signals + */ + +enum { + SIGNAL_READY, + /* Number of signals */ + SIGNAL_N +}; + +static guint signals[SIGNAL_N]; + +/* + * GObject definitions + */ + +struct _CapheInhibitorListPrivate { + /* List of inhibitors */ + CapheInhibitor *inhibitors[CAPHE_N_INHIBITORS]; + + /* For init-time */ + gboolean inhibitors_ready[CAPHE_N_INHIBITORS]; + gboolean ready; +}; + +typedef struct _CapheInhibitorListPrivate CapheInhibitorListPrivate; + +struct _CapheInhibitorList { + /* Parent instance structure */ + GObject parent_instance; + /* Private data */ + CapheInhibitorListPrivate *priv; +}; + +G_DEFINE_TYPE_WITH_PRIVATE(CapheInhibitorList, caphe_inhibitor_list, G_TYPE_OBJECT) + +/* + * Helpers + */ + +static gint +get_inhibitor_index(CapheInhibitor *inhibitors[], CapheInhibitor *inhibitor) +{ + gint i; + + for (i = 0; i < CAPHE_N_INHIBITORS; i++) { + if (inhibitors[i] == inhibitor) + return i; + } + + return -1; +} + +const gchar * +get_inhibitor_id(CapheInhibitor *inhibitors[], CapheInhibitor *inhibitor) +{ + gint i; + + for (i = 0; i < CAPHE_N_INHIBITORS; i++) { + if (inhibitors[i] == inhibitor) + return caphe_inhibitor_ids[i]; + } + + return "unknown"; +} + +/* + * Signal handlers + */ + +static void +on_inhibitor_notify_available(CapheInhibitor *inhibitor, + GParamSpec *pspec G_GNUC_UNUSED, + CapheInhibitorList *self) +{ + CapheInhibitorListPrivate *priv = self->priv; + gboolean available = caphe_inhibitor_get_available(inhibitor); + + /* Log */ + g_debug("Inhibitor '%s' availability changed: %s", + get_inhibitor_id(priv->inhibitors, inhibitor), + available ? "true" : "false"); + + /* We watch this signals only to know when all the inhibitors are ready */ + if (priv->ready == TRUE) + return; + + gint index; + + /* Update ready list */ + index = get_inhibitor_index(priv->inhibitors, inhibitor); + priv->inhibitors_ready[index] = TRUE; + + /* Check if every inhibitors are ready */ + for (index = 0; index < CAPHE_N_INHIBITORS; index++) { + if (priv->inhibitors_ready[index] == FALSE) + return; + } + + /* We're ready */ + g_debug("All inhibitors ready"); + priv->ready = TRUE; + + g_signal_emit(self, signals[SIGNAL_READY], 0); +} + +/* + * Public methods + */ + +CapheInhibitor ** +caphe_inhibitor_list_get_inhibitors(CapheInhibitorList *self) +{ + CapheInhibitorListPrivate *priv = self->priv; + + return priv->inhibitors; +} + +CapheInhibitorList * +caphe_inhibitor_list_new(void) +{ + return g_object_new(CAPHE_TYPE_INHIBITOR_LIST, NULL); +} + +/* + * GObject methods + */ + +static void +caphe_inhibitor_list_finalize(GObject *object) +{ + CapheInhibitorList *self = CAPHE_INHIBITOR_LIST(object); + CapheInhibitorListPrivate *priv = self->priv; + guint i; + + TRACE("%p", self); + + /* Disconnect and unref inhibitors */ + for (i = 0; i < CAPHE_N_INHIBITORS; i++) { + g_signal_handlers_disconnect_by_data(priv->inhibitors[i], self); + g_object_unref(priv->inhibitors[i]); + } + + /* Chain up */ + if (G_OBJECT_CLASS(caphe_inhibitor_list_parent_class)->finalize) + G_OBJECT_CLASS(caphe_inhibitor_list_parent_class)->finalize(object); +} + +static void +caphe_inhibitor_list_constructed(GObject *object) +{ + CapheInhibitorList *self = CAPHE_INHIBITOR_LIST(object); + CapheInhibitorListPrivate *priv = self->priv; + guint i; + + TRACE("%p", self); + + /* Create inhibitors */ + for (i = 0; i < CAPHE_N_INHIBITORS; i++) { + priv->inhibitors[i] = caphe_dbus_inhibitor_new(caphe_inhibitor_ids[i]); + + g_signal_connect_object(priv->inhibitors[i], "notify::available", + G_CALLBACK(on_inhibitor_notify_available), + self, 0); + } + + /* Chain up */ + if (G_OBJECT_CLASS(caphe_inhibitor_list_parent_class)->constructed) + G_OBJECT_CLASS(caphe_inhibitor_list_parent_class)->constructed(object); +} + +static void +caphe_inhibitor_list_init(CapheInhibitorList *self) +{ + CapheInhibitorListPrivate *priv = caphe_inhibitor_list_get_instance_private(self); + + TRACE("%p", self); + + /* Init some stuff */ + priv->ready = FALSE; + + /* Set private pointer */ + self->priv = priv; +} + +static void +caphe_inhibitor_list_class_init(CapheInhibitorListClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + + TRACE("%p", class); + + /* Override GObject methods */ + object_class->finalize = caphe_inhibitor_list_finalize; + object_class->constructed = caphe_inhibitor_list_constructed; + + /* Signals */ + signals[SIGNAL_READY] = + g_signal_new("ready", G_TYPE_FROM_CLASS(class), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); +} diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-inhibitor-list.h goodvibes-0.4.2/src/libcaphe/caphe-inhibitor-list.h --- goodvibes-0.3.6/src/libcaphe/caphe-inhibitor-list.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-inhibitor-list.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __LIBCAPHE_CAPHE_INHIBITOR_LIST_H__ +#define __LIBCAPHE_CAPHE_INHIBITOR_LIST_H__ + +#include + +#include "caphe-inhibitor.h" + +/* GObject declarations */ + +#define CAPHE_TYPE_INHIBITOR_LIST caphe_inhibitor_list_get_type() + +G_DECLARE_FINAL_TYPE(CapheInhibitorList, caphe_inhibitor_list, CAPHE, INHIBITOR_LIST, GObject) + +/* Methods */ + +CapheInhibitorList *caphe_inhibitor_list_new (void); +CapheInhibitor **caphe_inhibitor_list_get_inhibitors(CapheInhibitorList *self); + +#endif /* __LIBCAPHE_CAPHE_INHIBITOR_LIST_H__ */ diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-login-dbus-invokator.c goodvibes-0.4.2/src/libcaphe/caphe-login-dbus-invokator.c --- goodvibes-0.3.6/src/libcaphe/caphe-login-dbus-invokator.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-login-dbus-invokator.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,195 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include +#include + +#include "caphe-trace.h" +#include "caphe-dbus-invokator.h" +#include "caphe-login-dbus-invokator.h" + +/* + * Debug macros + */ + +#define debug(proxy, fmt, ...) \ + g_debug("[%s]: " fmt, \ + proxy ? g_dbus_proxy_get_name(proxy) : "SessionManager", \ + ##__VA_ARGS__) + +/* + * GObject definitions + */ + +struct _CapheLoginDbusInvokatorPrivate { + gint32 fd; +}; + +typedef struct _CapheLoginDbusInvokatorPrivate CapheLoginDbusInvokatorPrivate; + +struct _CapheLoginDbusInvokator { + /* Parent instance structure */ + CapheDbusInvokator parent_instance; + /* Private data */ + CapheLoginDbusInvokatorPrivate *priv; +}; + +G_DEFINE_TYPE_WITH_PRIVATE(CapheLoginDbusInvokator, caphe_login_dbus_invokator, + CAPHE_TYPE_DBUS_INVOKATOR) + +/* + * DbusInvokator methods + */ + +static gboolean +caphe_login_dbus_invokator_is_inhibited(CapheDbusInvokator *dbus_invokator) +{ + CapheLoginDbusInvokator *self = CAPHE_LOGIN_DBUS_INVOKATOR(dbus_invokator); + CapheLoginDbusInvokatorPrivate *priv = self->priv; + + return priv->fd != -1; +} + +static void +caphe_login_dbus_invokator_uninhibit(CapheDbusInvokator *dbus_invokator) +{ + CapheLoginDbusInvokator *self = CAPHE_LOGIN_DBUS_INVOKATOR(dbus_invokator); + CapheLoginDbusInvokatorPrivate *priv = self->priv; + GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); + + if (priv->fd < 0) { + debug(proxy, "Already uninhibited (no fd)"); + return; + } + + close(priv->fd); + priv->fd = -1; + + debug(proxy, "Uninhibited"); +} + +static gboolean +caphe_login_dbus_invokator_inhibit(CapheDbusInvokator *dbus_invokator, + const gchar *application, const gchar *reason, + GError **error) +{ + CapheLoginDbusInvokator *self = CAPHE_LOGIN_DBUS_INVOKATOR(dbus_invokator); + CapheLoginDbusInvokatorPrivate *priv = self->priv; + GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); + GUnixFDList *fd_list = NULL; + gint32 fd_index; + GVariant *res; + + if (priv->fd >= 0) { + debug(proxy, "Already inhibited (fd: %d)", priv->fd); + return TRUE; + } + + if (proxy == NULL) { + debug(proxy, "No proxy"); + return FALSE; + } + + /* + * Documentation at: + * https://www.freedesktop.org/wiki/Software/systemd/inhibit/ + */ + res = g_dbus_proxy_call_with_unix_fd_list_sync(proxy, + "Inhibit", + g_variant_new( + "(ssss)", + "sleep", + application, + reason, + "block"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, /* in_fd_list */ + &fd_list, /* out_fd_list */ + NULL, /* cancellable */ + error); + + if (res == NULL) + return FALSE; + + g_variant_get(res, "(h)", &fd_index); + g_variant_unref(res); + debug(proxy, "Fd index: %d", fd_index); + + priv->fd = g_unix_fd_list_get(fd_list, fd_index, NULL); + g_object_unref(fd_list); + debug(proxy, "Inhibited (fd: %d)", priv->fd); + + return TRUE; +} + +/* + * GObject methods + */ + +static void +caphe_login_dbus_invokator_finalize(GObject *object) +{ + CapheDbusInvokator *dbus_invokator = CAPHE_DBUS_INVOKATOR(object); + + TRACE("%p", object); + + /* Ensure uninhibition */ + caphe_login_dbus_invokator_uninhibit(dbus_invokator); + + if (G_OBJECT_CLASS(caphe_login_dbus_invokator_parent_class)->finalize) + G_OBJECT_CLASS(caphe_login_dbus_invokator_parent_class)->finalize(object); +} + +static void +caphe_login_dbus_invokator_init(CapheLoginDbusInvokator *self) +{ + CapheLoginDbusInvokatorPrivate *priv = + caphe_login_dbus_invokator_get_instance_private(self); + + TRACE("%p", self); + + /* Initialize inhibit file descriptor */ + priv->fd = -1; + + /* Initialize private pointer */ + self->priv = priv; +} + +static void +caphe_login_dbus_invokator_class_init(CapheLoginDbusInvokatorClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + CapheDbusInvokatorClass *dbus_invokator_class = CAPHE_DBUS_INVOKATOR_CLASS(class); + + TRACE("%p", class); + + /* GObject methods */ + object_class->finalize = caphe_login_dbus_invokator_finalize; + + /* Implement methods */ + dbus_invokator_class->inhibit = caphe_login_dbus_invokator_inhibit; + dbus_invokator_class->uninhibit = caphe_login_dbus_invokator_uninhibit; + dbus_invokator_class->is_inhibited = caphe_login_dbus_invokator_is_inhibited; +} diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-login-dbus-invokator.h goodvibes-0.4.2/src/libcaphe/caphe-login-dbus-invokator.h --- goodvibes-0.3.6/src/libcaphe/caphe-login-dbus-invokator.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-login-dbus-invokator.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __LIBCAPHE_CAPHE_LOGIN_DBUS_INVOKATOR_H__ +#define __LIBCAPHE_CAPHE_LOGIN_DBUS_INVOKATOR_H__ + +#include + +#include "caphe-dbus-invokator.h" + +/* GObject declarations */ + +#define CAPHE_TYPE_LOGIN_DBUS_INVOKATOR caphe_login_dbus_invokator_get_type() + +G_DECLARE_FINAL_TYPE(CapheLoginDbusInvokator, caphe_login_dbus_invokator, + CAPHE, LOGIN_DBUS_INVOKATOR, CapheDbusInvokator) + +/* Methods */ + +CapheDbusInvokator *caphe_login_dbus_invokator_new(void); + +#endif /* __LIBCAPHE_CAPHE_LOGIN_DBUS_INVOKATOR_H__ */ diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-portal-dbus-invokator.c goodvibes-0.4.2/src/libcaphe/caphe-portal-dbus-invokator.c --- goodvibes-0.3.6/src/libcaphe/caphe-portal-dbus-invokator.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-portal-dbus-invokator.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,198 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include + +#include "caphe-trace.h" +#include "caphe-dbus-invokator.h" +#include "caphe-portal-dbus-invokator.h" + +/* + * Debug macros + */ + +#define debug(proxy, fmt, ...) \ + g_debug("[%s]: " fmt, \ + proxy ? g_dbus_proxy_get_name(proxy) : "Portal", \ + ##__VA_ARGS__) + +/* + * GObject definitions + */ + +struct _CaphePortalDbusInvokatorPrivate { + char *handle; +}; + +typedef struct _CaphePortalDbusInvokatorPrivate CaphePortalDbusInvokatorPrivate; + +struct _CaphePortalDbusInvokator { + /* Parent instance structure */ + CapheDbusInvokator parent_instance; + /* Private data */ + CaphePortalDbusInvokatorPrivate *priv; +}; + +G_DEFINE_TYPE_WITH_PRIVATE(CaphePortalDbusInvokator, caphe_portal_dbus_invokator, + CAPHE_TYPE_DBUS_INVOKATOR) + +/* + * DbusInvokator methods + */ + +static gboolean +caphe_portal_dbus_invokator_is_inhibited(CapheDbusInvokator *dbus_invokator) +{ + CaphePortalDbusInvokator *self = CAPHE_PORTAL_DBUS_INVOKATOR(dbus_invokator); + CaphePortalDbusInvokatorPrivate *priv = self->priv; + + return priv->handle != NULL; +} + +static void +caphe_portal_dbus_invokator_uninhibit(CapheDbusInvokator *dbus_invokator) +{ + CaphePortalDbusInvokator *self = CAPHE_PORTAL_DBUS_INVOKATOR(dbus_invokator); + CaphePortalDbusInvokatorPrivate *priv = self->priv; + GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); + + if (priv->handle == NULL) { + debug(proxy, "Not inhibited (no handle)"); + return; + } + + if (proxy == NULL) { + debug(proxy, "No proxy"); + return; + } + + g_dbus_connection_call(g_dbus_proxy_get_connection(proxy), + "org.freedesktop.portal.Desktop", + priv->handle, + "org.freedesktop.portal.Request", + "Close", + g_variant_new("()"), + G_VARIANT_TYPE_UNIT, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, NULL, NULL); + + g_free(priv->handle); + priv->handle = NULL; + + debug(proxy, "Uninhibited"); +} + +static gboolean +caphe_portal_dbus_invokator_inhibit(CapheDbusInvokator *dbus_invokator, + const gchar *application G_GNUC_UNUSED, + const gchar *reason, GError **error) +{ + CaphePortalDbusInvokator *self = CAPHE_PORTAL_DBUS_INVOKATOR(dbus_invokator); + CaphePortalDbusInvokatorPrivate *priv = self->priv; + GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); + GVariant *res; + + if (priv->handle) { + debug(proxy, "Already inhibited (handle: %s)", priv->handle); + return TRUE; + } + + if (proxy == NULL) { + debug(proxy, "No proxy"); + return FALSE; + } + + GVariantBuilder options; + g_variant_builder_init(&options, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&options, "{sv}", "reason", g_variant_new_string(reason)); + res = g_dbus_proxy_call_sync(proxy, + "Inhibit", + g_variant_new("(su@a{sv})", + "", /* window */ + 4, + g_variant_builder_end(&options)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + error); + + if (res == NULL) + return FALSE; + + g_variant_get(res, "(o)", &priv->handle); + g_variant_unref(res); + + debug(proxy, "Inhibited (handle: %s)", priv->handle); + + return TRUE; +} + +/* + * GObject methods + */ + +static void +caphe_portal_dbus_invokator_finalize(GObject *object) +{ + CapheDbusInvokator *dbus_invokator = CAPHE_DBUS_INVOKATOR(object); + + TRACE("%p", object); + + /* Ensure uninhibition */ + caphe_portal_dbus_invokator_uninhibit(dbus_invokator); + + /* Chain up */ + if (G_OBJECT_CLASS(caphe_portal_dbus_invokator_parent_class)->finalize) + G_OBJECT_CLASS(caphe_portal_dbus_invokator_parent_class)->finalize(object); +} + +static void +caphe_portal_dbus_invokator_init(CaphePortalDbusInvokator *self) +{ + CaphePortalDbusInvokatorPrivate *priv = + caphe_portal_dbus_invokator_get_instance_private(self); + + TRACE("%p", self); + + /* Initialize private pointer */ + self->priv = priv; +} + +static void +caphe_portal_dbus_invokator_class_init(CaphePortalDbusInvokatorClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + CapheDbusInvokatorClass *dbus_invokator_class = CAPHE_DBUS_INVOKATOR_CLASS(class); + + TRACE("%p", class); + + /* GObject methods */ + object_class->finalize = caphe_portal_dbus_invokator_finalize; + + /* Implement methods */ + dbus_invokator_class->inhibit = caphe_portal_dbus_invokator_inhibit; + dbus_invokator_class->uninhibit = caphe_portal_dbus_invokator_uninhibit; + dbus_invokator_class->is_inhibited = caphe_portal_dbus_invokator_is_inhibited; +} diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-portal-dbus-invokator.h goodvibes-0.4.2/src/libcaphe/caphe-portal-dbus-invokator.h --- goodvibes-0.3.6/src/libcaphe/caphe-portal-dbus-invokator.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-portal-dbus-invokator.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __LIBCAPHE_CAPHE_PORTAL_DBUS_INVOKATOR_H__ +#define __LIBCAPHE_CAPHE_PORTAL_DBUS_INVOKATOR_H__ + +#include + +#include "caphe-dbus-invokator.h" + +/* GObject declarations */ + +#define CAPHE_TYPE_PORTAL_DBUS_INVOKATOR caphe_portal_dbus_invokator_get_type() + +G_DECLARE_FINAL_TYPE(CaphePortalDbusInvokator, caphe_portal_dbus_invokator, + CAPHE, PORTAL_DBUS_INVOKATOR, CapheDbusInvokator) + +/* Methods */ + +CapheDbusInvokator *caphe_portal_dbus_invokator_new(void); + +#endif /* __LIBCAPHE_CAPHE_PORTAL_DBUS_INVOKATOR_H__ */ diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-power-dbus-invokator.c goodvibes-0.4.2/src/libcaphe/caphe-power-dbus-invokator.c --- goodvibes-0.3.6/src/libcaphe/caphe-power-dbus-invokator.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-power-dbus-invokator.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,191 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include + +#include "caphe-trace.h" +#include "caphe-dbus-invokator.h" +#include "caphe-power-dbus-invokator.h" + +/* + * Debug macros + */ + + +#define debug(proxy, fmt, ...) \ + g_debug("[%s]: " fmt, \ + proxy ? g_dbus_proxy_get_name(proxy) : "PowerManagement", \ + ##__VA_ARGS__) + +/* + * GObject definitions + */ + +struct _CaphePowerDbusInvokatorPrivate { + guint32 cookie; +}; + +typedef struct _CaphePowerDbusInvokatorPrivate CaphePowerDbusInvokatorPrivate; + +struct _CaphePowerDbusInvokator { + /* Parent instance structure */ + CapheDbusInvokator parent_instance; + /* Private data */ + CaphePowerDbusInvokatorPrivate *priv; +}; + +G_DEFINE_TYPE_WITH_PRIVATE(CaphePowerDbusInvokator, caphe_power_dbus_invokator, + CAPHE_TYPE_DBUS_INVOKATOR) + +/* + * DbusInvokator methods + */ + +static gboolean +caphe_power_dbus_invokator_is_inhibited(CapheDbusInvokator *dbus_invokator) +{ + CaphePowerDbusInvokator *self = CAPHE_POWER_DBUS_INVOKATOR(dbus_invokator); + CaphePowerDbusInvokatorPrivate *priv = self->priv; + + return priv->cookie != 0; +} + +static void +caphe_power_dbus_invokator_uninhibit(CapheDbusInvokator *dbus_invokator) +{ + CaphePowerDbusInvokator *self = CAPHE_POWER_DBUS_INVOKATOR(dbus_invokator); + CaphePowerDbusInvokatorPrivate *priv = self->priv; + GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); + + if (priv->cookie == 0) { + debug(proxy, "Not inhibited (no cookie)"); + return; + } + + if (proxy == NULL) { + debug(proxy, "No proxy"); + return; + } + + g_dbus_proxy_call(proxy, + "UnInhibit", + g_variant_new("(u)", + priv->cookie), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, NULL, NULL); + + priv->cookie = 0; + + debug(proxy, "Uninhibited"); +} + +static gboolean +caphe_power_dbus_invokator_inhibit(CapheDbusInvokator *dbus_invokator, + const gchar *application, const gchar *reason, + GError **error) +{ + CaphePowerDbusInvokator *self = CAPHE_POWER_DBUS_INVOKATOR(dbus_invokator); + CaphePowerDbusInvokatorPrivate *priv = self->priv; + GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); + GVariant *res; + + if (priv->cookie != 0) { + debug(proxy, "Already inhibited (cookie: %u)", priv->cookie); + return TRUE; + } + + if (proxy == NULL) { + debug(proxy, "No proxy"); + return FALSE; + } + + res = g_dbus_proxy_call_sync(proxy, + "Inhibit", + g_variant_new("(ss)", + application, + reason), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + error); + + if (res == NULL) + return FALSE; + + g_variant_get(res, "(u)", &priv->cookie); + g_variant_unref(res); + + debug(proxy, "Inhibited (cookie: %u)", priv->cookie); + + return TRUE; +} + +/* + * GObject methods + */ + +static void +caphe_power_dbus_invokator_finalize(GObject *object) +{ + CapheDbusInvokator *dbus_invokator = CAPHE_DBUS_INVOKATOR(object); + + TRACE("%p", object); + + /* Ensure uninhibition */ + caphe_power_dbus_invokator_uninhibit(dbus_invokator); + + /* Chain up */ + if (G_OBJECT_CLASS(caphe_power_dbus_invokator_parent_class)->finalize) + G_OBJECT_CLASS(caphe_power_dbus_invokator_parent_class)->finalize(object); +} + +static void +caphe_power_dbus_invokator_init(CaphePowerDbusInvokator *self) +{ + CaphePowerDbusInvokatorPrivate *priv = + caphe_power_dbus_invokator_get_instance_private(self); + + TRACE("%p", self); + + /* Initialize private pointer */ + self->priv = priv; +} + +static void +caphe_power_dbus_invokator_class_init(CaphePowerDbusInvokatorClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + CapheDbusInvokatorClass *dbus_invokator_class = CAPHE_DBUS_INVOKATOR_CLASS(class); + + TRACE("%p", class); + + /* GObject methods */ + object_class->finalize = caphe_power_dbus_invokator_finalize; + + /* Implement methods */ + dbus_invokator_class->inhibit = caphe_power_dbus_invokator_inhibit; + dbus_invokator_class->uninhibit = caphe_power_dbus_invokator_uninhibit; + dbus_invokator_class->is_inhibited = caphe_power_dbus_invokator_is_inhibited; +} diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-power-dbus-invokator.h goodvibes-0.4.2/src/libcaphe/caphe-power-dbus-invokator.h --- goodvibes-0.3.6/src/libcaphe/caphe-power-dbus-invokator.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-power-dbus-invokator.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __LIBCAPHE_CAPHE_POWER_DBUS_INVOKATOR_H__ +#define __LIBCAPHE_CAPHE_POWER_DBUS_INVOKATOR_H__ + +#include + +#include "caphe-dbus-invokator.h" + +/* GObject declarations */ + +#define CAPHE_TYPE_POWER_DBUS_INVOKATOR caphe_power_dbus_invokator_get_type() + +G_DECLARE_FINAL_TYPE(CaphePowerDbusInvokator, caphe_power_dbus_invokator, + CAPHE, POWER_DBUS_INVOKATOR, CapheDbusInvokator) + +/* Methods */ + +CapheDbusInvokator *caphe_power_dbus_invokator_new(void); + +#endif /* __LIBCAPHE_CAPHE_POWER_DBUS_INVOKATOR_H__ */ diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-session-dbus-invokator.c goodvibes-0.4.2/src/libcaphe/caphe-session-dbus-invokator.c --- goodvibes-0.3.6/src/libcaphe/caphe-session-dbus-invokator.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-session-dbus-invokator.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,206 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include + +#include "caphe-trace.h" +#include "caphe-dbus-invokator.h" +#include "caphe-session-dbus-invokator.h" + +/* + * Debug macros + */ + +#define debug(proxy, fmt, ...) \ + g_debug("[%s]: " fmt, \ + proxy ? g_dbus_proxy_get_name(proxy) : "SessionManager", \ + ##__VA_ARGS__) + +/* + * GObject definitions + */ + +struct _CapheSessionDbusInvokatorPrivate { + guint32 cookie; +}; + +typedef struct _CapheSessionDbusInvokatorPrivate CapheSessionDbusInvokatorPrivate; + +struct _CapheSessionDbusInvokator { + /* Parent instance structure */ + CapheDbusInvokator parent_instance; + /* Private data */ + CapheSessionDbusInvokatorPrivate *priv; +}; + +G_DEFINE_TYPE_WITH_PRIVATE(CapheSessionDbusInvokator, caphe_session_dbus_invokator, + CAPHE_TYPE_DBUS_INVOKATOR) + +/* + * DbusInvokator methods + */ + +static gboolean +caphe_session_dbus_invokator_is_inhibited(CapheDbusInvokator *dbus_invokator) +{ + CapheSessionDbusInvokator *self = CAPHE_SESSION_DBUS_INVOKATOR(dbus_invokator); + CapheSessionDbusInvokatorPrivate *priv = self->priv; + + return priv->cookie != 0; +} + +static void +caphe_session_dbus_invokator_uninhibit(CapheDbusInvokator *dbus_invokator) +{ + CapheSessionDbusInvokator *self = CAPHE_SESSION_DBUS_INVOKATOR(dbus_invokator); + CapheSessionDbusInvokatorPrivate *priv = self->priv; + GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); + + if (priv->cookie == 0) { + debug(proxy, "Not inhibited (no cookie)"); + return; + } + + if (proxy == NULL) { + debug(proxy, "No proxy"); + return; + } + + g_dbus_proxy_call(proxy, + "Uninhibit", + g_variant_new("(u)", + priv->cookie), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, NULL, NULL); + + priv->cookie = 0; + + debug(proxy, "Uninhibited"); +} + +static gboolean +caphe_session_dbus_invokator_inhibit(CapheDbusInvokator *dbus_invokator, + const gchar *application, const gchar *reason, + GError **error) +{ + CapheSessionDbusInvokator *self = CAPHE_SESSION_DBUS_INVOKATOR(dbus_invokator); + CapheSessionDbusInvokatorPrivate *priv = self->priv; + GDBusProxy *proxy = caphe_dbus_invokator_get_proxy(dbus_invokator); + GVariant *res; + + if (priv->cookie != 0) { + debug(proxy, "Already inhibited (cookie: %u)", priv->cookie); + return TRUE; + } + + if (proxy == NULL) { + debug(proxy, "No proxy"); + return FALSE; + } + + /* + * From org.gnome.SessionManager.xml, the 4 arguments to pass are: + * - app_id The application identifier + * - toplevel_xid The toplevel X window identifier + * - reason The reason for the inhibit + * - flags Flags that specify what should be inhibited + * + * The flags parameter must include at least one of the following: + * - 1 Inhibit logging out + * - 2 Inhibit user switching + * - 4 Inhibit suspending the session or computer + * - 8 Inhibit the session being marked as idle + * - 16 Inhibit auto-mounting removable media for the session + */ + res = g_dbus_proxy_call_sync(proxy, + "Inhibit", + g_variant_new("(susu)", + application, + 0, + reason, + 4), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + error); + + if (res == NULL) + return FALSE; + + g_variant_get(res, "(u)", &priv->cookie); + g_variant_unref(res); + + debug(proxy, "Inhibited (cookie: %u)", priv->cookie); + + return TRUE; +} + +/* + * GObject methods + */ + +static void +caphe_session_dbus_invokator_finalize(GObject *object) +{ + CapheDbusInvokator *dbus_invokator = CAPHE_DBUS_INVOKATOR(object); + + TRACE("%p", object); + + /* Ensure uninhibition */ + caphe_session_dbus_invokator_uninhibit(dbus_invokator); + + /* Chain up */ + if (G_OBJECT_CLASS(caphe_session_dbus_invokator_parent_class)->finalize) + G_OBJECT_CLASS(caphe_session_dbus_invokator_parent_class)->finalize(object); +} + +static void +caphe_session_dbus_invokator_init(CapheSessionDbusInvokator *self) +{ + CapheSessionDbusInvokatorPrivate *priv = + caphe_session_dbus_invokator_get_instance_private(self); + + TRACE("%p", self); + + /* Initialize private pointer */ + self->priv = priv; +} + +static void +caphe_session_dbus_invokator_class_init(CapheSessionDbusInvokatorClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + CapheDbusInvokatorClass *dbus_invokator_class = CAPHE_DBUS_INVOKATOR_CLASS(class); + + TRACE("%p", class); + + /* GObject methods */ + object_class->finalize = caphe_session_dbus_invokator_finalize; + + /* Implement methods */ + dbus_invokator_class->inhibit = caphe_session_dbus_invokator_inhibit; + dbus_invokator_class->uninhibit = caphe_session_dbus_invokator_uninhibit; + dbus_invokator_class->is_inhibited = caphe_session_dbus_invokator_is_inhibited; +} diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-session-dbus-invokator.h goodvibes-0.4.2/src/libcaphe/caphe-session-dbus-invokator.h --- goodvibes-0.3.6/src/libcaphe/caphe-session-dbus-invokator.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-session-dbus-invokator.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __LIBCAPHE_CAPHE_SESSION_DBUS_INVOKATOR_H__ +#define __LIBCAPHE_CAPHE_SESSION_DBUS_INVOKATOR_H__ + +#include + +#include "caphe-dbus-invokator.h" + +/* GObject declarations */ + +#define CAPHE_TYPE_SESSION_DBUS_INVOKATOR caphe_session_dbus_invokator_get_type() + +G_DECLARE_FINAL_TYPE(CapheSessionDbusInvokator, caphe_session_dbus_invokator, + CAPHE, SESSION_DBUS_INVOKATOR, CapheDbusInvokator) + +/* Methods */ + +CapheDbusInvokator *caphe_session_dbus_invokator_new(void); + +#endif /* __LIBCAPHE_CAPHE_SESSION_DBUS_INVOKATOR_H__ */ diff -Nru goodvibes-0.3.6/src/libcaphe/caphe-trace.h goodvibes-0.4.2/src/libcaphe/caphe-trace.h --- goodvibes-0.3.6/src/libcaphe/caphe-trace.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/caphe-trace.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __LIBCAPHE_CAPHE_TRACE_H__ +#define __LIBCAPHE_CAPHE_TRACE_H__ + +#include + +#ifdef ENABLE_TRACE +#define CAPHE_TRACE_ENABLED 1 +#else +#define CAPHE_TRACE_ENABLED 0 +#endif + +#define TRACE(fmt, ...) \ + do { \ + if (CAPHE_TRACE_ENABLED) \ + g_debug("-> %s(" fmt ")", __func__, ##__VA_ARGS__); \ + } while (0) + +#endif /* __LIBCAPHE_CAPHE_TRACE_H__ */ diff -Nru goodvibes-0.3.6/src/libcaphe/meson.build goodvibes-0.4.2/src/libcaphe/meson.build --- goodvibes-0.3.6/src/libcaphe/meson.build 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/meson.build 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +caphe_sources = [ + 'caphe.c', + 'caphe-cup.c', + 'caphe-dbus-inhibitor.c', + 'caphe-dbus-invokator.c', + 'caphe-dbus-proxy.c', + 'caphe-inhibitor.c', + 'caphe-inhibitor-list.c', + 'caphe-login-dbus-invokator.c', + 'caphe-portal-dbus-invokator.c', + 'caphe-power-dbus-invokator.c', + 'caphe-session-dbus-invokator.c', +] + +caphe_dependencies = [ + glib_dep, + gobject_dep, + gio_dep, + gio_unix_dep +] + +libcaphe = static_library('caphe', + sources: [ caphe_sources ], + dependencies: caphe_dependencies, + c_args: [ + '-DG_LOG_DOMAIN="Caphe"', + #'-DENABLE_TRACE', + ], +) + +libcaphe_dep = declare_dependency( + dependencies: caphe_dependencies, + link_with: libcaphe, +) + +subdir('tests') diff -Nru goodvibes-0.3.6/src/libcaphe/README.md goodvibes-0.4.2/src/libcaphe/README.md --- goodvibes-0.3.6/src/libcaphe/README.md 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/README.md 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,33 @@ +Libcaphe +======== + +Libcaphe is a little library that inhibits sleep/suspend. + +You use it in your application if you want to prevent the system from going to +sleep. A typical use-case is for audio/video players, who might want to inhibit +sleep while playing. + +The code is inspired by [Caffeine-ng](https://gitlab.com/hobarrera/caffeine-ng). + +Libcaphe will work if one of the following D-Bus services is present on your +system: + +- `org.gnome.SessionManager` +- `org.xfce.SessionManager` +- `org.freedesktop.PowerManagement` +- `org.freedesktop.login1` + +Notice that the prefered way to inhibit for GTK+ applications is to use +`gtk_application_inhibit()`. I use this library mainly to support old systems +that rely on `org.freedesktop.PowerManagement`, which has been deprecated a +while ago, but is still widely used. + + + +About the name +-------------- + +"Cà phê" is the Vietnamese for coffee. + +At the moment of this writing, Vietnam is the second largest producer in the +world after Brazil, and I thought the world ought to know :) diff -Nru goodvibes-0.3.6/src/libcaphe/tests/main.c goodvibes-0.4.2/src/libcaphe/tests/main.c --- goodvibes-0.3.6/src/libcaphe/tests/main.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/tests/main.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,188 @@ +/* + * Libcaphe + * + * Copyright (C) 2016-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * Compilation: + * packages="glib-2.0 gio-2.0 gio-unix-2.0" + * gcc $(pkg-config --cflags --libs $packages) *.c -o main + * gcc $(pkg-config --cflags --libs $packages) -DENABLE_TRACE *.c -o main + * + * Execution: + * G_MESSAGES_DEBUG=all ./main + */ + +#include +#include + +#include +#include +#include + +#include "libcaphe/caphe.h" + +#define INHIBIT_REASON "Ice-coffee with milk" + +#define print(fmt, ...) g_print(fmt "\n", ##__VA_ARGS__) + +static GMainLoop *main_loop; + +static void +on_caphe_notify_inhibitor(CapheCup *caphe, + GParamSpec *pspec G_GNUC_UNUSED, + gpointer user_data G_GNUC_UNUSED) +{ + CapheInhibitor *inhibitor = caphe_cup_get_inhibitor(caphe); + + if (inhibitor) + print("Inhibited with inhibitor: %s", caphe_inhibitor_get_name(inhibitor)); + else + print("Uninhibited"); +} + +static gboolean +on_stress_step_4(CapheCup *caphe) +{ + if (!caphe_cup_is_inhibited(caphe)) + g_error("Should be inhibited !"); + + return G_SOURCE_REMOVE; +} + +static gboolean +on_stress_step_3(CapheCup *caphe) +{ + if (!caphe_cup_is_inhibited(caphe)) + g_error("Should be inhibited !"); + + print("Sending inhibit request for a different reason"); + caphe_cup_inhibit(caphe, "Expresso"); + + print("Waiting 1 sec. Expect inhibited."); + g_timeout_add_seconds(1, (GSourceFunc) on_stress_step_4, caphe); + + return G_SOURCE_REMOVE; +} + +static gboolean +on_stress_step_2(CapheCup *caphe) +{ + if (caphe_cup_is_inhibited(caphe)) + g_error("Shouldn't be inhibited !"); + + print("Sending batch of requests."); + caphe_cup_uninhibit(caphe); + caphe_cup_inhibit(caphe, INHIBIT_REASON); + caphe_cup_inhibit(caphe, INHIBIT_REASON "dfdf"); + caphe_cup_uninhibit(caphe); + caphe_cup_inhibit(caphe, INHIBIT_REASON); + + print("Waiting 1 sec. Expect inhibited."); + g_timeout_add_seconds(1, (GSourceFunc) on_stress_step_3, caphe); + + return G_SOURCE_REMOVE; +} + +static gboolean +when_idle_stress(CapheCup *caphe) +{ + print("Sending 1st batch of requests."); + caphe_cup_inhibit(caphe, INHIBIT_REASON); + caphe_cup_inhibit(caphe, INHIBIT_REASON); + caphe_cup_uninhibit(caphe); + caphe_cup_inhibit(caphe, INHIBIT_REASON); + caphe_cup_uninhibit(caphe); + + print("Waiting 1 second. Expect uninhibited."); + g_timeout_add_seconds(1, (GSourceFunc) on_stress_step_2, caphe); + + return G_SOURCE_REMOVE; +} + +static gboolean +when_idle_inhibit(CapheCup *caphe) +{ + print("Inhibiting..."); + caphe_cup_inhibit(caphe, INHIBIT_REASON); + + return G_SOURCE_REMOVE; +} + +static gboolean +sigint_handler(gpointer user_data G_GNUC_UNUSED) +{ + g_main_loop_quit(main_loop); + + return FALSE; +} + +static void +print_usage(const char *progname) +{ + print("Usage: %s ", progname); +} + +int +main(int argc, char *argv[]) +{ + CapheCup *caphe; + GSourceFunc idle_func; + + /* Process input arguments */ + if (argc == 1 || argc > 2) { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + + if (!g_strcmp0(argv[1], "inhibit")) + idle_func = (GSourceFunc) when_idle_inhibit; + else if (!g_strcmp0(argv[1], "stress")) + idle_func = (GSourceFunc) when_idle_stress; + else { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + + /* Init */ + caphe_init(); + caphe = caphe_cup_get_default(); + g_signal_connect(caphe, "notify::inhibitor", G_CALLBACK(on_caphe_notify_inhibitor), NULL); + + /* Add idle function. Priorities to try: + * - G_PRIORITY_LOW + * - G_PRIORITY_HIGH + */ + g_idle_add_full(G_PRIORITY_LOW, idle_func, caphe, NULL); + + /* Be ready to catch interruptions */ + g_unix_signal_add(SIGINT, sigint_handler, NULL); + + /* Main loop */ + print("-- Running the main loop --"); + main_loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(main_loop); + + /* Cleanup */ + print("-- Main loop exited --"); + g_main_loop_unref(main_loop); + caphe_cleanup(); + + return EXIT_SUCCESS; +} diff -Nru goodvibes-0.3.6/src/libcaphe/tests/meson.build goodvibes-0.4.2/src/libcaphe/tests/meson.build --- goodvibes-0.3.6/src/libcaphe/tests/meson.build 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/libcaphe/tests/meson.build 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +executable('caphe-test', [ 'main.c' ], + dependencies: libcaphe_dep, + include_directories: root_inc, + install: false +) diff -Nru goodvibes-0.3.6/src/main.c goodvibes-0.4.2/src/main.c --- goodvibes-0.3.6/src/main.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/main.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -32,14 +32,14 @@ #include #include -#include "additions/glib.h" +#include "framework/glib-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" -#ifdef UI_ENABLED +#ifdef GV_UI_ENABLED #include "ui/gv-ui.h" #endif -#ifdef UI_ENABLED +#ifdef GV_UI_ENABLED #include "gv-graphical-application.h" #else #include "gv-console-application.h" @@ -53,13 +53,13 @@ static const gchar * string_package_info(void) { - return PACKAGE_CAMEL_NAME " " PACKAGE_VERSION; + return GV_NAME_CAPITAL " " PACKAGE_VERSION; } static const gchar * string_copyright(void) { - return PACKAGE_COPYRIGHT " " PACKAGE_AUTHOR_NAME " " PACKAGE_AUTHOR_EMAIL; + return GV_COPYRIGHT " " GV_AUTHOR_NAME " <" GV_AUTHOR_EMAIL ">"; } static const gchar * @@ -87,7 +87,7 @@ text = g_strjoin(", ", glib_get_compile_version_string(), gv_core_audio_backend_compile_version_string(), -#ifdef UI_ENABLED +#ifdef GV_UI_ENABLED gv_ui_toolkit_compile_version_string(), #endif NULL); @@ -104,7 +104,7 @@ text = g_strjoin(", ", glib_get_runtime_version_string(), gv_core_audio_backend_runtime_version_string(), -#ifdef UI_ENABLED +#ifdef GV_UI_ENABLED gv_ui_toolkit_runtime_version_string(), #endif NULL); @@ -140,17 +140,17 @@ /* Initialize i18n */ setlocale(LC_ALL, NULL); - bindtextdomain(PACKAGE_NAME, LOCALE_DIR); - bind_textdomain_codeset(PACKAGE_NAME, "UTF-8"); - textdomain(PACKAGE_NAME); + bindtextdomain(GETTEXT_PACKAGE, GV_LOCALEDIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + textdomain(GETTEXT_PACKAGE); /* Set application name */ g_set_prgname(PACKAGE_NAME); - g_set_application_name(_("Goodvibes Radio Player")); + g_set_application_name(_("Goodvibes")); -#ifdef UI_ENABLED +#ifdef GV_UI_ENABLED /* Set application icon */ - gtk_window_set_default_icon_name(PACKAGE_NAME); + gtk_window_set_default_icon_name(GV_ICON_NAME); #endif /* Parse command-line, and run some init code at the same time */ @@ -185,14 +185,15 @@ INFO("%s", string_package_info()); INFO("%s", string_copyright()); INFO("Started on %s, with pid %ld", string_date_now(), (long) getpid()); - INFO("Compiled against: %s", string_compile_libraries()); - INFO("Running along : %s", string_runtime_libraries()); + INFO("Compiled against : %s", string_compile_libraries()); + INFO("Running along : %s", string_runtime_libraries()); + INFO("Gettext locale dir: %s", GV_LOCALEDIR); /* Create the application */ -#ifdef UI_ENABLED - app = gv_graphical_application_new(PACKAGE_APPLICATION_ID); +#ifdef GV_UI_ENABLED + app = gv_graphical_application_new(GV_APPLICATION_ID); #else - app = gv_console_application_new(PACKAGE_APPLICATION_ID); + app = gv_console_application_new(GV_APPLICATION_ID); #endif /* Quit on SIGINT */ diff -Nru goodvibes-0.3.6/src/Makefile.am goodvibes-0.4.2/src/Makefile.am --- goodvibes-0.3.6/src/Makefile.am 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/Makefile.am 1970-01-01 00:00:00.000000000 +0000 @@ -1,319 +0,0 @@ -# Process this file with automake to produce Makefile.in - -# ----------------------------------------------------- # -# Enum Types Generation Template # -# ----------------------------------------------------- # - -# There's a bit of Makefile Magic going on here. -# We define a template, that we invoke later on to generate rules -# dynamically. It saves quite a lot of annoying copy/pasting, right ? - -define make_types -$(1).c: $(2) - $$(AM_V_GEN) glib-mkenums \ - --fhead "#include \"$(1).h\"\n" \ - --fhead "\n" \ - --fprod "/* Enumerations from \"@filename@\" */\n" \ - --fprod "\n" \ - --fprod "#include \"@filename@\"\n" \ - --fprod "\n" \ - --vhead "GType\n" \ - --vhead "@enum_name@_get_type(void)\n" \ - --vhead "{\n" \ - --vhead " static GType etype = 0;\n" \ - --vhead "\n" \ - --vhead " if (etype == 0) {\n" \ - --vhead " static const G@Type@Value values[] = {\n" \ - --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" },\n"\ - --vtail " { 0, NULL, NULL }\n" \ - --vtail " };\n" \ - --vtail " etype = g_@type@_register_static(\"@EnumName@\", values);\n"\ - --vtail " }\n" \ - --vtail "\n" \ - --vtail " return etype;\n" \ - --vtail "}\n" \ - $$^ > $$@ - -$(1).h: $(2) - $(eval ns := __GOODVIBES_$(shell basename $(1) | tr a-z- A-Z_)_H__) - $$(AM_V_GEN) glib-mkenums \ - --fhead "#ifndef $(ns)\n" \ - --fhead "#define $(ns)\n" \ - --fhead "\n" \ - --fhead "#include \n" \ - --fhead "\n" \ - --fprod "/* Enumerations from \"@filename@\" */\n" \ - --fprod "\n" \ - --vhead "GType @enum_name@_get_type(void) G_GNUC_CONST;\n" \ - --vhead "#define @ENUMNAME@_ENUM_TYPE (@enum_name@_get_type())\n" \ - --vhead "\n" \ - --ftail "#endif /* $(ns) */\n" \ - $$^ > $$@ -endef - - - -# ----------------------------------------------------- # -# Additions # -# ----------------------------------------------------- # - -gv_additions_sources = \ - additions/glib.c additions/glib.h \ - additions/glib-object.c additions/glib-object.h \ - additions/gst.c additions/gst.h - -if UI_ENABLED -gv_additions_sources += \ - additions/gtk.c additions/gtk.h -endif - - - -# ----------------------------------------------------- # -# Framework # -# ----------------------------------------------------- # - -# Sources - -gv_framework_sources = \ - framework/log.c framework/log.h \ - framework/gv-configurable.c framework/gv-configurable.h \ - framework/gv-errorable.c framework/gv-errorable.h \ - framework/gv-feature.c framework/gv-feature.h \ - framework/gv-file-helpers.c framework/gv-file-helpers.h \ - framework/gv-framework.c framework/gv-framework.h \ - framework/gv-param-specs.h \ - framework/uri-schemes.c framework/uri-schemes.h \ - framework/vt-codes.h - -# Generated types - -gv_framework_built_sources = \ - framework/gv-framework-enum-types.c \ - framework/gv-framework-enum-types.h - -gv_framework_types_prereqs = \ - framework/gv-feature.h - -$(eval $(call make_types,framework/gv-framework-enum-types,$(gv_framework_types_prereqs))) - -# Compiler options - handled in core compiler options - - - -# ----------------------------------------------------- # -# Core # -# ----------------------------------------------------- # - -# Sources - -gv_core_sources = \ - core/gv-core.c core/gv-core.h \ - core/gv-core-internal.h \ - core/gv-engine.c core/gv-engine.h \ - core/gv-metadata.c core/gv-metadata.h \ - core/gv-player.c core/gv-player.h \ - core/gv-playlist.c core/gv-playlist.h \ - core/gv-station.c core/gv-station.h \ - core/gv-station-list.c core/gv-station-list.h - -# Enum Types - -gv_core_built_sources = \ - core/gv-core-enum-types.c \ - core/gv-core-enum-types.h - -gv_core_types_prereqs = \ - core/gv-engine.h \ - core/gv-player.h - -$(eval $(call make_types,core/gv-core-enum-types,$(gv_core_types_prereqs))) - -# Compiler options - -gv_core_cflags = \ - $(GLIB_CFLAGS) \ - $(LIBSOUP_CFLAGS) \ - $(GST_CFLAGS) - -gv_core_static_ldadd = - -gv_core_shared_ldadd = \ - -lm \ - $(GLIB_LIBS) \ - $(LIBSOUP_LIBS) \ - $(GST_LIBS) - - - -# ----------------------------------------------------- # -# User Interface # -# ----------------------------------------------------- # - -# Sources - -if UI_ENABLED - -gv_ui_sources = \ - ui/gv-about-dialog.c ui/gv-about-dialog.h \ - ui/gv-main-window.c ui/gv-main-window.h \ - ui/gv-main-window-manager.c ui/gv-main-window-manager.h \ - ui/gv-prefs-window.c ui/gv-prefs-window.h \ - ui/gv-station-context-menu.c ui/gv-station-context-menu.h \ - ui/gv-station-dialog.c ui/gv-station-dialog.h \ - ui/gv-stations-tree-view.c ui/gv-stations-tree-view.h \ - ui/gv-status-icon.c ui/gv-status-icon.h \ - ui/gv-ui.c ui/gv-ui.h \ - ui/gv-ui-internal.h \ - ui/gv-ui-helpers.c ui/gv-ui-helpers.h - -# Enum Types - -gv_ui_built_sources = \ - ui/gv-ui-enum-types.c \ - ui/gv-ui-enum-types.h - -gv_ui_types_prereqs = \ - ui/gv-main-window.h \ - ui/gv-status-icon.h - -$(eval $(call make_types,ui/gv-ui-enum-types,$(gv_ui_types_prereqs))) - -# Compiler options - -gv_ui_cflags = $(UI_CFLAGS) -DUI_ENABLED -gv_ui_shared_ldadd = $(UI_LIBS) - -endif # UI_ENABLED - - - -# ----------------------------------------------------- # -# Features # -# ----------------------------------------------------- # - -# Core features - -gv_feat_sources = feat/gv-feat.c feat/gv-feat.h -gv_feat_cflags = -gv_feat_static_ldadd = -gv_feat_shared_ldadd = - -if CONSOLE_OUTPUT_ENABLED -gv_feat_sources += feat/gv-console-output.c feat/gv-console-output.h -gv_feat_cflags += -DCONSOLE_OUTPUT_ENABLED -endif - -if DBUS_SERVER_ENABLED -gv_feat_sources += feat/gv-dbus-server.c feat/gv-dbus-server.h \ - feat/gv-dbus-server-native.c feat/gv-dbus-server-native.h \ - feat/gv-dbus-server-mpris2.c feat/gv-dbus-server-mpris2.h -gv_feat_cflags += -DDBUS_SERVER_ENABLED -endif - -if INHIBITOR_ENABLED -gv_feat_sources += feat/gv-inhibitor.c feat/gv-inhibitor.h -gv_feat_cflags += $(CAPHE_CFLAGS) -DINHIBITOR_ENABLED -gv_feat_static_ldadd += $(CAPHE_LIBS) -endif - -# UI features - -if HOTKEYS_ENABLED -gv_feat_sources += feat/gv-hotkeys.c feat/gv-hotkeys.h -gv_feat_cflags += $(HOTKEYS_CFLAGS) -DHOTKEYS_ENABLED -gv_feat_shared_ldadd += $(HOTKEYS_LIBS) -endif - -if NOTIFICATIONS_ENABLED -gv_feat_sources += feat/gv-notifications.c feat/gv-notifications.h -gv_feat_cflags += -DNOTIFICATIONS_ENABLED -endif - - - -# ----------------------------------------------------- # -# Goodvibes Radio Player # -# ----------------------------------------------------- # - -# We use sort() to remove duplicates in CFLAGS and LDADD. -# I know, it's not recommended to use sort() in Automake, -# but it works and does a wonderful job, so let it be. - -# Also, notice in LDADD that the static libraries MUST come first, -# otherwise the link might fail. If you're interested in the matter, -# here's a bit of reading I recommend: -# http://eli.thegreenplace.net/2013/07/09/library-order-in-static-linking - -goodvibes_SOURCES = \ - $(gv_additions_sources) \ - $(gv_framework_sources) \ - $(gv_framework_built_sources) \ - $(gv_core_sources) \ - $(gv_core_built_sources) \ - $(gv_ui_sources) \ - $(gv_ui_built_sources) \ - $(gv_feat_sources) - -if UI_ENABLED -goodvibes_SOURCES += gv-graphical-application.c gv-graphical-application.h -else -goodvibes_SOURCES += gv-console-application.c gv-console-application.h -endif - -goodvibes_SOURCES += \ - main.c \ - options.c options.h - -goodvibes_CFLAGS = \ - -DLOCALE_DIR=\"$(localedir)\" - -goodvibes_CFLAGS += $(sort \ - $(gv_framework_cflags) \ - $(gv_core_cflags) \ - $(gv_ui_cflags) \ - $(gv_feat_cflags) \ - ) - -goodvibes_LDADD = \ - $(gv_core_static_ldadd) \ - $(gv_feat_static_ldadd) - -goodvibes_LDADD += $(sort \ - $(gv_framework_shared_ldadd) \ - $(gv_core_shared_ldadd) \ - $(gv_ui_shared_ldadd) \ - $(gv_feat_shared_ldadd) \ - ) - - - -# ----------------------------------------------------- # -# Goodvibes Command-Line Client # -# ----------------------------------------------------- # - -goodvibes_client_SOURCES = client.c -goodvibes_client_CPPFLAGS = $(GLIB_CFLAGS) -goodvibes_client_LDADD = $(GLIB_LIBS) - - - -# ----------------------------------------------------- # - -bin_PROGRAMS = goodvibes goodvibes-client - -BUILT_SOURCES = \ - $(gv_framework_built_sources) \ - $(gv_core_built_sources) \ - $(gv_ui_built_sources) - -CLEANFILES = $(BUILT_SOURCES) - -print-flags: - @echo -- CPPFLAGS -- - @echo $(CPPFLAGS) $(AM_CPPFLAGS) $(goodvibes_CPPFLAGS) - @echo -- CFLAGS -- - @echo $(CFLAGS) $(AM_CFLAGS) $(goodvibes_CFLAGS) - @echo -- LDADD -- - @echo $(LDADD) $(AM_LDADD) $(goodvibes_LDADD) - @echo -- done -- diff -Nru goodvibes-0.3.6/src/meson.build goodvibes-0.4.2/src/meson.build --- goodvibes-0.3.6/src/meson.build 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/meson.build 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Subdirectories + +root_inc = include_directories('.') + +subdir('libcaphe') +subdir('framework') +subdir('core') +if gv_ui_enabled + subdir('ui') +endif +subdir('feat') + +# Source and dependencies + +goodvibes_sources = [ + 'main.c', + 'options.c', +] + +goodvibes_dependencies = [ + gvframework_dep, + gvcore_dep, + gvfeat_dep, + math_dep, +] + +if gv_ui_enabled + goodvibes_sources += 'gv-graphical-application.c' + goodvibes_dependencies += gvui_dep +else + goodvibes_sources += 'gv-console-application.c' +endif + +# Executable definition + +executable('goodvibes', goodvibes_sources, + dependencies: goodvibes_dependencies, + include_directories: root_inc, + install: true +) + +executable('goodvibes-client', [ 'client.c' ], + dependencies: [ glib_dep, gio_dep ], + install: true +) diff -Nru goodvibes-0.3.6/src/options.c goodvibes-0.4.2/src/options.c --- goodvibes-0.3.6/src/options.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/options.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,9 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout - * - * SPDX-License-Identifier: GPL-3.0-or-later + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -26,8 +24,9 @@ #include +#include "framework/gv-framework.h" #include "core/gv-core.h" -#ifdef UI_ENABLED +#ifdef GV_UI_ENABLED #include "ui/gv-ui.h" #endif @@ -56,7 +55,7 @@ "version", 'v', 0, G_OPTION_ARG_NONE, &options.print_version, "Print the version and exit", NULL }, -#ifdef UI_ENABLED +#ifdef GV_UI_ENABLED { "without-ui", 0, 0, G_OPTION_ARG_NONE, &options.without_ui, "Disable the graphical user interface at startup", NULL @@ -92,7 +91,7 @@ context = g_option_context_new("[STATION]"); g_option_context_set_summary (context, - PACKAGE_CAMEL_NAME " is a lightweight internet radio player for GNU/Linux.\n" + GV_NAME_CAPITAL " is a lightweight internet radio player for GNU/Linux.\n" "It offers a simple way to have your favorite radio stations at easy reach.\n" "\n" "To control it via the command line, see the '" PACKAGE_NAME "-client' executable."); @@ -100,7 +99,7 @@ /* Add option groups and perform some init code at the same time */ g_option_context_add_group(context, gv_core_audio_backend_init_get_option_group()); -#ifdef UI_ENABLED +#ifdef GV_UI_ENABLED g_option_context_add_group(context, gv_ui_toolkit_init_get_option_group()); #endif diff -Nru goodvibes-0.3.6/src/options.h goodvibes-0.4.2/src/options.h --- goodvibes-0.3.6/src/options.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/options.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -29,7 +29,7 @@ const gchar *log_level; const gchar *output_file; gboolean print_version; -#ifdef UI_ENABLED +#ifdef GV_UI_ENABLED gboolean without_ui; gboolean status_icon; #endif diff -Nru goodvibes-0.3.6/src/ui/gtk-additions.c goodvibes-0.4.2/src/ui/gtk-additions.c --- goodvibes-0.3.6/src/ui/gtk-additions.c 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gtk-additions.c 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,57 @@ +/* + * Goodvibes Radio Player + * + * Copyright (C) 2015-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +/* + * Version Information + */ + +const gchar * +gtk_get_runtime_version_string(void) +{ + static gchar *version_string; + + if (version_string == NULL) { + version_string = g_strdup_printf("GTK+ %u.%u.%u", + gtk_get_major_version(), + gtk_get_minor_version(), + gtk_get_micro_version()); + } + + return version_string; +} + +const gchar * +gtk_get_compile_version_string(void) +{ + static gchar *version_string; + + if (version_string == NULL) { + version_string = g_strdup_printf("GTK+ %u.%u.%u", + GTK_MAJOR_VERSION, + GTK_MINOR_VERSION, + GTK_MICRO_VERSION); + } + + return version_string; +} diff -Nru goodvibes-0.3.6/src/ui/gtk-additions.h goodvibes-0.4.2/src/ui/gtk-additions.h --- goodvibes-0.3.6/src/ui/gtk-additions.h 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gtk-additions.h 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * Goodvibes Radio Player + * + * Copyright (C) 2015-2018 Arnaud Rebillout + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GOODVIBES_FRAMEWORK_GTK_ADDITIONS_H__ +#define __GOODVIBES_FRAMEWORK_GTK_ADDITIONS_H__ + +#include + +/* + * Version Information + */ + +const gchar *gtk_get_runtime_version_string(void); +const gchar *gtk_get_compile_version_string(void); + +/* + * GtkBuilder + */ + +#define gtk_builder_get_widget(builder, name) \ + GTK_WIDGET(gtk_builder_get_object(builder, name)) + +#define gtk_builder_get_object(builder, name) \ + G_OBJECT(gtk_builder_get_object(builder, name)) + +/* + * Convenient macros to save widgets from a GtkBuilder instance. + * If the widget is not found, it is considered as a programming error, + * therefore ending the execution of the program. + * This macro also ensures that the widget name in the ui file is the same + * as the one used in the C file, therefore enforcing a consistent naming + * across the code. + */ + +#define GTK_BUILDER_SAVE_WIDGET(builder, str, name) \ + do { \ + str->name = gtk_builder_get_widget(builder, #name); \ + g_assert(GTK_IS_WIDGET(str->name)); \ + } while (0) + +#define GTK_BUILDER_SAVE_OBJECT(builder, str, name) \ + do { \ + str->name = gtk_builder_get_object(builder, #name); \ + g_assert(G_IS_OBJECT(str->name)); \ + } while (0) + +/* + * GtkWidget + */ + +#define gtk_widget_set_margins(widget, margin) \ + do { \ + gtk_widget_set_margin_start(widget, margin); \ + gtk_widget_set_margin_end(widget, margin); \ + gtk_widget_set_margin_top(widget, margin); \ + gtk_widget_set_margin_bottom(widget, margin); \ + } while (0) + +#endif /* __GOODVIBES_FRAMEWORK_GTK_ADDITIONS_H__ */ diff -Nru goodvibes-0.3.6/src/ui/gv-about-dialog.c goodvibes-0.4.2/src/ui/gv-about-dialog.c --- goodvibes-0.3.6/src/ui/gv-about-dialog.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-about-dialog.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -21,8 +21,10 @@ #include +#include "framework/gv-framework.h" + static const gchar *authors[] = { - PACKAGE_AUTHOR_NAME " " PACKAGE_AUTHOR_EMAIL, + GV_AUTHOR_NAME " <" GV_AUTHOR_EMAIL ">", NULL }; @@ -33,8 +35,12 @@ static const gchar *translators = "Weblate https://hosted.weblate.org/projects/goodvibes/translations\n" \ + "Lukáš Linhart - Czech (cs)\n" \ "Michal Čihař - Czech (cs)\n" \ "Andreas Kleinert - German (de)\n" \ + "Vinz - German (de)\n" \ + "Wolf Berg - German (de)\n" \ + "Benages - Spanish (es)\n" \ "Étienne Deparis - French (fr)\n" \ "Allan Nordhøy - Norwegian Bokmål (nb_NO)\n" \ "Heimen Stoffels - Dutch (nl)\n" \ @@ -57,12 +63,12 @@ "artists", artists, "authors", authors, "comments", comments, - "copyright", PACKAGE_COPYRIGHT " " PACKAGE_AUTHOR_NAME, + "copyright", GV_COPYRIGHT " " GV_AUTHOR_NAME, "license-type", GTK_LICENSE_GPL_3_0, - "logo-icon-name", PACKAGE_NAME, + "logo-icon-name", GV_ICON_NAME, "translator-credits", translators, "version", PACKAGE_VERSION, - "website", PACKAGE_HOMEPAGE, + "website", GV_HOMEPAGE, NULL); g_free(comments); diff -Nru goodvibes-0.3.6/src/ui/gv-about-dialog.h goodvibes-0.4.2/src/ui/gv-about-dialog.h --- goodvibes-0.3.6/src/ui/gv-about-dialog.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-about-dialog.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/ui/gv-main-window.c goodvibes-0.4.2/src/ui/gv-main-window.c --- goodvibes-0.3.6/src/ui/gv-main-window.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-main-window.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -23,19 +23,18 @@ #include #include -#include "additions/glib-object.h" -#include "additions/gtk.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" +#include "ui/gtk-additions.h" #include "ui/gv-ui-enum-types.h" #include "ui/gv-ui-helpers.h" #include "ui/gv-ui-internal.h" -#include "ui/gv-ui-helpers.h" #include "ui/gv-stations-tree-view.h" #include "ui/gv-main-window.h" -#define UI_FILE "main-window.glade" +#define UI_RESOURCE_PATH GV_APPLICATION_PATH "/Ui/main-window.glade" /* * Properties @@ -534,7 +533,7 @@ g_idle_add((GSourceFunc) when_idle_compute_natural_height, self); } -static void +static gboolean on_stations_tree_view_map_event(GtkWidget *stations_tree_view G_GNUC_UNUSED, GdkEvent *event G_GNUC_UNUSED, GvMainWindowManager *self) @@ -543,6 +542,8 @@ * height we have is correct. */ g_idle_add((GSourceFunc) when_idle_compute_natural_height, self); + + return GDK_EVENT_PROPAGATE; } /* @@ -565,17 +566,17 @@ //DEBUG("Main window %s focus", focus_event->in ? "gained" : "lost"); if (focus_event->in) - return FALSE; + return GDK_EVENT_PROPAGATE; if (!POPUP_WINDOW_CLOSE_ON_FOCUS_OUT) - return FALSE; + return GDK_EVENT_PROPAGATE; if (gv_stations_tree_view_has_context_menu(stations_tree_view)) - return FALSE; + return GDK_EVENT_PROPAGATE; gtk_window_close(window); - return FALSE; + return GDK_EVENT_PROPAGATE; } static gboolean @@ -590,21 +591,21 @@ switch (event->keyval) { case GDK_KEY_Escape: - /* Close window if 'Esc' key is pressed */ + /* Close window if is pressed */ gtk_window_close(GTK_WINDOW(self)); break; case GDK_KEY_space: - /* Play/Stop when space is pressed */ + /* Toggle playback if is pressed */ gtk_widget_grab_focus(priv->play_button); gv_player_toggle(player); - return TRUE; // consume event + return GDK_EVENT_STOP; // consume event default: break; } - return FALSE; + return GDK_EVENT_PROPAGATE; } /* @@ -623,10 +624,10 @@ * and hiding would make the save operation fail. */ - /* We must return TRUE here to prevent the window from being destroyed. + /* We must stop the event to prevent the window from being destroyed. * The window will be destroyed later on during the cleanup process. */ - return TRUE; + return GDK_EVENT_STOP; } static gboolean @@ -641,21 +642,21 @@ switch (event->keyval) { case GDK_KEY_Escape: - /* Iconify window if 'Esc' key is pressed */ + /* Iconify window if is pressed */ gtk_window_iconify(GTK_WINDOW(self)); break; case GDK_KEY_space: - /* Play/Stop when space is pressed */ + /* Toggle playback if is pressed */ gtk_widget_grab_focus(priv->play_button); gv_player_toggle(player); - return TRUE; // consume event + return GDK_EVENT_STOP; // consume event default: break; } - return FALSE; + return GDK_EVENT_PROPAGATE; } /* @@ -832,11 +833,9 @@ { GvMainWindowPrivate *priv = self->priv; GtkBuilder *builder; - gchar *uifile; /* Build the ui */ - gv_builder_load(UI_FILE, &builder, &uifile); - DEBUG("Built from ui file '%s'", uifile); + builder = gtk_builder_new_from_resource(UI_RESOURCE_PATH); /* Save widget pointers */ @@ -870,8 +869,7 @@ gtk_container_add(GTK_CONTAINER(self), priv->window_vbox); /* Cleanup */ - g_object_unref(G_OBJECT(builder)); - g_free(uifile); + g_object_unref(builder); } static void @@ -1114,17 +1112,17 @@ properties[PROP_THEME_VARIANT] = g_param_spec_enum("theme-variant", "Theme variant", NULL, - GV_MAIN_WINDOW_THEME_VARIANT_ENUM_TYPE, + GV_TYPE_MAIN_WINDOW_THEME_VARIANT, GV_MAIN_WINDOW_THEME_DEFAULT, GV_PARAM_DEFAULT_FLAGS | G_PARAM_READWRITE); g_object_class_install_properties(object_class, PROP_N, properties); /* Register transform function */ - g_value_register_transform_func(GV_MAIN_WINDOW_THEME_VARIANT_ENUM_TYPE, + g_value_register_transform_func(GV_TYPE_MAIN_WINDOW_THEME_VARIANT, G_TYPE_STRING, gv_value_transform_enum_string); g_value_register_transform_func(G_TYPE_STRING, - GV_MAIN_WINDOW_THEME_VARIANT_ENUM_TYPE, + GV_TYPE_MAIN_WINDOW_THEME_VARIANT, gv_value_transform_string_enum); } diff -Nru goodvibes-0.3.6/src/ui/gv-main-window.h goodvibes-0.4.2/src/ui/gv-main-window.h --- goodvibes-0.3.6/src/ui/gv-main-window.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-main-window.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/ui/gv-main-window-manager.c goodvibes-0.4.2/src/ui/gv-main-window-manager.c --- goodvibes-0.3.6/src/ui/gv-main-window-manager.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-main-window-manager.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -23,6 +23,7 @@ #include #include +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "ui/gv-ui-internal.h" #include "ui/gv-main-window.h" @@ -207,7 +208,7 @@ gv_main_window_manager_save_configuration_delayed(self); - return FALSE; + return GDK_EVENT_PROPAGATE; } /* diff -Nru goodvibes-0.3.6/src/ui/gv-main-window-manager.h goodvibes-0.4.2/src/ui/gv-main-window-manager.h --- goodvibes-0.3.6/src/ui/gv-main-window-manager.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-main-window-manager.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/ui/gv-prefs-window.c goodvibes-0.4.2/src/ui/gv-prefs-window.c --- goodvibes-0.3.6/src/ui/gv-prefs-window.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-prefs-window.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -23,18 +23,17 @@ #include #include -#include "additions/gtk.h" -#include "additions/glib-object.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" #include "feat/gv-feat.h" +#include "ui/gtk-additions.h" #include "ui/gv-ui-enum-types.h" -#include "ui/gv-ui-helpers.h" #include "ui/gv-ui-internal.h" #include "ui/gv-prefs-window.h" -#define UI_FILE "prefs-window.glade" +#define UI_RESOURCE_PATH GV_APPLICATION_PATH "/Ui/prefs-window.glade" /* * GObject definitions @@ -169,7 +168,7 @@ if (event->keyval == GDK_KEY_Escape) gtk_window_close(window); - return FALSE; + return GDK_EVENT_PROPAGATE; } /* @@ -339,11 +338,9 @@ { GvPrefsWindowPrivate *priv = self->priv; GtkBuilder *builder; - gchar *uifile; /* Build the ui */ - gv_builder_load(UI_FILE, &builder, &uifile); - DEBUG("Built from ui file '%s'", uifile); + builder = gtk_builder_new_from_resource(UI_RESOURCE_PATH); /* Save widget pointers */ @@ -404,8 +401,7 @@ gtk_container_add(GTK_CONTAINER(self), priv->window_vbox); /* Cleanup */ - g_object_unref(G_OBJECT(builder)); - g_free(uifile); + g_object_unref(builder); } static void diff -Nru goodvibes-0.3.6/src/ui/gv-prefs-window.h goodvibes-0.4.2/src/ui/gv-prefs-window.h --- goodvibes-0.3.6/src/ui/gv-prefs-window.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-prefs-window.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/ui/gv-station-context-menu.c goodvibes-0.4.2/src/ui/gv-station-context-menu.c --- goodvibes-0.3.6/src/ui/gv-station-context-menu.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-station-context-menu.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -23,10 +23,10 @@ #include #include -#include "additions/gtk.h" -#include "additions/glib-object.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" +#include "ui/gtk-additions.h" #include "ui/gv-station-dialog.h" #include "ui/gv-ui-internal.h" diff -Nru goodvibes-0.3.6/src/ui/gv-station-context-menu.h goodvibes-0.4.2/src/ui/gv-station-context-menu.h --- goodvibes-0.3.6/src/ui/gv-station-context-menu.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-station-context-menu.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/ui/gv-station-dialog.c goodvibes-0.4.2/src/ui/gv-station-dialog.c --- goodvibes-0.3.6/src/ui/gv-station-dialog.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-station-dialog.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -24,16 +24,15 @@ #include #include -#include "additions/gtk.h" -#include "additions/glib-object.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" -#include "ui/gv-ui-helpers.h" +#include "ui/gtk-additions.h" #include "ui/gv-ui-internal.h" #include "ui/gv-station-dialog.h" -#define UI_FILE "station-dialog.glade" +#define UI_RESOURCE_PATH GV_APPLICATION_PATH "/Ui/station-dialog.glade" /* * Properties @@ -260,11 +259,9 @@ GvStationDialogPrivate *priv = self->priv; GtkWidget *content_area; GtkBuilder *builder; - gchar *uifile; /* Build the ui */ - gv_builder_load(UI_FILE, &builder, &uifile); - DEBUG("Built from ui file '%s'", uifile); + builder = gtk_builder_new_from_resource(UI_RESOURCE_PATH); /* Save widget pointers */ @@ -288,8 +285,7 @@ (GTK_DIALOG(self), GTK_RESPONSE_OK); /* Cleanup */ - g_object_unref(G_OBJECT(builder)); - g_free(uifile); + g_object_unref(builder); } static void diff -Nru goodvibes-0.3.6/src/ui/gv-station-dialog.h goodvibes-0.4.2/src/ui/gv-station-dialog.h --- goodvibes-0.3.6/src/ui/gv-station-dialog.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-station-dialog.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/ui/gv-stations-tree-view.c goodvibes-0.4.2/src/ui/gv-stations-tree-view.c --- goodvibes-0.3.6/src/ui/gv-stations-tree-view.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-stations-tree-view.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -23,7 +23,7 @@ #include #include -#include "additions/glib-object.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" #include "ui/gv-station-context-menu.h" @@ -276,8 +276,8 @@ static gboolean on_tree_view_button_press_event(GvStationsTreeView *self, - GdkEventButton *event, - gpointer data G_GNUC_UNUSED) + GdkEventButton *event, + gpointer data G_GNUC_UNUSED) { GvStationsTreeViewPrivate *priv = self->priv; @@ -294,20 +294,20 @@ * According from the doc, we MUST check that. */ if (event->window != gtk_tree_view_get_bin_window(tree_view)) - return FALSE; + return GDK_EVENT_PROPAGATE; /* Handle only single-click */ if (event->type != GDK_BUTTON_PRESS) - return FALSE; + return GDK_EVENT_PROPAGATE; /* Handle only right-click */ if (event->button != 3) - return FALSE; + return GDK_EVENT_PROPAGATE; /* Do nothing if there's already a context menu (this case shouldn't happen) */ if (priv->context_menu) { WARNING("Context menu already exists !"); - return FALSE; + return GDK_EVENT_PROPAGATE; } /* Get row at this position */ @@ -316,7 +316,7 @@ &path, NULL, NULL, NULL); if (path == NULL) - return FALSE; + return GDK_EVENT_PROPAGATE; /* Get corresponding station */ gtk_tree_model_get_iter(tree_model, &iter, path); @@ -352,7 +352,7 @@ /* Free at last */ gtk_tree_path_free(path); - return FALSE; + return GDK_EVENT_PROPAGATE; } /* diff -Nru goodvibes-0.3.6/src/ui/gv-stations-tree-view.h goodvibes-0.4.2/src/ui/gv-stations-tree-view.h --- goodvibes-0.3.6/src/ui/gv-stations-tree-view.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-stations-tree-view.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/ui/gv-status-icon.c goodvibes-0.4.2/src/ui/gv-status-icon.c --- goodvibes-0.3.6/src/ui/gv-status-icon.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-status-icon.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -25,10 +25,10 @@ #include #include -#include "additions/gtk.h" -#include "additions/glib-object.h" +#include "framework/glib-object-additions.h" #include "framework/gv-framework.h" #include "core/gv-core.h" +#include "ui/gtk-additions.h" #include "ui/gv-ui-enum-types.h" #include "ui/gv-ui-helpers.h" #include "ui/gv-ui-internal.h" @@ -36,6 +36,7 @@ #include "ui/gv-status-icon.h" +#define UI_RESOURCE_PATH GV_APPLICATION_PATH "/Ui/status-icon-menu.glade" #define ICON_MIN_SIZE 16 /* @@ -246,7 +247,7 @@ /* Here we only handle the middle-click */ if (event->button != 2) - return FALSE; + return GDK_EVENT_PROPAGATE; switch (priv->middle_click_action) { case GV_STATUS_ICON_MIDDLE_CLICK_TOGGLE: @@ -261,7 +262,7 @@ break; } - return FALSE; + return GDK_EVENT_PROPAGATE; } static gboolean @@ -302,7 +303,7 @@ break; } - return FALSE; + return GDK_EVENT_PROPAGATE; } static gboolean @@ -507,11 +508,9 @@ GtkBuilder *builder; GMenuModel *model; GtkWidget *menu; - gchar *uifile; /* Load the menu model */ - gv_builder_load("status-icon-menu.glade", &builder, &uifile); - DEBUG("Popup menu built from ui file '%s'", uifile); + builder = gtk_builder_new_from_resource(UI_RESOURCE_PATH); /* Build the menu */ model = G_MENU_MODEL(gtk_builder_get_object(builder, "status-icon-menu")); @@ -524,7 +523,6 @@ priv->popup_menu = g_object_ref_sink(menu); /* Cleanup */ - g_free(uifile); g_object_unref(builder); } @@ -600,29 +598,29 @@ properties[PROP_MIDDLE_CLICK_ACTION] = g_param_spec_enum("middle-click-action", "Middle click action", NULL, - GV_STATUS_ICON_MIDDLE_CLICK_ENUM_TYPE, + GV_TYPE_STATUS_ICON_MIDDLE_CLICK, GV_STATUS_ICON_MIDDLE_CLICK_TOGGLE, GV_PARAM_DEFAULT_FLAGS | G_PARAM_READWRITE); properties[PROP_SCROLL_ACTION] = g_param_spec_enum("scroll-action", "Scroll action", NULL, - GV_STATUS_ICON_SCROLL_ENUM_TYPE, + GV_TYPE_STATUS_ICON_SCROLL, GV_STATUS_ICON_SCROLL_STATION, GV_PARAM_DEFAULT_FLAGS | G_PARAM_READWRITE); g_object_class_install_properties(object_class, PROP_N, properties); /* Register transform function */ - g_value_register_transform_func(GV_STATUS_ICON_MIDDLE_CLICK_ENUM_TYPE, + g_value_register_transform_func(GV_TYPE_STATUS_ICON_MIDDLE_CLICK, G_TYPE_STRING, gv_value_transform_enum_string); g_value_register_transform_func(G_TYPE_STRING, - GV_STATUS_ICON_MIDDLE_CLICK_ENUM_TYPE, + GV_TYPE_STATUS_ICON_MIDDLE_CLICK, gv_value_transform_string_enum); - g_value_register_transform_func(GV_STATUS_ICON_SCROLL_ENUM_TYPE, + g_value_register_transform_func(GV_TYPE_STATUS_ICON_SCROLL, G_TYPE_STRING, gv_value_transform_enum_string); g_value_register_transform_func(G_TYPE_STRING, - GV_STATUS_ICON_SCROLL_ENUM_TYPE, + GV_TYPE_STATUS_ICON_SCROLL, gv_value_transform_string_enum); } diff -Nru goodvibes-0.3.6/src/ui/gv-status-icon.h goodvibes-0.4.2/src/ui/gv-status-icon.h --- goodvibes-0.3.6/src/ui/gv-status-icon.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-status-icon.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/ui/gv-ui.c goodvibes-0.4.2/src/ui/gv-ui.c --- goodvibes-0.3.6/src/ui/gv-ui.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-ui.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -21,9 +21,9 @@ #include -#include "additions/gtk.h" #include "framework/gv-framework.h" #include "core/gv-core.h" +#include "ui/gtk-additions.h" #include "ui/gv-about-dialog.h" #include "ui/gv-main-window.h" #include "ui/gv-main-window-manager.h" @@ -31,6 +31,10 @@ #include "ui/gv-station-dialog.h" #include "ui/gv-status-icon.h" +#include "ui/resources/gv-ui-resources.h" + +#define UI_SCHEMA_ID_SUFFIX "Ui" + /* * Public variables */ @@ -170,8 +174,20 @@ { GList *item; + /* Create resource + * + * The resource object is a bit special, it's a static resource, + * it lives in the data segment, which is read-only. So calling + * g_object_ref() on it causes a segfault, for example. + * + * Actually, we don't even need to keep a reference to this object. + * All we want is to initialize the resource, which is triggered + * by the first access (lazy init). + */ + gv_ui_get_resource(); + /* Create ui objects */ - gv_ui_settings = g_settings_new(PACKAGE_APPLICATION_ID ".Ui"); + gv_ui_settings = gv_get_settings(UI_SCHEMA_ID_SUFFIX); ui_objects = g_list_append(ui_objects, gv_ui_settings); gv_ui_main_window = gv_main_window_new(app, status_icon_mode); @@ -191,6 +207,6 @@ /* Register objects in the framework */ for (item = ui_objects; item; item = item->next) { GObject *object = G_OBJECT(item->data); - gv_framework_register(object); + gv_framework_register_object(object); } } diff -Nru goodvibes-0.3.6/src/ui/gv-ui.h goodvibes-0.4.2/src/ui/gv-ui.h --- goodvibes-0.3.6/src/ui/gv-ui.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-ui.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/ui/gv-ui-helpers.c goodvibes-0.4.2/src/ui/gv-ui-helpers.c --- goodvibes-0.3.6/src/ui/gv-ui-helpers.c 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-ui-helpers.c 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -20,14 +20,6 @@ */ #include -#include - -#include "framework/gv-file-helpers.h" - - -/* - * GValue transform functions - */ void gv_value_transform_enum_string(const GValue *src_value, GValue *dest_value) @@ -66,36 +58,3 @@ g_type_class_unref(enum_class); } - -/* - * Gtk builder helpers - */ - -void -gv_builder_load(const char *filename, GtkBuilder **builder_out, gchar **uifile_out) -{ - gchar *ui_filename; - gchar *file_found; - GtkBuilder *builder; - - g_return_if_fail(builder_out != NULL); - - /* Prepend the 'ui' prefix */ - ui_filename = g_build_filename("ui/", filename, NULL); - - /* Find the location of the ui file */ - file_found = gv_get_first_existing_path(GV_DIR_CURRENT_DATA | GV_DIR_SYSTEM_DATA, - ui_filename); - g_assert_nonnull(file_found); - g_free(ui_filename); - - /* Build ui from file */ - builder = gtk_builder_new_from_file(file_found); - - /* Fill output parameters */ - *builder_out = builder; - if (uifile_out) - *uifile_out = file_found; - else - g_free(file_found); -} diff -Nru goodvibes-0.3.6/src/ui/gv-ui-helpers.h goodvibes-0.4.2/src/ui/gv-ui-helpers.h --- goodvibes-0.3.6/src/ui/gv-ui-helpers.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-ui-helpers.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -23,19 +23,8 @@ #define __GOODVIBES_UI_GV_UI_HELPERS_H__ #include -#include - -/* - * GValue transform functions - */ void gv_value_transform_enum_string(const GValue *src_value, GValue *dest_value); void gv_value_transform_string_enum(const GValue *src_value, GValue *dest_value); -/* - * Gtk builder helpers - */ - -void gv_builder_load(const char *filename, GtkBuilder **builder, gchar **uifile); - #endif /* __GOODVIBES_UI_GV_UI_HELPERS_H__ */ diff -Nru goodvibes-0.3.6/src/ui/gv-ui-internal.h goodvibes-0.4.2/src/ui/gv-ui-internal.h --- goodvibes-0.3.6/src/ui/gv-ui-internal.h 2018-03-31 11:26:53.000000000 +0000 +++ goodvibes-0.4.2/src/ui/gv-ui-internal.h 2018-11-10 06:04:58.000000000 +0000 @@ -1,7 +1,7 @@ /* * Goodvibes Radio Player * - * Copyright (C) 2015-2017 Arnaud Rebillout + * Copyright (C) 2015-2018 Arnaud Rebillout * * SPDX-License-Identifier: GPL-3.0-or-later * diff -Nru goodvibes-0.3.6/src/ui/meson.build goodvibes-0.4.2/src/ui/meson.build --- goodvibes-0.3.6/src/ui/meson.build 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/ui/meson.build 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Subdirectories + +subdir('resources') + +# Sources and dependencies + +ui_sources = [ + 'gtk-additions.c', + 'gv-about-dialog.c', + 'gv-main-window.c', + 'gv-main-window-manager.c', + 'gv-prefs-window.c', + 'gv-station-context-menu.c', + 'gv-station-dialog.c', + 'gv-stations-tree-view.c', + 'gv-status-icon.c', + 'gv-ui.c', + 'gv-ui-helpers.c', +] + +ui_dependencies = [ + glib_dep, + gobject_dep, + gio_dep, + gtk_dep, + gvframework_dep, + gvcore_dep, +] + +ui_enum_headers = [ 'gv-main-window.h', 'gv-status-icon.h' ] +ui_enums = gnome.mkenums_simple('gv-ui-enum-types', + sources: ui_enum_headers +) +ui_enum_h = ui_enums[1] + +# Library definition + +gvui = static_library('gvui', + sources: [ ui_enums, ui_resources, ui_sources ], + dependencies: ui_dependencies, + include_directories: root_inc, +) + +gvui_dep = declare_dependency( + dependencies: ui_dependencies, + sources: [ ui_enum_h ], + link_with: gvui, +) diff -Nru goodvibes-0.3.6/src/ui/resources/app-menu.glade goodvibes-0.4.2/src/ui/resources/app-menu.glade --- goodvibes-0.3.6/src/ui/resources/app-menu.glade 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/ui/resources/app-menu.glade 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,39 @@ + + + +
+ + Add Station + app.add-station + <Primary>a + +
+
+ + Preferences + app.preferences + +
+
+ + Online Help + app.help + F1 + + + About + app.about + + + Close UI + app.close-ui + <Primary>c + + + Quit + app.quit + <Primary>q + +
+
+
diff -Nru goodvibes-0.3.6/src/ui/resources/io.gitlab.Goodvibes.Ui.gresource.xml.in goodvibes-0.4.2/src/ui/resources/io.gitlab.Goodvibes.Ui.gresource.xml.in --- goodvibes-0.3.6/src/ui/resources/io.gitlab.Goodvibes.Ui.gresource.xml.in 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/ui/resources/io.gitlab.Goodvibes.Ui.gresource.xml.in 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,11 @@ + + + + app-menu.glade + main-window.glade + menubar.glade + prefs-window.glade + station-dialog.glade + status-icon-menu.glade + + diff -Nru goodvibes-0.3.6/src/ui/resources/main-window.glade goodvibes-0.4.2/src/ui/resources/main-window.glade --- goodvibes-0.3.6/src/ui/resources/main-window.glade 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/ui/resources/main-window.glade 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,228 @@ + + + + + + True + False + media-skip-forward-symbolic + + + True + False + media-playback-start-symbolic + + + True + False + media-skip-backward-symbolic + + + True + False + media-playlist-repeat-symbolic + + + True + False + media-playlist-shuffle-symbolic + + + True + False + 6 + 6 + 6 + 6 + vertical + + + True + False + vertical + + + True + False + No station selected + end + + + + + + False + True + 0 + + + + + True + False + Stopped + end + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + start + + + True + True + True + play_image + none + True + + + True + True + 0 + True + + + + + True + True + True + prev_image + none + True + + + True + True + 1 + True + + + + + True + True + True + next_image + none + True + + + True + True + 2 + True + + + + + True + True + True + repeat_image + none + True + + + True + True + 3 + True + True + + + + + True + True + True + shuffle_image + none + True + + + True + True + 4 + True + True + + + + + True + True + False + True + none + vertical + audio-volume-muted-symbolic +audio-volume-high-symbolic +audio-volume-low-symbolic +audio-volume-medium-symbolic + + + True + True + center + center + none + + + + + True + True + center + center + none + + + + + True + True + 5 + True + True + + + + + False + True + 1 + + + + + True + True + in + + + + + + True + True + 2 + + + + diff -Nru goodvibes-0.3.6/src/ui/resources/menubar.glade goodvibes-0.4.2/src/ui/resources/menubar.glade --- goodvibes-0.3.6/src/ui/resources/menubar.glade 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/ui/resources/menubar.glade 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,49 @@ + + + + + Menu +
+ + Add Station + app.add-station + <Primary>a + +
+
+ + Preferences + app.preferences + +
+
+ + Close UI + app.close-ui + <Primary>c + + + Quit + app.quit + <Primary>q + +
+
+ + Help +
+ + Online Help + app.help + F1 + +
+
+ + About + app.about + +
+
+
+
diff -Nru goodvibes-0.3.6/src/ui/resources/meson.build goodvibes-0.4.2/src/ui/resources/meson.build --- goodvibes-0.3.6/src/ui/resources/meson.build 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/ui/resources/meson.build 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Resources + +ui_resources_conf = configuration_data() +ui_resources_conf.set('path', gv_application_path) + +ui_resources_file = configure_file( + input: gv_application_id + '.Ui.gresource.xml.in', + output: gv_application_id + '.Ui.gresource.xml', + configuration: ui_resources_conf, +) + +ui_resources = gnome.compile_resources('gv-ui-resources', + ui_resources_file, + c_name: 'gv_ui', + export: true, +) + +# Validation + +ui_glade_files = [ + 'app-menu.glade', + 'main-window.glade', + 'menubar.glade', + 'prefs-window.glade', + 'station-dialog.glade', + 'status-icon-menu.glade', +] + +validator = find_program(join_paths(meson.source_root(), 'scripts/meson/validate-ui-file')) +foreach file : ui_glade_files + test('Validate ' + file, validator, + args: [ files(file) ], + ) +endforeach diff -Nru goodvibes-0.3.6/src/ui/resources/prefs-window.glade goodvibes-0.4.2/src/ui/resources/prefs-window.glade --- goodvibes-0.3.6/src/ui/resources/prefs-window.glade 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/ui/resources/prefs-window.glade 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,617 @@ + + + + + + 100 + 1 + 10 + + + True + False + vertical + + + True + True + + + True + False + vertical + + + True + False + 0 + none + + + True + False + + + Autoplay on Startup + True + True + False + True + + + 0 + 0 + + + + + Custom Output Pipeline + True + True + False + True + True + + + 0 + 1 + + + + + True + False + 6 + + + True + True + True + + + False + True + 0 + + + + + Apply + True + True + True + + + False + True + 1 + + + + + 0 + 2 + + + + + + + True + False + Playback + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + end + + + True + True + + + 1 + 0 + + + + + True + False + end + Prevent sleep while playing + + + 0 + 0 + + + + + + + True + False + System + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + end + + + True + True + + + 1 + 0 + + + + + True + True + + + 1 + 1 + + + + + True + False + end + Native D-Bus Server + + + 0 + 0 + + + + + True + False + end + MPRIS2 D-Bus Server + + + 0 + 1 + + + + + + + True + False + D-Bus + + + + + False + True + 2 + + + + + + + True + False + Misc + + + False + + + + + True + False + vertical + + + True + False + 0 + none + + + True + False + end + + + Autoset Window Height + True + True + False + True + + + 0 + 1 + + + + + True + False + end + Theme Variant + + + 0 + 0 + + + + + True + False + 0 + + System Default + Prefer Dark + Prefer Light + + + + 1 + 0 + + + + + + + + + + True + False + Window + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + end + + + True + False + start + Send Notifications + + + 0 + 0 + + + + + True + True + + + 1 + 0 + + + + + + + True + False + Notifications + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + end + + + True + True + + + 1 + 0 + + + + + True + False + Console Output + + + 0 + 0 + + + + + + + True + False + Console + + + + + False + True + 2 + + + + + 1 + + + + + True + False + Display + + + 1 + False + + + + + True + False + vertical + + + True + False + 0 + none + + + True + False + end + + + True + True + + + 1 + 0 + + + + + True + False + end + Multimedia Hotkeys + + + 0 + 0 + + + + + + + True + False + Keyboard + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + end + + + True + False + end + Middle Click + + + 0 + 0 + + + + + True + False + 0 + + Toggle Play/Pause + Mute + + + + 1 + 0 + + + + + True + False + end + Scrolling + + + 0 + 1 + + + + + True + False + 0 + + Change Station + Change Volume + + + + 1 + 1 + + + + + + + True + False + Mouse (Status Icon Mode) + + + + + False + True + 1 + + + + + 2 + + + + + True + False + Controls + + + 2 + False + + + + + True + True + 0 + + + + + True + False + end + + + Close + True + True + True + + + True + True + 0 + + + + + False + True + 1 + + + + diff -Nru goodvibes-0.3.6/src/ui/resources/station-dialog.glade goodvibes-0.4.2/src/ui/resources/station-dialog.glade --- goodvibes-0.3.6/src/ui/resources/station-dialog.glade 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/ui/resources/station-dialog.glade 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,53 @@ + + + + + + True + False + + + True + False + Name + + + 0 + 0 + + + + + True + True + True + + + 1 + 0 + + + + + True + False + URI + + + 0 + 1 + + + + + True + True + True + + + 1 + 1 + + + + diff -Nru goodvibes-0.3.6/src/ui/resources/status-icon-menu.glade goodvibes-0.4.2/src/ui/resources/status-icon-menu.glade --- goodvibes-0.3.6/src/ui/resources/status-icon-menu.glade 1970-01-01 00:00:00.000000000 +0000 +++ goodvibes-0.4.2/src/ui/resources/status-icon-menu.glade 2018-11-10 06:04:58.000000000 +0000 @@ -0,0 +1,31 @@ + + + +
+ + Add Station + app.add-station + +
+
+ + Preferences + app.preferences + +
+
+ + Online Help + app.help + + + About + app.about + + + Quit + app.quit + +
+
+