summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrej Shadura <andrew.shadura@collabora.co.uk>2020-03-22 21:20:47 +0100
committerAndrej Shadura <andrew.shadura@collabora.co.uk>2020-03-22 21:20:47 +0100
commitb58a71636eb07843032e644211285b282a307d97 (patch)
tree9fbb580e5038b22cf1a3b9155f27b46554b54515
parent1a988068635ca5f8a74c4654098d07f92bc0dcf4 (diff)
New upstream version 4.0
-rw-r--r--.clang-format7
-rw-r--r--.mailmap1
-rw-r--r--.travis.yml2
-rw-r--r--AUTHORS6
-rw-r--r--COPYING2
-rw-r--r--acinclude.m414
-rw-r--r--audacious.desktop2
-rw-r--r--config.h.in7
-rwxr-xr-xconfigure688
-rw-r--r--configure.ac7
-rw-r--r--contrib/macpack/Audacious.app/Contents/Info.plist34
l---------contrib/macpack/Audacious.app/Contents/MacOS/audacious1
-rw-r--r--contrib/macpack/Audacious.app/Contents/PkgInfo2
-rw-r--r--contrib/macpack/Audacious.app/Contents/version.plist16
-rw-r--r--images/README-svg19
-rw-r--r--images/about-logo.svg2
-rw-r--r--images/application-exit.svg2
-rw-r--r--images/applications-graphics.svg2
-rw-r--r--images/applications-internet.svg2
-rw-r--r--images/applications-system.svg2
-rw-r--r--images/audacious.svg2
-rw-r--r--images/audio-card.svg2
-rw-r--r--images/audio-volume-high.svg2
-rw-r--r--images/audio-volume-low.svg2
-rw-r--r--images/audio-volume-medium.svg2
-rw-r--r--images/audio-volume-muted.svg2
-rw-r--r--images/audio-x-generic.svg2
-rw-r--r--images/dialog-question.svg2
-rw-r--r--images/dialog-warning.svg2
-rw-r--r--images/document-new.svg2
-rw-r--r--images/document-open-recent.svg2
-rw-r--r--images/document-open.svg2
-rw-r--r--images/document-save.svg2
-rw-r--r--images/edit-clear.svg2
-rw-r--r--images/edit-cut.svg2
-rw-r--r--images/edit-delete.svg2
-rw-r--r--images/edit-find.svg2
-rw-r--r--images/edit-paste.svg2
-rw-r--r--images/face-smile.svg2
-rw-r--r--images/folder-remote.svg2
-rw-r--r--images/go-down.svg2
-rw-r--r--images/go-next.svg2
-rw-r--r--images/go-previous.svg2
-rw-r--r--images/go-up.svg2
-rw-r--r--images/help-about.svg2
-rw-r--r--images/insert-text.svg2
-rw-r--r--images/media-optical.svg2
-rw-r--r--images/media-playlist-repeat.svg2
-rw-r--r--images/media-playlist-shuffle.svg2
-rw-r--r--images/meson.build2
-rw-r--r--images/preferences-desktop-font.svg1
-rw-r--r--images/preferences-system.svg2
-rw-r--r--images/process-stop.svg2
-rw-r--r--images/system-run.svg2
-rw-r--r--images/text-x-generic.svg2
-rw-r--r--images/user-desktop.svg2
-rw-r--r--images/user-trash.svg2
-rw-r--r--images/view-refresh.svg2
-rw-r--r--images/view-sort-ascending.svg2
-rw-r--r--images/view-sort-descending.svg2
-rw-r--r--images/window-close.svg2
-rw-r--r--man/audtool.1.in11
-rw-r--r--man/meson.build9
-rw-r--r--meson.build154
-rw-r--r--meson_options.txt4
-rw-r--r--po/LINGUAS46
-rw-r--r--po/bg.po22
-rw-r--r--po/cs.po36
-rw-r--r--po/da.po10
-rw-r--r--po/de.po5
-rw-r--r--po/el.po60
-rw-r--r--po/en_GB.po22
-rw-r--r--po/fr.po16
-rw-r--r--po/id_ID.po8
-rw-r--r--po/ja.po22
-rw-r--r--po/meson.build15
-rw-r--r--po/pl.po32
-rw-r--r--po/pt_BR.po33
-rw-r--r--po/pt_PT.po7
-rw-r--r--po/ru.po4
-rw-r--r--po/sv.po12
-rw-r--r--po/tr.po48
-rw-r--r--po/uk.po188
-rw-r--r--src/audacious/Makefile4
-rw-r--r--src/audacious/dbus-server.cc48
-rw-r--r--src/audacious/main.cc14
-rw-r--r--src/audacious/meson.build24
-rw-r--r--src/audacious/signals.cc9
-rw-r--r--src/audtool/audtool.h4
-rw-r--r--src/audtool/handlers_general.c2
-rw-r--r--src/audtool/handlers_playback.c2
-rw-r--r--src/audtool/handlers_playlist.c12
-rw-r--r--src/audtool/handlers_playqueue.c2
-rw-r--r--src/audtool/handlers_vitals.c2
-rw-r--r--src/audtool/main.c6
-rw-r--r--src/audtool/meson.build23
-rw-r--r--src/audtool/report.c2
-rw-r--r--src/config.h.meson21
-rw-r--r--src/dbus/aud-dbus.xml6
-rw-r--r--src/dbus/meson.build29
-rw-r--r--src/libaudcore/Makefile3
-rw-r--r--src/libaudcore/adder.cc464
-rw-r--r--src/libaudcore/art-search.cc119
-rw-r--r--src/libaudcore/art.cc193
-rw-r--r--src/libaudcore/audio.cc430
-rw-r--r--src/libaudcore/audstrings.cc756
-rw-r--r--src/libaudcore/audstrings.h137
-rw-r--r--src/libaudcore/charset.cc148
-rw-r--r--src/libaudcore/config.cc340
-rw-r--r--src/libaudcore/cue-cache.cc59
-rw-r--r--src/libaudcore/cue-cache.h6
-rw-r--r--src/libaudcore/drct.cc206
-rw-r--r--src/libaudcore/drct.h72
-rw-r--r--src/libaudcore/effect.cc157
-rw-r--r--src/libaudcore/equalizer-preset.cc153
-rw-r--r--src/libaudcore/equalizer.cc150
-rw-r--r--src/libaudcore/equalizer.h28
-rw-r--r--src/libaudcore/eventqueue.cc68
-rw-r--r--src/libaudcore/export.h12
-rw-r--r--src/libaudcore/fft.cc55
-rw-r--r--src/libaudcore/history.cc30
-rw-r--r--src/libaudcore/hook.cc104
-rw-r--r--src/libaudcore/hook.h106
-rw-r--r--src/libaudcore/i18n.h19
-rw-r--r--src/libaudcore/index.cc165
-rw-r--r--src/libaudcore/index.h223
-rw-r--r--src/libaudcore/inifile.cc60
-rw-r--r--src/libaudcore/inifile.h16
-rw-r--r--src/libaudcore/interface.cc157
-rw-r--r--src/libaudcore/interface.h36
-rw-r--r--src/libaudcore/internal.h137
-rw-r--r--src/libaudcore/list.cc8
-rw-r--r--src/libaudcore/list.h61
-rw-r--r--src/libaudcore/logger.cc77
-rw-r--r--src/libaudcore/mainloop.cc204
-rw-r--r--src/libaudcore/mainloop.h28
-rw-r--r--src/libaudcore/meson.build126
-rw-r--r--src/libaudcore/multihash.cc98
-rw-r--r--src/libaudcore/multihash.h206
-rw-r--r--src/libaudcore/objects.h201
-rw-r--r--src/libaudcore/output.cc775
-rw-r--r--src/libaudcore/output.h42
-rw-r--r--src/libaudcore/parse.cc23
-rw-r--r--src/libaudcore/parse.h15
-rw-r--r--src/libaudcore/playback.cc547
-rw-r--r--src/libaudcore/playlist-cache.cc65
-rw-r--r--src/libaudcore/playlist-data.cc1008
-rw-r--r--src/libaudcore/playlist-data.h182
-rw-r--r--src/libaudcore/playlist-files.cc115
-rw-r--r--src/libaudcore/playlist-internal.h45
-rw-r--r--src/libaudcore/playlist-utils.cc383
-rw-r--r--src/libaudcore/playlist.cc1149
-rw-r--r--src/libaudcore/playlist.h254
-rw-r--r--src/libaudcore/plugin-init.cc312
-rw-r--r--src/libaudcore/plugin-load.cc112
-rw-r--r--src/libaudcore/plugin-registry.cc547
-rw-r--r--src/libaudcore/plugin.h308
-rw-r--r--src/libaudcore/plugins-internal.h55
-rw-r--r--src/libaudcore/plugins.h45
-rw-r--r--src/libaudcore/preferences.cc74
-rw-r--r--src/libaudcore/preferences.h424
-rw-r--r--src/libaudcore/probe-buffer.cc80
-rw-r--r--src/libaudcore/probe-buffer.h29
-rw-r--r--src/libaudcore/probe.cc176
-rw-r--r--src/libaudcore/probe.h49
-rw-r--r--src/libaudcore/ringbuf.cc117
-rw-r--r--src/libaudcore/ringbuf.h180
-rw-r--r--src/libaudcore/runtime.cc316
-rw-r--r--src/libaudcore/runtime.h181
-rw-r--r--src/libaudcore/scanner.cc80
-rw-r--r--src/libaudcore/scanner.h18
-rw-r--r--src/libaudcore/stringbuf.cc134
-rw-r--r--src/libaudcore/strpool.cc125
-rw-r--r--src/libaudcore/templates.h327
-rw-r--r--src/libaudcore/tests/test-mainloop.cc21
-rw-r--r--src/libaudcore/threads.h100
-rw-r--r--src/libaudcore/timer.cc80
-rw-r--r--src/libaudcore/tinylock.cc38
-rw-r--r--src/libaudcore/tinylock.h (renamed from src/libaudcore/tinylock.h.in)39
-rw-r--r--src/libaudcore/tuple-compiler.cc286
-rw-r--r--src/libaudcore/tuple-compiler.h10
-rw-r--r--src/libaudcore/tuple.cc560
-rw-r--r--src/libaudcore/tuple.h188
-rw-r--r--src/libaudcore/util.cc141
-rw-r--r--src/libaudcore/vfs.cc253
-rw-r--r--src/libaudcore/vfs.h138
-rw-r--r--src/libaudcore/vfs_async.cc76
-rw-r--r--src/libaudcore/vfs_async.h13
-rw-r--r--src/libaudcore/vfs_local.cc219
-rw-r--r--src/libaudcore/vfs_local.h15
-rw-r--r--src/libaudcore/vis-runner.cc130
-rw-r--r--src/libaudcore/visualization.cc104
-rw-r--r--src/libaudcore/visualizer.h19
-rw-r--r--src/libaudgui/Makefile6
-rw-r--r--src/libaudgui/eq-preset.cc69
-rw-r--r--src/libaudgui/equalizer.cc6
-rw-r--r--src/libaudgui/images.gresource.xml1
-rw-r--r--src/libaudgui/infopopup.cc26
-rw-r--r--src/libaudgui/infowin.cc51
-rw-r--r--src/libaudgui/init.cc2
-rw-r--r--src/libaudgui/libaudgui-gtk.h4
-rw-r--r--src/libaudgui/playlists.cc2
-rw-r--r--src/libaudgui/prefs-widget.cc2
-rw-r--r--src/libaudgui/prefs-window.cc26
-rw-r--r--src/libaudgui/preset-browser.cc76
-rw-r--r--src/libaudgui/preset-browser.h7
-rw-r--r--src/libaudgui/url-opener.cc2
-rw-r--r--src/libaudgui/util.cc93
-rw-r--r--src/libaudqt/Makefile17
-rw-r--r--src/libaudqt/about-qt.cc84
-rw-r--r--src/libaudqt/art-qt.cc57
-rw-r--r--src/libaudqt/audqt.cc212
-rw-r--r--src/libaudqt/colorbutton.cc62
-rw-r--r--src/libaudqt/colorbutton.h52
-rw-r--r--src/libaudqt/eq-preset-qt.cc414
-rw-r--r--src/libaudqt/equalizer-qt.cc197
-rw-r--r--src/libaudqt/export.h12
-rw-r--r--src/libaudqt/file-entry.cc128
-rw-r--r--src/libaudqt/fileopener.cc160
-rw-r--r--src/libaudqt/font-entry.cc167
-rw-r--r--src/libaudqt/iface.h48
-rw-r--r--src/libaudqt/images.qrc1
-rw-r--r--src/libaudqt/info-widget.cc392
-rw-r--r--src/libaudqt/info-widget.h25
-rw-r--r--src/libaudqt/infopopup-qt.cc197
-rw-r--r--src/libaudqt/infowin-qt.cc279
-rw-r--r--src/libaudqt/libaudqt-internal.h19
-rw-r--r--src/libaudqt/libaudqt.h155
-rw-r--r--src/libaudqt/log-inspector.cc239
-rw-r--r--src/libaudqt/menu-qt.cc79
-rw-r--r--src/libaudqt/menu.h81
-rw-r--r--src/libaudqt/meson.build58
-rw-r--r--src/libaudqt/playlist-management.cc120
-rw-r--r--src/libaudqt/plugin-menu-qt.cc51
-rw-r--r--src/libaudqt/prefs-builder.cc112
-rw-r--r--src/libaudqt/prefs-plugin.cc93
-rw-r--r--src/libaudqt/prefs-pluginlist-model.cc122
-rw-r--r--src/libaudqt/prefs-pluginlist-model.h28
-rw-r--r--src/libaudqt/prefs-widget-qt.cc347
-rw-r--r--src/libaudqt/prefs-widget.h135
-rw-r--r--src/libaudqt/prefs-window-qt.cc883
-rw-r--r--src/libaudqt/queue-manager-qt.cc173
-rw-r--r--src/libaudqt/treeview.cc77
-rw-r--r--src/libaudqt/treeview.h49
-rw-r--r--src/libaudqt/url-opener-qt.cc117
-rw-r--r--src/libaudqt/util-qt.cc70
-rw-r--r--src/libaudqt/volumebutton.cc171
-rw-r--r--src/libaudtag/Makefile4
-rw-r--r--src/libaudtag/ape/ape.cc22
-rw-r--r--src/libaudtag/builtin.h2
-rw-r--r--src/libaudtag/id3/id3v22.cc2
-rw-r--r--src/libaudtag/id3/id3v24.cc2
-rw-r--r--src/libaudtag/meson.build27
-rw-r--r--src/libguess/meson.build15
-rw-r--r--src/meson.build36
-rw-r--r--win32/merge.sh2
-rwxr-xr-x[-rw-r--r--]win32/notes.html101
-rw-r--r--win32/patches/gtk-parentheses.diff67
-rw-r--r--win32/patches/lame-3.99.diff61
-rw-r--r--win32/patches/libbs2b-makefile.am.diff11
-rw-r--r--win32/patches/libcdio-0.83.diff40
-rw-r--r--win32/patches/libcue-install-dll.diff11
-rw-r--r--win32/patches/libfaad-decoder.c.diff13
-rw-r--r--win32/patches/libfaad-main.c.diff10
-rw-r--r--win32/patches/libfaad-makefile.am.diff11
-rw-r--r--win32/patches/libmp3lame.sym.diff8
266 files changed, 14114 insertions, 10600 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..9c546c4
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,7 @@
+BasedOnStyle: LLVM
+IndentWidth: 4
+AccessModifierOffset: -4
+BreakBeforeBraces: Allman
+PointerAlignment: Middle
+SpaceAfterTemplateKeyword: false
+AlwaysBreakTemplateDeclarations: Yes
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000..28c0689
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1 @@
+Ariadne Conill <ariadne@dereferenced.org> <nenolod@dereferenced.org>
diff --git a/.travis.yml b/.travis.yml
index ea5e23b..fea03d3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,7 @@ before_install:
- sudo apt-get install libgtk2.0-dev qtbase5-dev
script:
- ./autogen.sh
- - ./configure --prefix=/opt/aud --enable-qt
+ - ./configure --prefix=/opt/aud --enable-gtk
- make
- cd src/libaudcore/tests
- make test
diff --git a/AUTHORS b/AUTHORS
index 67b67f1..b02f864 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -4,8 +4,8 @@ Audacious was originally based on the X Multimedia System (“XMMS”) via its
GTK+ 2.x port Beep Media Player (“BMP”). Audacious has changed quite a bit
since its first release, however, and little XMMS/BMP code remains.
-The Audacious project began in 2005 under the leadership of William Pitcock
-(“nenolod”). Many people have made contributions, both large and small, since
+The Audacious project began in 2005 under the leadership of Ariadne Conill
+(“kaniini”). Many people have made contributions, both large and small, since
that time. At present, the project is led by John Lindgren and Michał Lipski
(“tallica”), with help from a few others. Special thanks go to Michał Lipski
for setting up and maintaining the current website, and to Thomas Lange for
@@ -29,6 +29,7 @@ Audacious was written by:
Daniel Barkalow
René Bertin
Christian Birchinger
+ Ariadne Conill
Ralf Ertzinger
Michael Färber
Matti Hämäläinen
@@ -41,7 +42,6 @@ Audacious was written by:
Giacomo Lozito
Mikael Magnusson
Tomasz Moń
- William Pitcock
Paula Stanciu
Ben Tucker
Tony Vroon
diff --git a/COPYING b/COPYING
index ac6c59e..ff618fb 100644
--- a/COPYING
+++ b/COPYING
@@ -1,6 +1,6 @@
LICENSE
-Copyright © 2001-2018 Audacious developers and others
+Copyright © 2001-2020 Audacious developers and others
(A list of the copyright holders is provided in the AUTHORS file.)
diff --git a/acinclude.m4 b/acinclude.m4
index 401f335..5e25b37 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -177,16 +177,18 @@ dnl =======================
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.32)
PKG_CHECK_MODULES(GMODULE, gmodule-2.0 >= 2.32)
+AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_32], [target GLib 2.32])
+
dnl GTK+ support
dnl =============
AC_ARG_ENABLE(gtk,
- AS_HELP_STRING(--disable-gtk, [Disable GTK+ support (default=enabled)]),
- USE_GTK=$enableval, USE_GTK=yes)
+ AS_HELP_STRING(--enable-gtk, [Enable GTK+ support (default=disabled)]),
+ USE_GTK=$enableval, USE_GTK=no)
if test $USE_GTK = yes ; then
PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.24)
- AC_DEFINE(USE_GTK, 1, [Define if GTK+ support enabled])
+ AC_DEFINE([USE_GTK], [1], [Define if GTK+ support enabled])
fi
AC_SUBST(USE_GTK)
@@ -210,14 +212,14 @@ dnl Qt support
dnl ==========
AC_ARG_ENABLE(qt,
- AS_HELP_STRING(--enable-qt, [Enable Qt support (default=disabled)]),
- USE_QT=$enableval, USE_QT=no)
+ AS_HELP_STRING(--disable-qt, [Disable Qt support (default=enabled)]),
+ USE_QT=$enableval, USE_QT=yes)
if test $USE_QT = yes ; then
PKG_CHECK_MODULES([QTCORE], [Qt5Core >= 5.2])
PKG_CHECK_VAR([QTBINPATH], [Qt5Core >= 5.2], [host_bins])
PKG_CHECK_MODULES([QT], [Qt5Core Qt5Gui Qt5Widgets >= 5.2])
- AC_DEFINE(USE_QT, 1, [Define if Qt support enabled])
+ AC_DEFINE([USE_QT], [1], [Define if Qt support enabled])
# needed if Qt was built with -reduce-relocations
QTCORE_CFLAGS="$QTCORE_CFLAGS -fPIC"
diff --git a/audacious.desktop b/audacious.desktop
index fe29e70..1ecd8c9 100644
--- a/audacious.desktop
+++ b/audacious.desktop
@@ -10,7 +10,7 @@ Exec=audacious %U
TryExec=audacious
StartupNotify=true
Terminal=false
-MimeType=application/ogg;application/x-cue;application/x-ogg;application/xspf+xml;audio/midi;audio/mp3;audio/mp4;audio/mpeg;audio/mpegurl;audio/ogg;audio/prs.sid;audio/x-flac;audio/x-it;audio/x-mod;audio/x-mp3;audio/x-mpeg;audio/x-mpegurl;audio/x-ms-asx;audio/x-ms-wma;audio/x-musepack;audio/x-s3m;audio/x-scpls;audio/x-stm;audio/x-vorbis+ogg;audio/x-wav;audio/x-wavpack;audio/x-xm;x-content/audio-cdda;
+MimeType=application/ogg;application/x-cue;application/x-ogg;application/xspf+xml;audio/aac;audio/flac;audio/midi;audio/mp3;audio/mp4;audio/mpeg;audio/mpegurl;audio/ogg;audio/prs.sid;audio/wav;audio/x-flac;audio/x-it;audio/x-mod;audio/x-mp3;audio/x-mpeg;audio/x-mpegurl;audio/x-ms-asx;audio/x-ms-wma;audio/x-musepack;audio/x-s3m;audio/x-scpls;audio/x-stm;audio/x-vorbis+ogg;audio/x-wav;audio/x-wavpack;audio/x-xm;x-content/audio-cdda;
Comment[ar]=استمع إلى الموسيقى
Comment[be]=Слухайце музыку
diff --git a/config.h.in b/config.h.in
index 52da6ba..7b294bd 100644
--- a/config.h.in
+++ b/config.h.in
@@ -16,10 +16,17 @@
/* Define to compiler syntax for public symbols */
#undef EXPORT
+/* target GLib 2.32 */
+#undef GLIB_VERSION_MIN_REQUIRED
+
/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the
CoreFoundation framework. */
#undef HAVE_CFLOCALECOPYCURRENT
+/* Define to 1 if you have the Mac OS X function
+ CFLocaleCopyPreferredLanguages in the CoreFoundation framework. */
+#undef HAVE_CFLOCALECOPYPREFERREDLANGUAGES
+
/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in
the CoreFoundation framework. */
#undef HAVE_CFPREFERENCESCOPYAPPVALUE
diff --git a/configure b/configure
index 0be2fa4..024d177 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for audacious 3.10.1.
+# Generated by GNU Autoconf 2.69 for audacious 4.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -9,7 +9,7 @@
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
#
-# Copyright (C) 2001-2018 Audacious developers and others
+# Copyright (C) 2001-2020 Audacious developers and others
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##
@@ -579,8 +579,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='audacious'
PACKAGE_TARNAME='audacious'
-PACKAGE_VERSION='3.10.1'
-PACKAGE_STRING='audacious 3.10.1'
+PACKAGE_VERSION='4.0'
+PACKAGE_STRING='audacious 4.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -648,11 +648,11 @@ LIBINTL
INTLLIBS
INTL_MACOSX_LIBS
XGETTEXT_EXTRA_OPTIONS
+MSGMERGE_FOR_MSGFMT_OPTION
MSGMERGE
XGETTEXT_015
XGETTEXT
GMSGFMT_015
-MSGFMT_015
GMSGFMT
MSGFMT
GETTEXT_MACRO_VERSION
@@ -1369,7 +1369,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures audacious 3.10.1 to adapt to many kinds of systems.
+\`configure' configures audacious 4.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1435,7 +1435,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of audacious 3.10.1:";;
+ short | recursive ) echo "Configuration of audacious 4.0:";;
esac
cat <<\_ACEOF
@@ -1444,8 +1444,8 @@ Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-largefile omit support for large files
- --disable-gtk Disable GTK+ support (default=enabled)
- --enable-qt Enable Qt support (default=disabled)
+ --enable-gtk Enable GTK+ support (default=disabled)
+ --disable-qt Disable Qt support (default=enabled)
--disable-rpath do not hardcode runtime library paths
--disable-nls do not use Native Language Support
--disable-dbus Disable D-Bus support (default=enabled)
@@ -1568,14 +1568,14 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-audacious configure 3.10.1
+audacious configure 4.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
-Copyright (C) 2001-2018 Audacious developers and others
+Copyright (C) 2001-2020 Audacious developers and others
_ACEOF
exit
fi
@@ -2036,7 +2036,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by audacious $as_me 3.10.1, which was
+It was created by audacious $as_me 4.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2398,7 +2398,7 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
-COPYRIGHT="Copyright (C) 2001-2018 Audacious developers and others"
+COPYRIGHT="Copyright (C) 2001-2020 Audacious developers and others"
cat >>confdefs.h <<_ACEOF
#define COPYRIGHT "$COPYRIGHT"
@@ -6389,11 +6389,15 @@ $as_echo "yes" >&6; }
fi
+$as_echo "#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_32" >>confdefs.h
+
+
+
# Check whether --enable-gtk was given.
if test "${enable_gtk+set}" = set; then :
enableval=$enable_gtk; USE_GTK=$enableval
else
- USE_GTK=yes
+ USE_GTK=no
fi
@@ -6696,7 +6700,7 @@ fi
if test "${enable_qt+set}" = set; then :
enableval=$enable_qt; USE_QT=$enableval
else
- USE_QT=no
+ USE_QT=yes
fi
@@ -7115,38 +7119,12 @@ if test "${PATH_SEPARATOR+set}" != set; then
}
fi
-ac_prog=ld
-if test "$GCC" = yes; then
- # Check if gcc -print-prog-name=ld gives a path.
+if test -n "$LD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld" >&5
+$as_echo_n "checking for ld... " >&6; }
+elif test "$GCC" = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
$as_echo_n "checking for ld used by $CC... " >&6; }
- case $host in
- *-*-mingw*)
- # gcc leaves a trailing carriage return which upsets mingw
- ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
- *)
- ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
- esac
- case $ac_prog in
- # Accept absolute paths.
- [\\/]* | ?:[\\/]*)
- re_direlt='/[^/][^/]*/\.\./'
- # Canonicalize the pathname of ld
- ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'`
- while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do
- ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
- done
- test -z "$LD" && LD="$ac_prog"
- ;;
- "")
- # If it fails, then pretend we aren't using GCC.
- ac_prog=ld
- ;;
- *)
- # If it is relative, then search for the first ld in PATH.
- with_gnu_ld=unknown
- ;;
- esac
elif test "$with_gnu_ld" = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
$as_echo_n "checking for GNU ld... " >&6; }
@@ -7154,44 +7132,129 @@ else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
$as_echo_n "checking for non-GNU ld... " >&6; }
fi
-if ${acl_cv_path_LD+:} false; then :
+if test -n "$LD"; then
+ # Let the user override the test with a path.
+ :
+else
+ if ${acl_cv_path_LD+:} false; then :
$as_echo_n "(cached) " >&6
else
- if test -z "$LD"; then
- acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in $PATH; do
- IFS="$acl_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
- acl_cv_path_LD="$ac_dir/$ac_prog"
- # Check to see if the program is GNU ld. I'd rather use --version,
- # but apparently some variants of GNU ld only accept -v.
- # Break only if it was the GNU/non-GNU ld that we prefer.
- case `"$acl_cv_path_LD" -v 2>&1 </dev/null` in
- *GNU* | *'with BFD'*)
- test "$with_gnu_ld" != no && break
- ;;
- *)
- test "$with_gnu_ld" != yes && break
- ;;
+
+ acl_cv_path_LD= # Final result of this test
+ ac_prog=ld # Program to search in $PATH
+ if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ acl_output=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ acl_output=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $acl_output in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ acl_output=`echo "$acl_output" | sed 's%\\\\%/%g'`
+ while echo "$acl_output" | grep "$re_direlt" > /dev/null 2>&1; do
+ acl_output=`echo $acl_output | sed "s%$re_direlt%/%"`
+ done
+ # Got the pathname. No search in PATH is needed.
+ acl_cv_path_LD="$acl_output"
+ ac_prog=
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
esac
fi
- done
- IFS="$acl_save_ifs"
+ if test -n "$ac_prog"; then
+ # Search for $ac_prog in $PATH.
+ acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$acl_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ acl_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$acl_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$acl_save_ifs"
+ fi
+ case $host in
+ *-*-aix*)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if defined __powerpc64__ || defined _ARCH_PPC64
+ int ok;
+ #else
+ error fail
+ #endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # The compiler produces 64-bit code. Add option '-b64' so that the
+ # linker groks 64-bit object files.
+ case "$acl_cv_path_LD " in
+ *" -b64 "*) ;;
+ *) acl_cv_path_LD="$acl_cv_path_LD -b64" ;;
+ esac
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+ sparc64-*-netbsd*)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if defined __sparcv9 || defined __arch64__
+ int ok;
+ #else
+ error fail
+ #endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
else
- acl_cv_path_LD="$LD" # Let the user override the test with a path.
+ # The compiler produces 32-bit code. Add option '-m elf32_sparc'
+ # so that the linker groks 32-bit object files.
+ case "$acl_cv_path_LD " in
+ *" -m elf32_sparc "*) ;;
+ *) acl_cv_path_LD="$acl_cv_path_LD -m elf32_sparc" ;;
+ esac
+
fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+ esac
+
fi
-LD="$acl_cv_path_LD"
+ LD="$acl_cv_path_LD"
+fi
if test -n "$LD"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
$as_echo "$LD" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
+ as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
fi
-test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
if ${acl_cv_prog_gnu_ld+:} false; then :
@@ -7248,67 +7311,324 @@ fi
- acl_libdirstem=lib
- acl_libdirstem2=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking 32-bit host C ABI" >&5
+$as_echo_n "checking 32-bit host C ABI... " >&6; }
+if ${gl_cv_host_cpu_c_abi_32bit+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$gl_cv_host_cpu_c_abi"; then
+ case "$gl_cv_host_cpu_c_abi" in
+ i386 | x86_64-x32 | arm | armhf | arm64-ilp32 | hppa | ia64-ilp32 | mips | mipsn32 | powerpc | riscv*-ilp32* | s390 | sparc)
+ gl_cv_host_cpu_c_abi_32bit=yes ;;
+ *)
+ gl_cv_host_cpu_c_abi_32bit=no ;;
+ esac
+ else
+ case "$host_cpu" in
+
+ i[4567]86 )
+ gl_cv_host_cpu_c_abi_32bit=yes
+ ;;
+
+ x86_64 )
+ # On x86_64 systems, the C compiler may be generating code in one of
+ # these ABIs:
+ # - 64-bit instruction set, 64-bit pointers, 64-bit 'long': x86_64.
+ # - 64-bit instruction set, 64-bit pointers, 32-bit 'long': x86_64
+ # with native Windows (mingw, MSVC).
+ # - 64-bit instruction set, 32-bit pointers, 32-bit 'long': x86_64-x32.
+ # - 32-bit instruction set, 32-bit pointers, 32-bit 'long': i386.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if (defined __x86_64__ || defined __amd64__ \
+ || defined _M_X64 || defined _M_AMD64) \
+ && !(defined __ILP32__ || defined _ILP32)
+ int ok;
+ #else
+ error fail
+ #endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gl_cv_host_cpu_c_abi_32bit=no
+else
+ gl_cv_host_cpu_c_abi_32bit=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+
+ arm* | aarch64 )
+ # Assume arm with EABI.
+ # On arm64 systems, the C compiler may be generating code in one of
+ # these ABIs:
+ # - aarch64 instruction set, 64-bit pointers, 64-bit 'long': arm64.
+ # - aarch64 instruction set, 32-bit pointers, 32-bit 'long': arm64-ilp32.
+ # - 32-bit instruction set, 32-bit pointers, 32-bit 'long': arm or armhf.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if defined __aarch64__ && !(defined __ILP32__ || defined _ILP32)
+ int ok;
+ #else
+ error fail
+ #endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gl_cv_host_cpu_c_abi_32bit=no
+else
+ gl_cv_host_cpu_c_abi_32bit=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+
+ hppa1.0 | hppa1.1 | hppa2.0* | hppa64 )
+ # On hppa, the C compiler may be generating 32-bit code or 64-bit
+ # code. In the latter case, it defines _LP64 and __LP64__.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __LP64__
+ int ok;
+ #else
+ error fail
+ #endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gl_cv_host_cpu_c_abi_32bit=no
+else
+ gl_cv_host_cpu_c_abi_32bit=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+
+ ia64* )
+ # On ia64 on HP-UX, the C compiler may be generating 64-bit code or
+ # 32-bit code. In the latter case, it defines _ILP32.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef _ILP32
+ int ok;
+ #else
+ error fail
+ #endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gl_cv_host_cpu_c_abi_32bit=yes
+else
+ gl_cv_host_cpu_c_abi_32bit=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+
+ mips* )
+ # We should also check for (_MIPS_SZPTR == 64), but gcc keeps this
+ # at 32.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if defined _MIPS_SZLONG && (_MIPS_SZLONG == 64)
+ int ok;
+ #else
+ error fail
+ #endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gl_cv_host_cpu_c_abi_32bit=no
+else
+ gl_cv_host_cpu_c_abi_32bit=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+
+ powerpc* )
+ # Different ABIs are in use on AIX vs. Mac OS X vs. Linux,*BSD.
+ # No need to distinguish them here; the caller may distinguish
+ # them based on the OS.
+ # On powerpc64 systems, the C compiler may still be generating
+ # 32-bit code. And on powerpc-ibm-aix systems, the C compiler may
+ # be generating 64-bit code.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if defined __powerpc64__ || defined _ARCH_PPC64
+ int ok;
+ #else
+ error fail
+ #endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gl_cv_host_cpu_c_abi_32bit=no
+else
+ gl_cv_host_cpu_c_abi_32bit=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+
+ rs6000 )
+ gl_cv_host_cpu_c_abi_32bit=yes
+ ;;
+
+ riscv32 | riscv64 )
+ # There are 6 ABIs: ilp32, ilp32f, ilp32d, lp64, lp64f, lp64d.
+ # Size of 'long' and 'void *':
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if defined __LP64__
+ int ok;
+ #else
+ error fail
+ #endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gl_cv_host_cpu_c_abi_32bit=no
+else
+ gl_cv_host_cpu_c_abi_32bit=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+
+ s390* )
+ # On s390x, the C compiler may be generating 64-bit (= s390x) code
+ # or 31-bit (= s390) code.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if defined __LP64__ || defined __s390x__
+ int ok;
+ #else
+ error fail
+ #endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gl_cv_host_cpu_c_abi_32bit=no
+else
+ gl_cv_host_cpu_c_abi_32bit=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+
+ sparc | sparc64 )
+ # UltraSPARCs running Linux have `uname -m` = "sparc64", but the
+ # C compiler still generates 32-bit code.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if defined __sparcv9 || defined __arch64__
+ int ok;
+ #else
+ error fail
+ #endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gl_cv_host_cpu_c_abi_32bit=no
+else
+ gl_cv_host_cpu_c_abi_32bit=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+
+ *)
+ gl_cv_host_cpu_c_abi_32bit=no
+ ;;
+ esac
+ fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_host_cpu_c_abi_32bit" >&5
+$as_echo "$gl_cv_host_cpu_c_abi_32bit" >&6; }
+
+ HOST_CPU_C_ABI_32BIT="$gl_cv_host_cpu_c_abi_32bit"
+
+
+
+
+
case "$host_os" in
solaris*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit host" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit host" >&5
$as_echo_n "checking for 64-bit host... " >&6; }
if ${gl_cv_solaris_64bit+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-
#ifdef _LP64
-sixtyfour bits
-#endif
+ int ok;
+ #else
+ error fail
+ #endif
_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "sixtyfour bits" >/dev/null 2>&1; then :
+if ac_fn_c_try_compile "$LINENO"; then :
gl_cv_solaris_64bit=yes
else
gl_cv_solaris_64bit=no
fi
-rm -f conftest*
-
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_solaris_64bit" >&5
-$as_echo "$gl_cv_solaris_64bit" >&6; }
- if test $gl_cv_solaris_64bit = yes; then
- acl_libdirstem=lib/64
- case "$host_cpu" in
- sparc*) acl_libdirstem2=lib/sparcv9 ;;
- i*86 | x86_64) acl_libdirstem2=lib/amd64 ;;
- esac
- fi
- ;;
- *)
- searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
- if test -n "$searchpath"; then
- acl_save_IFS="${IFS= }"; IFS=":"
- for searchdir in $searchpath; do
- if test -d "$searchdir"; then
- case "$searchdir" in
- */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
- */../ | */.. )
- # Better ignore directories of this form. They are misleading.
- ;;
- *) searchdir=`cd "$searchdir" && pwd`
- case "$searchdir" in
- */lib64 ) acl_libdirstem=lib64 ;;
- esac ;;
- esac
- fi
- done
- IFS="$acl_save_IFS"
- fi
- ;;
+$as_echo "$gl_cv_solaris_64bit" >&6; };;
esac
- test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the common suffixes of directories in the library search path" >&5
+$as_echo_n "checking for the common suffixes of directories in the library search path... " >&6; }
+if ${acl_cv_libdirstems+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ acl_libdirstem=lib
+ acl_libdirstem2=
+ case "$host_os" in
+ solaris*)
+ if test $gl_cv_solaris_64bit = yes; then
+ acl_libdirstem=lib/64
+ case "$host_cpu" in
+ sparc*) acl_libdirstem2=lib/sparcv9 ;;
+ i*86 | x86_64) acl_libdirstem2=lib/amd64 ;;
+ esac
+ fi
+ ;;
+ *)
+ if test "$HOST_CPU_C_ABI_32BIT" != yes; then
+ searchpath=`(if test -f /usr/bin/gcc \
+ && LC_ALL=C /usr/bin/gcc -print-search-dirs >/dev/null 2>/dev/null; then \
+ LC_ALL=C /usr/bin/gcc -print-search-dirs; \
+ else \
+ LC_ALL=C $CC -print-search-dirs; \
+ fi) 2>/dev/null \
+ | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
+ if test -n "$searchpath"; then
+ acl_save_IFS="${IFS= }"; IFS=":"
+ for searchdir in $searchpath; do
+ if test -d "$searchdir"; then
+ case "$searchdir" in
+ */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
+ */../ | */.. )
+ # Better ignore directories of this form. They are misleading.
+ ;;
+ *) searchdir=`cd "$searchdir" && pwd`
+ case "$searchdir" in
+ */lib64 ) acl_libdirstem=lib64 ;;
+ esac ;;
+ esac
+ fi
+ done
+ IFS="$acl_save_IFS"
+ fi
+ fi
+ ;;
+ esac
+ test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem"
+ acl_cv_libdirstems="$acl_libdirstem,$acl_libdirstem2"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_libdirstems" >&5
+$as_echo "$acl_cv_libdirstems" >&6; }
+ # Decompose acl_cv_libdirstems into acl_libdirstem and acl_libdirstem2.
+ acl_libdirstem=`echo "$acl_cv_libdirstems" | sed -e 's/,.*//'`
+ acl_libdirstem2=`echo "$acl_cv_libdirstems" | sed -e '/,/s/.*,//'`
@@ -7357,7 +7677,7 @@ if test "${with_libiconv_prefix+set}" = set; then :
additional_includedir="$withval/include"
additional_libdir="$withval/$acl_libdirstem"
if test "$acl_libdirstem2" != "$acl_libdirstem" \
- && ! test -d "$withval/$acl_libdirstem"; then
+ && test ! -d "$withval/$acl_libdirstem"; then
additional_libdir="$withval/$acl_libdirstem2"
fi
fi
@@ -7779,7 +8099,6 @@ fi
-
am_save_CPPFLAGS="$CPPFLAGS"
for element in $INCICONV; do
@@ -7980,15 +8299,27 @@ int result = 0;
#endif
/* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
provided. */
- if (/* Try standardized names. */
- iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
- /* Try IRIX, OSF/1 names. */
- && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
- /* Try AIX names. */
- && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
- /* Try HP-UX names. */
- && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
- result |= 16;
+ {
+ /* Try standardized names. */
+ iconv_t cd1 = iconv_open ("UTF-8", "EUC-JP");
+ /* Try IRIX, OSF/1 names. */
+ iconv_t cd2 = iconv_open ("UTF-8", "eucJP");
+ /* Try AIX names. */
+ iconv_t cd3 = iconv_open ("UTF-8", "IBM-eucJP");
+ /* Try HP-UX names. */
+ iconv_t cd4 = iconv_open ("utf8", "eucJP");
+ if (cd1 == (iconv_t)(-1) && cd2 == (iconv_t)(-1)
+ && cd3 == (iconv_t)(-1) && cd4 == (iconv_t)(-1))
+ result |= 16;
+ if (cd1 != (iconv_t)(-1))
+ iconv_close (cd1);
+ if (cd2 != (iconv_t)(-1))
+ iconv_close (cd2);
+ if (cd3 != (iconv_t)(-1))
+ iconv_close (cd3);
+ if (cd4 != (iconv_t)(-1))
+ iconv_close (cd4);
+ }
return result;
;
@@ -8078,13 +8409,15 @@ fi
$am_cv_proto_iconv" >&5
$as_echo "
$am_cv_proto_iconv" >&6; }
+ else
+ am_cv_proto_iconv_arg1=""
+ fi
cat >>confdefs.h <<_ACEOF
#define ICONV_CONST $am_cv_proto_iconv_arg1
_ACEOF
- fi
LIBS="$LIBS $LIBICONV"
@@ -8339,7 +8672,7 @@ $as_echo "$USE_NLS" >&6; }
- GETTEXT_MACRO_VERSION=0.19
+ GETTEXT_MACRO_VERSION=0.20
@@ -8454,12 +8787,7 @@ fi
- case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
- '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;;
- *) MSGFMT_015=$MSGFMT ;;
- esac
-
- case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
+ case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;;
*) GMSGFMT_015=$GMSGFMT ;;
esac
@@ -8611,7 +8939,15 @@ $as_echo "no" >&6; }
fi
- test -n "$localedir" || localedir='${datadir}/locale'
+ if LC_ALL=C $MSGMERGE --help | grep ' --for-msgfmt ' >/dev/null; then
+ MSGMERGE_FOR_MSGFMT_OPTION='--for-msgfmt'
+ else
+ if LC_ALL=C $MSGMERGE --help | grep ' --no-fuzzy-matching ' >/dev/null; then
+ MSGMERGE_FOR_MSGFMT_OPTION='--no-fuzzy-matching --no-location --quiet'
+ else
+ MSGMERGE_FOR_MSGFMT_OPTION='--no-location --quiet'
+ fi
+ fi
test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS=
@@ -8643,7 +8979,6 @@ fi
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5
$as_echo_n "checking for CFPreferencesCopyAppValue... " >&6; }
if ${gt_cv_func_CFPreferencesCopyAppValue+:} false; then :
@@ -8712,8 +9047,44 @@ $as_echo "$gt_cv_func_CFLocaleCopyCurrent" >&6; }
$as_echo "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h
fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyPreferredLanguages" >&5
+$as_echo_n "checking for CFLocaleCopyPreferredLanguages... " >&6; }
+if ${gt_cv_func_CFLocaleCopyPreferredLanguages+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gt_save_LIBS="$LIBS"
+ LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <CoreFoundation/CFLocale.h>
+int
+main ()
+{
+CFLocaleCopyPreferredLanguages();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ gt_cv_func_CFLocaleCopyPreferredLanguages=yes
+else
+ gt_cv_func_CFLocaleCopyPreferredLanguages=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$gt_save_LIBS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyPreferredLanguages" >&5
+$as_echo "$gt_cv_func_CFLocaleCopyPreferredLanguages" >&6; }
+ if test $gt_cv_func_CFLocaleCopyPreferredLanguages = yes; then
+
+$as_echo "#define HAVE_CFLOCALECOPYPREFERREDLANGUAGES 1" >>confdefs.h
+
+ fi
INTL_MACOSX_LIBS=
- if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then
+ if test $gt_cv_func_CFPreferencesCopyAppValue = yes \
+ || test $gt_cv_func_CFLocaleCopyCurrent = yes \
+ || test $gt_cv_func_CFLocaleCopyPreferredLanguages = yes; then
INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation"
fi
@@ -9001,15 +9372,27 @@ int result = 0;
#endif
/* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
provided. */
- if (/* Try standardized names. */
- iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
- /* Try IRIX, OSF/1 names. */
- && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
- /* Try AIX names. */
- && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
- /* Try HP-UX names. */
- && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
- result |= 16;
+ {
+ /* Try standardized names. */
+ iconv_t cd1 = iconv_open ("UTF-8", "EUC-JP");
+ /* Try IRIX, OSF/1 names. */
+ iconv_t cd2 = iconv_open ("UTF-8", "eucJP");
+ /* Try AIX names. */
+ iconv_t cd3 = iconv_open ("UTF-8", "IBM-eucJP");
+ /* Try HP-UX names. */
+ iconv_t cd4 = iconv_open ("utf8", "eucJP");
+ if (cd1 == (iconv_t)(-1) && cd2 == (iconv_t)(-1)
+ && cd3 == (iconv_t)(-1) && cd4 == (iconv_t)(-1))
+ result |= 16;
+ if (cd1 != (iconv_t)(-1))
+ iconv_close (cd1);
+ if (cd2 != (iconv_t)(-1))
+ iconv_close (cd2);
+ if (cd3 != (iconv_t)(-1))
+ iconv_close (cd3);
+ if (cd4 != (iconv_t)(-1))
+ iconv_close (cd4);
+ }
return result;
;
@@ -9062,7 +9445,6 @@ $as_echo "$LIBICONV" >&6; }
-
use_additional=yes
acl_save_prefix="$prefix"
@@ -9100,7 +9482,7 @@ if test "${with_libintl_prefix+set}" = set; then :
additional_includedir="$withval/include"
additional_libdir="$withval/$acl_libdirstem"
if test "$acl_libdirstem2" != "$acl_libdirstem" \
- && ! test -d "$withval/$acl_libdirstem"; then
+ && test ! -d "$withval/$acl_libdirstem"; then
additional_libdir="$withval/$acl_libdirstem2"
fi
fi
@@ -9516,7 +9898,6 @@ fi
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libintl" >&5
$as_echo_n "checking for GNU gettext in libintl... " >&6; }
if eval \${$gt_func_gnugettext_libintl+:} false; then :
@@ -9825,10 +10206,10 @@ CPPFLAGS="$CPPFLAGS -include config.h"
### ---------------------------------------------------------------------------
-GENERATED_FILES="audacious.pc buildsys.mk extra.mk man/audtool.1 man/audacious.1 src/libaudcore/audio.h src/libaudcore/tinylock.h win32/audacious.nsi win32/override/README.txt"
+GENERATED_FILES="audacious.pc buildsys.mk extra.mk man/audtool.1 man/audacious.1 src/libaudcore/audio.h win32/audacious.nsi win32/override/README.txt"
-ac_config_files="$ac_config_files audacious.pc buildsys.mk extra.mk man/audtool.1 man/audacious.1 src/libaudcore/audio.h src/libaudcore/tinylock.h win32/audacious.nsi win32/override/README.txt"
+ac_config_files="$ac_config_files audacious.pc buildsys.mk extra.mk man/audtool.1 man/audacious.1 src/libaudcore/audio.h win32/audacious.nsi win32/override/README.txt"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -10470,7 +10851,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by audacious $as_me 3.10.1, which was
+This file was extended by audacious $as_me 4.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -10536,7 +10917,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-audacious config.status 3.10.1
+audacious config.status 4.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -10655,9 +11036,8 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# INIT-COMMANDS
#
# Capture the value of obsolete ALL_LINGUAS because we need it to compute
- # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it
- # from automake < 1.5.
- eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"'
+ # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS.
+ OBSOLETE_ALL_LINGUAS="$ALL_LINGUAS"
# Capture the value of LINGUAS because we need it to compute CATALOGS.
LINGUAS="${LINGUAS-%UNSET%}"
@@ -10678,7 +11058,6 @@ do
"man/audtool.1") CONFIG_FILES="$CONFIG_FILES man/audtool.1" ;;
"man/audacious.1") CONFIG_FILES="$CONFIG_FILES man/audacious.1" ;;
"src/libaudcore/audio.h") CONFIG_FILES="$CONFIG_FILES src/libaudcore/audio.h" ;;
- "src/libaudcore/tinylock.h") CONFIG_FILES="$CONFIG_FILES src/libaudcore/tinylock.h" ;;
"win32/audacious.nsi") CONFIG_FILES="$CONFIG_FILES win32/audacious.nsi" ;;
"win32/override/README.txt") CONFIG_FILES="$CONFIG_FILES win32/override/README.txt" ;;
@@ -11279,14 +11658,11 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
if test -n "$OBSOLETE_ALL_LINGUAS"; then
test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete"
fi
- ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"`
- # Hide the ALL_LINGUAS assignment from automake < 1.5.
- eval 'ALL_LINGUAS''=$ALL_LINGUAS_'
+ ALL_LINGUAS=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"`
POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS"
else
# The set of available languages was given in configure.in.
- # Hide the ALL_LINGUAS assignment from automake < 1.5.
- eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS'
+ ALL_LINGUAS=$OBSOLETE_ALL_LINGUAS
fi
# Compute POFILES
# as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
diff --git a/configure.ac b/configure.ac
index 2bf0c32..f1cbddd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,13 +6,13 @@ dnl Initialize
dnl ==========
AC_PREREQ([2.59])
-AC_INIT([audacious], [3.10.1])
-AC_COPYRIGHT([Copyright (C) 2001-2018 Audacious developers and others])
+AC_INIT([audacious], [4.0])
+AC_COPYRIGHT([Copyright (C) 2001-2020 Audacious developers and others])
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE_NAME", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$PACKAGE_VERSION", [Version number of package])
-COPYRIGHT="Copyright (C) 2001-2018 Audacious developers and others"
+COPYRIGHT="Copyright (C) 2001-2020 Audacious developers and others"
AC_DEFINE_UNQUOTED(COPYRIGHT, "$COPYRIGHT", [Copyright])
AC_SUBST(COPYRIGHT)
@@ -114,7 +114,6 @@ define(GENERATED_FILES,
man/audtool.1
man/audacious.1
src/libaudcore/audio.h
- src/libaudcore/tinylock.h
win32/audacious.nsi
win32/override/README.txt)
diff --git a/contrib/macpack/Audacious.app/Contents/Info.plist b/contrib/macpack/Audacious.app/Contents/Info.plist
index 7898402..77e2fbd 100644
--- a/contrib/macpack/Audacious.app/Contents/Info.plist
+++ b/contrib/macpack/Audacious.app/Contents/Info.plist
@@ -1,24 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>English</string>
- <key>CFBundleDisplayName</key>
- <string>Audacious</string>
- <key>CFBundleExecutable</key>
+ <key>CFBundleName</key>
<string>Audacious</string>
- <key>CFBundleIconFile</key>
- <string>Audacious.icns</string>
<key>CFBundleIdentifier</key>
<string>org.audacious-media-player</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>3.6-devel</string>
- <key>CFBundleName</key>
+ <key>CFBundleDisplayName</key>
<string>Audacious</string>
- <key>CFBundleShortVersionString</key>
- <string>3.6</string>
+ <key>CFBundleIconFile</key>
+ <string>Audacious</string>
+ <key>CFBundleVersion</key>
+ <string>3.11.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>Auda</string>
+ <key>CFBundleExecutable</key>
+ <string>audacious</string>
+ <key>LSMultipleInstancesProhibited</key>
+ <true/>
+ <key>NSHighResolutionCapable</key>
+ <true/>
+ <key>NSHighResolutionMagnifyAllowed</key>
+ <false/>
<key>NSHumanReadableCopyright</key>
- <string>Copyright © 2001-2014 Audacious developers and others</string>
+ <string>Copyright © 2001-2018 Audacious developers and others</string>
</dict>
</plist>
diff --git a/contrib/macpack/Audacious.app/Contents/MacOS/audacious b/contrib/macpack/Audacious.app/Contents/MacOS/audacious
new file mode 120000
index 0000000..16ec655
--- /dev/null
+++ b/contrib/macpack/Audacious.app/Contents/MacOS/audacious
@@ -0,0 +1 @@
+/usr/local/bin/audacious \ No newline at end of file
diff --git a/contrib/macpack/Audacious.app/Contents/PkgInfo b/contrib/macpack/Audacious.app/Contents/PkgInfo
index 36500fb..7b9a4f2 100644
--- a/contrib/macpack/Audacious.app/Contents/PkgInfo
+++ b/contrib/macpack/Audacious.app/Contents/PkgInfo
@@ -1 +1 @@
-Audacious \ No newline at end of file
+APPLAuda \ No newline at end of file
diff --git a/contrib/macpack/Audacious.app/Contents/version.plist b/contrib/macpack/Audacious.app/Contents/version.plist
deleted file mode 100644
index 207b6c4..0000000
--- a/contrib/macpack/Audacious.app/Contents/version.plist
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>BuildVersion</key>
- <string>12</string>
- <key>CFBundleShortVersionString</key>
- <string>1.4</string>
- <key>CFBundleVersion</key>
- <string>220</string>
- <key>ProjectName</key>
- <string>Audacious</string>
- <key>SourceVersion</key>
- <string>1337</string>
-</dict>
-</plist>
diff --git a/images/README-svg b/images/README-svg
new file mode 100644
index 0000000..4cda348
--- /dev/null
+++ b/images/README-svg
@@ -0,0 +1,19 @@
+These SVG files have been un-optimized to work around the following librsvg bug:
+ https://bugzilla.gnome.org/show_bug.cgi?id=620923
+
+Basically, older versions of librsvg can't parse an optimized path like
+".123.456", they need it spelled out as "0.123 0.456".
+
+An SVG file can be un-optimized by the following regex replacements:
+
+Replace once:
+ ([^0-9])\.
+ \10\.
+
+Replace until no longer found:
+ ([0-9]+)\.([0-9]+)\.([0-9|\.|-]+)
+ \1\.\2 0\.\3
+
+Replace once:
+ www0
+ www
diff --git a/images/about-logo.svg b/images/about-logo.svg
index 65843a9..a3d3dda 100644
--- a/images/about-logo.svg
+++ b/images/about-logo.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="761.316" height="139.33" viewBox="0 0 201.432 36.865"><g word-spacing="0" letter-spacing="0" font-family="Circulate (BRK)" font-size="13.333" font-weight="400"><path d="M60.93 0c-2.442 0-4.746.458-6.911 1.374a18.135 18.135 0 0 0-5.705 3.79 17.894 17.894 0 0 0-2.764 3.578 14.717 14.717 0 0 0-2.282-1.208 14.67 14.67 0 0 0-5.945-1.224c-2.098 0-4.08.408-5.945 1.224a14.717 14.717 0 0 0-3.632 2.177c-.19-.212-.383-.42-.585-.622-1.437-1.437-3.133-2.572-5.087-3.406-1.926-.833-3.981-1.25-6.166-1.25-2.213 0-4.282.417-6.208 1.25A16.104 16.104 0 0 0 4.656 9.09c-1.437 1.437-2.572 3.133-3.406 5.087C.417 16.102 0 18.157 0 20.341c0 2.213.417 4.283 1.25 6.208a16.105 16.105 0 0 0 3.406 5.045A16.105 16.105 0 0 0 9.7 34.999c1.926.834 3.995 1.25 6.208 1.25 2.185 0 4.24-.416 6.166-1.25a16.124 16.124 0 0 0 4.34-2.711c.037.039.074.08.112.118 1.37 1.37 2.987 2.448 4.852 3.235a14.67 14.67 0 0 0 5.945 1.224c2.127 0 4.109-.408 5.945-1.224 1.865-.787 3.482-1.865 4.852-3.235a14.717 14.717 0 0 0 1.066-1.174 18.002 18.002 0 0 0 4.624 2.955c2.166.944 4.484 1.416 6.954 1.416 2.443 0 4.747-.458 6.913-1.375a17.602 17.602 0 0 0 5.241-3.349 16.105 16.105 0 0 0 .658.715 16.105 16.105 0 0 0 5.044 3.405c1.926.834 3.995 1.25 6.209 1.25 2.184 0 4.239-.416 6.165-1.25 1.954-.833 3.65-1.968 5.087-3.405a16.105 16.105 0 0 0 .548-.607 14.167 14.167 0 0 0 3.023 1.812c1.735.747 3.589 1.12 5.562 1.12 1.974 0 3.828-.373 5.563-1.12a13.791 13.791 0 0 0 4.53-3.006 13.65 13.65 0 0 0 .505-.533 14.896 14.896 0 0 0 3.107 1.824c1.774.769 3.682 1.153 5.723 1.153 2.01 0 3.904-.384 5.678-1.153a14.939 14.939 0 0 0 3.173-1.767 15.558 15.558 0 0 0 .74.81 15.217 15.217 0 0 0 4.98 3.378c1.906.838 3.94 1.256 6.107 1.256 2.165 0 4.2-.404 6.106-1.212a15.557 15.557 0 0 0 3.38-1.968c.244.283.494.56.759.825 1.37 1.37 2.987 2.448 4.852 3.235a14.672 14.672 0 0 0 5.945 1.224c2.127 0 4.11-.408 5.945-1.224 1.865-.787 3.482-1.865 4.852-3.235a14.717 14.717 0 0 0 .63-.683 14.896 14.896 0 0 0 3.19 1.885c1.775.769 3.683 1.153 5.723 1.153 2.012 0 3.905-.384 5.68-1.153a14.174 14.174 0 0 0 4.702-3.106c1.33-1.301 2.38-2.84 3.15-4.614.798-1.774 1.198-3.682 1.198-5.723 0-2.011-.385-3.904-1.154-5.679a14.174 14.174 0 0 0-3.105-4.702 14.895 14.895 0 0 0-4.659-3.15c-1.774-.8-3.682-1.198-5.723-1.198-2.011 0-3.919.384-5.723 1.153a14.29 14.29 0 0 0-4.658 3.106 14.895 14.895 0 0 0-.21.233 14.717 14.717 0 0 0-3.893-2.394 14.67 14.67 0 0 0-5.945-1.224c-2.098 0-4.08.408-5.945 1.224a14.717 14.717 0 0 0-2.913 1.638 15.557 15.557 0 0 0-1.012-1.13c-1.386-1.443-3.03-2.584-4.937-3.421-1.905-.837-3.94-1.256-6.106-1.256-2.165 0-4.215.419-6.15 1.256a16.075 16.075 0 0 0-4.221 2.608 14.895 14.895 0 0 0-4.625-3.12c-1.774-.798-3.682-1.197-5.723-1.197-2.01 0-3.919.385-5.723 1.154a14.29 14.29 0 0 0-4.658 3.105 14.895 14.895 0 0 0-.803.889 13.963 13.963 0 0 0-2.59-1.458c-1.734-.777-3.588-1.166-5.562-1.166-1.974 0-3.828.374-5.562 1.12a14.305 14.305 0 0 0-3.895 2.396C94.53 7.58 92.884 6.49 90.994 5.683c-1.926-.833-3.981-1.25-6.165-1.25-2.214 0-4.283.417-6.21 1.25a16.104 16.104 0 0 0-3.22 1.863 17.077 17.077 0 0 0-1.893-2.258 17.868 17.868 0 0 0-5.663-3.872C65.706.472 63.402 0 60.931 0z" aria-label="audacious"/><path fill="#d9d9d9" aria-label="audacious" d="M60.95 4.04c-1.899 0-3.689.355-5.372 1.067a14.091 14.091 0 0 0-4.432 2.945 14.156 14.156 0 0 0-2.977 4.4 12.81 12.81 0 0 0-.988 3.61 10.73 10.73 0 0 0-1.828-2.38 10.894 10.894 0 0 0-3.591-2.427 10.858 10.858 0 0 0-4.4-.906c-1.554 0-3.02.302-4.401.906a10.894 10.894 0 0 0-3.592 2.427 11.017 11.017 0 0 0-2.101 2.956 11.29 11.29 0 0 0-.325-.853 11.99 11.99 0 0 0-2.557-3.818 11.986 11.986 0 0 0-3.818-2.556 11.523 11.523 0 0 0-4.627-.939c-1.66 0-3.214.313-4.66.939a12.086 12.086 0 0 0-3.785 2.556 11.988 11.988 0 0 0-2.556 3.818A11.52 11.52 0 0 0 4 20.412c0 1.66.313 3.214.939 4.66a12.087 12.087 0 0 0 2.556 3.785 12.087 12.087 0 0 0 3.785 2.556c1.446.626 3 .939 4.66.939 1.64 0 3.182-.313 4.627-.939a11.987 11.987 0 0 0 3.818-2.556c.97-.97 1.755-2.089 2.359-3.355.071.192.147.383.23.573a11.148 11.148 0 0 0 2.394 3.591 11.148 11.148 0 0 0 3.592 2.395 10.86 10.86 0 0 0 4.4.906c1.575 0 3.042-.302 4.4-.906a11.148 11.148 0 0 0 3.592-2.395 10.894 10.894 0 0 0 2.427-3.591c.306-.699.533-1.42.684-2.162a13.84 13.84 0 0 0 6.953 6.691c1.682.734 3.483 1.1 5.403 1.1 1.898 0 3.689-.356 5.371-1.067 1.704-.712 3.182-1.693 4.433-2.944a13.539 13.539 0 0 0 2.786-3.862 12.087 12.087 0 0 0 3.006 5.026 12.087 12.087 0 0 0 3.786 2.556c1.445.626 2.998.939 4.659.939 1.64 0 3.182-.313 4.627-.939a11.989 11.989 0 0 0 3.818-2.556 12.087 12.087 0 0 0 2.854-4.559 10.093 10.093 0 0 0 1.87 2.682 10.22 10.22 0 0 0 3.236 2.233c1.251.54 2.589.81 4.012.81 1.424 0 2.761-.27 4.012-.81a9.948 9.948 0 0 0 3.268-2.168 9.846 9.846 0 0 0 2.233-3.203c.18-.402.33-.815.452-1.235a10.97 10.97 0 0 0 1.878 2.594 10.87 10.87 0 0 0 3.397 2.297c1.294.561 2.686.841 4.174.841 1.467 0 2.848-.28 4.142-.84a10.596 10.596 0 0 0 3.43-2.233 10.765 10.765 0 0 0 1.942-2.66 11.625 11.625 0 0 0 2.879 4.795 11.37 11.37 0 0 0 3.721 2.524c1.424.625 2.945.938 4.562.938 1.618 0 3.14-.302 4.563-.906a11.626 11.626 0 0 0 3.721-2.491 11.647 11.647 0 0 0 1.944-2.517c.118.381.256.757.418 1.126a11.148 11.148 0 0 0 2.394 3.591A11.148 11.148 0 0 0 162 32.061c1.38.604 2.847.906 4.4.906 1.575 0 3.042-.302 4.4-.906a11.148 11.148 0 0 0 3.592-2.395 10.894 10.894 0 0 0 2.427-3.591c.16-.368.298-.741.416-1.12a10.588 10.588 0 0 0 1.946 2.77c.971.97 2.104 1.736 3.398 2.297 1.294.56 2.685.841 4.174.841 1.467 0 2.847-.28 4.142-.84a10.337 10.337 0 0 0 3.43-2.266c.97-.949 1.736-2.07 2.297-3.365.582-1.294.873-2.686.873-4.174 0-1.467-.28-2.848-.84-4.142a10.337 10.337 0 0 0-2.266-3.43 10.863 10.863 0 0 0-3.397-2.297c-1.294-.583-2.686-.873-4.174-.873-1.467 0-2.859.28-4.174.84a10.421 10.421 0 0 0-3.398 2.266 10.863 10.863 0 0 0-2.622 4.258 10.822 10.822 0 0 0-2.232-3.158 10.894 10.894 0 0 0-3.591-2.427 10.86 10.86 0 0 0-4.4-.906c-1.554 0-3.02.302-4.401.906a10.894 10.894 0 0 0-3.592 2.427c-.67.67-1.243 1.42-1.724 2.25a10.986 10.986 0 0 0-.476-1.312 11.622 11.622 0 0 0-2.491-3.72 11.423 11.423 0 0 0-3.689-2.557 11.216 11.216 0 0 0-4.562-.938c-1.618 0-3.15.312-4.595.938a12.011 12.011 0 0 0-3.753 2.492 11.573 11.573 0 0 0-2.316 3.24 10.17 10.17 0 0 0-.209-.523 10.337 10.337 0 0 0-2.265-3.43 10.863 10.863 0 0 0-3.397-2.297c-1.294-.582-2.686-.873-4.174-.873-1.467 0-2.858.28-4.174.84a10.421 10.421 0 0 0-3.397 2.266 10.856 10.856 0 0 0-2.298 3.397c-.203.468-.368.95-.497 1.443a9.822 9.822 0 0 0-1.735-2.349 9.756 9.756 0 0 0-3.236-2.232 9.695 9.695 0 0 0-4.012-.841c-1.424 0-2.762.269-4.013.808a10.317 10.317 0 0 0-3.3 2.168 10.004 10.004 0 0 0-2.2 3.236l-.036.09a11.987 11.987 0 0 0-2.553-3.811 11.989 11.989 0 0 0-3.818-2.556 11.523 11.523 0 0 0-4.627-.939c-1.661 0-3.214.313-4.66.939a12.086 12.086 0 0 0-3.785 2.556 11.78 11.78 0 0 0-2.051 2.768 13.342 13.342 0 0 0-.7-2.153c-.711-1.704-1.693-3.182-2.944-4.433a13.885 13.885 0 0 0-4.4-3.01c-1.661-.733-3.451-1.1-5.371-1.1zm3.04 5.274c.26 0 .53.054.81.162.28.107.539.258.776.452a2.5 2.5 0 0 1 .583.68c.15.237.227.496.227.776 0 .346-.022.734-.065 1.165a4.17 4.17 0 0 1-.194 1.1v1.942c.021.086.032.27.032.55v.55a.53.53 0 0 1-.032.162v2.524a.365.365 0 0 1 .032.259v.517c.021.065.01.14-.032.227v1.779a.247.247 0 0 1 .032.097v.583c.021.107.032.215.032.323.022.108.033.173.033.194 0 .044.021.151.064.324.044.172.076.28.098.323v.13c0 .367-.152.712-.454 1.035a30.6 30.6 0 0 1-.776.81c-.173.15-.41.226-.712.226a4.14 4.14 0 0 1-1.52-.292 3.893 3.893 0 0 0-1.489-.29c-.388 0-.723.086-1.003.258a9.92 9.92 0 0 1-.971.518 1.246 1.246 0 0 1-.615.162H58.2a2.85 2.85 0 0 1-1.23-.26 14.917 14.917 0 0 1-1.1-.614 4.154 4.154 0 0 1-1.003-.939 6.478 6.478 0 0 1-.711-1.164 7.407 7.407 0 0 1-.453-1.327 7.606 7.606 0 0 1-.13-1.359V19.83c.022-.195.032-.367.032-.518a3.36 3.36 0 0 0 .033-.356v-.13a.524.524 0 0 0 .032-.129c.043-.431.108-.852.194-1.262.108-.41.27-.808.486-1.197.215-.366.474-.658.776-.873.324-.238.658-.475 1.003-.713.345-.237.68-.409 1.003-.517.346-.108.712-.216 1.1-.324.044 0 .13-.021.26-.064.15-.044.247-.076.29-.098h.227c.173 0 .335.011.485.033.173.022.346.032.518.032.216 0 .432-.01.647-.032a.984.984 0 0 0 .583-.323l.194-.292.13-.194v-1.359c0-.021.032-.108.096-.259.065-.15.119-.28.162-.388.151-.367.345-.636.582-.81.26-.193.572-.387.939-.581.15-.108.366-.162.647-.162zm60.54.226c.194 0 .4.043.615.13.238.064.453.172.647.323a1.6 1.6 0 0 1 .518.485c.151.194.226.4.226.615 0 .086-.042.205-.129.356-.064.151-.15.313-.259.485a5.222 5.222 0 0 1-.291.453 1.42 1.42 0 0 1-.259.26 1.785 1.785 0 0 1-1.003.323c-.302 0-.54-.108-.712-.324a4.73 4.73 0 0 0-.55-.582l-.453-.453c-.108-.13-.161-.313-.161-.55a.86.86 0 0 1 .193-.518c.13-.194.281-.356.454-.485.194-.151.388-.27.582-.356.216-.108.41-.162.582-.162zm-16.566 3.98h.226c.69 0 1.36.172 2.006.518.669.345 1.144.841 1.425 1.488.043.065.086.173.129.324.043.13.075.194.097.194v.162c0 .15-.065.312-.194.485a2.191 2.191 0 0 1-.421.485 3.211 3.211 0 0 1-.55.389c-.172.086-.335.13-.486.13a1.46 1.46 0 0 1-.517-.098 4.445 4.445 0 0 0-.453-.226 2.612 2.612 0 0 0-.42-.227.963.963 0 0 0-.486-.13h-1.78a.988.988 0 0 0-.323.098c-.28.108-.518.28-.712.518a3.189 3.189 0 0 0-.421.808c-.108.28-.183.583-.226.907a5.972 5.972 0 0 0-.065.841v.388c.173.41.4.788.68 1.133s.582.668.905.97l.098.032c.107.044.258.108.452.195l.292.129h1.714a9.87 9.87 0 0 1 .712-.291c.238-.086.486-.13.745-.13.237 0 .485.151.744.453.28.28.42.54.42.777v.032c-.15.755-.528 1.338-1.132 1.748a3.547 3.547 0 0 1-2.038.614c-.302 0-.637-.021-1.003-.064a3.58 3.58 0 0 1-.971-.26h-1.65c-.044 0-.162-.032-.356-.096a4.337 4.337 0 0 1-.389-.162 5.93 5.93 0 0 1-1.035-.55 2.742 2.742 0 0 1-.809-.842l-.194-.29a2.428 2.428 0 0 0-.259-.454 4.222 4.222 0 0 0-.259-.453 7.152 7.152 0 0 0-.13-.291c-.15-.28-.269-.54-.355-.777a9.034 9.034 0 0 0-.26-.841 16.079 16.079 0 0 0-.096-1.1 18.722 18.722 0 0 1-.032-1.1c0-.755.215-1.456.647-2.103a5.958 5.958 0 0 1 1.553-1.65c.065-.044.226-.14.485-.292.28-.172.475-.302.583-.388l.097-.032c.366-.13.722-.27 1.067-.42a3.544 3.544 0 0 1 1.1-.324h.518a1.65 1.65 0 0 1 .324-.033c.108-.021.173-.032.194-.032.043 0 .151-.021.324-.065.172-.043.28-.065.323-.065 0-.021.054-.032.162-.032zm-91.732.162c.582 0 1.187.086 1.812.259.647.194 1.186.42 1.618.68.453.237.82.528 1.1.873.28.345.497.766.648 1.262.15.474.269 1.046.355 1.715.043.237.076.474.097.711.043.238.065.475.065.713 0 .172-.032.334-.097.485-.065.13-.118.27-.162.42v.162c0 .086-.01.184-.032.292v.388l-.13.712a7.855 7.855 0 0 0-.032.711v.098c.022.086.065.247.13.485l.129.485v.194c0 .26-.065.507-.194.744a2.44 2.44 0 0 1-.518.648 2.489 2.489 0 0 1-.712.453 1.777 1.777 0 0 1-.744.161c-.345 0-.68-.075-1.003-.226a12.273 12.273 0 0 0-.938-.453.673.673 0 0 0-.26-.032h-.226c-.41 0-.809.075-1.197.226-.367.13-.733.27-1.1.42l-.324.163c-.15.086-.248.14-.291.162-.086.043-.15.054-.194.032h-.486a6.808 6.808 0 0 1-.647-.194 21.39 21.39 0 0 1-.615-.227.526.526 0 0 1-.129-.032c-.043-.021-.064-.043-.064-.064a23.36 23.36 0 0 1-1.1-.81 2.423 2.423 0 0 1-.745-1.132 16.56 16.56 0 0 0-.194-.615l-.13-.42v-1.618a.9.9 0 0 1 .065-.194c.065-.108.12-.184.162-.227.237-.431.54-.83.906-1.197a6.397 6.397 0 0 1 1.23-.97c.301-.174.614-.26.938-.26.323-.021.636-.086.938-.194.044-.021.13-.054.26-.097a7.44 7.44 0 0 0 .29-.129.907.907 0 0 1 .389-.065l.518-.065a1.56 1.56 0 0 0 .42-.161.436.436 0 0 0 .194-.389.507.507 0 0 0-.259-.453 1.02 1.02 0 0 0-.55-.162h-2.232c-.13.043-.27.075-.42.097a2.998 2.998 0 0 1-.421.032 1.42 1.42 0 0 1-.939-.356 1.242 1.242 0 0 1-.388-.906c0-.15.022-.29.065-.42.064-.13.129-.249.193-.356l.68-.68a.999.999 0 0 1 .55-.259c.216-.043.42-.075.615-.097.086-.021.27-.032.55-.032.302-.022.507-.032.615-.032.28-.151.593-.227.938-.227.367-.021.701-.032 1.003-.032zm68.92 0c.583 0 1.187.086 1.812.259.647.194 1.187.42 1.618.68.453.237.82.528 1.1.873.28.345.496.766.647 1.262a9.91 9.91 0 0 1 .356 1.715c.044.237.076.474.098.711.043.238.064.475.064.713 0 .172-.032.334-.097.485a2.44 2.44 0 0 0-.162.42v.162c0 .086-.01.184-.032.292v.388l-.13.712a7.856 7.856 0 0 0-.032.711v.098c.021.086.065.247.13.485l.129.485v.194c0 .26-.065.507-.194.744a2.44 2.44 0 0 1-.518.648 2.491 2.491 0 0 1-.712.453 1.777 1.777 0 0 1-.744.161c-.345 0-.68-.075-1.003-.226a12.273 12.273 0 0 0-.938-.453.673.673 0 0 0-.26-.032h-.226c-.41 0-.809.075-1.197.226-.367.13-.733.27-1.1.42l-.324.163c-.15.086-.248.14-.29.162-.087.043-.152.054-.195.032h-.486a6.808 6.808 0 0 1-.646-.194 21.396 21.396 0 0 1-.615-.227.526.526 0 0 1-.13-.032c-.043-.021-.064-.043-.064-.064a23.363 23.363 0 0 1-1.1-.81 2.423 2.423 0 0 1-.745-1.132c-.043-.15-.107-.356-.194-.615l-.13-.42v-1.618a.9.9 0 0 1 .065-.194 1.24 1.24 0 0 1 .163-.227 5.33 5.33 0 0 1 .905-1.197 6.397 6.397 0 0 1 1.23-.97c.302-.174.615-.26.938-.26.324-.021.637-.086.939-.194.043-.021.13-.054.259-.097.15-.064.247-.107.29-.129a.912.912 0 0 1 .39-.065l.516-.065a1.56 1.56 0 0 0 .421-.161.436.436 0 0 0 .194-.389.507.507 0 0 0-.259-.453 1.02 1.02 0 0 0-.55-.162h-2.232c-.13.043-.27.075-.42.097a2.998 2.998 0 0 1-.422.032c-.345 0-.658-.119-.938-.356a1.241 1.241 0 0 1-.388-.906c0-.15.021-.29.064-.42.065-.13.13-.249.195-.356l.68-.68a.997.997 0 0 1 .55-.259c.215-.043.42-.075.614-.097.086-.021.27-.032.55-.032.302-.022.507-.032.615-.032.28-.151.593-.227.938-.227.367-.021.701-.032 1.003-.032zm39.573.097a.79.79 0 0 1 .452.13c.151.064.292.15.421.258.302.216.529.421.68.615.15.173.237.442.258.809.022.259.044.55.066.873.043.302.064.594.064.874 0 .173-.01.324-.032.453-.022.13-.032.28-.032.453 0 .108-.011.227-.033.356 0 .13.021.248.065.356v1.36a1.362 1.362 0 0 0-.032.323c0 .172.01.345.032.517l.13.518c.02.215.042.432.064.647.021.194.054.399.097.615 0 .043.021.162.065.356.043.172.064.28.064.323v.13a.533.533 0 0 1 .033.162c0 .539-.227 1.024-.68 1.455-.453.41-.949.615-1.488.615h-.162a3.862 3.862 0 0 1-.744-.226 2.094 2.094 0 0 1-.518-.323 2.83 2.83 0 0 1-.42-.454c-.13-.194-.27-.42-.421-.68a1.377 1.377 0 0 1-.162-.679v-.388c.021-.086.076-.216.162-.388v-3.69a2.207 2.207 0 0 0-.065-.258V18.6c0-.173.022-.302.065-.388v-2.2c0-.216.064-.454.194-.713a3.367 3.367 0 0 1 1.165-1.294c.237-.15.474-.226.712-.226zm19.543.097h1.586l.226.065c.173.043.367.097.583.162.216.043.431.097.647.161.237.044.431.087.582.13.238.064.453.162.647.291.194.108.378.227.55.356a6.33 6.33 0 0 1 1.521 1.424c.432.56.734 1.186.906 1.876a2.8 2.8 0 0 1 .097.744c0 .238.022.475.065.712 0 .022.011.097.033.227a.899.899 0 0 1 .064.194v.712c0 .129-.01.27-.032.42 0 .151-.01.28-.032.388v.163c-.065.388-.238.819-.518 1.294a8.118 8.118 0 0 1-.971 1.391 9.228 9.228 0 0 1-1.197 1.23c-.41.345-.798.593-1.165.744a3.06 3.06 0 0 1-.453.129 4.074 4.074 0 0 1-.453.13 2.227 2.227 0 0 1-.42.032 1.32 1.32 0 0 0-.422.065h-1.844a.997.997 0 0 0-.614-.065 1.119 1.119 0 0 1-.648-.065 13.238 13.238 0 0 1-2.265-1.326 4.305 4.305 0 0 1-1.488-2.04 2.327 2.327 0 0 1-.13-.484 3.4 3.4 0 0 0-.096-.454.985.985 0 0 0-.033-.161 1.84 1.84 0 0 0-.097-.324 1.155 1.155 0 0 0-.097-.291.98.98 0 0 1-.032-.162.533.533 0 0 0-.033-.162v-.13a10.188 10.188 0 0 1-.129-.744 12.573 12.573 0 0 1-.033-.808c0-.194.022-.388.066-.582l.129-.583c.345-1.121.787-2.027 1.326-2.718.561-.712 1.435-1.24 2.621-1.585.26-.065.518-.119.777-.162.28-.043.539-.108.776-.194zm41.644.065c.107 0 .205.021.291.064a.865.865 0 0 0 .324.066h.226a4.87 4.87 0 0 0 .259-.098h2.07c.13.044.26.065.39.065.15 0 .3.022.452.065.15.065.323.173.518.324.215.13.41.29.582.485.194.194.356.4.485.615.13.216.195.42.195.614 0 .173-.076.378-.227.615-.13.216-.29.421-.485.615a2.8 2.8 0 0 1-.648.485 1.2 1.2 0 0 1-.614.195h-.453a3.813 3.813 0 0 1-.42-.097 15.945 15.945 0 0 1-.68-.292 1.474 1.474 0 0 0-.712-.194c-.302 0-.453.13-.453.388 0 .26.14.41.42.454.41 0 .842.032 1.295.096a1.88 1.88 0 0 1 1.197.55l.097.13c.065.065.097.108.097.13.151.172.302.312.453.42.151.108.313.226.486.356a.891.891 0 0 1 .323.42l.097.292c.043.13.086.27.13.42.064.151.118.292.161.421l.097.291v.42c0 .67-.194 1.263-.582 1.78a24.58 24.58 0 0 1-1.165 1.457c0 .021-.01.043-.032.064-.28.238-.55.42-.81.55a5.13 5.13 0 0 1-.71.324 6.665 6.665 0 0 1-.778.226c-.258.065-.55.151-.873.26h-1.262a4.093 4.093 0 0 0-.776-.195 9.495 9.495 0 0 1-.777-.097 3.7 3.7 0 0 0-.453-.13 5.733 5.733 0 0 1-.453-.161h-.292a2.807 2.807 0 0 0-.29-.033 1.312 1.312 0 0 1-.583-.226 2.935 2.935 0 0 1-.518-.518 4.558 4.558 0 0 1-.388-.582 1.657 1.657 0 0 1-.13-.615c0-.303.097-.561.292-.777.215-.216.453-.378.712-.486h.323c.302 0 .594.033.874.098.302.064.604.15.906.258h1.617c.087 0 .151-.042.195-.129a.52.52 0 0 0 .064-.226c0-.194-.086-.313-.258-.356a8.667 8.667 0 0 0-.453-.162c-.195-.065-.302-.108-.324-.13a1.6 1.6 0 0 0-.453 0 .86.86 0 0 1-.388-.096 16.53 16.53 0 0 0-.485-.227 18.25 18.25 0 0 1-.486-.226 3.85 3.85 0 0 1-.712-.583c-.259-.28-.507-.582-.744-.906-.216-.345-.4-.69-.55-1.035-.151-.345-.227-.647-.227-.906 0-.28.022-.55.065-.809.065-.28.14-.55.227-.81.172-.495.388-.894.647-1.196.259-.324.55-.583.873-.777a4.22 4.22 0 0 1 1.1-.453c.41-.13.852-.237 1.327-.323.043 0 .151-.022.324-.065.172-.043.28-.065.323-.065 0-.021.043-.032.13-.032zm-152.757.42c.367 0 .712.065 1.035.194.324.13.55.378.68.744.064.151.108.303.13.454.043.15.085.312.129.485l.258.582c.087.173.13.367.13.583 0 .302-.032.593-.097.874-.043.28-.065.57-.065.873 0 .216.01.432.032.647l.13.647c.043.367.086.755.13 1.165.064.41.28.734.646.971.065.043.162.097.292.162.13.065.205.097.226.097h.777a.535.535 0 0 0 .129-.032.759.759 0 0 0 .194-.13c.108-.064.216-.14.324-.226.13-.086.237-.184.323-.291l.033-.098c.021-.064.043-.118.064-.161.022-.044.043-.119.065-.227a1.64 1.64 0 0 0 .033-.194v-.582c.021-.151.032-.28.032-.389.021-.107.032-.183.032-.226 0-.043.022-.162.065-.356.043-.216.075-.345.097-.388.043-.194.065-.388.065-.582 0-.216.022-.421.065-.615l.129-.518a1.46 1.46 0 0 0 .097-.518c0-.15-.021-.28-.065-.388a1.435 1.435 0 0 1-.065-.453 2 2 0 0 1 .13-.68 2.26 2.26 0 0 1 .356-.68c.151-.215.323-.387.517-.517.216-.129.454-.194.712-.194.26 0 .529.054.81.162.28.108.539.259.776.453.259.194.464.42.615.68.172.237.259.495.259.776v1.974l-.163.582v1.683c.044.194.098.41.163.647.064.237.096.453.096.647a.72.72 0 0 1-.032.227.716.716 0 0 0-.032.226v.162c.021.043.043.108.064.194v1.553l-.129.518a2.187 2.187 0 0 1-.874 1.456 1.86 1.86 0 0 1-1.132.355h-.13l-1.1-.323h-2.2c-.388.173-.787.324-1.197.453-.41.13-.83.237-1.262.324h-.13c-.301 0-.604-.076-.906-.227-.28-.13-.55-.259-.808-.388a3.355 3.355 0 0 1-.744-.583 7.522 7.522 0 0 1-.745-.873c-.215-.324-.41-.647-.582-.971-.173-.324-.27-.614-.291-.873v-1.1c0-.151-.01-.303-.032-.454v-.776a3.055 3.055 0 0 1-.162-.971c0-.108.01-.205.032-.291.021-.108.032-.216.032-.324v-.194a24.974 24.974 0 0 0-.161-1.036 9.723 9.723 0 0 1-.065-1.067c0-.324.054-.637.162-.939.108-.323.258-.604.452-.841.195-.259.432-.464.713-.615.28-.173.593-.258.938-.258zm129.04 0c.366 0 .71.065 1.034.194.324.13.55.378.68.744.065.151.108.303.13.454.043.15.086.312.129.485l.259.582c.086.173.129.367.129.583 0 .302-.033.593-.097.874-.043.28-.065.57-.065.873 0 .216.011.432.033.647l.129.647c.043.367.086.755.13 1.165.064.41.28.734.647.971.064.043.162.097.291.162.13.065.205.097.226.097h.777a.535.535 0 0 0 .13-.032.759.759 0 0 0 .193-.13c.108-.064.216-.14.324-.226.13-.086.237-.184.323-.291l.033-.098a1.27 1.27 0 0 1 .065-.161 1.03 1.03 0 0 0 .064-.227 1.64 1.64 0 0 0 .033-.194v-.582c.021-.151.032-.28.032-.389.021-.107.032-.183.032-.226 0-.043.022-.162.065-.356.043-.216.076-.345.097-.388.043-.194.065-.388.065-.582 0-.216.021-.421.064-.615l.13-.518a1.46 1.46 0 0 0 .097-.518c0-.15-.022-.28-.065-.388a1.435 1.435 0 0 1-.065-.453 2 2 0 0 1 .13-.68 2.26 2.26 0 0 1 .356-.68c.15-.215.323-.387.518-.517a1.36 1.36 0 0 1 .712-.194c.258 0 .528.054.808.162.28.108.54.259.777.453.259.194.464.42.615.68.173.237.258.495.258.776v1.974l-.161.582v1.683c.043.194.097.41.161.647.065.237.098.453.098.647a.72.72 0 0 1-.033.227.716.716 0 0 0-.032.226v.162c.021.043.043.108.065.194v1.553l-.13.518a2.3 2.3 0 0 1-.13.485 2.186 2.186 0 0 1-.744.97c-.323.238-.7.356-1.132.356h-.13l-1.1-.323h-2.2c-.388.173-.787.324-1.197.453-.41.13-.83.237-1.262.324h-.129a2.01 2.01 0 0 1-.906-.227c-.28-.13-.55-.259-.81-.388a3.355 3.355 0 0 1-.743-.583 7.523 7.523 0 0 1-.744-.873c-.216-.324-.41-.647-.583-.971-.172-.324-.27-.614-.291-.873v-1.1c0-.151-.01-.303-.032-.454v-.776a3.055 3.055 0 0 1-.162-.971c0-.108.01-.205.032-.291a1.62 1.62 0 0 0 .033-.324v-.194a24.97 24.97 0 0 0-.162-1.036 9.723 9.723 0 0 1-.065-1.067c0-.324.054-.637.162-.939a2.63 2.63 0 0 1 .453-.841c.194-.259.431-.464.712-.615.28-.173.593-.258.938-.258zm-102.54 2.75l-.42.227-1.1 1.1a.76.76 0 0 0-.162.26 1.846 1.846 0 0 0-.098.323v1.164c0 .216.022.4.066.55.107.368.27.745.485 1.133.237.367.528.636.873.809.108.065.248.14.42.227l.292.129h.388c.022 0 .12-.043.292-.13.194-.086.334-.161.42-.226a1.138 1.138 0 0 0 .55-.938v-1.262a1.394 1.394 0 0 1-.129-.712 2.86 2.86 0 0 0-.032-.744 4.208 4.208 0 0 1-.065-.55 9.364 9.364 0 0 1-.033-.55l-.064-.13-.583-.55-.258-.13zm84.678.42a.572.572 0 0 0-.161.066c-.065.043-.12.076-.163.097-.237.173-.42.334-.55.485a1.827 1.827 0 0 0-.323.615 8.662 8.662 0 0 1-.162.453.807.807 0 0 0-.064.356c0 .151.042.324.129.518v1.359c0 .021.032.13.097.323.065.173.119.313.162.421.043.13.13.27.259.42.129.152.27.292.42.421a3.4 3.4 0 0 0 .518.324 1.3 1.3 0 0 0 .518.13c.41 0 .765-.152 1.067-.454.302-.323.55-.7.745-1.132a5.85 5.85 0 0 0 .42-1.36 6.71 6.71 0 0 0 .13-1.164c0-.173-.011-.345-.033-.518a1.078 1.078 0 0 0-.194-.517c-.043-.043-.15-.152-.323-.324-.173-.194-.292-.313-.356-.356a.965.965 0 0 0-.13-.097.315.315 0 0 0-.161-.065zm-129.007 3.69c-.172 0-.302.108-.388.324-.086.194-.13.355-.13.485 0 .345.108.593.324.744.216.13.475.194.777.194h.356c.064 0 .097-.021.097-.064.043-.044.118-.12.226-.227.13-.108.216-.184.259-.227a.46.46 0 0 0 .065-.258v-.583a.636.636 0 0 0-.162-.226c-.065-.108-.14-.162-.227-.162zm68.92 0c-.172 0-.302.108-.388.324-.086.194-.13.355-.13.485 0 .345.108.593.324.744.216.13.475.194.777.194h.356c.065 0 .097-.021.097-.064l.226-.227c.13-.108.216-.184.26-.227a.46.46 0 0 0 .064-.258v-.583a.636.636 0 0 0-.162-.226c-.065-.108-.14-.162-.227-.162z"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="761.316" height="139.33" viewBox="0 0 201.432 36.865"><g word-spacing="0" letter-spacing="0" font-family="Circulate (BRK)" font-size="13.333" font-weight="400"><path d="M60.93 0c-2.442 0-4.746 0.458-6.911 1.374a18.135 18.135 0 0 0-5.705 3.79 17.894 17.894 0 0 0-2.764 3.578 14.717 14.717 0 0 0-2.282-1.208 14.67 14.67 0 0 0-5.945-1.224c-2.098 0-4.08 0.408-5.945 1.224a14.717 14.717 0 0 0-3.632 2.177c-0.19-0.212-0.383-0.42-0.585-0.622-1.437-1.437-3.133-2.572-5.087-3.406-1.926-0.833-3.981-1.25-6.166-1.25-2.213 0-4.282 0.417-6.208 1.25A16.104 16.104 0 0 0 4.656 9.09c-1.437 1.437-2.572 3.133-3.406 5.087C0.417 16.102 0 18.157 0 20.341c0 2.213 0.417 4.283 1.25 6.208a16.105 16.105 0 0 0 3.406 5.045A16.105 16.105 0 0 0 9.7 34.999c1.926 0.834 3.995 1.25 6.208 1.25 2.185 0 4.24-0.416 6.166-1.25a16.124 16.124 0 0 0 4.34-2.711c0.037 0.039 0.074 0.08 0.112 0.118 1.37 1.37 2.987 2.448 4.852 3.235a14.67 14.67 0 0 0 5.945 1.224c2.127 0 4.109-0.408 5.945-1.224 1.865-0.787 3.482-1.865 4.852-3.235a14.717 14.717 0 0 0 1.066-1.174 18.002 18.002 0 0 0 4.624 2.955c2.166 0.944 4.484 1.416 6.954 1.416 2.443 0 4.747-0.458 6.913-1.375a17.602 17.602 0 0 0 5.241-3.349 16.105 16.105 0 0 0 0.658 0.715 16.105 16.105 0 0 0 5.044 3.405c1.926 0.834 3.995 1.25 6.209 1.25 2.184 0 4.239-0.416 6.165-1.25 1.954-0.833 3.65-1.968 5.087-3.405a16.105 16.105 0 0 0 0.548-0.607 14.167 14.167 0 0 0 3.023 1.812c1.735 0.747 3.589 1.12 5.562 1.12 1.974 0 3.828-0.373 5.563-1.12a13.791 13.791 0 0 0 4.53-3.006 13.65 13.65 0 0 0 0.505-0.533 14.896 14.896 0 0 0 3.107 1.824c1.774 0.769 3.682 1.153 5.723 1.153 2.01 0 3.904-0.384 5.678-1.153a14.939 14.939 0 0 0 3.173-1.767 15.558 15.558 0 0 0 0.74 0.81 15.217 15.217 0 0 0 4.98 3.378c1.906 0.838 3.94 1.256 6.107 1.256 2.165 0 4.2-0.404 6.106-1.212a15.557 15.557 0 0 0 3.38-1.968c0.244 0.283 0.494 0.56 0.759 0.825 1.37 1.37 2.987 2.448 4.852 3.235a14.672 14.672 0 0 0 5.945 1.224c2.127 0 4.11-0.408 5.945-1.224 1.865-0.787 3.482-1.865 4.852-3.235a14.717 14.717 0 0 0 0.63-0.683 14.896 14.896 0 0 0 3.19 1.885c1.775 0.769 3.683 1.153 5.723 1.153 2.012 0 3.905-0.384 5.68-1.153a14.174 14.174 0 0 0 4.702-3.106c1.33-1.301 2.38-2.84 3.15-4.614 0.798-1.774 1.198-3.682 1.198-5.723 0-2.011-0.385-3.904-1.154-5.679a14.174 14.174 0 0 0-3.105-4.702 14.895 14.895 0 0 0-4.659-3.15c-1.774-0.8-3.682-1.198-5.723-1.198-2.011 0-3.919 0.384-5.723 1.153a14.29 14.29 0 0 0-4.658 3.106 14.895 14.895 0 0 0-0.21 0.233 14.717 14.717 0 0 0-3.893-2.394 14.67 14.67 0 0 0-5.945-1.224c-2.098 0-4.08 0.408-5.945 1.224a14.717 14.717 0 0 0-2.913 1.638 15.557 15.557 0 0 0-1.012-1.13c-1.386-1.443-3.03-2.584-4.937-3.421-1.905-0.837-3.94-1.256-6.106-1.256-2.165 0-4.215 0.419-6.15 1.256a16.075 16.075 0 0 0-4.221 2.608 14.895 14.895 0 0 0-4.625-3.12c-1.774-0.798-3.682-1.197-5.723-1.197-2.01 0-3.919 0.385-5.723 1.154a14.29 14.29 0 0 0-4.658 3.105 14.895 14.895 0 0 0-0.803 0.889 13.963 13.963 0 0 0-2.59-1.458c-1.734-0.777-3.588-1.166-5.562-1.166-1.974 0-3.828 0.374-5.562 1.12a14.305 14.305 0 0 0-3.895 2.396C94.53 7.58 92.884 6.49 90.994 5.683c-1.926-0.833-3.981-1.25-6.165-1.25-2.214 0-4.283 0.417-6.21 1.25a16.104 16.104 0 0 0-3.22 1.863 17.077 17.077 0 0 0-1.893-2.258 17.868 17.868 0 0 0-5.663-3.872C65.706 0.472 63.402 0 60.931 0z" aria-label="audacious"/><path fill="#d9d9d9" aria-label="audacious" d="M60.95 4.04c-1.899 0-3.689 0.355-5.372 1.067a14.091 14.091 0 0 0-4.432 2.945 14.156 14.156 0 0 0-2.977 4.4 12.81 12.81 0 0 0-0.988 3.61 10.73 10.73 0 0 0-1.828-2.38 10.894 10.894 0 0 0-3.591-2.427 10.858 10.858 0 0 0-4.4-0.906c-1.554 0-3.02 0.302-4.401 0.906a10.894 10.894 0 0 0-3.592 2.427 11.017 11.017 0 0 0-2.101 2.956 11.29 11.29 0 0 0-0.325-0.853 11.99 11.99 0 0 0-2.557-3.818 11.986 11.986 0 0 0-3.818-2.556 11.523 11.523 0 0 0-4.627-0.939c-1.66 0-3.214 0.313-4.66 0.939a12.086 12.086 0 0 0-3.785 2.556 11.988 11.988 0 0 0-2.556 3.818A11.52 11.52 0 0 0 4 20.412c0 1.66 0.313 3.214 0.939 4.66a12.087 12.087 0 0 0 2.556 3.785 12.087 12.087 0 0 0 3.785 2.556c1.446 0.626 3 0.939 4.66 0.939 1.64 0 3.182-0.313 4.627-0.939a11.987 11.987 0 0 0 3.818-2.556c0.97-0.97 1.755-2.089 2.359-3.355 0.071 0.192 0.147 0.383 0.23 0.573a11.148 11.148 0 0 0 2.394 3.591 11.148 11.148 0 0 0 3.592 2.395 10.86 10.86 0 0 0 4.4 0.906c1.575 0 3.042-0.302 4.4-0.906a11.148 11.148 0 0 0 3.592-2.395 10.894 10.894 0 0 0 2.427-3.591c0.306-0.699 0.533-1.42 0.684-2.162a13.84 13.84 0 0 0 6.953 6.691c1.682 0.734 3.483 1.1 5.403 1.1 1.898 0 3.689-0.356 5.371-1.067 1.704-0.712 3.182-1.693 4.433-2.944a13.539 13.539 0 0 0 2.786-3.862 12.087 12.087 0 0 0 3.006 5.026 12.087 12.087 0 0 0 3.786 2.556c1.445 0.626 2.998 0.939 4.659 0.939 1.64 0 3.182-0.313 4.627-0.939a11.989 11.989 0 0 0 3.818-2.556 12.087 12.087 0 0 0 2.854-4.559 10.093 10.093 0 0 0 1.87 2.682 10.22 10.22 0 0 0 3.236 2.233c1.251 0.54 2.589 0.81 4.012 0.81 1.424 0 2.761-0.27 4.012-0.81a9.948 9.948 0 0 0 3.268-2.168 9.846 9.846 0 0 0 2.233-3.203c0.18-0.402 0.33-0.815 0.452-1.235a10.97 10.97 0 0 0 1.878 2.594 10.87 10.87 0 0 0 3.397 2.297c1.294 0.561 2.686 0.841 4.174 0.841 1.467 0 2.848-0.28 4.142-0.84a10.596 10.596 0 0 0 3.43-2.233 10.765 10.765 0 0 0 1.942-2.66 11.625 11.625 0 0 0 2.879 4.795 11.37 11.37 0 0 0 3.721 2.524c1.424 0.625 2.945 0.938 4.562 0.938 1.618 0 3.14-0.302 4.563-0.906a11.626 11.626 0 0 0 3.721-2.491 11.647 11.647 0 0 0 1.944-2.517c0.118 0.381 0.256 0.757 0.418 1.126a11.148 11.148 0 0 0 2.394 3.591A11.148 11.148 0 0 0 162 32.061c1.38 0.604 2.847 0.906 4.4 0.906 1.575 0 3.042-0.302 4.4-0.906a11.148 11.148 0 0 0 3.592-2.395 10.894 10.894 0 0 0 2.427-3.591c0.16-0.368 0.298-0.741 0.416-1.12a10.588 10.588 0 0 0 1.946 2.77c0.971 0.97 2.104 1.736 3.398 2.297 1.294 0.56 2.685 0.841 4.174 0.841 1.467 0 2.847-0.28 4.142-0.84a10.337 10.337 0 0 0 3.43-2.266c0.97-0.949 1.736-2.07 2.297-3.365 0.582-1.294 0.873-2.686 0.873-4.174 0-1.467-0.28-2.848-0.84-4.142a10.337 10.337 0 0 0-2.266-3.43 10.863 10.863 0 0 0-3.397-2.297c-1.294-0.583-2.686-0.873-4.174-0.873-1.467 0-2.859 0.28-4.174 0.84a10.421 10.421 0 0 0-3.398 2.266 10.863 10.863 0 0 0-2.622 4.258 10.822 10.822 0 0 0-2.232-3.158 10.894 10.894 0 0 0-3.591-2.427 10.86 10.86 0 0 0-4.4-0.906c-1.554 0-3.02 0.302-4.401 0.906a10.894 10.894 0 0 0-3.592 2.427c-0.67 0.67-1.243 1.42-1.724 2.25a10.986 10.986 0 0 0-0.476-1.312 11.622 11.622 0 0 0-2.491-3.72 11.423 11.423 0 0 0-3.689-2.557 11.216 11.216 0 0 0-4.562-0.938c-1.618 0-3.15 0.312-4.595 0.938a12.011 12.011 0 0 0-3.753 2.492 11.573 11.573 0 0 0-2.316 3.24 10.17 10.17 0 0 0-0.209-0.523 10.337 10.337 0 0 0-2.265-3.43 10.863 10.863 0 0 0-3.397-2.297c-1.294-0.582-2.686-0.873-4.174-0.873-1.467 0-2.858 0.28-4.174 0.84a10.421 10.421 0 0 0-3.397 2.266 10.856 10.856 0 0 0-2.298 3.397c-0.203 0.468-0.368 0.95-0.497 1.443a9.822 9.822 0 0 0-1.735-2.349 9.756 9.756 0 0 0-3.236-2.232 9.695 9.695 0 0 0-4.012-0.841c-1.424 0-2.762 0.269-4.013 0.808a10.317 10.317 0 0 0-3.3 2.168 10.004 10.004 0 0 0-2.2 3.236l-0.036 0.09a11.987 11.987 0 0 0-2.553-3.811 11.989 11.989 0 0 0-3.818-2.556 11.523 11.523 0 0 0-4.627-0.939c-1.661 0-3.214 0.313-4.66 0.939a12.086 12.086 0 0 0-3.785 2.556 11.78 11.78 0 0 0-2.051 2.768 13.342 13.342 0 0 0-0.7-2.153c-0.711-1.704-1.693-3.182-2.944-4.433a13.885 13.885 0 0 0-4.4-3.01c-1.661-0.733-3.451-1.1-5.371-1.1zm3.04 5.274c0.26 0 0.53 0.054 0.81 0.162 0.28 0.107 0.539 0.258 0.776 0.452a2.5 2.5 0 0 1 0.583 0.68c0.15 0.237 0.227 0.496 0.227 0.776 0 0.346-0.022 0.734-0.065 1.165a4.17 4.17 0 0 1-0.194 1.1v1.942c0.021 0.086 0.032 0.27 0.032 0.55v0.55a0.53 0.53 0 0 1-0.032 0.162v2.524a0.365 0.365 0 0 1 0.032 0.259v0.517c0.021 0.065 0.01 0.14-0.032 0.227v1.779a0.247 0.247 0 0 1 0.032 0.097v0.583c0.021 0.107 0.032 0.215 0.032 0.323 0.022 0.108 0.033 0.173 0.033 0.194 0 0.044 0.021 0.151 0.064 0.324 0.044 0.172 0.076 0.28 0.098 0.323v0.13c0 0.367-0.152 0.712-0.454 1.035a30.6 30.6 0 0 1-0.776 0.81c-0.173 0.15-0.41 0.226-0.712 0.226a4.14 4.14 0 0 1-1.52-0.292 3.893 3.893 0 0 0-1.489-0.29c-0.388 0-0.723 0.086-1.003 0.258a9.92 9.92 0 0 1-0.971 0.518 1.246 1.246 0 0 1-0.615 0.162H58.2a2.85 2.85 0 0 1-1.23-0.26 14.917 14.917 0 0 1-1.1-0.614 4.154 4.154 0 0 1-1.003-0.939 6.478 6.478 0 0 1-0.711-1.164 7.407 7.407 0 0 1-0.453-1.327 7.606 7.606 0 0 1-0.13-1.359V19.83c0.022-0.195 0.032-0.367 0.032-0.518a3.36 3.36 0 0 0 0.033-0.356v-0.13a0.524 0.524 0 0 0 0.032-0.129c0.043-0.431 0.108-0.852 0.194-1.262 0.108-0.41 0.27-0.808 0.486-1.197 0.215-0.366 0.474-0.658 0.776-0.873 0.324-0.238 0.658-0.475 1.003-0.713 0.345-0.237 0.68-0.409 1.003-0.517 0.346-0.108 0.712-0.216 1.1-0.324 0.044 0 0.13-0.021 0.26-0.064 0.15-0.044 0.247-0.076 0.29-0.098h0.227c0.173 0 0.335 0.011 0.485 0.033 0.173 0.022 0.346 0.032 0.518 0.032 0.216 0 0.432-0.01 0.647-0.032a0.984 0.984 0 0 0 0.583-0.323l0.194-0.292 0.13-0.194v-1.359c0-0.021 0.032-0.108 0.096-0.259 0.065-0.15 0.119-0.28 0.162-0.388 0.151-0.367 0.345-0.636 0.582-0.81 0.26-0.193 0.572-0.387 0.939-0.581 0.15-0.108 0.366-0.162 0.647-0.162zm60.54 0.226c0.194 0 0.4 0.043 0.615 0.13 0.238 0.064 0.453 0.172 0.647 0.323a1.6 1.6 0 0 1 0.518 0.485c0.151 0.194 0.226 0.4 0.226 0.615 0 0.086-0.042 0.205-0.129 0.356-0.064 0.151-0.15 0.313-0.259 0.485a5.222 5.222 0 0 1-0.291 0.453 1.42 1.42 0 0 1-0.259 0.26 1.785 1.785 0 0 1-1.003 0.323c-0.302 0-0.54-0.108-0.712-0.324a4.73 4.73 0 0 0-0.55-0.582l-0.453-0.453c-0.108-0.13-0.161-0.313-0.161-0.55a0.86 0.86 0 0 1 0.193-0.518c0.13-0.194 0.281-0.356 0.454-0.485 0.194-0.151 0.388-0.27 0.582-0.356 0.216-0.108 0.41-0.162 0.582-0.162zm-16.566 3.98h0.226c0.69 0 1.36 0.172 2.006 0.518 0.669 0.345 1.144 0.841 1.425 1.488 0.043 0.065 0.086 0.173 0.129 0.324 0.043 0.13 0.075 0.194 0.097 0.194v0.162c0 0.15-0.065 0.312-0.194 0.485a2.191 2.191 0 0 1-0.421 0.485 3.211 3.211 0 0 1-0.55 0.389c-0.172 0.086-0.335 0.13-0.486 0.13a1.46 1.46 0 0 1-0.517-0.098 4.445 4.445 0 0 0-0.453-0.226 2.612 2.612 0 0 0-0.42-0.227 0.963 0.963 0 0 0-0.486-0.13h-1.78a0.988 0.988 0 0 0-0.323 0.098c-0.28 0.108-0.518 0.28-0.712 0.518a3.189 3.189 0 0 0-0.421 0.808c-0.108 0.28-0.183 0.583-0.226 0.907a5.972 5.972 0 0 0-0.065 0.841v0.388c0.173 0.41 0.4 0.788 0.68 1.133s0.582 0.668 0.905 0.97l0.098 0.032c0.107 0.044 0.258 0.108 0.452 0.195l0.292 0.129h1.714a9.87 9.87 0 0 1 0.712-0.291c0.238-0.086 0.486-0.13 0.745-0.13 0.237 0 0.485 0.151 0.744 0.453 0.28 0.28 0.42 0.54 0.42 0.777v0.032c-0.15 0.755-0.528 1.338-1.132 1.748a3.547 3.547 0 0 1-2.038 0.614c-0.302 0-0.637-0.021-1.003-0.064a3.58 3.58 0 0 1-0.971-0.26h-1.65c-0.044 0-0.162-0.032-0.356-0.096a4.337 4.337 0 0 1-0.389-0.162 5.93 5.93 0 0 1-1.035-0.55 2.742 2.742 0 0 1-0.809-0.842l-0.194-0.29a2.428 2.428 0 0 0-0.259-0.454 4.222 4.222 0 0 0-0.259-0.453 7.152 7.152 0 0 0-0.13-0.291c-0.15-0.28-0.269-0.54-0.355-0.777a9.034 9.034 0 0 0-0.26-0.841 16.079 16.079 0 0 0-0.096-1.1 18.722 18.722 0 0 1-0.032-1.1c0-0.755 0.215-1.456 0.647-2.103a5.958 5.958 0 0 1 1.553-1.65c0.065-0.044 0.226-0.14 0.485-0.292 0.28-0.172 0.475-0.302 0.583-0.388l0.097-0.032c0.366-0.13 0.722-0.27 1.067-0.42a3.544 3.544 0 0 1 1.1-0.324h0.518a1.65 1.65 0 0 1 0.324-0.033c0.108-0.021 0.173-0.032 0.194-0.032 0.043 0 0.151-0.021 0.324-0.065 0.172-0.043 0.28-0.065 0.323-0.065 0-0.021 0.054-0.032 0.162-0.032zm-91.732 0.162c0.582 0 1.187 0.086 1.812 0.259 0.647 0.194 1.186 0.42 1.618 0.68 0.453 0.237 0.82 0.528 1.1 0.873 0.28 0.345 0.497 0.766 0.648 1.262 0.15 0.474 0.269 1.046 0.355 1.715 0.043 0.237 0.076 0.474 0.097 0.711 0.043 0.238 0.065 0.475 0.065 0.713 0 0.172-0.032 0.334-0.097 0.485-0.065 0.13-0.118 0.27-0.162 0.42v0.162c0 0.086-0.01 0.184-0.032 0.292v0.388l-0.13 0.712a7.855 7.855 0 0 0-0.032 0.711v0.098c0.022 0.086 0.065 0.247 0.13 0.485l0.129 0.485v0.194c0 0.26-0.065 0.507-0.194 0.744a2.44 2.44 0 0 1-0.518 0.648 2.489 2.489 0 0 1-0.712 0.453 1.777 1.777 0 0 1-0.744 0.161c-0.345 0-0.68-0.075-1.003-0.226a12.273 12.273 0 0 0-0.938-0.453 0.673 0.673 0 0 0-0.26-0.032h-0.226c-0.41 0-0.809 0.075-1.197 0.226-0.367 0.13-0.733 0.27-1.1 0.42l-0.324 0.163c-0.15 0.086-0.248 0.14-0.291 0.162-0.086 0.043-0.15 0.054-0.194 0.032h-0.486a6.808 6.808 0 0 1-0.647-0.194 21.39 21.39 0 0 1-0.615-0.227 0.526 0.526 0 0 1-0.129-0.032c-0.043-0.021-0.064-0.043-0.064-0.064a23.36 23.36 0 0 1-1.1-0.81 2.423 2.423 0 0 1-0.745-1.132 16.56 16.56 0 0 0-0.194-0.615l-0.13-0.42v-1.618a0.9 0.9 0 0 1 0.065-0.194c0.065-0.108 0.12-0.184 0.162-0.227 0.237-0.431 0.54-0.83 0.906-1.197a6.397 6.397 0 0 1 1.23-0.97c0.301-0.174 0.614-0.26 0.938-0.26 0.323-0.021 0.636-0.086 0.938-0.194 0.044-0.021 0.13-0.054 0.26-0.097a7.44 7.44 0 0 0 0.29-0.129 0.907 0.907 0 0 1 0.389-0.065l0.518-0.065a1.56 1.56 0 0 0 0.42-0.161 0.436 0.436 0 0 0 0.194-0.389 0.507 0.507 0 0 0-0.259-0.453 1.02 1.02 0 0 0-0.55-0.162h-2.232c-0.13 0.043-0.27 0.075-0.42 0.097a2.998 2.998 0 0 1-0.421 0.032 1.42 1.42 0 0 1-0.939-0.356 1.242 1.242 0 0 1-0.388-0.906c0-0.15 0.022-0.29 0.065-0.42 0.064-0.13 0.129-0.249 0.193-0.356l0.68-0.68a0.999 0.999 0 0 1 0.55-0.259c0.216-0.043 0.42-0.075 0.615-0.097 0.086-0.021 0.27-0.032 0.55-0.032 0.302-0.022 0.507-0.032 0.615-0.032 0.28-0.151 0.593-0.227 0.938-0.227 0.367-0.021 0.701-0.032 1.003-0.032zm68.92 0c0.583 0 1.187 0.086 1.812 0.259 0.647 0.194 1.187 0.42 1.618 0.68 0.453 0.237 0.82 0.528 1.1 0.873 0.28 0.345 0.496 0.766 0.647 1.262a9.91 9.91 0 0 1 0.356 1.715c0.044 0.237 0.076 0.474 0.098 0.711 0.043 0.238 0.064 0.475 0.064 0.713 0 0.172-0.032 0.334-0.097 0.485a2.44 2.44 0 0 0-0.162 0.42v0.162c0 0.086-0.01 0.184-0.032 0.292v0.388l-0.13 0.712a7.856 7.856 0 0 0-0.032 0.711v0.098c0.021 0.086 0.065 0.247 0.13 0.485l0.129 0.485v0.194c0 0.26-0.065 0.507-0.194 0.744a2.44 2.44 0 0 1-0.518 0.648 2.491 2.491 0 0 1-0.712 0.453 1.777 1.777 0 0 1-0.744 0.161c-0.345 0-0.68-0.075-1.003-0.226a12.273 12.273 0 0 0-0.938-0.453 0.673 0.673 0 0 0-0.26-0.032h-0.226c-0.41 0-0.809 0.075-1.197 0.226-0.367 0.13-0.733 0.27-1.1 0.42l-0.324 0.163c-0.15 0.086-0.248 0.14-0.29 0.162-0.087 0.043-0.152 0.054-0.195 0.032h-0.486a6.808 6.808 0 0 1-0.646-0.194 21.396 21.396 0 0 1-0.615-0.227 0.526 0.526 0 0 1-0.13-0.032c-0.043-0.021-0.064-0.043-0.064-0.064a23.363 23.363 0 0 1-1.1-0.81 2.423 2.423 0 0 1-0.745-1.132c-0.043-0.15-0.107-0.356-0.194-0.615l-0.13-0.42v-1.618a0.9 0.9 0 0 1 0.065-0.194 1.24 1.24 0 0 1 0.163-0.227 5.33 5.33 0 0 1 0.905-1.197 6.397 6.397 0 0 1 1.23-0.97c0.302-0.174 0.615-0.26 0.938-0.26 0.324-0.021 0.637-0.086 0.939-0.194 0.043-0.021 0.13-0.054 0.259-0.097 0.15-0.064 0.247-0.107 0.29-0.129a0.912 0.912 0 0 1 0.39-0.065l0.516-0.065a1.56 1.56 0 0 0 0.421-0.161 0.436 0.436 0 0 0 0.194-0.389 0.507 0.507 0 0 0-0.259-0.453 1.02 1.02 0 0 0-0.55-0.162h-2.232c-0.13 0.043-0.27 0.075-0.42 0.097a2.998 2.998 0 0 1-0.422 0.032c-0.345 0-0.658-0.119-0.938-0.356a1.241 1.241 0 0 1-0.388-0.906c0-0.15 0.021-0.29 0.064-0.42 0.065-0.13 0.13-0.249 0.195-0.356l0.68-0.68a0.997 0.997 0 0 1 0.55-0.259c0.215-0.043 0.42-0.075 0.614-0.097 0.086-0.021 0.27-0.032 0.55-0.032 0.302-0.022 0.507-0.032 0.615-0.032 0.28-0.151 0.593-0.227 0.938-0.227 0.367-0.021 0.701-0.032 1.003-0.032zm39.573 0.097a0.79 0.79 0 0 1 0.452 0.13c0.151 0.064 0.292 0.15 0.421 0.258 0.302 0.216 0.529 0.421 0.68 0.615 0.15 0.173 0.237 0.442 0.258 0.809 0.022 0.259 0.044 0.55 0.066 0.873 0.043 0.302 0.064 0.594 0.064 0.874 0 0.173-0.01 0.324-0.032 0.453-0.022 0.13-0.032 0.28-0.032 0.453 0 0.108-0.011 0.227-0.033 0.356 0 0.13 0.021 0.248 0.065 0.356v1.36a1.362 1.362 0 0 0-0.032 0.323c0 0.172 0.01 0.345 0.032 0.517l0.13 0.518c0.02 0.215 0.042 0.432 0.064 0.647 0.021 0.194 0.054 0.399 0.097 0.615 0 0.043 0.021 0.162 0.065 0.356 0.043 0.172 0.064 0.28 0.064 0.323v0.13a0.533 0.533 0 0 1 0.033 0.162c0 0.539-0.227 1.024-0.68 1.455-0.453 0.41-0.949 0.615-1.488 0.615h-0.162a3.862 3.862 0 0 1-0.744-0.226 2.094 2.094 0 0 1-0.518-0.323 2.83 2.83 0 0 1-0.42-0.454c-0.13-0.194-0.27-0.42-0.421-0.68a1.377 1.377 0 0 1-0.162-0.679v-0.388c0.021-0.086 0.076-0.216 0.162-0.388v-3.69a2.207 2.207 0 0 0-0.065-0.258V18.6c0-0.173 0.022-0.302 0.065-0.388v-2.2c0-0.216 0.064-0.454 0.194-0.713a3.367 3.367 0 0 1 1.165-1.294c0.237-0.15 0.474-0.226 0.712-0.226zm19.543 0.097h1.586l0.226 0.065c0.173 0.043 0.367 0.097 0.583 0.162 0.216 0.043 0.431 0.097 0.647 0.161 0.237 0.044 0.431 0.087 0.582 0.13 0.238 0.064 0.453 0.162 0.647 0.291 0.194 0.108 0.378 0.227 0.55 0.356a6.33 6.33 0 0 1 1.521 1.424c0.432 0.56 0.734 1.186 0.906 1.876a2.8 2.8 0 0 1 0.097 0.744c0 0.238 0.022 0.475 0.065 0.712 0 0.022 0.011 0.097 0.033 0.227a0.899 0.899 0 0 1 0.064 0.194v0.712c0 0.129-0.01 0.27-0.032 0.42 0 0.151-0.01 0.28-0.032 0.388v0.163c-0.065 0.388-0.238 0.819-0.518 1.294a8.118 8.118 0 0 1-0.971 1.391 9.228 9.228 0 0 1-1.197 1.23c-0.41 0.345-0.798 0.593-1.165 0.744a3.06 3.06 0 0 1-0.453 0.129 4.074 4.074 0 0 1-0.453 0.13 2.227 2.227 0 0 1-0.42 0.032 1.32 1.32 0 0 0-0.422 0.065h-1.844a0.997 0.997 0 0 0-0.614-0.065 1.119 1.119 0 0 1-0.648-0.065 13.238 13.238 0 0 1-2.265-1.326 4.305 4.305 0 0 1-1.488-2.04 2.327 2.327 0 0 1-0.13-0.484 3.4 3.4 0 0 0-0.096-0.454 0.985 0.985 0 0 0-0.033-0.161 1.84 1.84 0 0 0-0.097-0.324 1.155 1.155 0 0 0-0.097-0.291 0.98 0.98 0 0 1-0.032-0.162 0.533 0.533 0 0 0-0.033-0.162v-0.13a10.188 10.188 0 0 1-0.129-0.744 12.573 12.573 0 0 1-0.033-0.808c0-0.194 0.022-0.388 0.066-0.582l0.129-0.583c0.345-1.121 0.787-2.027 1.326-2.718 0.561-0.712 1.435-1.24 2.621-1.585 0.26-0.065 0.518-0.119 0.777-0.162 0.28-0.043 0.539-0.108 0.776-0.194zm41.644 0.065c0.107 0 0.205 0.021 0.291 0.064a0.865 0.865 0 0 0 0.324 0.066h0.226a4.87 4.87 0 0 0 0.259-0.098h2.07c0.13 0.044 0.26 0.065 0.39 0.065 0.15 0 0.3 0.022 0.452 0.065 0.15 0.065 0.323 0.173 0.518 0.324 0.215 0.13 0.41 0.29 0.582 0.485 0.194 0.194 0.356 0.4 0.485 0.615 0.13 0.216 0.195 0.42 0.195 0.614 0 0.173-0.076 0.378-0.227 0.615-0.13 0.216-0.29 0.421-0.485 0.615a2.8 2.8 0 0 1-0.648 0.485 1.2 1.2 0 0 1-0.614 0.195h-0.453a3.813 3.813 0 0 1-0.42-0.097 15.945 15.945 0 0 1-0.68-0.292 1.474 1.474 0 0 0-0.712-0.194c-0.302 0-0.453 0.13-0.453 0.388 0 0.26 0.14 0.41 0.42 0.454 0.41 0 0.842 0.032 1.295 0.096a1.88 1.88 0 0 1 1.197 0.55l0.097 0.13c0.065 0.065 0.097 0.108 0.097 0.13 0.151 0.172 0.302 0.312 0.453 0.42 0.151 0.108 0.313 0.226 0.486 0.356a0.891 0.891 0 0 1 0.323 0.42l0.097 0.292c0.043 0.13 0.086 0.27 0.13 0.42 0.064 0.151 0.118 0.292 0.161 0.421l0.097 0.291v0.42c0 0.67-0.194 1.263-0.582 1.78a24.58 24.58 0 0 1-1.165 1.457c0 0.021-0.01 0.043-0.032 0.064-0.28 0.238-0.55 0.42-0.81 0.55a5.13 5.13 0 0 1-0.71 0.324 6.665 6.665 0 0 1-0.778 0.226c-0.258 0.065-0.55 0.151-0.873 0.26h-1.262a4.093 4.093 0 0 0-0.776-0.195 9.495 9.495 0 0 1-0.777-0.097 3.7 3.7 0 0 0-0.453-0.13 5.733 5.733 0 0 1-0.453-0.161h-0.292a2.807 2.807 0 0 0-0.29-0.033 1.312 1.312 0 0 1-0.583-0.226 2.935 2.935 0 0 1-0.518-0.518 4.558 4.558 0 0 1-0.388-0.582 1.657 1.657 0 0 1-0.13-0.615c0-0.303 0.097-0.561 0.292-0.777 0.215-0.216 0.453-0.378 0.712-0.486h0.323c0.302 0 0.594 0.033 0.874 0.098 0.302 0.064 0.604 0.15 0.906 0.258h1.617c0.087 0 0.151-0.042 0.195-0.129a0.52 0.52 0 0 0 0.064-0.226c0-0.194-0.086-0.313-0.258-0.356a8.667 8.667 0 0 0-0.453-0.162c-0.195-0.065-0.302-0.108-0.324-0.13a1.6 1.6 0 0 0-0.453 0 0.86 0.86 0 0 1-0.388-0.096 16.53 16.53 0 0 0-0.485-0.227 18.25 18.25 0 0 1-0.486-0.226 3.85 3.85 0 0 1-0.712-0.583c-0.259-0.28-0.507-0.582-0.744-0.906-0.216-0.345-0.4-0.69-0.55-1.035-0.151-0.345-0.227-0.647-0.227-0.906 0-0.28 0.022-0.55 0.065-0.809 0.065-0.28 0.14-0.55 0.227-0.81 0.172-0.495 0.388-0.894 0.647-1.196 0.259-0.324 0.55-0.583 0.873-0.777a4.22 4.22 0 0 1 1.1-0.453c0.41-0.13 0.852-0.237 1.327-0.323 0.043 0 0.151-0.022 0.324-0.065 0.172-0.043 0.28-0.065 0.323-0.065 0-0.021 0.043-0.032 0.13-0.032zm-152.757 0.42c0.367 0 0.712 0.065 1.035 0.194 0.324 0.13 0.55 0.378 0.68 0.744 0.064 0.151 0.108 0.303 0.13 0.454 0.043 0.15 0.085 0.312 0.129 0.485l0.258 0.582c0.087 0.173 0.13 0.367 0.13 0.583 0 0.302-0.032 0.593-0.097 0.874-0.043 0.28-0.065 0.57-0.065 0.873 0 0.216 0.01 0.432 0.032 0.647l0.13 0.647c0.043 0.367 0.086 0.755 0.13 1.165 0.064 0.41 0.28 0.734 0.646 0.971 0.065 0.043 0.162 0.097 0.292 0.162 0.13 0.065 0.205 0.097 0.226 0.097h0.777a0.535 0.535 0 0 0 0.129-0.032 0.759 0.759 0 0 0 0.194-0.13c0.108-0.064 0.216-0.14 0.324-0.226 0.13-0.086 0.237-0.184 0.323-0.291l0.033-0.098c0.021-0.064 0.043-0.118 0.064-0.161 0.022-0.044 0.043-0.119 0.065-0.227a1.64 1.64 0 0 0 0.033-0.194v-0.582c0.021-0.151 0.032-0.28 0.032-0.389 0.021-0.107 0.032-0.183 0.032-0.226 0-0.043 0.022-0.162 0.065-0.356 0.043-0.216 0.075-0.345 0.097-0.388 0.043-0.194 0.065-0.388 0.065-0.582 0-0.216 0.022-0.421 0.065-0.615l0.129-0.518a1.46 1.46 0 0 0 0.097-0.518c0-0.15-0.021-0.28-0.065-0.388a1.435 1.435 0 0 1-0.065-0.453 2 2 0 0 1 0.13-0.68 2.26 2.26 0 0 1 0.356-0.68c0.151-0.215 0.323-0.387 0.517-0.517 0.216-0.129 0.454-0.194 0.712-0.194 0.26 0 0.529 0.054 0.81 0.162 0.28 0.108 0.539 0.259 0.776 0.453 0.259 0.194 0.464 0.42 0.615 0.68 0.172 0.237 0.259 0.495 0.259 0.776v1.974l-0.163 0.582v1.683c0.044 0.194 0.098 0.41 0.163 0.647 0.064 0.237 0.096 0.453 0.096 0.647a0.72 0.72 0 0 1-0.032 0.227 0.716 0.716 0 0 0-0.032 0.226v0.162c0.021 0.043 0.043 0.108 0.064 0.194v1.553l-0.129 0.518a2.187 2.187 0 0 1-0.874 1.456 1.86 1.86 0 0 1-1.132 0.355h-0.13l-1.1-0.323h-2.2c-0.388 0.173-0.787 0.324-1.197 0.453-0.41 0.13-0.83 0.237-1.262 0.324h-0.13c-0.301 0-0.604-0.076-0.906-0.227-0.28-0.13-0.55-0.259-0.808-0.388a3.355 3.355 0 0 1-0.744-0.583 7.522 7.522 0 0 1-0.745-0.873c-0.215-0.324-0.41-0.647-0.582-0.971-0.173-0.324-0.27-0.614-0.291-0.873v-1.1c0-0.151-0.01-0.303-0.032-0.454v-0.776a3.055 3.055 0 0 1-0.162-0.971c0-0.108 0.01-0.205 0.032-0.291 0.021-0.108 0.032-0.216 0.032-0.324v-0.194a24.974 24.974 0 0 0-0.161-1.036 9.723 9.723 0 0 1-0.065-1.067c0-0.324 0.054-0.637 0.162-0.939 0.108-0.323 0.258-0.604 0.452-0.841 0.195-0.259 0.432-0.464 0.713-0.615 0.28-0.173 0.593-0.258 0.938-0.258zm129.04 0c0.366 0 0.71 0.065 1.034 0.194 0.324 0.13 0.55 0.378 0.68 0.744 0.065 0.151 0.108 0.303 0.13 0.454 0.043 0.15 0.086 0.312 0.129 0.485l0.259 0.582c0.086 0.173 0.129 0.367 0.129 0.583 0 0.302-0.033 0.593-0.097 0.874-0.043 0.28-0.065 0.57-0.065 0.873 0 0.216 0.011 0.432 0.033 0.647l0.129 0.647c0.043 0.367 0.086 0.755 0.13 1.165 0.064 0.41 0.28 0.734 0.647 0.971 0.064 0.043 0.162 0.097 0.291 0.162 0.13 0.065 0.205 0.097 0.226 0.097h0.777a0.535 0.535 0 0 0 0.13-0.032 0.759 0.759 0 0 0 0.193-0.13c0.108-0.064 0.216-0.14 0.324-0.226 0.13-0.086 0.237-0.184 0.323-0.291l0.033-0.098a1.27 1.27 0 0 1 0.065-0.161 1.03 1.03 0 0 0 0.064-0.227 1.64 1.64 0 0 0 0.033-0.194v-0.582c0.021-0.151 0.032-0.28 0.032-0.389 0.021-0.107 0.032-0.183 0.032-0.226 0-0.043 0.022-0.162 0.065-0.356 0.043-0.216 0.076-0.345 0.097-0.388 0.043-0.194 0.065-0.388 0.065-0.582 0-0.216 0.021-0.421 0.064-0.615l0.13-0.518a1.46 1.46 0 0 0 0.097-0.518c0-0.15-0.022-0.28-0.065-0.388a1.435 1.435 0 0 1-0.065-0.453 2 2 0 0 1 0.13-0.68 2.26 2.26 0 0 1 0.356-0.68c0.15-0.215 0.323-0.387 0.518-0.517a1.36 1.36 0 0 1 0.712-0.194c0.258 0 0.528 0.054 0.808 0.162 0.28 0.108 0.54 0.259 0.777 0.453 0.259 0.194 0.464 0.42 0.615 0.68 0.173 0.237 0.258 0.495 0.258 0.776v1.974l-0.161 0.582v1.683c0.043 0.194 0.097 0.41 0.161 0.647 0.065 0.237 0.098 0.453 0.098 0.647a0.72 0.72 0 0 1-0.033 0.227 0.716 0.716 0 0 0-0.032 0.226v0.162c0.021 0.043 0.043 0.108 0.065 0.194v1.553l-0.13 0.518a2.3 2.3 0 0 1-0.13 0.485 2.186 2.186 0 0 1-0.744 0.97c-0.323 0.238-0.7 0.356-1.132 0.356h-0.13l-1.1-0.323h-2.2c-0.388 0.173-0.787 0.324-1.197 0.453-0.41 0.13-0.83 0.237-1.262 0.324h-0.129a2.01 2.01 0 0 1-0.906-0.227c-0.28-0.13-0.55-0.259-0.81-0.388a3.355 3.355 0 0 1-0.743-0.583 7.523 7.523 0 0 1-0.744-0.873c-0.216-0.324-0.41-0.647-0.583-0.971-0.172-0.324-0.27-0.614-0.291-0.873v-1.1c0-0.151-0.01-0.303-0.032-0.454v-0.776a3.055 3.055 0 0 1-0.162-0.971c0-0.108 0.01-0.205 0.032-0.291a1.62 1.62 0 0 0 0.033-0.324v-0.194a24.97 24.97 0 0 0-0.162-1.036 9.723 9.723 0 0 1-0.065-1.067c0-0.324 0.054-0.637 0.162-0.939a2.63 2.63 0 0 1 0.453-0.841c0.194-0.259 0.431-0.464 0.712-0.615 0.28-0.173 0.593-0.258 0.938-0.258zm-102.54 2.75l-0.42 0.227-1.1 1.1a0.76 0.76 0 0 0-0.162 0.26 1.846 1.846 0 0 0-0.098 0.323v1.164c0 0.216 0.022 0.4 0.066 0.55 0.107 0.368 0.27 0.745 0.485 1.133 0.237 0.367 0.528 0.636 0.873 0.809 0.108 0.065 0.248 0.14 0.42 0.227l0.292 0.129h0.388c0.022 0 0.12-0.043 0.292-0.13 0.194-0.086 0.334-0.161 0.42-0.226a1.138 1.138 0 0 0 0.55-0.938v-1.262a1.394 1.394 0 0 1-0.129-0.712 2.86 2.86 0 0 0-0.032-0.744 4.208 4.208 0 0 1-0.065-0.55 9.364 9.364 0 0 1-0.033-0.55l-0.064-0.13-0.583-0.55-0.258-0.13zm84.678 0.42a0.572 0.572 0 0 0-0.161 0.066c-0.065 0.043-0.12 0.076-0.163 0.097-0.237 0.173-0.42 0.334-0.55 0.485a1.827 1.827 0 0 0-0.323 0.615 8.662 8.662 0 0 1-0.162 0.453 0.807 0.807 0 0 0-0.064 0.356c0 0.151 0.042 0.324 0.129 0.518v1.359c0 0.021 0.032 0.13 0.097 0.323 0.065 0.173 0.119 0.313 0.162 0.421 0.043 0.13 0.13 0.27 0.259 0.42 0.129 0.152 0.27 0.292 0.42 0.421a3.4 3.4 0 0 0 0.518 0.324 1.3 1.3 0 0 0 0.518 0.13c0.41 0 0.765-0.152 1.067-0.454 0.302-0.323 0.55-0.7 0.745-1.132a5.85 5.85 0 0 0 0.42-1.36 6.71 6.71 0 0 0 0.13-1.164c0-0.173-0.011-0.345-0.033-0.518a1.078 1.078 0 0 0-0.194-0.517c-0.043-0.043-0.15-0.152-0.323-0.324-0.173-0.194-0.292-0.313-0.356-0.356a0.965 0.965 0 0 0-0.13-0.097 0.315 0.315 0 0 0-0.161-0.065zm-129.007 3.69c-0.172 0-0.302 0.108-0.388 0.324-0.086 0.194-0.13 0.355-0.13 0.485 0 0.345 0.108 0.593 0.324 0.744 0.216 0.13 0.475 0.194 0.777 0.194h0.356c0.064 0 0.097-0.021 0.097-0.064 0.043-0.044 0.118-0.12 0.226-0.227 0.13-0.108 0.216-0.184 0.259-0.227a0.46 0.46 0 0 0 0.065-0.258v-0.583a0.636 0.636 0 0 0-0.162-0.226c-0.065-0.108-0.14-0.162-0.227-0.162zm68.92 0c-0.172 0-0.302 0.108-0.388 0.324-0.086 0.194-0.13 0.355-0.13 0.485 0 0.345 0.108 0.593 0.324 0.744 0.216 0.13 0.475 0.194 0.777 0.194h0.356c0.065 0 0.097-0.021 0.097-0.064l0.226-0.227c0.13-0.108 0.216-0.184 0.26-0.227a0.46 0.46 0 0 0 0.064-0.258v-0.583a0.636 0.636 0 0 0-0.162-0.226c-0.065-0.108-0.14-0.162-0.227-0.162z"/></g></svg> \ No newline at end of file
diff --git a/images/application-exit.svg b/images/application-exit.svg
index c34ae18..29ffab7 100644
--- a/images/application-exit.svg
+++ b/images/application-exit.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#555"><path d="M3 1c-1.108 0-2 .892-2 2v2.994L3 6V3h10v10H3v-3l-2-.006V13c0 1.108.892 2 2 2h10c1.108 0 2-.892 2-2V3c0-1.108-.892-2-2-2z"/><path d="M7.212 4L5.826 5.386l1.635 1.635L0 7v2l7.461.021-1.635 1.634 1.386 1.386 4-4.041z"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#555"><path d="M3 1c-1.108 0-2 0.892-2 2v2.994L3 6V3h10v10H3v-3l-2-0.006V13c0 1.108 0.892 2 2 2h10c1.108 0 2-0.892 2-2V3c0-1.108-0.892-2-2-2z"/><path d="M7.212 4L5.826 5.386l1.635 1.635L0 7v2l7.461 0.021-1.635 1.634 1.386 1.386 4-4.041z"/></g></svg> \ No newline at end of file
diff --git a/images/applications-graphics.svg b/images/applications-graphics.svg
index 394d0ba..d7da760 100644
--- a/images/applications-graphics.svg
+++ b/images/applications-graphics.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#555"><path d="M7.892.003c-2.11.03-4.945.802-4.897 3.28.05 2.587 2.917 1.662 3.15 2.719.035-.045.088-.082.125-.125.197-.214.395-.388.593-.594.312-.352.636-.679.967-1.031 1.106-1.178 1.154-1.25 3.796-3.25-1.035-.62-2.258-.965-3.297-1-.134-.004-.296-.001-.437 0zm-1.903 1.53c.827 0 1.497.672 1.497 1.5a1.499 1.499 0 1 1-1.497-1.5zm7.269.662C11.84 4.43 10.89 5.751 9.888 6.783c-.639.657-1.163 1.311-1.622 1.78-.839.891-1.938 1.942-3.15 3.094.063 1.469.81 2.746 3.244 3.218 3.898.756 8.027-1.824 7.611-7.061-.178-2.248-1.405-4.281-2.713-5.619zm.342 3.807a1 1 0 0 1 0 2 1 1 0 0 1 0-2zm-.624 3a1 1 0 0 1 0 1.999 1 1 0 0 1 0-2zM7.986 11a1 1 0 0 1 0 2 1 1 0 0 1 0-2zm2.994 0a1 1 0 0 1 0 2 1 1 0 0 1 0-2zM0 13.5c1.552 0 1.394-1.788 2.147-2.286.874-.577 1.639.138 1.792.726.192.742-.117 1.631-1.13 1.885-1.074.268-2.662.276-2.809-.326z"/><path d="M14.037.003c-1.8 1.299-4.206 3.302-6.115 5.333-.173.185-.34.363-.504.547-.104.108-.212.196-.315.308-.066.077-.126.163-.19.24-1.873 2.07-3.72 4.68-4.917 6.632 2.978-2.297 4.916-4.165 6.147-5.47.24-.246.53-.567.85-.923 1.204-1.335 2.926-3.438 5.044-6.667z"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#555"><path d="M7.892 0.003c-2.11 0.03-4.945 0.802-4.897 3.28 0.05 2.587 2.917 1.662 3.15 2.719 0.035-0.045 0.088-0.082 0.125-0.125 0.197-0.214 0.395-0.388 0.593-0.594 0.312-0.352 0.636-0.679 0.967-1.031 1.106-1.178 1.154-1.25 3.796-3.25-1.035-0.62-2.258-0.965-3.297-1-0.134-0.004-0.296-0.001-0.437 0zm-1.903 1.53c0.827 0 1.497 0.672 1.497 1.5a1.499 1.499 0 1 1-1.497-1.5zm7.269 0.662C11.84 4.43 10.89 5.751 9.888 6.783c-0.639 0.657-1.163 1.311-1.622 1.78-0.839 0.891-1.938 1.942-3.15 3.094 0.063 1.469 0.81 2.746 3.244 3.218 3.898 0.756 8.027-1.824 7.611-7.061-0.178-2.248-1.405-4.281-2.713-5.619zm0.342 3.807a1 1 0 0 1 0 2 1 1 0 0 1 0-2zm-0.624 3a1 1 0 0 1 0 1.999 1 1 0 0 1 0-2zM7.986 11a1 1 0 0 1 0 2 1 1 0 0 1 0-2zm2.994 0a1 1 0 0 1 0 2 1 1 0 0 1 0-2zM0 13.5c1.552 0 1.394-1.788 2.147-2.286 0.874-0.577 1.639 0.138 1.792 0.726 0.192 0.742-0.117 1.631-1.13 1.885-1.074 0.268-2.662 0.276-2.809-0.326z"/><path d="M14.037 0.003c-1.8 1.299-4.206 3.302-6.115 5.333-0.173 0.185-0.34 0.363-0.504 0.547-0.104 0.108-0.212 0.196-0.315 0.308-0.066 0.077-0.126 0.163-0.19 0.24-1.873 2.07-3.72 4.68-4.917 6.632 2.978-2.297 4.916-4.165 6.147-5.47 0.24-0.246 0.53-0.567 0.85-0.923 1.204-1.335 2.926-3.438 5.044-6.667z"/></g></svg> \ No newline at end of file
diff --git a/images/applications-internet.svg b/images/applications-internet.svg
index 05c7709..33fd294 100644
--- a/images/applications-internet.svg
+++ b/images/applications-internet.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm-.5 1.938c.067-.008.151.003.219 0 .008.031-.049.145-.125.312-.486 1.061-.514 2.304-.063 2.969.082.12.157.235.157.25 0 .015-.088.03-.188.03-.234.001-.455-.141-.906-.499-.2-.159-.462-.292-.563-.313-.158-.031-.2-.017-.406.188-.191.19-.25.294-.25.469 0 .663.787 1.19 2.25 1.5 1.987.42 2.476.799 2.531 1.843.069 1.31-.628 2.298-2.156 3.063-.182.091-.298.127-.375.156-.034-.003-.06.003-.094 0a1.113 1.113 0 0 1-.03-.312c0-.696-.275-1.412-.688-1.813a5.258 5.258 0 0 0-.688-.5c-.266-.164-.534-.356-.594-.437-.099-.136-.107-.219-.03-.469.138-.457.303-.711.624-1 .168-.151.338-.278.375-.281.037-.003-.215-.08-.594-.157-.378-.077-.932-.24-1.218-.343-.524-.19-1.23-.587-1.5-.875-.012-.013-.022-.02-.032-.032a5.026 5.026 0 0 1 2.907-3.406c.3-.127.61-.214.937-.281.163-.033.332-.045.5-.063zm4.688 2.343c.117.073.56 1.032.687 1.5.163.604.152 1.65 0 2.25-.058.229-.132.442-.156.469-.025.027-.114-.127-.219-.313-.105-.185-.44-.58-.719-.874-.804-.849-.93-1.292-.594-1.97.17-.34.91-1.118 1-1.062z" fill="#555" enable-background="new"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm-0.5 1.938c0.067-0.008 0.151 0.003 0.219 0 0.008 0.031-0.049 0.145-0.125 0.312-0.486 1.061-0.514 2.304-0.063 2.969 0.082 0.12 0.157 0.235 0.157 0.25 0 0.015-0.088 0.03-0.188 0.03-0.234 0.001-0.455-0.141-0.906-0.499-0.2-0.159-0.462-0.292-0.563-0.313-0.158-0.031-0.2-0.017-0.406 0.188-0.191 0.19-0.25 0.294-0.25 0.469 0 0.663 0.787 1.19 2.25 1.5 1.987 0.42 2.476 0.799 2.531 1.843 0.069 1.31-0.628 2.298-2.156 3.063-0.182 0.091-0.298 0.127-0.375 0.156-0.034-0.003-0.06 0.003-0.094 0a1.113 1.113 0 0 1-0.03-0.312c0-0.696-0.275-1.412-0.688-1.813a5.258 5.258 0 0 0-0.688-0.5c-0.266-0.164-0.534-0.356-0.594-0.437-0.099-0.136-0.107-0.219-0.03-0.469 0.138-0.457 0.303-0.711 0.624-1 0.168-0.151 0.338-0.278 0.375-0.281 0.037-0.003-0.215-0.08-0.594-0.157-0.378-0.077-0.932-0.24-1.218-0.343-0.524-0.19-1.23-0.587-1.5-0.875-0.012-0.013-0.022-0.02-0.032-0.032a5.026 5.026 0 0 1 2.907-3.406c0.3-0.127 0.61-0.214 0.937-0.281 0.163-0.033 0.332-0.045 0.5-0.063zm4.688 2.343c0.117 0.073 0.56 1.032 0.687 1.5 0.163 0.604 0.152 1.65 0 2.25-0.058 0.229-0.132 0.442-0.156 0.469-0.025 0.027-0.114-0.127-0.219-0.313-0.105-0.185-0.44-0.58-0.719-0.874-0.804-0.849-0.93-1.292-0.594-1.97 0.17-0.34 0.91-1.118 1-1.062z" fill="#555" enable-background="new"/></svg> \ No newline at end of file
diff --git a/images/applications-system.svg b/images/applications-system.svg
index e43d7cc..fce52ef 100644
--- a/images/applications-system.svg
+++ b/images/applications-system.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M6.5 1C5.669 1 5 1.669 5 2.5V4H2c-.554 0-1 .446-1 1v3h1.5C3.331 8 4 8.669 4 9.5S3.331 11 2.5 11H1v3c0 .554.446 1 1 1h3v-1.5c0-.831.669-1.5 1.5-1.5s1.5.669 1.5 1.5V15h3c.554 0 1-.446 1-1v-3h1.5c.831 0 1.5-.669 1.5-1.5S14.331 8 13.5 8H12V5c0-.554-.446-1-1-1H8V2.5C8 1.669 7.331 1 6.5 1z" fill="#555"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M6.5 1C5.669 1 5 1.669 5 2.5V4H2c-0.554 0-1 0.446-1 1v3h1.5C3.331 8 4 8.669 4 9.5S3.331 11 2.5 11H1v3c0 0.554 0.446 1 1 1h3v-1.5c0-0.831 0.669-1.5 1.5-1.5s1.5 0.669 1.5 1.5V15h3c0.554 0 1-0.446 1-1v-3h1.5c0.831 0 1.5-0.669 1.5-1.5S14.331 8 13.5 8H12V5c0-0.554-0.446-1-1-1H8V2.5C8 1.669 7.331 1 6.5 1z" fill="#555"/></svg> \ No newline at end of file
diff --git a/images/audacious.svg b/images/audacious.svg
index 5b712f5..4951a6e 100644
--- a/images/audacious.svg
+++ b/images/audacious.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" height="96" width="96"><path d="M96 48a48 48 0 0 1-48 48A48 48 0 0 1 0 48 48 48 0 0 1 48 0a48 48 0 0 1 48 48z"/><g font-size="56" font-weight="400" fill="#d9d9d9" font-family="Circulate BRK"><path d="M48 12c-5.008 0-9.691.944-14.049 2.83-4.358 1.886-8.162 4.455-11.414 7.707-3.252 3.252-5.82 7.09-7.707 11.512C12.944 38.407 12 43.057 12 48c0 5.008.944 9.691 2.83 14.049 1.886 4.358 4.455 8.162 7.707 11.414 3.252 3.252 7.056 5.82 11.414 7.707C38.31 83.056 42.991 84 48 84c4.943 0 9.593-.944 13.951-2.83 4.423-1.886 8.26-4.455 11.512-7.707 3.252-3.252 5.82-7.056 7.707-11.414C83.056 57.69 84 53.009 84 48c0-4.943-.944-9.593-2.83-13.951-1.886-4.423-4.455-8.26-7.707-11.512-3.252-3.252-7.09-5.82-11.512-7.707C57.593 12.944 52.943 12 48 12zm.879 15.707c1.756 0 3.577.261 5.463.781 1.951.586 3.576 1.269 4.877 2.05 1.366.715 2.473 1.591 3.318 2.632.846 1.04 1.496 2.31 1.951 3.807.456 1.43.812 3.153 1.073 5.17.13.715.227 1.43.293 2.146.13.715.195 1.431.195 2.146 0 .52-.098 1.008-.293 1.463-.195.39-.358.813-.488 1.268v.488c0 .26-.033.554-.098.88a1984.653 1984.653 0 0 0 0 1.169l-.389 2.147A23.663 23.663 0 0 0 64.684 56v.293c.065.26.193.747.388 1.463.195.715.326 1.203.39 1.463v.586c0 .78-.193 1.528-.583 2.244A7.377 7.377 0 0 1 63.316 64a7.51 7.51 0 0 1-2.146 1.365 5.356 5.356 0 0 1-2.242.489 7.08 7.08 0 0 1-3.026-.684c-.975-.52-1.92-.975-2.83-1.365-.13-.065-.389-.098-.779-.098h-.684a9.877 9.877 0 0 0-3.609.684c-1.106.39-2.21.812-3.316 1.267l-.977.488c-.455.26-.747.424-.877.489-.26.13-.456.162-.586.097h-1.463c-.325-.065-.975-.26-1.95-.586a63.062 63.062 0 0 1-1.854-.683c-.066 0-.196-.033-.391-.098-.13-.065-.195-.13-.195-.195a70.297 70.297 0 0 1-3.319-2.438c-1.105-.975-1.852-2.115-2.242-3.416a47.63 47.63 0 0 0-.586-1.853l-.39-1.268v-4.879c0-.065.065-.258.195-.584.195-.325.358-.553.488-.683a15.995 15.995 0 0 1 2.73-3.61 19.3 19.3 0 0 1 3.71-2.927c.91-.52 1.852-.78 2.828-.78a10.44 10.44 0 0 0 2.83-.586 7.11 7.11 0 0 1 .78-.292c.454-.196.748-.326.878-.391.26-.13.65-.195 1.17-.195l1.56-.196c.52-.13.945-.29 1.27-.486.39-.26.586-.652.586-1.172 0-.585-.261-1.04-.781-1.365a3.077 3.077 0 0 0-1.659-.488h-6.732c-.39.13-.812.228-1.268.293-.455.065-.879.097-1.27.097-1.04 0-1.982-.357-2.827-1.072-.78-.78-1.172-1.692-1.172-2.733 0-.455.065-.877.195-1.267.195-.39.391-.75.586-1.074L36 29.755c.52-.454 1.073-.713 1.658-.778.65-.13 1.268-.228 1.854-.293.26-.065.812-.098 1.658-.098.91-.065 1.528-.098 1.853-.098.846-.455 1.79-.683 2.83-.683a51.967 51.967 0 0 1 3.026-.098z" style="text-align:start;line-height:125%"/><path d="M44.585 52.878c0 1.04.326 1.789.976 2.244.65.39 1.43.585 2.341.585h1.074c.195 0 .292-.065.292-.195l.683-.683c.39-.325.65-.553.78-.683.13-.195.196-.455.196-.78V51.61c-.065-.195-.228-.423-.488-.683-.195-.325-.423-.488-.683-.488h-3.61c-.52 0-.91.325-1.17.976-.26.585-.39 1.073-.39 1.463" style="text-align:start;line-height:125%"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" height="96" width="96"><path d="M96 48a48 48 0 0 1-48 48A48 48 0 0 1 0 48 48 48 0 0 1 48 0a48 48 0 0 1 48 48z"/><g font-size="56" font-weight="400" fill="#d9d9d9" font-family="Circulate BRK"><path d="M48 12c-5.008 0-9.691 0.944-14.049 2.83-4.358 1.886-8.162 4.455-11.414 7.707-3.252 3.252-5.82 7.09-7.707 11.512C12.944 38.407 12 43.057 12 48c0 5.008 0.944 9.691 2.83 14.049 1.886 4.358 4.455 8.162 7.707 11.414 3.252 3.252 7.056 5.82 11.414 7.707C38.31 83.056 42.991 84 48 84c4.943 0 9.593-0.944 13.951-2.83 4.423-1.886 8.26-4.455 11.512-7.707 3.252-3.252 5.82-7.056 7.707-11.414C83.056 57.69 84 53.009 84 48c0-4.943-0.944-9.593-2.83-13.951-1.886-4.423-4.455-8.26-7.707-11.512-3.252-3.252-7.09-5.82-11.512-7.707C57.593 12.944 52.943 12 48 12zm0.879 15.707c1.756 0 3.577 0.261 5.463 0.781 1.951 0.586 3.576 1.269 4.877 2.05 1.366 0.715 2.473 1.591 3.318 2.632 0.846 1.04 1.496 2.31 1.951 3.807 0.456 1.43 0.812 3.153 1.073 5.17 0.13 0.715 0.227 1.43 0.293 2.146 0.13 0.715 0.195 1.431 0.195 2.146 0 0.52-0.098 1.008-0.293 1.463-0.195 0.39-0.358 0.813-0.488 1.268v0.488c0 0.26-0.033 0.554-0.098 0.88a1984.653 1984.653 0 0 0 0 1.169l-0.389 2.147A23.663 23.663 0 0 0 64.684 56v0.293c0.065 0.26 0.193 0.747 0.388 1.463 0.195 0.715 0.326 1.203 0.39 1.463v0.586c0 0.78-0.193 1.528-0.583 2.244A7.377 7.377 0 0 1 63.316 64a7.51 7.51 0 0 1-2.146 1.365 5.356 5.356 0 0 1-2.242 0.489 7.08 7.08 0 0 1-3.026-0.684c-0.975-0.52-1.92-0.975-2.83-1.365-0.13-0.065-0.389-0.098-0.779-0.098h-0.684a9.877 9.877 0 0 0-3.609 0.684c-1.106 0.39-2.21 0.812-3.316 1.267l-0.977 0.488c-0.455 0.26-0.747 0.424-0.877 0.489-0.26 0.13-0.456 0.162-0.586 0.097h-1.463c-0.325-0.065-0.975-0.26-1.95-0.586a63.062 63.062 0 0 1-1.854-0.683c-0.066 0-0.196-0.033-0.391-0.098-0.13-0.065-0.195-0.13-0.195-0.195a70.297 70.297 0 0 1-3.319-2.438c-1.105-0.975-1.852-2.115-2.242-3.416a47.63 47.63 0 0 0-0.586-1.853l-0.39-1.268v-4.879c0-0.065 0.065-0.258 0.195-0.584 0.195-0.325 0.358-0.553 0.488-0.683a15.995 15.995 0 0 1 2.73-3.61 19.3 19.3 0 0 1 3.71-2.927c0.91-0.52 1.852-0.78 2.828-0.78a10.44 10.44 0 0 0 2.83-0.586 7.11 7.11 0 0 1 0.78-0.292c0.454-0.196 0.748-0.326 0.878-0.391 0.26-0.13 0.65-0.195 1.17-0.195l1.56-0.196c0.52-0.13 0.945-0.29 1.27-0.486 0.39-0.26 0.586-0.652 0.586-1.172 0-0.585-0.261-1.04-0.781-1.365a3.077 3.077 0 0 0-1.659-0.488h-6.732c-0.39 0.13-0.812 0.228-1.268 0.293-0.455 0.065-0.879 0.097-1.27 0.097-1.04 0-1.982-0.357-2.827-1.072-0.78-0.78-1.172-1.692-1.172-2.733 0-0.455 0.065-0.877 0.195-1.267 0.195-0.39 0.391-0.75 0.586-1.074L36 29.755c0.52-0.454 1.073-0.713 1.658-0.778 0.65-0.13 1.268-0.228 1.854-0.293 0.26-0.065 0.812-0.098 1.658-0.098 0.91-0.065 1.528-0.098 1.853-0.098 0.846-0.455 1.79-0.683 2.83-0.683a51.967 51.967 0 0 1 3.026-0.098z" style="text-align:start;line-height:125%"/><path d="M44.585 52.878c0 1.04 0.326 1.789 0.976 2.244 0.65 0.39 1.43 0.585 2.341 0.585h1.074c0.195 0 0.292-0.065 0.292-0.195l0.683-0.683c0.39-0.325 0.65-0.553 0.78-0.683 0.13-0.195 0.196-0.455 0.196-0.78V51.61c-0.065-0.195-0.228-0.423-0.488-0.683-0.195-0.325-0.423-0.488-0.683-0.488h-3.61c-0.52 0-0.91 0.325-1.17 0.976-0.26 0.585-0.39 1.073-0.39 1.463" style="text-align:start;line-height:125%"/></g></svg> \ No newline at end of file
diff --git a/images/audio-card.svg b/images/audio-card.svg
index 4aec807..7d19bad 100644
--- a/images/audio-card.svg
+++ b/images/audio-card.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M468-118c-2 0-2 2-2 2v9c0 2 2 2 2 2h10c2 0 2-2 2-2v-9s0-2-2-2zm3 3h5v5.5a1.5 1.5 0 1 1-1.5-1.5c.173 0 .346.04.5.094V-113h-3v3.5a1.5 1.5 0 1 1-1.5-1.5c.173 0 .346.04.5.094V-113z" fill="#555" transform="translate(-465 119.035)" filter="url(#a)"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M468-118c-2 0-2 2-2 2v9c0 2 2 2 2 2h10c2 0 2-2 2-2v-9s0-2-2-2zm3 3h5v5.5a1.5 1.5 0 1 1-1.5-1.5c0.173 0 0.346 0.04 0.5 0.094V-113h-3v3.5a1.5 1.5 0 1 1-1.5-1.5c0.173 0 0.346 0.04 0.5 0.094V-113z" fill="#555" transform="translate(-465 119.035)" filter="url(#a)"/></svg> \ No newline at end of file
diff --git a/images/audio-volume-high.svg b/images/audio-volume-high.svg
index 4799c83..4eb32fd 100644
--- a/images/audio-volume-high.svg
+++ b/images/audio-volume-high.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M8 1L3.955 5.043H.954v6h3.09L8 14.999V1zm2 0v1.5c2.32.74 4 2.93 4 5.5s-1.68 4.76-4 5.5V15c3.15-.78 5.5-3.6 5.5-7S13.15 1.78 10 1zm0 4v6a3.42 3.42 0 0 0 1.79-3A3.4 3.4 0 0 0 10 5z" fill="#4d4d4d"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M8 1L3.955 5.043H0.954v6h3.09L8 14.999V1zm2 0v1.5c2.32 0.74 4 2.93 4 5.5s-1.68 4.76-4 5.5V15c3.15-0.78 5.5-3.6 5.5-7S13.15 1.78 10 1zm0 4v6a3.42 3.42 0 0 0 1.79-3A3.4 3.4 0 0 0 10 5z" fill="#4d4d4d"/></svg> \ No newline at end of file
diff --git a/images/audio-volume-low.svg b/images/audio-volume-low.svg
index e24ea40..ec1f44d 100644
--- a/images/audio-volume-low.svg
+++ b/images/audio-volume-low.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#4d4d4d"><path d="M8 1L4.09 4.998H1v6h3.088L8 15V1z"/><path d="M10 1v1.5c2.32.74 4 2.93 4 5.5s-1.68 4.76-4 5.5V15c3.15-.78 5.5-3.6 5.5-7S13.15 1.78 10 1z" opacity=".35"/><path d="M11.79 8A3.4 3.4 0 0 0 10 5v6a3.42 3.42 0 0 0 1.79-3z" opacity=".35"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#4d4d4d"><path d="M8 1L4.09 4.998H1v6h3.088L8 15V1z"/><path d="M10 1v1.5c2.32 0.74 4 2.93 4 5.5s-1.68 4.76-4 5.5V15c3.15-0.78 5.5-3.6 5.5-7S13.15 1.78 10 1z" opacity="0.35"/><path d="M11.79 8A3.4 3.4 0 0 0 10 5v6a3.42 3.42 0 0 0 1.79-3z" opacity="0.35"/></g></svg> \ No newline at end of file
diff --git a/images/audio-volume-medium.svg b/images/audio-volume-medium.svg
index 126763f..03eed1f 100644
--- a/images/audio-volume-medium.svg
+++ b/images/audio-volume-medium.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#4d4d4d"><path d="M8 1L4.09 4.998H1v6h3.088L8 15V1zm2 4v6c1.06-.58 1.79-1.7 1.79-3S11.07 5.58 10 5z"/><path d="M10 1v1.5c2.32.74 4 2.93 4 5.5s-1.68 4.76-4 5.5V15c3.15-.78 5.5-3.6 5.5-7S13.15 1.78 10 1z" opacity=".35"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#4d4d4d"><path d="M8 1L4.09 4.998H1v6h3.088L8 15V1zm2 4v6c1.06-0.58 1.79-1.7 1.79-3S11.07 5.58 10 5z"/><path d="M10 1v1.5c2.32 0.74 4 2.93 4 5.5s-1.68 4.76-4 5.5V15c3.15-0.78 5.5-3.6 5.5-7S13.15 1.78 10 1z" opacity="0.35"/></g></svg> \ No newline at end of file
diff --git a/images/audio-volume-muted.svg b/images/audio-volume-muted.svg
index 09224d9..ac33bdf 100644
--- a/images/audio-volume-muted.svg
+++ b/images/audio-volume-muted.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#4d4d4d"><path d="M8 1L4.09 4.998H1v6h3.088L8 15V1zM10 1v1.5c2.32.74 4 2.93 4 5.5s-1.68 4.76-4 5.5V15c3.15-.78 5.5-3.6 5.5-7S13.15 1.78 10 1z" opacity=".35"/><path d="M11.79 8A3.4 3.4 0 0 0 10 5v6a3.42 3.42 0 0 0 1.79-3z" opacity=".35"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#4d4d4d"><path d="M8 1L4.09 4.998H1v6h3.088L8 15V1zM10 1v1.5c2.32 0.74 4 2.93 4 5.5s-1.68 4.76-4 5.5V15c3.15-0.78 5.5-3.6 5.5-7S13.15 1.78 10 1z" opacity="0.35"/><path d="M11.79 8A3.4 3.4 0 0 0 10 5v6a3.42 3.42 0 0 0 1.79-3z" opacity="0.35"/></g></svg> \ No newline at end of file
diff --git a/images/audio-x-generic.svg b/images/audio-x-generic.svg
index 4661eed..c85e674 100644
--- a/images/audio-x-generic.svg
+++ b/images/audio-x-generic.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M15 1L5 2v8.95A1.953 3.071 73.862 0 0 4 11a1.953 3.071 73.862 0 0-3 2.5A1.953 3.071 73.862 0 0 4 15a1.953 3.071 73.862 0 0 3-2.5V5.8l6-.6v4.75a1.953 3.071 73.862 0 0-1 .05 1.953 3.071 73.862 0 0-3 2.5 1.953 3.071 73.862 0 0 3 1.5 1.953 3.071 73.862 0 0 3-2.5V1z" fill="#555"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M15 1L5 2v8.95A1.953 3.071 73.862 0 0 4 11a1.953 3.071 73.862 0 0-3 2.5A1.953 3.071 73.862 0 0 4 15a1.953 3.071 73.862 0 0 3-2.5V5.8l6-0.6v4.75a1.953 3.071 73.862 0 0-1 0.05 1.953 3.071 73.862 0 0-3 2.5 1.953 3.071 73.862 0 0 3 1.5 1.953 3.071 73.862 0 0 3-2.5V1z" fill="#555"/></svg> \ No newline at end of file
diff --git a/images/dialog-question.svg b/images/dialog-question.svg
index db8c479..749ef63 100644
--- a/images/dialog-question.svg
+++ b/images/dialog-question.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;block-progression:tb;isolation:auto;mix-blend-mode:normal" d="M7.984 0a1 1 0 0 0-.691.293l-7 7a1 1 0 0 0 0 1.414l7 7a1 1 0 0 0 1.414 0l7-7a1 1 0 0 0 0-1.414l-7-7A1 1 0 0 0 7.984 0zM8 4a2 2 0 1 1 0 4v1H7V7h1a1 1 0 1 0-1-1H6a2 2 0 0 1 2-2zm-.5 5.75a.75.75 0 1 1 0 1.5.75.75 0 0 1 0-1.5z" color="#000" font-weight="400" font-family="sans-serif" white-space="normal" overflow="visible" fill="#4d4d4d" fill-rule="evenodd" enable-background="accumulate"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;block-progression:tb;isolation:auto;mix-blend-mode:normal" d="M7.984 0a1 1 0 0 0-0.691 0.293l-7 7a1 1 0 0 0 0 1.414l7 7a1 1 0 0 0 1.414 0l7-7a1 1 0 0 0 0-1.414l-7-7A1 1 0 0 0 7.984 0zM8 4a2 2 0 1 1 0 4v1H7V7h1a1 1 0 1 0-1-1H6a2 2 0 0 1 2-2zm-0.5 5.75a0.75 0.75 0 1 1 0 1.5 0.75 0.75 0 0 1 0-1.5z" color="#000" font-weight="400" font-family="sans-serif" white-space="normal" overflow="visible" fill="#4d4d4d" fill-rule="evenodd" enable-background="accumulate"/></svg> \ No newline at end of file
diff --git a/images/dialog-warning.svg b/images/dialog-warning.svg
index 04bf09f..ba1bb83 100644
--- a/images/dialog-warning.svg
+++ b/images/dialog-warning.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16.002" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;block-progression:tb;isolation:auto;mix-blend-mode:normal" d="M7.956.667a1 1 0 0 0-.824.504l-7 12.338a1 1 0 0 0 .87 1.494h14a1 1 0 0 0 .868-1.494l-7-12.338a1 1 0 0 0-.914-.504zm-.955 3.336h2v6h-2v-6zm0 7h2v2h-2v-2z" class="warning" color="#000" font-weight="400" font-family="sans-serif" white-space="normal" overflow="visible" fill="#ff9800" fill-rule="evenodd" enable-background="accumulate"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16.002" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;block-progression:tb;isolation:auto;mix-blend-mode:normal" d="M7.956 0.667a1 1 0 0 0-0.824 0.504l-7 12.338a1 1 0 0 0 0.87 1.494h14a1 1 0 0 0 0.868-1.494l-7-12.338a1 1 0 0 0-0.914-0.504zm-0.955 3.336h2v6h-2v-6zm0 7h2v2h-2v-2z" class="warning" color="#000" font-weight="400" font-family="sans-serif" white-space="normal" overflow="visible" fill="#ff9800" fill-rule="evenodd" enable-background="accumulate"/></svg> \ No newline at end of file
diff --git a/images/document-new.svg b/images/document-new.svg
index 7e89a4a..d9d9fbc 100644
--- a/images/document-new.svg
+++ b/images/document-new.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16.003" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M2.844 1.003c-.282.047-.844.25-.844 1v13c0 1 1 1 1 1h10c1 0 1-1 1-1 .019-.046.005-7.453 0-10l-4-4H3s-.063-.015-.156 0zm4.156 5h2v2h2v2H9v2H7v-2H5v-2h2v-2z" fill="#555" enable-background="new"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16.003" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M2.844 1.003c-0.282 0.047-0.844 0.25-0.844 1v13c0 1 1 1 1 1h10c1 0 1-1 1-1 0.019-0.046 0.005-7.453 0-10l-4-4H3s-0.063-0.015-0.156 0zm4.156 5h2v2h2v2H9v2H7v-2H5v-2h2v-2z" fill="#555" enable-background="new"/></svg> \ No newline at end of file
diff --git a/images/document-open-recent.svg b/images/document-open-recent.svg
index cf53e98..a2fcb23 100644
--- a/images/document-open-recent.svg
+++ b/images/document-open-recent.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#4d4d4d"><path d="M8 1.003a7 7 0 0 0-7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0-7-7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5z"/><path style="marker:none" d="M10.406 5.187a.504.504 0 0 0-.25.157L8 7.5 6.344 5.844c-.157-.257-.568-.307-.782-.094-.213.213-.163.624.094.781l2 2a.519.519 0 0 0 .688 0l2.5-2.5c.293-.298-.025-.91-.438-.843z" color="#bebebe" overflow="visible" enable-background="accumulate"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#4d4d4d"><path d="M8 1.003a7 7 0 0 0-7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0-7-7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5z"/><path style="marker:none" d="M10.406 5.187a0.504 0.504 0 0 0-0.25 0.157L8 7.5 6.344 5.844c-0.157-0.257-0.568-0.307-0.782-0.094-0.213 0.213-0.163 0.624 0.094 0.781l2 2a0.519 0.519 0 0 0 0.688 0l2.5-2.5c0.293-0.298-0.025-0.91-0.438-0.843z" color="#bebebe" overflow="visible" enable-background="accumulate"/></g></svg> \ No newline at end of file
diff --git a/images/document-open.svg b/images/document-open.svg
index b0ac18d..bbc81b5 100644
--- a/images/document-open.svg
+++ b/images/document-open.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#555"><path d="M8 .723l4.332 6.307H9.991L10 13H6.002l-.009-5.97H3.618zM.995 14.031V16H15l-.005-1.969z"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#555"><path d="M8 0.723l4.332 6.307H9.991L10 13H6.002l-0.009-5.97H3.618zM0.995 14.031V16H15l-0.005-1.969z"/></g></svg> \ No newline at end of file
diff --git a/images/document-save.svg b/images/document-save.svg
index 72e1af9..5f5ce5d 100644
--- a/images/document-save.svg
+++ b/images/document-save.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#555"><path d="M7.988 13.325L3.656 7.02h2.341v-6l4 .03v5.97h2.373zM.995 14.031V16H15l-.005-1.969z"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#555"><path d="M7.988 13.325L3.656 7.02h2.341v-6l4 0.03v5.97h2.373zM0.995 14.031V16H15l-0.005-1.969z"/></g></svg> \ No newline at end of file
diff --git a/images/edit-clear.svg b/images/edit-clear.svg
index ff3b91e..f582873 100644
--- a/images/edit-clear.svg
+++ b/images/edit-clear.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M5 2.003l-5 6 5 6h11v-12zm2 3h1c.277 0 .526.113.707.293L10 6.59l1.293-1.293c.18-.18.43-.293.707-.293h1v1a.996.996 0 0 1-.293.707l-1.293 1.293 1.293 1.293c.18.181.293.43.293.707v1h-1a.996.996 0 0 1-.707-.293L10 9.417 8.707 10.71a.996.996 0 0 1-.707.293H7v-1c0-.277.112-.526.293-.707l1.293-1.293L7.293 6.71A.996.996 0 0 1 7 6.003z" fill="#555"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M5 2.003l-5 6 5 6h11v-12zm2 3h1c0.277 0 0.526 0.113 0.707 0.293L10 6.59l1.293-1.293c0.18-0.18 0.43-0.293 0.707-0.293h1v1a0.996 0.996 0 0 1-0.293 0.707l-1.293 1.293 1.293 1.293c0.18 0.181 0.293 0.43 0.293 0.707v1h-1a0.996 0.996 0 0 1-0.707-0.293L10 9.417 8.707 10.71a0.996 0.996 0 0 1-0.707 0.293H7v-1c0-0.277 0.112-0.526 0.293-0.707l1.293-1.293L7.293 6.71A0.996 0.996 0 0 1 7 6.003z" fill="#555"/></svg> \ No newline at end of file
diff --git a/images/edit-cut.svg b/images/edit-cut.svg
index 063876d..33ab7c2 100644
--- a/images/edit-cut.svg
+++ b/images/edit-cut.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M4.5 2.007a2.5 2.5 0 0 0 0 5c.446 0 .856-.14 1.218-.344l1.97 1.844-1.97 1.843a2.473 2.473 0 0 0-1.218-.343 2.5 2.5 0 1 0 2.5 2.5c0-.23-.036-.446-.094-.657L9.03 9.788l4.469 4.219H15v-1L6.906 5.163A2.46 2.46 0 0 0 7 4.507a2.5 2.5 0 0 0-2.5-2.5zm0 1.5a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm9-.5L9.562 6.725l1.313 1.282 4.125-4v-1zm-9 8.5a1 1 0 1 1 0 2 1 1 0 0 1 0-2z" fill="#555"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M4.5 2.007a2.5 2.5 0 0 0 0 5c0.446 0 0.856-0.14 1.218-0.344l1.97 1.844-1.97 1.843a2.473 2.473 0 0 0-1.218-0.343 2.5 2.5 0 1 0 2.5 2.5c0-0.23-0.036-0.446-0.094-0.657L9.03 9.788l4.469 4.219H15v-1L6.906 5.163A2.46 2.46 0 0 0 7 4.507a2.5 2.5 0 0 0-2.5-2.5zm0 1.5a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm9-0.5L9.562 6.725l1.313 1.282 4.125-4v-1zm-9 8.5a1 1 0 1 1 0 2 1 1 0 0 1 0-2z" fill="#555"/></svg> \ No newline at end of file
diff --git a/images/edit-delete.svg b/images/edit-delete.svg
index 586437e..4535069 100644
--- a/images/edit-delete.svg
+++ b/images/edit-delete.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g color="#000" font-weight="400" font-family="Sans" fill="#555"><path style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;block-progression:tb;marker:none" d="M2 4.996v9c0 .524.476 1 1 1h9c.523 0 1-.476 1-1v-9zM1 2.996v1l13-.003v-.997c0-1-1-1.003-1-1.003h-3s0-1-1-1H6c-1 0-1 1-1 1H2s-1 .003-1 1.003z" overflow="visible" enable-background="accumulate"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g color="#000" font-weight="400" font-family="Sans" fill="#555"><path style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;block-progression:tb;marker:none" d="M2 4.996v9c0 0.524 0.476 1 1 1h9c0.523 0 1-0.476 1-1v-9zM1 2.996v1l13-0.003v-0.997c0-1-1-1.003-1-1.003h-3s0-1-1-1H6c-1 0-1 1-1 1H2s-1 0.003-1 1.003z" overflow="visible" enable-background="accumulate"/></g></svg> \ No newline at end of file
diff --git a/images/edit-find.svg b/images/edit-find.svg
index 5e964c0..02a68a2 100644
--- a/images/edit-find.svg
+++ b/images/edit-find.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;block-progression:tb;marker:none" d="M6.49.997c3.028 0 5.53 2.475 5.53 5.5 0 1.15-.389 2.208-1 3.094L14.83 13.4l-1.406 1.437-3.809-3.809a5.513 5.513 0 0 1-3.125.97c-3.029 0-5.5-2.475-5.5-5.5 0-3.026 2.471-5.5 5.5-5.5zm0 2a3.483 3.483 0 0 0-3.5 3.5c0 1.945 1.552 3.5 3.5 3.5 1.947 0 3.5-1.555 3.5-3.5s-1.553-3.5-3.5-3.5z" color="#000" font-weight="400" font-family="Sans" overflow="visible" fill="#555" enable-background="new"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;block-progression:tb;marker:none" d="M6.49 0.997c3.028 0 5.53 2.475 5.53 5.5 0 1.15-0.389 2.208-1 3.094L14.83 13.4l-1.406 1.437-3.809-3.809a5.513 5.513 0 0 1-3.125 0.97c-3.029 0-5.5-2.475-5.5-5.5 0-3.026 2.471-5.5 5.5-5.5zm0 2a3.483 3.483 0 0 0-3.5 3.5c0 1.945 1.552 3.5 3.5 3.5 1.947 0 3.5-1.555 3.5-3.5s-1.553-3.5-3.5-3.5z" color="#000" font-weight="400" font-family="Sans" overflow="visible" fill="#555" enable-background="new"/></svg> \ No newline at end of file
diff --git a/images/edit-paste.svg b/images/edit-paste.svg
index 5637bcc..5857a74 100644
--- a/images/edit-paste.svg
+++ b/images/edit-paste.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="marker:none" d="M8 .003a2 2 0 0 0-2 2H3c-1 0-1 1-1 1v11c0 1 1 1 1 1h10s1 0 1-1v-11c0-1-1-1-1-1h-3c0-.138-.005-.276-.031-.406A2.008 2.008 0 0 0 7.999.003zm0 1c.414 0 .754.266.906.625A.94.94 0 0 1 9 2.003a1 1 0 1 1-1-1zm-4 3h1v1h6v-1h1v9H4v-9z" color="#000" fill="#555" overflow="visible" enable-background="accumulate"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="marker:none" d="M8 0.003a2 2 0 0 0-2 2H3c-1 0-1 1-1 1v11c0 1 1 1 1 1h10s1 0 1-1v-11c0-1-1-1-1-1h-3c0-0.138-0.005-0.276-0.031-0.406A2.008 2.008 0 0 0 7.999 0.003zm0 1c0.414 0 0.754 0.266 0.906 0.625A0.94 0.94 0 0 1 9 2.003a1 1 0 1 1-1-1zm-4 3h1v1h6v-1h1v9H4v-9z" color="#000" fill="#555" overflow="visible" enable-background="accumulate"/></svg> \ No newline at end of file
diff --git a/images/face-smile.svg b/images/face-smile.svg
index bef6576..e49c792 100644
--- a/images/face-smile.svg
+++ b/images/face-smile.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="marker:none" d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zM5 5.002a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm6 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zM5.174 9.83A4 4 0 0 0 8 11.003a4 4 0 0 0 2.826-1.173l.707.707A4.999 4.999 0 0 1 8 12.003a4.999 4.999 0 0 1-3.533-1.466l.707-.707z" color="#bebebe" overflow="visible" fill="#555" enable-background="accumulate"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="marker:none" d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zM5 5.002a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm6 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zM5.174 9.83A4 4 0 0 0 8 11.003a4 4 0 0 0 2.826-1.173l0.707 0.707A4.999 4.999 0 0 1 8 12.003a4.999 4.999 0 0 1-3.533-1.466l0.707-0.707z" color="#bebebe" overflow="visible" fill="#555" enable-background="accumulate"/></svg> \ No newline at end of file
diff --git a/images/folder-remote.svg b/images/folder-remote.svg
index dcf6794..ff3dccf 100644
--- a/images/folder-remote.svg
+++ b/images/folder-remote.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="text-indent:0;text-align:start;line-height:normal;text-transform:none;block-progression:tb;marker:none;-inkscape-font-specification:Sans" d="M1.844 1C1.562 1.047 1 1.25 1 2v11s0 1 1 1h12s1 0 1-1V4c0-1-1-1-1-1H9L7 1H2s-.063-.016-.156 0zm7.75 6c1.309 0 2.487.469 3.468 1.188L9.594 12l-3.47-3.781C7.11 7.492 8.275 7 9.595 7z" font-weight="400" color="#000" fill="#555" overflow="visible" enable-background="accumulate" font-family="Sans"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="text-indent:0;text-align:start;line-height:normal;text-transform:none;block-progression:tb;marker:none;-inkscape-font-specification:Sans" d="M1.844 1C1.562 1.047 1 1.25 1 2v11s0 1 1 1h12s1 0 1-1V4c0-1-1-1-1-1H9L7 1H2s-0.063-0.016-0.156 0zm7.75 6c1.309 0 2.487 0.469 3.468 1.188L9.594 12l-3.47-3.781C7.11 7.492 8.275 7 9.595 7z" font-weight="400" color="#000" fill="#555" overflow="visible" enable-background="accumulate" font-family="Sans"/></svg> \ No newline at end of file
diff --git a/images/go-down.svg b/images/go-down.svg
index 7a1cabc..9eb6700 100644
--- a/images/go-down.svg
+++ b/images/go-down.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#555" d="M2 8.212l1.386-1.386 3.635 3.635L7 2h2l.021 8.461 3.634-3.635 1.386 1.386-6.041 6z"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#555" d="M2 8.212l1.386-1.386 3.635 3.635L7 2h2l0.021 8.461 3.634-3.635 1.386 1.386-6.041 6z"/></svg> \ No newline at end of file
diff --git a/images/go-next.svg b/images/go-next.svg
index ac1e41b..dbf6a2c 100644
--- a/images/go-next.svg
+++ b/images/go-next.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#555" d="M8.212 2L6.826 3.386l3.635 3.635L2 7v2l8.461.021-3.635 3.634 1.385 1.386L14.212 8z"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#555" d="M8.212 2L6.826 3.386l3.635 3.635L2 7v2l8.461 0.021-3.635 3.634 1.385 1.386L14.212 8z"/></svg> \ No newline at end of file
diff --git a/images/go-previous.svg b/images/go-previous.svg
index a9f46b1..b027aec 100644
--- a/images/go-previous.svg
+++ b/images/go-previous.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#555" d="M7.788 2l1.386 1.386-3.635 3.635L14 7v2l-8.461.021 3.635 3.634-1.386 1.386-6-6.041z"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#555" d="M7.788 2l1.386 1.386-3.635 3.635L14 7v2l-8.461 0.021 3.635 3.634-1.386 1.386-6-6.041z"/></svg> \ No newline at end of file
diff --git a/images/go-up.svg b/images/go-up.svg
index fbb8780..b36eef2 100644
--- a/images/go-up.svg
+++ b/images/go-up.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#555" d="M2 7.788l1.386 1.386 3.635-3.635L7 14h2l.021-8.461 3.634 3.635 1.386-1.386-6.041-6z"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#555" d="M2 7.788l1.386 1.386 3.635-3.635L7 14h2l0.021-8.461 3.634 3.635 1.386-1.386-6.041-6z"/></svg> \ No newline at end of file
diff --git a/images/help-about.svg b/images/help-about.svg
index afcfcb4..91c078a 100644
--- a/images/help-about.svg
+++ b/images/help-about.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M9 15.003H7v-2h2zm2.07-7.75l-.9.92c-.72.73-1.17 1.33-1.17 2.83H7v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H4c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z" fill="#555" enable-background="new"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M9 15.003H7v-2h2zm2.07-7.75l-0.9 0.92c-0.72 0.73-1.17 1.33-1.17 2.83H7v-0.5c0-1.1 0.45-2.1 1.17-2.83l1.24-1.26c0.37-0.36 0.59-0.86 0.59-1.41 0-1.1-0.9-2-2-2s-2 0.9-2 2H4c0-2.21 1.79-4 4-4s4 1.79 4 4c0 0.88-0.36 1.68-0.93 2.25z" fill="#555" enable-background="new"/></svg> \ No newline at end of file
diff --git a/images/insert-text.svg b/images/insert-text.svg
index a4d48b1..37a1852 100644
--- a/images/insert-text.svg
+++ b/images/insert-text.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#555"><path d="M4.3 2l-2.858 8H2.87l.607-1.714h2.785L6.871 10H8.46L5.442 2zm.57 2.286l1 2.857h-2z"/><path style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;block-progression:tb;marker:none" d="M10 5v1h2.5c.214 0 .5.307.5.5V7h-2.5c-.46 0-.868.192-1.125.484A1.509 1.509 0 0 0 9 8.5c.003.36.134.726.39 1.016.257.289.656.484 1.11.484H14v-.422c.008-.047 0-.078 0-.078v-3A1.5 1.5 0 0 0 12.5 5H10zm.5 3H13v1h-2.5c-.199 0-.283-.055-.36-.14A.572.572 0 0 1 10 8.5a.56.56 0 0 1 .125-.36c.073-.082.164-.14.375-.14z" color="#000" font-weight="400" font-family="Sans" overflow="visible" enable-background="accumulate"/><path d="M5 11.997l3 4 3-4z"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#555"><path d="M4.3 2l-2.858 8H2.87l0.607-1.714h2.785L6.871 10H8.46L5.442 2zm0.57 2.286l1 2.857h-2z"/><path style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;block-progression:tb;marker:none" d="M10 5v1h2.5c0.214 0 0.5 0.307 0.5 0.5V7h-2.5c-0.46 0-0.868 0.192-1.125 0.484A1.509 1.509 0 0 0 9 8.5c0.003 0.36 0.134 0.726 0.39 1.016 0.257 0.289 0.656 0.484 1.11 0.484H14v-0.422c0.008-0.047 0-0.078 0-0.078v-3A1.5 1.5 0 0 0 12.5 5H10zm0.5 3H13v1h-2.5c-0.199 0-0.283-0.055-0.36-0.14A0.572 0.572 0 0 1 10 8.5a0.56 0.56 0 0 1 0.125-0.36c0.073-0.082 0.164-0.14 0.375-0.14z" color="#000" font-weight="400" font-family="Sans" overflow="visible" enable-background="accumulate"/><path d="M5 11.997l3 4 3-4z"/></g></svg> \ No newline at end of file
diff --git a/images/media-optical.svg b/images/media-optical.svg
index bb93d2f..4e6505e 100644
--- a/images/media-optical.svg
+++ b/images/media-optical.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;block-progression:tb;marker:none" d="M353-118c-3.842 0-7 3.158-7 7s3.158 7 7 7c3.843 0 7-3.158 7-7s-3.157-7-7-7zm0 5c1.099 0 2 .901 2 2s-.901 2-2 2c-1.098 0-2-.901-2-2s.902-2 2-2z" color="#bebebe" font-weight="400" font-family="Sans" overflow="visible" fill="#555" enable-background="accumulate" transform="translate(-345 119.003)" filter="url(#a)"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;block-progression:tb;marker:none" d="M353-118c-3.842 0-7 3.158-7 7s3.158 7 7 7c3.843 0 7-3.158 7-7s-3.157-7-7-7zm0 5c1.099 0 2 0.901 2 2s-0.901 2-2 2c-1.098 0-2-0.901-2-2s0.902-2 2-2z" color="#bebebe" font-weight="400" font-family="Sans" overflow="visible" fill="#555" enable-background="accumulate" transform="translate(-345 119.003)" filter="url(#a)"/></svg> \ No newline at end of file
diff --git a/images/media-playlist-repeat.svg b/images/media-playlist-repeat.svg
index d98c082..f0d3992 100644
--- a/images/media-playlist-repeat.svg
+++ b/images/media-playlist-repeat.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#555"><path color="#000" d="M4 3C2.355 3 1 4.355 1 6v4c0 1.645 1.355 3 3 3h8c1.645 0 3-1.355 3-3V6c0-1.645-1.355-3-3-3h-1v2h1c.571 0 1 .429 1 1v4c0 .571-.429 1-1 1H4c-.571 0-1-.429-1-1V6c0-.571.429-1 1-1h3V3H4z"/><path d="M10 4L6 1v6z"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#555"><path color="#000" d="M4 3C2.355 3 1 4.355 1 6v4c0 1.645 1.355 3 3 3h8c1.645 0 3-1.355 3-3V6c0-1.645-1.355-3-3-3h-1v2h1c0.571 0 1 0.429 1 1v4c0 0.571-0.429 1-1 1H4c-0.571 0-1-0.429-1-1V6c0-0.571 0.429-1 1-1h3V3H4z"/><path d="M10 4L6 1v6z"/></g></svg> \ No newline at end of file
diff --git a/images/media-playlist-shuffle.svg b/images/media-playlist-shuffle.svg
index a4fb9ad..31e0100 100644
--- a/images/media-playlist-shuffle.svg
+++ b/images/media-playlist-shuffle.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#555"><path color="#555" d="M1 3v2h4c.572 0 1 .429 1 1v4c0 1.645 1.356 3 3 3h5v-2H9c-.571 0-1-.429-1-1V6c0-1.645-1.355-3-3-3zM9 3c-.23 0-.44.044-.656.094.481.55.861 1.177 1.031 1.906H14V3H9zM1 13h4c.23 0 .441-.044.656-.094-.48-.55-.86-1.177-1.03-1.906H1z"/><path d="M12 1v6l4-3zM12 9v6l4-3z"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#555"><path color="#555" d="M1 3v2h4c0.572 0 1 0.429 1 1v4c0 1.645 1.356 3 3 3h5v-2H9c-0.571 0-1-0.429-1-1V6c0-1.645-1.355-3-3-3zM9 3c-0.23 0-0.44 0.044-0.656 0.094 0.481 0.55 0.861 1.177 1.031 1.906H14V3H9zM1 13h4c0.23 0 0.441-0.044 0.656-0.094-0.48-0.55-0.86-1.177-1.03-1.906H1z"/><path d="M12 1v6l4-3zM12 9v6l4-3z"/></g></svg> \ No newline at end of file
diff --git a/images/meson.build b/images/meson.build
new file mode 100644
index 0000000..3076150
--- /dev/null
+++ b/images/meson.build
@@ -0,0 +1,2 @@
+install_data('audacious.png', install_dir: install_unscalable_iconpath)
+install_data('audacious.svg', install_dir: install_scalable_iconpath)
diff --git a/images/preferences-desktop-font.svg b/images/preferences-desktop-font.svg
new file mode 100644
index 0000000..7a92811
--- /dev/null
+++ b/images/preferences-desktop-font.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m 4,3 0,2 1,0 4,0 c 0.42816,0 1,0.61414 1,1 l 0,1 -3,0 -2,0 c -0.91927,0 -1.7356,0.38396 -2.25,0.96875 -0.5144,0.58479 -0.75639,1.31063 -0.75,2.03125 0.006,0.72062 0.26893,1.45271 0.78125,2.03125 0.51232,0.57854 1.31047,0.96875 2.21875,0.96875 l 7,0 1,0 0.15625,0 0.84375,0 0,-1 0,-1 0,-5 c 0,-1.63434 -1.3198,-3 -3,-3 l -2,0 -4,0 -1,0 z m 3,6 3,0 0,2 -3,0 c -0.39787,0 -0.56691,-0.10979 -0.71875,-0.28125 -0.15184,-0.17146 -0.27877,-0.43937 -0.28125,-0.71875 -0.002,-0.27938 0.10467,-0.55354 0.25,-0.71875 0.14533,-0.16521 0.32764,-0.28125 0.75,-0.28125 z" color="#000" fill="#555"/></svg> \ No newline at end of file
diff --git a/images/preferences-system.svg b/images/preferences-system.svg
index c18f12f..8965825 100644
--- a/images/preferences-system.svg
+++ b/images/preferences-system.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M6.25 1l-.154 1.844a5.5 5.5 0 0 0-1.608.93l-1.676-.79-1.75 3.032 1.522 1.056A5.5 5.5 0 0 0 2.5 8a5.5 5.5 0 0 0 .08.932L1.062 9.984l1.75 3.032 1.672-.787a5.5 5.5 0 0 0 1.612.923L6.25 15h3.5l.154-1.844a5.5 5.5 0 0 0 1.608-.93l1.675.79 1.75-3.032-1.521-1.056A5.5 5.5 0 0 0 13.5 8a5.5 5.5 0 0 0-.08-.932l1.517-1.052-1.75-3.032-1.671.787a5.5 5.5 0 0 0-1.612-.923L9.75 1h-3.5zM8 6a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2 2 2 0 0 1 2-2z" fill="#555" enable-background="new"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M6.25 1l-0.154 1.844a5.5 5.5 0 0 0-1.608 0.93l-1.676-0.79-1.75 3.032 1.522 1.056A5.5 5.5 0 0 0 2.5 8a5.5 5.5 0 0 0 0.08 0.932L1.062 9.984l1.75 3.032 1.672-0.787a5.5 5.5 0 0 0 1.612 0.923L6.25 15h3.5l0.154-1.844a5.5 5.5 0 0 0 1.608-0.93l1.675 0.79 1.75-3.032-1.521-1.056A5.5 5.5 0 0 0 13.5 8a5.5 5.5 0 0 0-0.08-0.932l1.517-1.052-1.75-3.032-1.671 0.787a5.5 5.5 0 0 0-1.612-0.923L9.75 1h-3.5zM8 6a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2 2 2 0 0 1 2-2z" fill="#555" enable-background="new"/></svg> \ No newline at end of file
diff --git a/images/process-stop.svg b/images/process-stop.svg
index ece8f92..e2415ed 100644
--- a/images/process-stop.svg
+++ b/images/process-stop.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;block-progression:tb;marker:none" d="M5.218 1l-.312.281L1.28 4.906 1 5.22V10.78l.28.313 3.626 3.625.312.281h5.563l.312-.281 3.625-3.625.282-.313V5.22l-.282-.313-3.625-3.625L10.781 1H5.218zm-.25 3.938h1c.276 0 .538.1.72.28l1.28 1.278L9.25 5.22c.18-.181.442-.281.718-.281h1v1c0 .276-.1.537-.28.718L9.405 7.934l1.281 1.285c.181.18.283.442.281.719v1h-1c-.276 0-.537-.1-.718-.282L7.968 9.371l-1.28 1.285a1.015 1.015 0 0 1-.72.282h-1v-1c0-.277.1-.538.282-.72l1.28-1.284-1.28-1.278a1.015 1.015 0 0 1-.282-.718v-1z" color="#000" font-weight="400" font-family="Sans" overflow="visible" fill="#555" enable-background="accumulate"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;block-progression:tb;marker:none" d="M5.218 1l-0.312 0.281L1.28 4.906 1 5.22V10.78l0.28 0.313 3.626 3.625 0.312 0.281h5.563l0.312-0.281 3.625-3.625 0.282-0.313V5.22l-0.282-0.313-3.625-3.625L10.781 1H5.218zm-0.25 3.938h1c0.276 0 0.538 0.1 0.72 0.28l1.28 1.278L9.25 5.22c0.18-0.181 0.442-0.281 0.718-0.281h1v1c0 0.276-0.1 0.537-0.28 0.718L9.405 7.934l1.281 1.285c0.181 0.18 0.283 0.442 0.281 0.719v1h-1c-0.276 0-0.537-0.1-0.718-0.282L7.968 9.371l-1.28 1.285a1.015 1.015 0 0 1-0.72 0.282h-1v-1c0-0.277 0.1-0.538 0.282-0.72l1.28-1.284-1.28-1.278a1.015 1.015 0 0 1-0.282-0.718v-1z" color="#000" font-weight="400" font-family="Sans" overflow="visible" fill="#555" enable-background="accumulate"/></svg> \ No newline at end of file
diff --git a/images/system-run.svg b/images/system-run.svg
index 677aad9..611169d 100644
--- a/images/system-run.svg
+++ b/images/system-run.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#555"><path d="M7.759 5.994l-.11 1.317a3.929 3.929 0 0 0-1.149.664L5.303 7.41l-1.25 2.165 1.087.755a3.929 3.929 0 0 0-.06.663 3.929 3.929 0 0 0 .057.665l-1.084.752 1.25 2.165 1.194-.562a3.929 3.929 0 0 0 1.151.66l.11 1.32h2.5l.11-1.317a3.929 3.929 0 0 0 1.149-.664l1.197.563 1.25-2.165-1.087-.755a3.929 3.929 0 0 0 .06-.662 3.929 3.929 0 0 0-.057-.666l1.084-.752-1.25-2.165-1.194.562a3.929 3.929 0 0 0-1.151-.66l-.11-1.32h-2.5zm1.25 3.571a1.429 1.429 0 0 1 1.428 1.429 1.429 1.429 0 0 1-1.428 1.428 1.429 1.429 0 0 1-1.429-1.428A1.429 1.429 0 0 1 9.01 9.565zM7.188 6.263l-.338-.717a2.357 2.357 0 0 0 .398-.69l.79-.066v-1.5l-.79-.066a2.357 2.357 0 0 0-.168-.363 2.357 2.357 0 0 0-.23-.328l.338-.716-1.299-.75-.452.65a2.357 2.357 0 0 0-.796.002l-.453-.653-1.299.75.338.718a2.357 2.357 0 0 0-.398.69l-.79.066v1.5l.79.066a2.357 2.357 0 0 0 .168.362 2.357 2.357 0 0 0 .23.329l-.338.716 1.299.75.452-.65a2.357 2.357 0 0 0 .796-.003l.453.653 1.299-.75zm-1.721-1.48a.857.857 0 0 1-1.17-.315.857.857 0 0 1 .313-1.17.857.857 0 0 1 1.17.313.857.857 0 0 1-.313 1.171z" enable-background="new"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#555"><path d="M7.759 5.994l-0.11 1.317a3.929 3.929 0 0 0-1.149 0.664L5.303 7.41l-1.25 2.165 1.087 0.755a3.929 3.929 0 0 0-0.06 0.663 3.929 3.929 0 0 0 0.057 0.665l-1.084 0.752 1.25 2.165 1.194-0.562a3.929 3.929 0 0 0 1.151 0.66l0.11 1.32h2.5l0.11-1.317a3.929 3.929 0 0 0 1.149-0.664l1.197 0.563 1.25-2.165-1.087-0.755a3.929 3.929 0 0 0 0.06-0.662 3.929 3.929 0 0 0-0.057-0.666l1.084-0.752-1.25-2.165-1.194 0.562a3.929 3.929 0 0 0-1.151-0.66l-0.11-1.32h-2.5zm1.25 3.571a1.429 1.429 0 0 1 1.428 1.429 1.429 1.429 0 0 1-1.428 1.428 1.429 1.429 0 0 1-1.429-1.428A1.429 1.429 0 0 1 9.01 9.565zM7.188 6.263l-0.338-0.717a2.357 2.357 0 0 0 0.398-0.69l0.79-0.066v-1.5l-0.79-0.066a2.357 2.357 0 0 0-0.168-0.363 2.357 2.357 0 0 0-0.23-0.328l0.338-0.716-1.299-0.75-0.452 0.65a2.357 2.357 0 0 0-0.796 0.002l-0.453-0.653-1.299 0.75 0.338 0.718a2.357 2.357 0 0 0-0.398 0.69l-0.79 0.066v1.5l0.79 0.066a2.357 2.357 0 0 0 0.168 0.362 2.357 2.357 0 0 0 0.23 0.329l-0.338 0.716 1.299 0.75 0.452-0.65a2.357 2.357 0 0 0 0.796-0.003l0.453 0.653 1.299-0.75zm-1.721-1.48a0.857 0.857 0 0 1-1.17-0.315 0.857 0.857 0 0 1 0.313-1.17 0.857 0.857 0 0 1 1.17 0.313 0.857 0.857 0 0 1-0.313 1.171z" enable-background="new"/></g></svg> \ No newline at end of file
diff --git a/images/text-x-generic.svg b/images/text-x-generic.svg
index 13c8af1..2459a41 100644
--- a/images/text-x-generic.svg
+++ b/images/text-x-generic.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="text-indent:0;text-align:start;line-height:normal;text-transform:none;block-progression:tb;marker:none;-inkscape-font-specification:Sans" d="M2.813 1A1 1 0 0 0 2 2v13a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V5.562a1 1 0 0 0-.281-.718L10.156 1.28A1 1 0 0 0 9.438 1H3a1 1 0 0 0-.094 0 1 1 0 0 0-.093 0zM4 3h5v3h3v8H4V3z" font-weight="400" color="#000" fill="#555" overflow="visible" enable-background="accumulate" font-family="Sans"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path style="text-indent:0;text-align:start;line-height:normal;text-transform:none;block-progression:tb;marker:none;-inkscape-font-specification:Sans" d="M2.813 1A1 1 0 0 0 2 2v13a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V5.562a1 1 0 0 0-0.281-0.718L10.156 1.28A1 1 0 0 0 9.438 1H3a1 1 0 0 0-0.094 0 1 1 0 0 0-0.093 0zM4 3h5v3h3v8H4V3z" font-weight="400" color="#000" fill="#555" overflow="visible" enable-background="accumulate" font-family="Sans"/></svg> \ No newline at end of file
diff --git a/images/user-desktop.svg b/images/user-desktop.svg
index c4905c5..898963a 100644
--- a/images/user-desktop.svg
+++ b/images/user-desktop.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M1 13.035c0 .554.446 1 1 1h12c.554 0 1-.446 1-1v-10c0-.554-.446-1-1-1H2c-.554 0-1 .446-1 1zm9-1v-4h1.5l1.5 1.5v2.5z" fill="#555"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M1 13.035c0 0.554 0.446 1 1 1h12c0.554 0 1-0.446 1-1v-10c0-0.554-0.446-1-1-1H2c-0.554 0-1 0.446-1 1zm9-1v-4h1.5l1.5 1.5v2.5z" fill="#555"/></svg> \ No newline at end of file
diff --git a/images/user-trash.svg b/images/user-trash.svg
index 9e262bb..7c3cf22 100644
--- a/images/user-trash.svg
+++ b/images/user-trash.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g font-weight="400" color="#000" fill="#555" font-family="Sans"><path style="text-indent:0;text-align:start;line-height:normal;text-transform:none;block-progression:tb;marker:none;-inkscape-font-specification:Sans" d="M2 4.996v9c0 .524.476 1 1 1h9c.523 0 1-.476 1-1v-9zM1 2.996v1l13-.003v-.997c0-1-1-1.003-1-1.003h-3s0-1-1-1H6c-1 0-1 1-1 1H2s-1 .003-1 1.003z" overflow="visible" enable-background="accumulate"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g font-weight="400" color="#000" fill="#555" font-family="Sans"><path style="text-indent:0;text-align:start;line-height:normal;text-transform:none;block-progression:tb;marker:none;-inkscape-font-specification:Sans" d="M2 4.996v9c0 0.524 0.476 1 1 1h9c0.523 0 1-0.476 1-1v-9zM1 2.996v1l13-0.003v-0.997c0-1-1-1.003-1-1.003h-3s0-1-1-1H6c-1 0-1 1-1 1H2s-1 0.003-1 1.003z" overflow="visible" enable-background="accumulate"/></g></svg> \ No newline at end of file
diff --git a/images/view-refresh.svg b/images/view-refresh.svg
index 9e06b76..65cdc39 100644
--- a/images/view-refresh.svg
+++ b/images/view-refresh.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#555"><path d="M7.998 1.016a7 7 0 0 0 0 14 7 7 0 0 0 6.718-5H12.56c-.774 1.76-2.517 3-4.562 3a5 5 0 0 1 0-10c2.045 0 3.788 1.24 4.562 3h2.156a7 7 0 0 0-6.718-5z"/><path d="M8.998 7.016l6-6v6z"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g fill="#555"><path d="M7.998 1.016a7 7 0 0 0 0 14 7 7 0 0 0 6.718-5H12.56c-0.774 1.76-2.517 3-4.562 3a5 5 0 0 1 0-10c2.045 0 3.788 1.24 4.562 3h2.156a7 7 0 0 0-6.718-5z"/><path d="M8.998 7.016l6-6v6z"/></g></svg> \ No newline at end of file
diff --git a/images/view-sort-ascending.svg b/images/view-sort-ascending.svg
index 10fc675..f041e7d 100644
--- a/images/view-sort-ascending.svg
+++ b/images/view-sort-ascending.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g color="#000" fill="#555"><path style="marker:none" d="M2.5 13c-.822 0-1.5-.678-1.5-1.5S1.678 10 2.5 10s1.5.678 1.5 1.5S3.322 13 2.5 13zm0-4C1.678 9 1 8.322 1 7.5S1.678 6 2.5 6 4 6.678 4 7.5 3.322 9 2.5 9zm0-4C1.678 5 1 4.322 1 3.5S1.678 2 2.5 2 4 2.678 4 3.5 3.322 5 2.5 5zM8 3v4H4.937L10 14l5.188-7H12V3z" overflow="visible" enable-background="new"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g color="#000" fill="#555"><path style="marker:none" d="M2.5 13c-0.822 0-1.5-0.678-1.5-1.5S1.678 10 2.5 10s1.5 0.678 1.5 1.5S3.322 13 2.5 13zm0-4C1.678 9 1 8.322 1 7.5S1.678 6 2.5 6 4 6.678 4 7.5 3.322 9 2.5 9zm0-4C1.678 5 1 4.322 1 3.5S1.678 2 2.5 2 4 2.678 4 3.5 3.322 5 2.5 5zM8 3v4H4.937L10 14l5.188-7H12V3z" overflow="visible" enable-background="new"/></g></svg> \ No newline at end of file
diff --git a/images/view-sort-descending.svg b/images/view-sort-descending.svg
index 5a73a24..488c65e 100644
--- a/images/view-sort-descending.svg
+++ b/images/view-sort-descending.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g color="#000" fill="#555"><path style="marker:none" d="M2.5 2C1.678 2 1 2.678 1 3.5S1.678 5 2.5 5 4 4.322 4 3.5 3.322 2 2.5 2zm0 4C1.678 6 1 6.678 1 7.5S1.678 9 2.5 9 4 8.322 4 7.5 3.322 6 2.5 6zm0 4c-.822 0-1.5.678-1.5 1.5S1.678 13 2.5 13 4 12.322 4 11.5 3.322 10 2.5 10zM8 13V9H4.937L10 2l5.188 7H12v4z" overflow="visible" enable-background="new"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g color="#000" fill="#555"><path style="marker:none" d="M2.5 2C1.678 2 1 2.678 1 3.5S1.678 5 2.5 5 4 4.322 4 3.5 3.322 2 2.5 2zm0 4C1.678 6 1 6.678 1 7.5S1.678 9 2.5 9 4 8.322 4 7.5 3.322 6 2.5 6zm0 4c-0.822 0-1.5 0.678-1.5 1.5S1.678 13 2.5 13 4 12.322 4 11.5 3.322 10 2.5 10zM8 13V9H4.937L10 2l5.188 7H12v4z" overflow="visible" enable-background="new"/></g></svg> \ No newline at end of file
diff --git a/images/window-close.svg b/images/window-close.svg
index 03b1b9d..5a6f04e 100644
--- a/images/window-close.svg
+++ b/images/window-close.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M5 4.003a1 1 0 0 0-1 1 1 1 0 0 0 .293.707l2.293 2.293-2.293 2.293a1 1 0 0 0-.293.707 1 1 0 0 0 1 1 1 1 0 0 0 .707-.293L8 9.417l2.283 2.284a1 1 0 0 0 .717.302 1 1 0 0 0 1-1 1 1 0 0 0-.293-.707L9.414 8.003l2.283-2.283A1 1 0 0 0 12 5.003a1 1 0 0 0-1-1 1 1 0 0 0-.707.293L8 6.59 5.717 4.306a1 1 0 0 0-.01-.01A1 1 0 0 0 5 4.003z" fill="#444" enable-background="new"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><path d="M5 4.003a1 1 0 0 0-1 1 1 1 0 0 0 0.293 0.707l2.293 2.293-2.293 2.293a1 1 0 0 0-0.293 0.707 1 1 0 0 0 1 1 1 1 0 0 0 0.707-0.293L8 9.417l2.283 2.284a1 1 0 0 0 0.717 0.302 1 1 0 0 0 1-1 1 1 0 0 0-0.293-0.707L9.414 8.003l2.283-2.283A1 1 0 0 0 12 5.003a1 1 0 0 0-1-1 1 1 0 0 0-0.707 0.293L8 6.59 5.717 4.306a1 1 0 0 0-0.01-0.01A1 1 0 0 0 5 4.003z" fill="#444" enable-background="new"/></svg> \ No newline at end of file
diff --git a/man/audtool.1.in b/man/audtool.1.in
index 048a22b..a1ca8b6 100644
--- a/man/audtool.1.in
+++ b/man/audtool.1.in
@@ -370,13 +370,14 @@ them at \fIhttps://redmine.audacious-media-player.org/projects/audacious\fR.
.SH AUTHORS
.B audtool
-was written by George Averill <nhjm@nhjm.net> and William
-Pitcock <nenolod@atheme.org>.
+was written by George Averill <nhjm@nhjm.net> and Ariadne
+Conill <ariadne@dereferenced.org>.
.PP
This manual page was written by Adam Cecile <gandalf@le-vert.net> and Kiyoshi
-Aman <kiyoshi@atheme.org>. Some additional tweaks were done by William Pitcock
-<nenolod@atheme.org> and Tony Vroon <chainsaw@gentoo.org>. The manual page was
-updated for Audacious 3.7 and later by John Lindgren <john@jlindgren.net>.
+Aman <kiyoshi@atheme.org>. Some additional tweaks were done by Ariadne Conill
+<ariadne@dereferenced.org> and Tony Vroon <chainsaw@gentoo.org>. The manual
+page was updated for Audacious 3.7 and later by John Lindgren
+<john@jlindgren.net>.
.PP
This work is licensed under a Creative Commons Attribution 3.0 Unported License
<https://creativecommons.org/licenses/by/3.0/>.
diff --git a/man/meson.build b/man/meson.build
new file mode 100644
index 0000000..d65eca2
--- /dev/null
+++ b/man/meson.build
@@ -0,0 +1,9 @@
+mans = ['audtool.1', 'audacious.1']
+
+foreach man : mans
+ configure_file(input: '@0@.in'.format(man),
+ output: man,
+ configuration: conf,
+ install: true,
+ install_dir: join_paths(get_option('mandir'), 'man1'))
+endforeach
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..450277d
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,154 @@
+project('audacious', 'c', 'cpp',
+ version: '4.0-devel',
+ meson_version: '>= 0.50')
+
+
+copyright = 'Copyright (C) 2001-2020 Audacious developers and others'
+
+
+qt5 = import('qt5')
+gnome = import('gnome')
+
+
+glib_req = '>= 2.32'
+glib_dep = dependency('glib-2.0', version: glib_req, required: true)
+gmodule_dep = dependency('gmodule-2.0', version: glib_req, required: true)
+
+
+if get_option('qt')
+ qt_req = '>= 5.2'
+ qt_dep = dependency('qt5', version: qt_req, required: true, modules: ['Core', 'Widgets', 'Gui'])
+endif
+
+
+cc = meson.get_compiler('c')
+cxx = meson.get_compiler('cpp')
+
+
+if cc.get_id() == 'gcc' or cc.get_id() == 'clang'
+ common_flags = [
+ '-pipe',
+ '-ffast-math',
+ '-Wall',
+ '-Wtype-limits',
+ '-Wno-stringop-truncation'
+ ]
+
+ cxx_flags = [
+ '-Wno-non-virtual-dtor',
+ '-Woverloaded-virtual'
+ ]
+
+ check_cflags = ['-std=gnu99'] + common_flags
+ check_cxxflags = ['-std=gnu++11'] + common_flags + cxx_flags
+
+ foreach arg : check_cflags
+ if cc.has_argument(arg)
+ add_project_arguments(arg, language: 'c')
+ endif
+ endforeach
+
+ foreach arg : check_cxxflags
+ if cxx.has_argument(arg)
+ add_project_arguments(arg, language: 'cpp')
+ endif
+ endforeach
+endif
+
+
+conf = configuration_data()
+conf.set_quoted('BUILDSTAMP', '???')
+conf.set_quoted('COPYRIGHT', copyright)
+conf.set_quoted('PACKAGE', meson.project_name())
+conf.set_quoted('VERSION', meson.project_version())
+conf.set('PACKAGE_VERSION', meson.project_version())
+if host_machine.endian() == 'big'
+ conf.set10('WORDS_BIGENDIAN', true)
+ conf.set10('BIGENDIAN', true)
+else
+ conf.set10('BIGENDIAN', false)
+endif
+
+
+# XXX - investigate to see if we can do better
+conf.set_quoted('PLUGIN_SUFFIX', '.so')
+if host_machine.system() == 'windows'
+ conf.set_quoted('PLUGIN_SUFFIX', '.dll')
+elif host_machine.system() == 'darwin'
+ conf.set_quoted('PLUGIN_SUFFIX', '.dylib')
+endif
+
+
+if host_machine.system() == 'windows'
+ conf.set('EXPORT', '__declspec(dllexport)')
+ conf.set_quoted('PLUGIN_SUFFIX', '.dll')
+elif cc.get_id() == 'gcc' or cc.get_id() == 'clang'
+ add_project_arguments('-fvisibility=hidden', language: 'c')
+ add_project_arguments('-fvisibility=hidden', language: 'cpp')
+ conf.set('EXPORT', '__attribute__((visibility("default")))')
+endif
+
+
+install_bindir = get_option('bindir')
+install_datadir = join_paths(get_option('datadir'), 'audacious')
+install_plugindir = join_paths(get_option('libdir'), 'audacious')
+install_localedir = get_option('localedir')
+install_desktoppath = join_paths(get_option('datadir'), 'applications')
+install_desktopfile = join_paths(install_desktoppath, 'audacious.desktop')
+install_iconpath = join_paths(get_option('datadir'), 'icons')
+install_unscalable_iconpath = join_paths(install_iconpath, 'hicolor', '48x48', 'apps')
+install_scalable_iconpath = join_paths(install_iconpath, 'hicolor', 'scalable', 'apps')
+install_iconfile = join_paths(install_unscalable_iconpath, 'audacious.png')
+
+
+conf.set_quoted('INSTALL_BINDIR', join_paths(get_option('prefix'), install_bindir))
+conf.set_quoted('INSTALL_DATADIR', join_paths(get_option('prefix'), install_datadir))
+conf.set_quoted('INSTALL_PLUGINDIR', join_paths(get_option('prefix'), install_plugindir))
+conf.set_quoted('INSTALL_LOCALEDIR', join_paths(get_option('prefix'), install_localedir))
+conf.set_quoted('INSTALL_DESKTOPFILE', join_paths(get_option('prefix'), install_desktopfile))
+conf.set_quoted('INSTALL_ICONFILE', join_paths(get_option('prefix'), install_iconfile))
+conf.set('plugindir', install_plugindir)
+conf.set('datarootdir', get_option('datadir'))
+
+
+if get_option('dbus')
+ conf.set10('USE_DBUS', true)
+endif
+
+
+if get_option('qt')
+ conf.set10('USE_QT', true)
+endif
+
+
+subdir('src')
+subdir('po')
+subdir('man')
+subdir('images')
+
+
+install_data('AUTHORS', 'COPYING')
+
+
+install_data('audacious.desktop', install_dir: install_desktoppath)
+
+
+pkg = import('pkgconfig')
+
+# When Meson fixes the utter disappointment that is
+# https://github.com/mesonbuild/meson/issues/5836,
+# use libaudcore_lib as base dependency here.
+pkg.generate(
+ libraries: ['-L${libdir} -laudcore'],
+ variables: [
+ 'plugin_dir=${libdir}/audacious',
+
+ # Appease broken third-party plugin build systems.
+ 'audacious_include_dir=${includedir}',
+ 'include_dir=${includedir}',
+ 'lib_dir=${libdir}'
+ ],
+ description: 'versatile and handy multi platform media player',
+ name: 'audacious',
+ url: 'https://audacious-media-player.org'
+)
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..6942ba6
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,4 @@
+option('dbus', type: 'boolean', value: true,
+ description: 'Whether DBus support is enabled')
+option('qt', type: 'boolean', value: true,
+ description: 'Whether Qt support is enabled')
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644
index 0000000..587c36f
--- /dev/null
+++ b/po/LINGUAS
@@ -0,0 +1,46 @@
+ar
+be
+bg
+ca
+cmn
+cs
+da
+de
+el
+en_GB
+es_AR
+es_MX
+es
+et
+eu
+fa_IR
+fi
+fr
+gl
+hu
+id_ID
+it
+ja
+ko
+ky
+lt
+lv
+ml_IN
+ms
+nl
+pl
+pt_BR
+pt_PT
+ro
+ru
+si
+sk
+sr
+sr_RS
+sv
+ta
+tr
+uk
+zh_CN
+zh_TW
+
diff --git a/po/bg.po b/po/bg.po
index f1feada..0e4c2c7 100644
--- a/po/bg.po
+++ b/po/bg.po
@@ -7,7 +7,7 @@
# Elusiv_man <breaker9loc@gmail.com>, 2014
# Ivailo Monev <xakepa10@gmail.com>, 2014
# Kiril Kirilov (Cybercop) <acybecop_montana@abv.bg>, 2012
-# Kiril Kirilov <cybercop_montana@abv.bg>, 2014-2015,2018
+# Kiril Kirilov <cybercop_montana@abv.bg>, 2014-2015
# Myselus, 2016-2017
# Pandi3a <pandi3a@gmail.com>, 2012
# Pandi3a <pandi3a@gmail.com>, 2012
@@ -20,8 +20,8 @@ msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
-"Last-Translator: Kiril Kirilov <cybercop_montana@abv.bg>\n"
+"PO-Revision-Date: 2018-07-02 04:50+0000\n"
+"Last-Translator: Радослав Иванов <reckku@gmail.com>\n"
"Language-Team: Bulgarian (http://www.transifex.com/audacious/audacious/"
"language/bg/)\n"
"Language: bg\n"
@@ -847,7 +847,7 @@ msgstr "Разширения"
#: src/libaudgui/prefs-window.cc:88 src/libaudqt/prefs-window-qt.cc:142
msgid "Advanced"
-msgstr "Разширени"
+msgstr ""
#: src/libaudgui/prefs-window.cc:92 src/libaudqt/prefs-pluginlist-model.cc:37
msgid "General"
@@ -1132,11 +1132,11 @@ msgstr "Показване на часовете отделно (1:30:00 с/у 9
#: src/libaudgui/prefs-window.cc:306 src/libaudqt/prefs-window-qt.cc:336
msgid "<b>Export</b>"
-msgstr "<b>Изнасяне</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:307 src/libaudqt/prefs-window-qt.cc:337
msgid "Use relative paths when possible"
-msgstr "Използване на алтернативни пътища, когато е възможно"
+msgstr ""
#: src/libaudgui/prefs-window.cc:312 src/libaudqt/prefs-window-qt.cc:342
msgid "<b>Album Art</b>"
@@ -1189,15 +1189,15 @@ msgstr "Знакът „\\“ да се тълкува като разделит
#: src/libaudgui/prefs-window.cc:342 src/libaudqt/prefs-window-qt.cc:372
msgid "<b>Playlist</b>"
-msgstr "<b>Списък</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:343 src/libaudqt/prefs-window-qt.cc:373
msgid "Add folders recursively"
-msgstr "Рекурсивно добавяне на папки"
+msgstr ""
#: src/libaudgui/prefs-window.cc:345 src/libaudqt/prefs-window-qt.cc:375
msgid "Add folders nested within playlist files"
-msgstr "Добавяне на папки, включени в списъци за изпълнение"
+msgstr ""
#: src/libaudgui/prefs-window.cc:347 src/libaudqt/prefs-window-qt.cc:377
msgid "<b>Metadata</b>"
@@ -1338,7 +1338,7 @@ msgstr "Информация"
#: src/libaudgui/url-opener.cc:55 src/libaudqt/url-opener-qt.cc:39
msgid "_Save to history"
-msgstr "_Запазване в историята"
+msgstr ""
#: src/libaudgui/url-opener.cc:63 src/libaudqt/url-opener-qt.cc:47
msgid "Open URL"
@@ -1350,7 +1350,7 @@ msgstr "Добавяне на интернет адрес"
#: src/libaudgui/url-opener.cc:92 src/libaudqt/url-opener-qt.cc:68
msgid "C_lear history"
-msgstr "_Изчистване на историята"
+msgstr ""
#: src/libaudgui/url-opener.cc:104 src/libaudqt/url-opener-qt.cc:62
msgid "Enter URL:"
diff --git a/po/cs.po b/po/cs.po
index dc88fe2..6e34933 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -18,14 +18,14 @@
# fri, 2012
# Petr Písař <petr.pisar@atlas.cz>, 2007-2012
# Petr Šimáček <petr.simacek@gmail.com>, 2014,2017
-# Roman Horník <roman.hornik@debian-linux.cz>, 2016,2018
+# Roman Horník <roman.hornik@debian-linux.cz>, 2016
msgid ""
msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
-"Last-Translator: Roman Horník <roman.hornik@debian-linux.cz>\n"
+"PO-Revision-Date: 2018-07-02 04:50+0000\n"
+"Last-Translator: John Lindgren <john@jlindgren.net>\n"
"Language-Team: Czech (http://www.transifex.com/audacious/audacious/language/"
"cs/)\n"
"Language: cs\n"
@@ -818,7 +818,7 @@ msgstr "_Nastavení"
#: src/libaudgui/prefs-window.cc:742 src/libaudqt/prefs-window-qt.cc:596
#: src/libaudqt/prefs-window-qt.cc:599
msgid "_About"
-msgstr "_O programu"
+msgstr "_O Programu"
#: src/libaudgui/prefs-widget.cc:277
msgid "Choose File"
@@ -852,7 +852,7 @@ msgstr "Moduly"
#: src/libaudgui/prefs-window.cc:88 src/libaudqt/prefs-window-qt.cc:142
msgid "Advanced"
-msgstr "Pokročilé"
+msgstr ""
#: src/libaudgui/prefs-window.cc:92 src/libaudqt/prefs-pluginlist-model.cc:37
msgid "General"
@@ -1020,7 +1020,7 @@ msgstr "ms"
#: src/libaudgui/prefs-window.cc:218 src/libaudqt/prefs-window-qt.cc:248
msgid "Soft clipping"
-msgstr "Měkké oříznutí"
+msgstr "Měké oříznutí"
#: src/libaudgui/prefs-window.cc:220 src/libaudqt/prefs-window-qt.cc:250
msgid "Use software volume control (not recommended)"
@@ -1084,7 +1084,7 @@ msgstr "Používat proxy"
#: src/libaudgui/prefs-window.cc:268 src/libaudqt/prefs-window-qt.cc:298
msgid "Use authentication with proxy"
-msgstr "Použít ověřování pomocí proxy serveru"
+msgstr "Autentizovat se na proxy"
#: src/libaudgui/prefs-window.cc:275 src/libaudqt/prefs-window-qt.cc:305
msgid "Auto character encoding detector for:"
@@ -1112,7 +1112,7 @@ msgstr "Přejít dál, když současná skladba je smazána"
#: src/libaudgui/prefs-window.cc:294 src/libaudqt/prefs-window-qt.cc:324
msgid "Clear the playlist when opening files"
-msgstr "Při otevírání souborů vyprázdnit seznam skladeb"
+msgstr "Při otvírání souborů vyprázdnit seznam skladeb"
#: src/libaudgui/prefs-window.cc:296 src/libaudqt/prefs-window-qt.cc:326
msgid "Open files in a temporary playlist"
@@ -1136,11 +1136,11 @@ msgstr "Zobrazit hodiny odděleně (1:30:00 oproti 90:00)"
#: src/libaudgui/prefs-window.cc:306 src/libaudqt/prefs-window-qt.cc:336
msgid "<b>Export</b>"
-msgstr "<b>Exportovat</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:307 src/libaudqt/prefs-window-qt.cc:337
msgid "Use relative paths when possible"
-msgstr "Použít relativní cesty kdykoliv je to možné"
+msgstr ""
#: src/libaudgui/prefs-window.cc:312 src/libaudqt/prefs-window-qt.cc:342
msgid "<b>Album Art</b>"
@@ -1156,7 +1156,7 @@ msgstr "Vyloučit obrázky vyhovují těmto slovům (oddělené čárkou):"
#: src/libaudgui/prefs-window.cc:317 src/libaudqt/prefs-window-qt.cc:347
msgid "Search for images matching song file name"
-msgstr "Hledat obrázky odpovídající názvu hudebního souboru"
+msgstr "Hledat obrázky odpovídající názevu hudebního souboru"
#: src/libaudgui/prefs-window.cc:319 src/libaudqt/prefs-window-qt.cc:349
msgid "Search recursively"
@@ -1172,7 +1172,7 @@ msgstr "<b>Vyskakovací okno s podrobnostmi</b>"
#: src/libaudgui/prefs-window.cc:326 src/libaudqt/prefs-window-qt.cc:356
msgid "Show popup information"
-msgstr "Zobrazit informace ve vyskakovacím oknu"
+msgstr "Zobrazit popup informace"
#: src/libaudgui/prefs-window.cc:328 src/libaudqt/prefs-window-qt.cc:358
msgid "Popup delay (tenths of a second):"
@@ -1188,19 +1188,19 @@ msgstr "<b>Kompatibilita</b>"
#: src/libaudgui/prefs-window.cc:339 src/libaudqt/prefs-window-qt.cc:369
msgid "Interpret \\ (backward slash) as a folder delimiter"
-msgstr "Interpretovat \\ (zpětné lomítko) jako oddělovač složek"
+msgstr "Interpret \\ (zpětné lomítko) jako oddělovač složky"
#: src/libaudgui/prefs-window.cc:342 src/libaudqt/prefs-window-qt.cc:372
msgid "<b>Playlist</b>"
-msgstr "<b>Playlist</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:343 src/libaudqt/prefs-window-qt.cc:373
msgid "Add folders recursively"
-msgstr "Přidat složky rekurzivně"
+msgstr ""
#: src/libaudgui/prefs-window.cc:345 src/libaudqt/prefs-window-qt.cc:375
msgid "Add folders nested within playlist files"
-msgstr "Přidat složky vnořené do souborů playlistu"
+msgstr ""
#: src/libaudgui/prefs-window.cc:347 src/libaudqt/prefs-window-qt.cc:377
msgid "<b>Metadata</b>"
@@ -1341,7 +1341,7 @@ msgstr "Informace"
#: src/libaudgui/url-opener.cc:55 src/libaudqt/url-opener-qt.cc:39
msgid "_Save to history"
-msgstr "_Uložit do historie"
+msgstr ""
#: src/libaudgui/url-opener.cc:63 src/libaudqt/url-opener-qt.cc:47
msgid "Open URL"
@@ -1353,7 +1353,7 @@ msgstr "Přidat URL"
#: src/libaudgui/url-opener.cc:92 src/libaudqt/url-opener-qt.cc:68
msgid "C_lear history"
-msgstr "_Vyčistit historii"
+msgstr ""
#: src/libaudgui/url-opener.cc:104 src/libaudqt/url-opener-qt.cc:62
msgid "Enter URL:"
diff --git a/po/da.po b/po/da.po
index ac19a49..4fefca4 100644
--- a/po/da.po
+++ b/po/da.po
@@ -10,7 +10,7 @@ msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
+"PO-Revision-Date: 2018-07-03 21:07+0000\n"
"Last-Translator: scootergrisen\n"
"Language-Team: Danish (http://www.transifex.com/audacious/audacious/language/"
"da/)\n"
@@ -280,7 +280,7 @@ msgstr "Om Audacious"
#: src/libaudqt/playlist-management.cc:75 src/libaudqt/prefs-plugin.cc:131
#: src/libaudqt/url-opener-qt.cc:79
msgid "_Cancel"
-msgstr "_Annuller"
+msgstr "_Afbryd"
#: src/libaudgui/confirm.cc:51 src/libaudqt/playlist-management.cc:73
msgid "_Don’t ask again"
@@ -494,7 +494,7 @@ msgstr "Kvalitet:"
#: src/libaudgui/infowin.cc:52
msgid "Bitrate:"
-msgstr "Bithastighed:"
+msgstr "Bitfrekvens:"
#: src/libaudgui/infowin.cc:86
msgid "Acid Jazz"
@@ -1265,7 +1265,7 @@ msgstr "Indstillinger for Audacious"
#: src/libaudgui/preset-browser.cc:50 src/libaudgui/util.cc:172
msgid "Cancel"
-msgstr "Annuller"
+msgstr "Afbryd"
#: src/libaudgui/preset-browser.cc:51
msgid "Save"
@@ -1394,7 +1394,7 @@ msgstr "Teknisk"
#: src/libaudqt/info-widget.cc:58
msgid "Bitrate"
-msgstr "Bithastighed"
+msgstr "Bitfrekvens"
#: src/libaudqt/log-inspector.cc:137
msgid "Level"
diff --git a/po/de.po b/po/de.po
index eedd2da..5cc7e25 100644
--- a/po/de.po
+++ b/po/de.po
@@ -18,7 +18,7 @@ msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
+"PO-Revision-Date: 2018-08-04 20:29+0200\n"
"Last-Translator: Thomas Lange\n"
"Language-Team: German (http://www.transifex.com/audacious/audacious/language/"
"de/)\n"
@@ -1451,6 +1451,3 @@ msgstr "Dienste"
#: src/libaudqt/util-qt.cc:80
msgid "Copy"
msgstr "Kopieren"
-
-#~ msgid "Plugins ..."
-#~ msgstr "Plugins ..."
diff --git a/po/el.po b/po/el.po
index 66d7b0b..bf214da 100644
--- a/po/el.po
+++ b/po/el.po
@@ -20,8 +20,8 @@ msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
-"Last-Translator: Ioannis LM\n"
+"PO-Revision-Date: 2018-07-02 04:50+0000\n"
+"Last-Translator: Γιάννης Ανθυμίδης\n"
"Language-Team: Greek (http://www.transifex.com/audacious/audacious/language/"
"el/)\n"
"Language: el\n"
@@ -533,7 +533,7 @@ msgstr "Bluegrass"
#: src/libaudgui/infowin.cc:91
msgid "Blues"
-msgstr "Blues"
+msgstr "Μπλουζ"
#: src/libaudgui/infowin.cc:92
msgid "Chamber Music"
@@ -545,7 +545,7 @@ msgstr "Κλασική Μουσική"
#: src/libaudgui/infowin.cc:94
msgid "Country"
-msgstr "Country"
+msgstr "Κάντρι"
#: src/libaudgui/infowin.cc:95
msgid "Death Metal"
@@ -553,7 +553,7 @@ msgstr "Death Metal"
#: src/libaudgui/infowin.cc:96
msgid "Disco"
-msgstr "Disco"
+msgstr "Ντίσκο"
#: src/libaudgui/infowin.cc:97
msgid "Easy Listening"
@@ -561,11 +561,11 @@ msgstr "Easy Listening"
#: src/libaudgui/infowin.cc:98
msgid "Folk"
-msgstr "Folk"
+msgstr "Φολκ"
#: src/libaudgui/infowin.cc:99
msgid "Funk"
-msgstr "Funk"
+msgstr "Φανκ"
#: src/libaudgui/infowin.cc:100
msgid "Gangsta Rap"
@@ -589,7 +589,7 @@ msgstr "Heavy Metal"
#: src/libaudgui/infowin.cc:105
msgid "Hip-hop"
-msgstr "Hip-hop"
+msgstr "Χιπ χοπ"
#: src/libaudgui/infowin.cc:106
msgid "House"
@@ -597,7 +597,7 @@ msgstr "House"
#: src/libaudgui/infowin.cc:107
msgid "Jazz"
-msgstr "Jazz"
+msgstr "Τζαζ"
#: src/libaudgui/infowin.cc:108
msgid "Jungle"
@@ -605,7 +605,7 @@ msgstr "Jungle"
#: src/libaudgui/infowin.cc:109
msgid "Metal"
-msgstr "Metal"
+msgstr "Μέταλ"
#: src/libaudgui/infowin.cc:110
msgid "New Age"
@@ -621,7 +621,7 @@ msgstr "Noise"
#: src/libaudgui/infowin.cc:113
msgid "Pop"
-msgstr "Pop"
+msgstr "Ποπ"
#: src/libaudgui/infowin.cc:114
msgid "Punk Rock"
@@ -629,15 +629,15 @@ msgstr "Punk Rock"
#: src/libaudgui/infowin.cc:115
msgid "Rap"
-msgstr "Rap"
+msgstr "Ραπ"
#: src/libaudgui/infowin.cc:116
msgid "Reggae"
-msgstr "Reggae"
+msgstr "Ρέγκε"
#: src/libaudgui/infowin.cc:117
msgid "Rock"
-msgstr "Rock"
+msgstr "Ροκ"
#: src/libaudgui/infowin.cc:118
msgid "Rock and Roll"
@@ -657,11 +657,11 @@ msgstr "Soul"
#: src/libaudgui/infowin.cc:122
msgid "Swing"
-msgstr "Swing"
+msgstr "Σουίνγκ"
#: src/libaudgui/infowin.cc:123
msgid "Techno"
-msgstr "Techno"
+msgstr "Τέκνο"
#: src/libaudgui/infowin.cc:124
msgid "Trip-hop"
@@ -827,7 +827,7 @@ msgstr "Επιλογή αρχείου"
#: src/libaudgui/prefs-widget.cc:281
msgid "Choose Folder"
-msgstr "Επιλογή φακέλου"
+msgstr "Επιλογή Φακέλου"
#: src/libaudgui/prefs-window.cc:82 src/libaudqt/prefs-window-qt.cc:136
msgid "Appearance"
@@ -853,7 +853,7 @@ msgstr "Πρόσθετα"
#: src/libaudgui/prefs-window.cc:88 src/libaudqt/prefs-window-qt.cc:142
msgid "Advanced"
-msgstr "Προχωρημένα"
+msgstr ""
#: src/libaudgui/prefs-window.cc:92 src/libaudqt/prefs-pluginlist-model.cc:37
msgid "General"
@@ -1037,7 +1037,7 @@ msgstr "Καταγραφή ροής:"
#: src/libaudgui/prefs-window.cc:229 src/libaudqt/prefs-window-qt.cc:259
msgid "<b>ReplayGain</b>"
-msgstr "<b>ReplayGain (ομαλοποίηση έντασης)</b>"
+msgstr "<b>ReplayGain</b>"
#: src/libaudgui/prefs-window.cc:230 src/libaudqt/prefs-window-qt.cc:260
msgid "Enable ReplayGain"
@@ -1137,11 +1137,11 @@ msgstr "Εμφάνιση της ώρας χωριστά (1:30:00 αντί 90:00)
#: src/libaudgui/prefs-window.cc:306 src/libaudqt/prefs-window-qt.cc:336
msgid "<b>Export</b>"
-msgstr "<b>Εξαγωγή</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:307 src/libaudqt/prefs-window-qt.cc:337
msgid "Use relative paths when possible"
-msgstr "Χρήση των σχετικών διαδρομών, όταν είναι δυνατόν"
+msgstr ""
#: src/libaudgui/prefs-window.cc:312 src/libaudqt/prefs-window-qt.cc:342
msgid "<b>Album Art</b>"
@@ -1150,12 +1150,12 @@ msgstr "<b>Άλμπουμ</b>"
#: src/libaudgui/prefs-window.cc:313 src/libaudqt/prefs-window-qt.cc:343
msgid "Search for images matching these words (comma-separated):"
msgstr ""
-"Αναζήτηση εικόνων που ταιριάζουν με τις λέξεις (διαχωρισμένες με κόμμα):"
+"Αναζήτηση εικόνων που ταιριάζουν με αυτά τα λόγια (διαχωρισμένα με κόμμα):"
#: src/libaudgui/prefs-window.cc:315 src/libaudqt/prefs-window-qt.cc:345
msgid "Exclude images matching these words (comma-separated):"
msgstr ""
-"Εξαίρεση εικόνων που ταιριάζουν με τις λέξεις (διαχωρισμένες με κόμμα):"
+"Εξαίρεση εικόνων που ταιριάζουν με αυτά τα λόγια (διαχωρισμένα με κόμμα):"
#: src/libaudgui/prefs-window.cc:317 src/libaudqt/prefs-window-qt.cc:347
msgid "Search for images matching song file name"
@@ -1163,7 +1163,7 @@ msgstr "Αναζήτηση εικόνων που ταιριάζουν με το
#: src/libaudgui/prefs-window.cc:319 src/libaudqt/prefs-window-qt.cc:349
msgid "Search recursively"
-msgstr "Αναδρομική αναζήτηση"
+msgstr "Αναζήτηση αναδρομικά"
#: src/libaudgui/prefs-window.cc:321 src/libaudqt/prefs-window-qt.cc:351
msgid "Search depth:"
@@ -1195,15 +1195,15 @@ msgstr "Εξήγηση με \\\\ (αντιπλάγια μπάρα) ως διαχ
#: src/libaudgui/prefs-window.cc:342 src/libaudqt/prefs-window-qt.cc:372
msgid "<b>Playlist</b>"
-msgstr "<b>Λίστα αναπαραγωγής</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:343 src/libaudqt/prefs-window-qt.cc:373
msgid "Add folders recursively"
-msgstr "Αναδρομική προσθήκη φακέλων"
+msgstr ""
#: src/libaudgui/prefs-window.cc:345 src/libaudqt/prefs-window-qt.cc:375
msgid "Add folders nested within playlist files"
-msgstr "Προσθήκη των ενσωματωμένων φακέλων στα αρχεία της λίστας αναπαραγωγής"
+msgstr ""
#: src/libaudgui/prefs-window.cc:347 src/libaudqt/prefs-window-qt.cc:377
msgid "<b>Metadata</b>"
@@ -1316,7 +1316,7 @@ msgstr "Αποθήκευση αρχείου EQF"
#: src/libaudgui/preset-browser.cc:127
msgid "<name>.eqf"
-msgstr "<name>.eqf"
+msgstr "<όνομα>.eqf"
#: src/libaudgui/preset-browser.cc:141
msgid "Import Winamp Presets"
@@ -1344,7 +1344,7 @@ msgstr "Πληροφόρηση"
#: src/libaudgui/url-opener.cc:55 src/libaudqt/url-opener-qt.cc:39
msgid "_Save to history"
-msgstr "_Αποθήκευση"
+msgstr ""
#: src/libaudgui/url-opener.cc:63 src/libaudqt/url-opener-qt.cc:47
msgid "Open URL"
@@ -1356,7 +1356,7 @@ msgstr "Προσθήκη διεύθυνσης URL"
#: src/libaudgui/url-opener.cc:92 src/libaudqt/url-opener-qt.cc:68
msgid "C_lear history"
-msgstr "_Καθαρισμός ιστορικού"
+msgstr ""
#: src/libaudgui/url-opener.cc:104 src/libaudqt/url-opener-qt.cc:62
msgid "Enter URL:"
diff --git a/po/en_GB.po b/po/en_GB.po
index a4bf379..d6cd915 100644
--- a/po/en_GB.po
+++ b/po/en_GB.po
@@ -3,13 +3,13 @@
# This file is distributed under the same license as the Audacious package.
#
# Translators:
-# Andi Chandler <andi@gowling.com>, 2013,2015-2018
+# Andi Chandler <andi@gowling.com>, 2013,2015-2017
msgid ""
msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
+"PO-Revision-Date: 2018-07-02 04:50+0000\n"
"Last-Translator: Andi Chandler <andi@gowling.com>\n"
"Language-Team: English (United Kingdom) (http://www.transifex.com/audacious/"
"audacious/language/en_GB/)\n"
@@ -835,7 +835,7 @@ msgstr "Plug-ins"
#: src/libaudgui/prefs-window.cc:88 src/libaudqt/prefs-window-qt.cc:142
msgid "Advanced"
-msgstr "Advanced"
+msgstr ""
#: src/libaudgui/prefs-window.cc:92 src/libaudqt/prefs-pluginlist-model.cc:37
msgid "General"
@@ -1119,11 +1119,11 @@ msgstr "Show hours separately (1:30:00 vs. 90:00)"
#: src/libaudgui/prefs-window.cc:306 src/libaudqt/prefs-window-qt.cc:336
msgid "<b>Export</b>"
-msgstr "<b>Export</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:307 src/libaudqt/prefs-window-qt.cc:337
msgid "Use relative paths when possible"
-msgstr "Use relative paths when possible"
+msgstr ""
#: src/libaudgui/prefs-window.cc:312 src/libaudqt/prefs-window-qt.cc:342
msgid "<b>Album Art</b>"
@@ -1175,15 +1175,15 @@ msgstr "Interpret \\ (backward slash) as a folder delimiter"
#: src/libaudgui/prefs-window.cc:342 src/libaudqt/prefs-window-qt.cc:372
msgid "<b>Playlist</b>"
-msgstr "<b>Playlist</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:343 src/libaudqt/prefs-window-qt.cc:373
msgid "Add folders recursively"
-msgstr "Add folders recursively"
+msgstr ""
#: src/libaudgui/prefs-window.cc:345 src/libaudqt/prefs-window-qt.cc:375
msgid "Add folders nested within playlist files"
-msgstr "Add folders nested within playlist files"
+msgstr ""
#: src/libaudgui/prefs-window.cc:347 src/libaudqt/prefs-window-qt.cc:377
msgid "<b>Metadata</b>"
@@ -1324,7 +1324,7 @@ msgstr "Information"
#: src/libaudgui/url-opener.cc:55 src/libaudqt/url-opener-qt.cc:39
msgid "_Save to history"
-msgstr "_Save to history"
+msgstr ""
#: src/libaudgui/url-opener.cc:63 src/libaudqt/url-opener-qt.cc:47
msgid "Open URL"
@@ -1336,7 +1336,7 @@ msgstr "Add URL"
#: src/libaudgui/url-opener.cc:92 src/libaudqt/url-opener-qt.cc:68
msgid "C_lear history"
-msgstr "C_lear history"
+msgstr ""
#: src/libaudgui/url-opener.cc:104 src/libaudqt/url-opener-qt.cc:62
msgid "Enter URL:"
@@ -1437,7 +1437,7 @@ msgstr "Services"
#: src/libaudqt/util-qt.cc:80
msgid "Copy"
-msgstr "Copy"
+msgstr ""
#~ msgid "Plugins ..."
#~ msgstr "Plugins ..."
diff --git a/po/fr.po b/po/fr.po
index 5c6c362..e79fda9 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -3,23 +3,23 @@
# This file is distributed under the same license as the Audacious package.
#
# Translators:
-# AO <ao@localizationlab.org>, 2012-2013
-# AO <ao@localizationlab.org>, 2017-2018
-# AO <ao@localizationlab.org>, 2016
-# AO <ao@localizationlab.org>, 2016
+# French language coordinator <french.coordinator@rbox.me>, 2012-2013
+# French language coordinator <french.coordinator@rbox.me>, 2017-2018
+# French language coordinator <french.coordinator@rbox.me>, 2016
+# French language coordinator <french.coordinator@rbox.me>, 2016
# Oxayotl <jagw40k@free.fr>, 2013-2014
# Oxayotl <jagw40k@free.fr>, 2011-2012
# Oxayotl <jagw40k@free.fr>, 2011
# Oxayotl <jagw40k@free.fr>, 2011,2013
-# AO <ao@localizationlab.org>, 2015
-# AO <ao@localizationlab.org>, 2013-2015
+# French language coordinator <french.coordinator@rbox.me>, 2015
+# French language coordinator <french.coordinator@rbox.me>, 2013-2015
msgid ""
msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
-"Last-Translator: AO <ao@localizationlab.org>\n"
+"PO-Revision-Date: 2018-07-04 21:45+0000\n"
+"Last-Translator: French language coordinator <french.coordinator@rbox.me>\n"
"Language-Team: French (http://www.transifex.com/audacious/audacious/language/"
"fr/)\n"
"Language: fr\n"
diff --git a/po/id_ID.po b/po/id_ID.po
index c2bfe0d..d6dfd9f 100644
--- a/po/id_ID.po
+++ b/po/id_ID.po
@@ -24,15 +24,15 @@
# <sakrasemangat@gmail.com>, 2012
# <samsul@kplibanyumas.org>, 2012
# se7entime <se7entime@openmailbox.org>, 2012
-# Adrianus Yoza Aprilio <yoza1404@gmail.com>, 2012
-# Adrianus Yoza Aprilio <yoza1404@gmail.com>, 2012
-# Adrianus Yoza Aprilio <yoza1404@gmail.com>, 2012
+# Yoza Aprilio <yoza1404@gmail.com>, 2012
+# Yoza Aprilio <yoza1404@gmail.com>, 2012
+# Yoza Aprilio <yoza1404@gmail.com>, 2012
msgid ""
msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
+"PO-Revision-Date: 2018-07-02 04:50+0000\n"
"Last-Translator: Rahman Yusri Aftian <aftian@yahoo.com>\n"
"Language-Team: Indonesian (Indonesia) (http://www.transifex.com/audacious/"
"audacious/language/id_ID/)\n"
diff --git a/po/ja.po b/po/ja.po
index 3a05e6d..1dcfc41 100644
--- a/po/ja.po
+++ b/po/ja.po
@@ -4,7 +4,7 @@
#
# Translators:
# ABE Tsunehiko, 2013
-# ABE Tsunehiko, 2015-2018
+# ABE Tsunehiko, 2015-2017
# natird zoto <dritan86@gmail.com>, 2012
# ABE Tsunehiko, 2013
# Nastuko Toda <m2330880989@shibuya-center.com>, 2012
@@ -21,8 +21,8 @@ msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
-"Last-Translator: ABE Tsunehiko\n"
+"PO-Revision-Date: 2018-07-02 04:50+0000\n"
+"Last-Translator: TAKAHASHI Shuuji <shuuji3@gmail.com>\n"
"Language-Team: Japanese (http://www.transifex.com/audacious/audacious/"
"language/ja/)\n"
"Language: ja\n"
@@ -845,7 +845,7 @@ msgstr "プラグイン"
#: src/libaudgui/prefs-window.cc:88 src/libaudqt/prefs-window-qt.cc:142
msgid "Advanced"
-msgstr "高度"
+msgstr ""
#: src/libaudgui/prefs-window.cc:92 src/libaudqt/prefs-pluginlist-model.cc:37
msgid "General"
@@ -1129,11 +1129,11 @@ msgstr "時分秒表示を使う (例 1:30:00)"
#: src/libaudgui/prefs-window.cc:306 src/libaudqt/prefs-window-qt.cc:336
msgid "<b>Export</b>"
-msgstr "<b>エクスポート</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:307 src/libaudqt/prefs-window-qt.cc:337
msgid "Use relative paths when possible"
-msgstr "可能な限り相対パスを使う"
+msgstr ""
#: src/libaudgui/prefs-window.cc:312 src/libaudqt/prefs-window-qt.cc:342
msgid "<b>Album Art</b>"
@@ -1185,15 +1185,15 @@ msgstr "\\ (バックスラッシュ) をフォルダーの区切り文字とし
#: src/libaudgui/prefs-window.cc:342 src/libaudqt/prefs-window-qt.cc:372
msgid "<b>Playlist</b>"
-msgstr "<b>プレイリスト</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:343 src/libaudqt/prefs-window-qt.cc:373
msgid "Add folders recursively"
-msgstr "再帰的にフォルダーを追加する"
+msgstr ""
#: src/libaudgui/prefs-window.cc:345 src/libaudqt/prefs-window-qt.cc:375
msgid "Add folders nested within playlist files"
-msgstr "プレイリスト内に入れ子にされたフォルダーを追加する"
+msgstr ""
#: src/libaudgui/prefs-window.cc:347 src/libaudqt/prefs-window-qt.cc:377
msgid "<b>Metadata</b>"
@@ -1334,7 +1334,7 @@ msgstr "情報"
#: src/libaudgui/url-opener.cc:55 src/libaudqt/url-opener-qt.cc:39
msgid "_Save to history"
-msgstr "履歴に追加 (_S)"
+msgstr ""
#: src/libaudgui/url-opener.cc:63 src/libaudqt/url-opener-qt.cc:47
msgid "Open URL"
@@ -1346,7 +1346,7 @@ msgstr "URL を追加"
#: src/libaudgui/url-opener.cc:92 src/libaudqt/url-opener-qt.cc:68
msgid "C_lear history"
-msgstr "履歴を削除 (_L)"
+msgstr ""
#: src/libaudgui/url-opener.cc:104 src/libaudqt/url-opener-qt.cc:62
msgid "Enter URL:"
diff --git a/po/meson.build b/po/meson.build
new file mode 100644
index 0000000..e05db57
--- /dev/null
+++ b/po/meson.build
@@ -0,0 +1,15 @@
+i18n = import('i18n')
+
+
+i18n.gettext('audacious',
+ args: [
+ '--default-domain=audacious',
+ '--language=C',
+ '--keyword=_',
+ '--keyword=N_',
+ '--from-code=UTF-8',
+ '--msgid-bugs-address="https://redmine.audacious-media-player.org/"',
+ '--directory=%0%'.format(meson.source_root()),
+ '--files-from=POTFILES.in'
+ ]
+)
diff --git a/po/pl.po b/po/pl.po
index 54752d8..1482e68 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -27,7 +27,7 @@ msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
+"PO-Revision-Date: 2018-07-02 06:30+0000\n"
"Last-Translator: No Ne\n"
"Language-Team: Polish (http://www.transifex.com/audacious/audacious/language/"
"pl/)\n"
@@ -85,7 +85,7 @@ msgstr "Wyświetl główne okno programu"
#: src/audacious/main.cc:76
msgid "Display the jump-to-song window"
-msgstr "Wyświetla okno przejścia do piosenki"
+msgstr "Wyświetla okno \"Przejdź do ścieżki\""
#: src/audacious/main.cc:77
msgid "Start without a graphical interface"
@@ -231,7 +231,7 @@ msgstr "Błąd wczytywania wtyczki"
#: src/libaudcore/probe.cc:171
msgid "Seek error"
-msgstr "Błąd wyszukiwania"
+msgstr "Znajdź błąd"
#: src/libaudcore/probe.cc:179
msgid "File format not recognized"
@@ -500,7 +500,7 @@ msgstr "Rok wydania"
#: src/libaudgui/infopopup.cc:210 src/libaudgui/prefs-window.cc:147
#: src/libaudqt/infopopup-qt.cc:126 src/libaudqt/prefs-window-qt.cc:192
msgid "Track"
-msgstr "Ścieżka"
+msgstr "Utwór"
#: src/libaudgui/infopopup.cc:211 src/libaudqt/infopopup-qt.cc:128
#: src/libaudqt/info-widget.cc:55
@@ -686,11 +686,11 @@ msgstr "Błąd zapisu"
#: src/libaudgui/infowin.cc:306 src/libaudgui/prefs-window.cc:86
#: src/libaudqt/infowin-qt.cc:123 src/libaudqt/prefs-window-qt.cc:140
msgid "Song Info"
-msgstr "Informacje o piosence"
+msgstr "Informacje o nagraniu"
#: src/libaudgui/infowin.cc:360 src/libaudqt/info-widget.cc:47
msgid "Album Artist"
-msgstr "Wykonawca albumu"
+msgstr "Artysta albumu"
#: src/libaudgui/infowin.cc:363 src/libaudgui/prefs-window.cc:111
#: src/libaudqt/info-widget.cc:46 src/libaudqt/prefs-window-qt.cc:156
@@ -699,11 +699,11 @@ msgstr "Komentarz"
#: src/libaudgui/infowin.cc:373 src/libaudqt/info-widget.cc:44
msgid "Track Number"
-msgstr "Numer ścieżki"
+msgstr "Numer nagrania"
#: src/libaudgui/infowin.cc:380
msgid "Clea_r fields when moving to next song"
-msgstr "Czyść pola podczas p_rzechodzenia do następnej piosenki"
+msgstr "Czyść pola podczas p_rzechodzenia do następnego utworu"
#: src/libaudgui/infowin.cc:394 src/libaudqt/infowin-qt.cc:148
msgid "_Save"
@@ -745,7 +745,7 @@ msgstr "U_suń z kolejki"
#: src/libaudgui/jump-to-track.cc:240
msgid "Jump to Song"
-msgstr "Przejdź do piosenki"
+msgstr "Przejdź do ścieżki"
#: src/libaudgui/jump-to-track.cc:265
msgid "Filter: "
@@ -884,7 +884,7 @@ msgstr "Transport"
#: src/libaudgui/prefs-window.cc:103 src/libaudqt/prefs-window-qt.cc:148
msgid "Album artist"
-msgstr "Wykonawca albumu"
+msgstr "Artysta albumu"
#: src/libaudgui/prefs-window.cc:105 src/libaudqt/prefs-window-qt.cc:150
msgid "Track number"
@@ -1116,7 +1116,7 @@ msgstr "Wstrzymaj zamiast natychmiastowego wznowienia"
#: src/libaudgui/prefs-window.cc:292 src/libaudqt/prefs-window-qt.cc:322
msgid "Advance when the current song is deleted"
-msgstr "Przejdź do następnej, gdy usunę odtwarzaną piosenkę"
+msgstr "Przejdź do następnej gdy usunę odtwarzaną ścieżkę"
#: src/libaudgui/prefs-window.cc:294 src/libaudqt/prefs-window-qt.cc:324
msgid "Clear the playlist when opening files"
@@ -1128,11 +1128,11 @@ msgstr "Dodaj pliki do tymczasowej listy odtwarzania"
#: src/libaudgui/prefs-window.cc:298 src/libaudqt/prefs-window-qt.cc:328
msgid "<b>Song Display</b>"
-msgstr "<b>Wyświetlanie piosenki</b>"
+msgstr "<b>Wyświetlanie ścieżki</b>"
#: src/libaudgui/prefs-window.cc:299 src/libaudqt/prefs-window-qt.cc:329
msgid "Show song numbers"
-msgstr "Pokaż numery piosenek"
+msgstr "Numery ścieżek"
#: src/libaudgui/prefs-window.cc:301 src/libaudqt/prefs-window-qt.cc:331
msgid "Show leading zeroes (02:00 vs. 2:00)"
@@ -1164,7 +1164,7 @@ msgstr "Wyklucz obrazy pasujące do tych słów (oddzielone przecinkiem):"
#: src/libaudgui/prefs-window.cc:317 src/libaudqt/prefs-window-qt.cc:347
msgid "Search for images matching song file name"
-msgstr "Wyszukaj obrazy pasujące do nazwy pliku piosenki"
+msgstr "Wyszukaj obrazy pasujące do nazwy pliku utworu"
#: src/libaudgui/prefs-window.cc:319 src/libaudqt/prefs-window-qt.cc:349
msgid "Search recursively"
@@ -1188,7 +1188,7 @@ msgstr "Opóźnij wyskakujące komunikaty (dziesiąte sekundy):"
#: src/libaudgui/prefs-window.cc:332 src/libaudqt/prefs-window-qt.cc:362
msgid "Show time scale for current song"
-msgstr "Pokaż skalę czasową dla bieżącej piosenki"
+msgstr "Pokaż skalę czasową dla bieżącej ścieżki"
#: src/libaudgui/prefs-window.cc:338 src/libaudqt/prefs-window-qt.cc:368
msgid "<b>Compatibility</b>"
@@ -1220,7 +1220,7 @@ msgstr "Odgadnij brakujące metadane ze ścieżki pliku"
#: src/libaudgui/prefs-window.cc:350 src/libaudqt/prefs-window-qt.cc:380
msgid "Do not load metadata for songs until played"
-msgstr "Opóźnij wczytywanie metadanych piosenek do czasu odtworzenia"
+msgstr "Opóźnij wczytywanie metadanych ścieżek do czasu odtworzenia"
#: src/libaudgui/prefs-window.cc:352 src/libaudqt/prefs-window-qt.cc:382
msgid "Probe content of files with no recognized file name extension"
diff --git a/po/pt_BR.po b/po/pt_BR.po
index 9f19e7c..3d93fab 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -4,7 +4,6 @@
#
# Translators:
# Alexandro Casanova <shorterfire@gmail.com>, 2012-2014
-# Bruno Lima <brunolima.18@outlook.com>, 2018
# Cleber de Souza Corrêa <cscorrea@gmail.com>, 2014
# Cleiton Lima <cleitoncfl@yahoo.com.br>, 2011
# Cleiton Lima <cleitoncfl@yahoo.com.br>, 2011
@@ -23,7 +22,6 @@
# Rodrigo de Araujo <araujorodrigo1984@gmail.com>, 2016
# Rodrigo de Araujo <araujorodrigo1984@gmail.com>, 2016
# Rodrigo de Almeida Sottomaior Macedo <rmsolucoeseminformatic4@gmail.com>, 2012
-# Rui <xymarior@yandex.com>, 2018
# Alexandro Casanova <shorterfire@gmail.com>, 2012-2013
# Alexandro Casanova <shorterfire@gmail.com>, 2012
# vitorgatti <vitorgatti@yahoo.com.br>, 2012
@@ -33,8 +31,9 @@ msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
-"Last-Translator: Rui <xymarior@yandex.com>\n"
+"PO-Revision-Date: 2018-07-02 04:50+0000\n"
+"Last-Translator: Rodrigo de Almeida Sottomaior Macedo "
+"<rmsolucoeseminformatic4@gmail.com>\n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/audacious/"
"audacious/language/pt_BR/)\n"
"Language: pt_BR\n"
@@ -151,7 +150,7 @@ msgstr ""
#: src/libaudcore/adder.cc:445
msgid "No files found."
-msgstr "Nenhum arquivo encontrado."
+msgstr "Nenum arquivo encontrado."
#: src/libaudcore/adder.cc:467 src/libaudcore/playlist.cc:88
msgid "New Playlist"
@@ -546,7 +545,7 @@ msgstr "Blues"
#: src/libaudgui/infowin.cc:92
msgid "Chamber Music"
-msgstr "Chamber Music"
+msgstr "Música de cámara"
#: src/libaudgui/infowin.cc:93
msgid "Classical"
@@ -566,7 +565,7 @@ msgstr "Disco"
#: src/libaudgui/infowin.cc:97
msgid "Easy Listening"
-msgstr "Easy Listening"
+msgstr "Fácil de escutar"
#: src/libaudgui/infowin.cc:98
msgid "Folk"
@@ -618,15 +617,15 @@ msgstr "Metal"
#: src/libaudgui/infowin.cc:110
msgid "New Age"
-msgstr "New Age"
+msgstr "New age"
#: src/libaudgui/infowin.cc:111
msgid "New Wave"
-msgstr "New Wave"
+msgstr "New wave"
#: src/libaudgui/infowin.cc:112
msgid "Noise"
-msgstr "Noise"
+msgstr "Ruído"
#: src/libaudgui/infowin.cc:113
msgid "Pop"
@@ -862,7 +861,7 @@ msgstr "Plugins"
#: src/libaudgui/prefs-window.cc:88 src/libaudqt/prefs-window-qt.cc:142
msgid "Advanced"
-msgstr "Avançado"
+msgstr ""
#: src/libaudgui/prefs-window.cc:92 src/libaudqt/prefs-pluginlist-model.cc:37
msgid "General"
@@ -1146,11 +1145,11 @@ msgstr "Mostrar horas separadamente (1:30:00 vs. 90:00)"
#: src/libaudgui/prefs-window.cc:306 src/libaudqt/prefs-window-qt.cc:336
msgid "<b>Export</b>"
-msgstr "<b>Exportar</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:307 src/libaudqt/prefs-window-qt.cc:337
msgid "Use relative paths when possible"
-msgstr "Use caminhos relativos quando possível"
+msgstr ""
#: src/libaudgui/prefs-window.cc:312 src/libaudqt/prefs-window-qt.cc:342
msgid "<b>Album Art</b>"
@@ -1204,11 +1203,11 @@ msgstr ""
#: src/libaudgui/prefs-window.cc:342 src/libaudqt/prefs-window-qt.cc:372
msgid "<b>Playlist</b>"
-msgstr "<b>Lista de Reprodução</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:343 src/libaudqt/prefs-window-qt.cc:373
msgid "Add folders recursively"
-msgstr "Adicionar pastas recursivamente"
+msgstr ""
#: src/libaudgui/prefs-window.cc:345 src/libaudqt/prefs-window-qt.cc:375
msgid "Add folders nested within playlist files"
@@ -1354,7 +1353,7 @@ msgstr "Informação "
#: src/libaudgui/url-opener.cc:55 src/libaudqt/url-opener-qt.cc:39
msgid "_Save to history"
-msgstr "_Adicionar ao histórico"
+msgstr ""
#: src/libaudgui/url-opener.cc:63 src/libaudqt/url-opener-qt.cc:47
msgid "Open URL"
@@ -1366,7 +1365,7 @@ msgstr "Adicionar URL"
#: src/libaudgui/url-opener.cc:92 src/libaudqt/url-opener-qt.cc:68
msgid "C_lear history"
-msgstr "_Limpar histórico"
+msgstr ""
#: src/libaudgui/url-opener.cc:104 src/libaudqt/url-opener-qt.cc:62
msgid "Enter URL:"
diff --git a/po/pt_PT.po b/po/pt_PT.po
index 16b4f3d..8935797 100644
--- a/po/pt_PT.po
+++ b/po/pt_PT.po
@@ -6,7 +6,6 @@
# Alexandro Casanova <shorterfire@gmail.com>, 2012
# Pitxyoki <Pitxyoki@gmail.com>, 2010
# Pitxyoki <Pitxyoki@gmail.com>, 2010
-# Rui <xymarior@yandex.com>, 2018
# Alexandro Casanova <shorterfire@gmail.com>, 2012
# Sérgio Marques <smarquespt@gmail.com>, 2012-2018
# Alexandro Casanova <shorterfire@gmail.com>, 2012
@@ -16,8 +15,8 @@ msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
-"Last-Translator: Rui <xymarior@yandex.com>\n"
+"PO-Revision-Date: 2018-07-05 23:06+0000\n"
+"Last-Translator: Sérgio Marques <smarquespt@gmail.com>\n"
"Language-Team: Portuguese (Portugal) (http://www.transifex.com/audacious/"
"audacious/language/pt_PT/)\n"
"Language: pt_PT\n"
@@ -1190,7 +1189,7 @@ msgstr "Adicionar pastas recursivamente"
#: src/libaudgui/prefs-window.cc:345 src/libaudqt/prefs-window-qt.cc:375
msgid "Add folders nested within playlist files"
-msgstr "Adicionar pastas dentro de ficheiros de listas de reprodução"
+msgstr ""
#: src/libaudgui/prefs-window.cc:347 src/libaudqt/prefs-window-qt.cc:377
msgid "<b>Metadata</b>"
diff --git a/po/ru.po b/po/ru.po
index 355eec2..de89566 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -7,7 +7,7 @@
# Денис <alpi_bel@mail.ru>, 2014
# michurin <a.michurin@gmail.com>, 2011
# Andrei Stepanov, 2014,2016
-# Andrei Stepanov <adem4ik@gmail.com>, 2014,2016
+# Andrei Stepanov, 2014,2016
# Ilyas B Arinov <arinov.ilyas@gmail.com>, 2014
# Danila E <KnightDanila@gmail.com>, 2018
# dartraiden, 2018
@@ -45,7 +45,7 @@ msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
+"PO-Revision-Date: 2018-07-29 18:16+0000\n"
"Last-Translator: dartraiden\n"
"Language-Team: Russian (http://www.transifex.com/audacious/audacious/"
"language/ru/)\n"
diff --git a/po/sv.po b/po/sv.po
index 0d1403f..8ce125e 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -19,7 +19,7 @@ msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
+"PO-Revision-Date: 2018-07-31 15:57+0000\n"
"Last-Translator: Jonatan Nyberg\n"
"Language-Team: Swedish (http://www.transifex.com/audacious/audacious/"
"language/sv/)\n"
@@ -402,7 +402,7 @@ msgstr "16 kHz"
#: src/libaudgui/equalizer.cc:129 src/libaudqt/equalizer-qt.cc:142
msgid "Equalizer"
-msgstr "Equalizer"
+msgstr "Equalisation"
#: src/libaudgui/equalizer.cc:143
msgid "Presets ..."
@@ -599,7 +599,7 @@ msgstr "Jungle"
#: src/libaudgui/infowin.cc:109
msgid "Metal"
-msgstr "Metal"
+msgstr "Metall"
#: src/libaudgui/infowin.cc:110
msgid "New Age"
@@ -1161,15 +1161,15 @@ msgstr "Sökdjup:"
#: src/libaudgui/prefs-window.cc:325 src/libaudqt/prefs-window-qt.cc:355
msgid "<b>Popup Information</b>"
-msgstr "<b>Poppupp-information</b>"
+msgstr "<b>Popup-information</b>"
#: src/libaudgui/prefs-window.cc:326 src/libaudqt/prefs-window-qt.cc:356
msgid "Show popup information"
-msgstr "Visa poppupp-information"
+msgstr "Visa popup-information"
#: src/libaudgui/prefs-window.cc:328 src/libaudqt/prefs-window-qt.cc:358
msgid "Popup delay (tenths of a second):"
-msgstr "Poppupp-fördröjning (tiondelar av en sekund):"
+msgstr "Popup-fördröjning (tiondelar av en sekund):"
#: src/libaudgui/prefs-window.cc:332 src/libaudqt/prefs-window-qt.cc:362
msgid "Show time scale for current song"
diff --git a/po/tr.po b/po/tr.po
index 5272030..5e6276a 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -9,8 +9,7 @@
# Imnune <alikoc@hush.ai>, 2012
# Ali Orhun Akkirman <the.alorak@gmail.com>, 2013
# hsngrms <dead-bodies-everywhere@hotmail.com>, 2012
-# Dragon Blogger <dodokur@gmail.com>, 2018
-# Dragon Blogger <dodokur@gmail.com>, 2016
+# Dragon xarax <dodokur@gmail.com>, 2016
# Emre FIRAT <emrefirat93@gmail.com>, 2013
# Emin Tufan <etcetin@gmail.com>, 2016
# Emre FIRAT <emrefirat93@gmail.com>, 2013
@@ -28,15 +27,14 @@
# M. Tayyip Yel <m.tayyib.yel@gmail.com>, 2013
# tarkan255 <t.oguzman@hotmail.com>, 2012
# Volkan Gezer <volkangezer@gmail.com>, 2014-2015
-# yaşar çiv <yasarciv67@gmail.com>, 2018
# Zekeriya Cihan <zekeriya.cihan@gmail.com>, 2013
msgid ""
msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
-"Last-Translator: yaşar çiv <yasarciv67@gmail.com>\n"
+"PO-Revision-Date: 2018-07-02 04:50+0000\n"
+"Last-Translator: Akferzan <akferzan@gmail.com>\n"
"Language-Team: Turkish (http://www.transifex.com/audacious/audacious/"
"language/tr/)\n"
"Language: tr\n"
@@ -129,7 +127,7 @@ msgstr ""
#: src/audacious/main.cc:185
msgid "Select instance to run/control"
-msgstr "Çalıştırılacak/kontrol edilecek örneği seçin"
+msgstr ""
#: src/audacious/main.cc:367 src/libaudqt/audqt.cc:63
msgid "Audacious"
@@ -175,7 +173,7 @@ msgstr "(karakter kodlama hatası)"
#: src/libaudcore/drct.cc:96
msgid ""
"Stream recording must be configured in Audio Settings before it can be used."
-msgstr "Akış kaydı, kullanılmadan önce Ses Ayarları'nda yapılandırılmalıdır."
+msgstr ""
#: src/libaudcore/output.cc:195
msgid "Error opening output stream"
@@ -183,7 +181,7 @@ msgstr "Çıktı akışı açılırken hata"
#: src/libaudcore/output.cc:248
msgid "Error recording output stream"
-msgstr "Çıkış akışı kaydedilirken hata oluştu"
+msgstr ""
#: src/libaudcore/playback.cc:373
#, c-format
@@ -860,7 +858,7 @@ msgstr "Eklentiler"
#: src/libaudgui/prefs-window.cc:88 src/libaudqt/prefs-window-qt.cc:142
msgid "Advanced"
-msgstr "Gelişmiş"
+msgstr ""
#: src/libaudgui/prefs-window.cc:92 src/libaudqt/prefs-pluginlist-model.cc:37
msgid "General"
@@ -974,7 +972,7 @@ msgstr "Çözüldüğü gibi"
#: src/libaudgui/prefs-window.cc:141 src/libaudqt/prefs-window-qt.cc:186
msgid "After applying ReplayGain"
-msgstr "ReplayGain'i uyguladıktan sonra"
+msgstr ""
#: src/libaudgui/prefs-window.cc:142 src/libaudqt/prefs-window-qt.cc:187
msgid "After applying effects"
@@ -986,11 +984,11 @@ msgstr "Dengeleme uygulandıktan sonra"
#: src/libaudgui/prefs-window.cc:149 src/libaudqt/prefs-window-qt.cc:194
msgid "Based on shuffle"
-msgstr "Karıştırmaya dayalı"
+msgstr ""
#: src/libaudgui/prefs-window.cc:161 src/libaudqt/prefs-window-qt.cc:206
msgid "Interface:"
-msgstr "Arayüz:"
+msgstr ""
#: src/libaudgui/prefs-window.cc:180 src/libaudqt/prefs-window-qt.cc:216
msgid "Output plugin:"
@@ -1044,7 +1042,7 @@ msgstr "Akışı kaydet:"
#: src/libaudgui/prefs-window.cc:229 src/libaudqt/prefs-window-qt.cc:259
msgid "<b>ReplayGain</b>"
-msgstr "<b>ReplayGain</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:230 src/libaudqt/prefs-window-qt.cc:260
msgid "Enable ReplayGain"
@@ -1052,7 +1050,7 @@ msgstr "ReplayGain'i etkinleştir"
#: src/libaudgui/prefs-window.cc:232 src/libaudqt/prefs-window-qt.cc:262
msgid "Mode:"
-msgstr "Mod:"
+msgstr ""
#: src/libaudgui/prefs-window.cc:236 src/libaudqt/prefs-window-qt.cc:266
msgid "Prevent clipping (recommended)"
@@ -1144,11 +1142,11 @@ msgstr "Saatleri ayrı ayrı göster (1:30:00'a karşı 90:00)"
#: src/libaudgui/prefs-window.cc:306 src/libaudqt/prefs-window-qt.cc:336
msgid "<b>Export</b>"
-msgstr "<b>Dışa1Dışa aktar</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:307 src/libaudqt/prefs-window-qt.cc:337
msgid "Use relative paths when possible"
-msgstr "Mümkün olduğunda göreli yollar kullanın"
+msgstr ""
#: src/libaudgui/prefs-window.cc:312 src/libaudqt/prefs-window-qt.cc:342
msgid "<b>Album Art</b>"
@@ -1200,15 +1198,15 @@ msgstr "Geriye yatık taksimi ( \\ ) klasör sınırlayıcı olarak yorumla"
#: src/libaudgui/prefs-window.cc:342 src/libaudqt/prefs-window-qt.cc:372
msgid "<b>Playlist</b>"
-msgstr "<b>Oynatma Liistesi</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:343 src/libaudqt/prefs-window-qt.cc:373
msgid "Add folders recursively"
-msgstr "Dizinleri tekrarlı olarak ekle"
+msgstr ""
#: src/libaudgui/prefs-window.cc:345 src/libaudqt/prefs-window-qt.cc:375
msgid "Add folders nested within playlist files"
-msgstr "Oynatma listesi dosyalarında yuvalanmış dizinler ekle"
+msgstr ""
#: src/libaudgui/prefs-window.cc:347 src/libaudqt/prefs-window-qt.cc:377
msgid "<b>Metadata</b>"
@@ -1277,7 +1275,7 @@ msgstr "Özel metin:"
#: src/libaudgui/prefs-window.cc:756 src/libaudqt/prefs-window-qt.cc:719
#, c-format
msgid "Enable audio stream recording with %s"
-msgstr "%s ile ses akışı kaydını etkinleştir "
+msgstr ""
#: src/libaudgui/prefs-window.cc:765 src/libaudqt/prefs-window-qt.cc:730
msgid "No audio recording plugin available"
@@ -1313,7 +1311,7 @@ msgstr "Önayar Dosyasını Kaydet"
#: src/libaudgui/preset-browser.cc:109
msgid "<name>.preset"
-msgstr "<name>.preset"
+msgstr ""
#: src/libaudgui/preset-browser.cc:127
msgid "Save EQF File"
@@ -1321,7 +1319,7 @@ msgstr "EQF Dosyasını Kaydet"
#: src/libaudgui/preset-browser.cc:127
msgid "<name>.eqf"
-msgstr "<name>.eqf"
+msgstr ""
#: src/libaudgui/preset-browser.cc:141
msgid "Import Winamp Presets"
@@ -1349,7 +1347,7 @@ msgstr "Bilgi"
#: src/libaudgui/url-opener.cc:55 src/libaudqt/url-opener-qt.cc:39
msgid "_Save to history"
-msgstr "_Geçmişe kaydet"
+msgstr ""
#: src/libaudgui/url-opener.cc:63 src/libaudqt/url-opener-qt.cc:47
msgid "Open URL"
@@ -1361,7 +1359,7 @@ msgstr "URL Ekle"
#: src/libaudgui/url-opener.cc:92 src/libaudqt/url-opener-qt.cc:68
msgid "C_lear history"
-msgstr "Geçmişi temiz_le"
+msgstr ""
#: src/libaudgui/url-opener.cc:104 src/libaudqt/url-opener-qt.cc:62
msgid "Enter URL:"
@@ -1450,7 +1448,7 @@ msgstr "Uyarı"
#: src/libaudqt/log-inspector.cc:219
msgid "Cl_ear"
-msgstr "Temizl_e"
+msgstr ""
#: src/libaudqt/log-inspector.cc:232
msgid "Log Level:"
diff --git a/po/uk.po b/po/uk.po
index 8fff92c..ff9af36 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -16,15 +16,15 @@
# Rustam Tsurik <rustam.tsurik@gmail.com>, 2013
# Rustam Tsurik <rustam.tsurik@gmail.com>, 2013
# Oleg <kvantarium@gmail.com>, 2012
-# Taras Holyj, 2017-2018
+# Taras Shevchenko, 2017
# Yaroslav Yenkala <hyper-news@yandex.ru>, 2016
msgid ""
msgstr ""
"Project-Id-Version: Audacious\n"
"Report-Msgid-Bugs-To: https://redmine.audacious-media-player.org/\n"
"POT-Creation-Date: 2018-08-04 20:34+0200\n"
-"PO-Revision-Date: 2018-12-26 05:38+0000\n"
-"Last-Translator: Taras Holyj\n"
+"PO-Revision-Date: 2018-07-02 04:50+0000\n"
+"Last-Translator: Rax Garfield <admin@dvizho.ks.ua>\n"
"Language-Team: Ukrainian (http://www.transifex.com/audacious/audacious/"
"language/uk/)\n"
"Language: uk\n"
@@ -98,7 +98,7 @@ msgstr "Виводити налагоджувальні повідомлення
#: src/audacious/main.cc:81
msgid "Run in Qt mode"
-msgstr "Запуск у режимі Qt"
+msgstr "Запуск в режимі Qt"
#: src/audacious/main.cc:138
#, c-format
@@ -154,12 +154,12 @@ msgstr "Новий список відтворення"
#: src/libaudcore/audstrings.cc:659 src/libaudcore/tuple.cc:520
msgid "Standard input"
-msgstr "Стандартний ввід"
+msgstr "Стандартний вхід"
#: src/libaudcore/audstrings.cc:661
#, c-format
msgid "Audio CD, track %s"
-msgstr "Авдіодиск, стежка %s"
+msgstr "Аудіодиск, доріжка %s"
#: src/libaudcore/audstrings.cc:665 src/libaudcore/tuple.cc:496
msgid "(character encoding error)"
@@ -189,7 +189,7 @@ msgstr ""
#: src/libaudcore/playback.cc:505
msgid "Invalid audio format"
-msgstr "Хибний авдіоформат"
+msgstr "Хибний формат аудіо"
#: src/libaudcore/playlist.cc:89
msgid "Now Playing"
@@ -222,7 +222,7 @@ msgstr "Неможливо зберегти %s: непідтримуване р
#: src/libaudcore/probe.cc:54
msgid "Error loading plugin"
-msgstr "Помилка завантаження втулку"
+msgstr "Помилка завантаження модуля"
#: src/libaudcore/probe.cc:171
msgid "Seek error"
@@ -255,12 +255,12 @@ msgstr[3] "%d каналів"
#: src/libaudcore/tuple.cc:768
msgid "Audio CD"
-msgstr "Авдіодиск"
+msgstr "Аудіодиск"
#: src/libaudcore/tuple.cc:850
#, c-format
msgid "Track %d"
-msgstr "Стежка %d"
+msgstr "Доріжка %d"
#: src/libaudcore/tuple.cc:855
msgid "(unknown title)"
@@ -268,7 +268,7 @@ msgstr "(невідома назва)"
#: src/libaudcore/vfs.cc:79
msgid "Unknown URI scheme"
-msgstr "Невідома схема ланки"
+msgstr "Невідома схема посилання"
#: src/libaudcore/vfs_local.cc:85 src/libaudcore/vfs_local.cc:330
#: src/libaudcore/vfs_local.cc:385
@@ -307,15 +307,15 @@ msgstr "_Більше не питати"
#: src/libaudgui/confirm.cc:70 src/libaudqt/playlist-management.cc:79
#, c-format
msgid "Do you want to permanently remove “%s”?"
-msgstr "Чи ви хочете усунути “%s”?"
+msgstr "Ви хочете видалити “%s”?"
#: src/libaudgui/confirm.cc:73 src/libaudqt/playlist-management.cc:74
msgid "_Remove"
-msgstr "_Усунути"
+msgstr "_Видалити"
#: src/libaudgui/confirm.cc:76 src/libaudqt/playlist-management.cc:78
msgid "Remove Playlist"
-msgstr "Усунення списку відтворення"
+msgstr "Видалення списку відтворення"
#: src/libaudgui/confirm.cc:95 src/libaudqt/playlist-management.cc:40
msgid "What would you like to call this playlist?"
@@ -323,19 +323,19 @@ msgstr "Як би Ви хотіли назвати цей список відт
#: src/libaudgui/confirm.cc:96 src/libaudqt/playlist-management.cc:42
msgid "_Rename"
-msgstr "_Змінити назву"
+msgstr "_Перейменувати"
#: src/libaudgui/confirm.cc:97 src/libaudqt/playlist-management.cc:62
msgid "Rename Playlist"
-msgstr "Зміна назви списку відтворення"
+msgstr "Перейменування списку відтворення"
#: src/libaudgui/eq-preset.cc:208 src/libaudgui/eq-preset.cc:215
msgid "Preset File ..."
-msgstr "Файл пресетів ..."
+msgstr "Файл налаштувань ..."
#: src/libaudgui/eq-preset.cc:209 src/libaudgui/eq-preset.cc:216
msgid "EQF File ..."
-msgstr "Файл налаштувань еквалайзеру ..."
+msgstr "Файл налаштувань еквалайзера ..."
#: src/libaudgui/eq-preset.cc:211
msgid "Winamp Presets ..."
@@ -343,15 +343,15 @@ msgstr "Файл налаштувань Winamp ..."
#: src/libaudgui/eq-preset.cc:220 src/libaudqt/fileopener.cc:70
msgid "Import"
-msgstr "Імпортування"
+msgstr "Імпорт"
#: src/libaudgui/eq-preset.cc:221 src/libaudqt/fileopener.cc:71
msgid "Export"
-msgstr "Експортування"
+msgstr "Експорт"
#: src/libaudgui/eq-preset.cc:236
msgid "Equalizer Presets"
-msgstr "Налаштування еквалайзеру"
+msgstr "Налаштування еквалайзера"
#: src/libaudgui/eq-preset.cc:258
msgid "Save Preset"
@@ -423,7 +423,9 @@ msgstr "Скинути на нуль"
#: src/libaudgui/equalizer.cc:154 src/libaudqt/equalizer-qt.cc:123
msgid "Preamp"
-msgstr "Попереднє підсилення"
+msgstr ""
+"Попереднє\n"
+"підсилення"
#: src/libaudgui/file-opener.cc:78 src/libaudqt/fileopener.cc:57
msgid "Open Files"
@@ -484,7 +486,7 @@ msgstr "Альбом"
#: src/libaudgui/prefs-window.cc:106 src/libaudqt/infopopup-qt.cc:122
#: src/libaudqt/info-widget.cc:45 src/libaudqt/prefs-window-qt.cc:151
msgid "Genre"
-msgstr "Напрямок"
+msgstr "Жанр"
#: src/libaudgui/infopopup.cc:209 src/libaudgui/infowin.cc:370
#: src/libaudgui/prefs-window.cc:110 src/libaudqt/infopopup-qt.cc:124
@@ -495,7 +497,7 @@ msgstr "Рік"
#: src/libaudgui/infopopup.cc:210 src/libaudgui/prefs-window.cc:147
#: src/libaudqt/infopopup-qt.cc:126 src/libaudqt/prefs-window-qt.cc:192
msgid "Track"
-msgstr "Стежка"
+msgstr "Доріжка"
#: src/libaudgui/infopopup.cc:211 src/libaudqt/infopopup-qt.cc:128
#: src/libaudqt/info-widget.cc:55
@@ -516,159 +518,159 @@ msgstr "Бітрейт:"
#: src/libaudgui/infowin.cc:86
msgid "Acid Jazz"
-msgstr "Ейсид-джаз"
+msgstr "Acid Jazz"
#: src/libaudgui/infowin.cc:87
msgid "Acid Rock"
-msgstr "Ейсид-рок"
+msgstr "Acid Rock"
#: src/libaudgui/infowin.cc:88
msgid "Ambient"
-msgstr "Ембієнт"
+msgstr "Ambient"
#: src/libaudgui/infowin.cc:89
msgid "Bebop"
-msgstr "Бібоп"
+msgstr "Bebop"
#: src/libaudgui/infowin.cc:90
msgid "Bluegrass"
-msgstr "Блуґрас"
+msgstr "Bluegrass"
#: src/libaudgui/infowin.cc:91
msgid "Blues"
-msgstr "Блюз"
+msgstr "Blues"
#: src/libaudgui/infowin.cc:92
msgid "Chamber Music"
-msgstr "Камерна музика"
+msgstr "Chamber Music"
#: src/libaudgui/infowin.cc:93
msgid "Classical"
-msgstr "Класична музика"
+msgstr "Classical"
#: src/libaudgui/infowin.cc:94
msgid "Country"
-msgstr "Кантрі"
+msgstr "Country"
#: src/libaudgui/infowin.cc:95
msgid "Death Metal"
-msgstr "Дет-метал"
+msgstr "Death Metal"
#: src/libaudgui/infowin.cc:96
msgid "Disco"
-msgstr "Диско"
+msgstr "Disco"
#: src/libaudgui/infowin.cc:97
msgid "Easy Listening"
-msgstr "Легка музика"
+msgstr "Easy Listening"
#: src/libaudgui/infowin.cc:98
msgid "Folk"
-msgstr "Народна музика"
+msgstr "Folk"
#: src/libaudgui/infowin.cc:99
msgid "Funk"
-msgstr "Фанк"
+msgstr "Funk"
#: src/libaudgui/infowin.cc:100
msgid "Gangsta Rap"
-msgstr "Ґанґста-реп"
+msgstr "Gangsta Rap"
#: src/libaudgui/infowin.cc:101
msgid "Gospel"
-msgstr "Ґоспел"
+msgstr "Gospel"
#: src/libaudgui/infowin.cc:102
msgid "Grunge"
-msgstr "Ґрандж"
+msgstr "Grunge"
#: src/libaudgui/infowin.cc:103
msgid "Hard Rock"
-msgstr "Гардрок"
+msgstr "Hard Rock"
#: src/libaudgui/infowin.cc:104
msgid "Heavy Metal"
-msgstr "Гевіметал "
+msgstr "Heavy Metal"
#: src/libaudgui/infowin.cc:105
msgid "Hip-hop"
-msgstr "Гіп-гоп"
+msgstr "Hip-hop"
#: src/libaudgui/infowin.cc:106
msgid "House"
-msgstr "Гавз"
+msgstr "House"
#: src/libaudgui/infowin.cc:107
msgid "Jazz"
-msgstr "Джаз"
+msgstr "Jazz"
#: src/libaudgui/infowin.cc:108
msgid "Jungle"
-msgstr "Джанґл"
+msgstr "Jungle"
#: src/libaudgui/infowin.cc:109
msgid "Metal"
-msgstr "Метал"
+msgstr "Metal"
#: src/libaudgui/infowin.cc:110
msgid "New Age"
-msgstr "Ню-ейдж"
+msgstr "New Age"
#: src/libaudgui/infowin.cc:111
msgid "New Wave"
-msgstr "Нова хвиля"
+msgstr "New Wave"
#: src/libaudgui/infowin.cc:112
msgid "Noise"
-msgstr "Нойз"
+msgstr "Noise"
#: src/libaudgui/infowin.cc:113
msgid "Pop"
-msgstr "Поп-музика"
+msgstr "Pop"
#: src/libaudgui/infowin.cc:114
msgid "Punk Rock"
-msgstr "Панк-рок"
+msgstr "Punk Rock"
#: src/libaudgui/infowin.cc:115
msgid "Rap"
-msgstr "Реп"
+msgstr "Rap"
#: src/libaudgui/infowin.cc:116
msgid "Reggae"
-msgstr "Реґей"
+msgstr "Reggae"
#: src/libaudgui/infowin.cc:117
msgid "Rock"
-msgstr "Рок"
+msgstr "Rock"
#: src/libaudgui/infowin.cc:118
msgid "Rock and Roll"
-msgstr "Рок-н-рол"
+msgstr "Rock and Roll"
#: src/libaudgui/infowin.cc:119
msgid "Rhythm and Blues"
-msgstr "Ритм-енд-блюз"
+msgstr "Rhythm and Blues"
#: src/libaudgui/infowin.cc:120
msgid "Ska"
-msgstr "Ска"
+msgstr "Ska"
#: src/libaudgui/infowin.cc:121
msgid "Soul"
-msgstr "Совл"
+msgstr "Soul"
#: src/libaudgui/infowin.cc:122
msgid "Swing"
-msgstr "Свінг"
+msgstr "Swing"
#: src/libaudgui/infowin.cc:123
msgid "Techno"
-msgstr "Техно"
+msgstr "Techno"
#: src/libaudgui/infowin.cc:124
msgid "Trip-hop"
-msgstr "Трип-гоп"
+msgstr "Trip-hop"
#: src/libaudgui/infowin.cc:217
msgid "Save successful"
@@ -694,7 +696,7 @@ msgstr "Коментар"
#: src/libaudgui/infowin.cc:373 src/libaudqt/info-widget.cc:44
msgid "Track Number"
-msgstr "Номер стежки"
+msgstr "Номер пісні"
#: src/libaudgui/infowin.cc:380
msgid "Clea_r fields when moving to next song"
@@ -736,7 +738,7 @@ msgstr "_Додати до черги"
#: src/libaudgui/jump-to-track.cc:101
msgid "Un_queue"
-msgstr "В_илучити з черги"
+msgstr "В_илучити із черги"
#: src/libaudgui/jump-to-track.cc:240
msgid "Jump to Song"
@@ -794,7 +796,7 @@ msgstr "_Імпортувати"
#: src/libaudgui/plugin-menu.cc:40 src/libaudqt/plugin-menu-qt.cc:45
msgid "_Plugins ..."
-msgstr "_Втулки ..."
+msgstr "_Модулі ..."
#: src/libaudgui/plugin-prefs.cc:109 src/libaudqt/prefs-plugin.cc:56
#, c-format
@@ -850,11 +852,11 @@ msgstr "Списки відтворення"
#: src/libaudgui/prefs-window.cc:87 src/libaudqt/prefs-window-qt.cc:141
msgid "Plugins"
-msgstr "Втулки"
+msgstr "Модулі"
#: src/libaudgui/prefs-window.cc:88 src/libaudqt/prefs-window-qt.cc:142
msgid "Advanced"
-msgstr "Розширені"
+msgstr ""
#: src/libaudgui/prefs-window.cc:92 src/libaudqt/prefs-pluginlist-model.cc:37
msgid "General"
@@ -870,7 +872,7 @@ msgstr "Візуалізація"
#: src/libaudgui/prefs-window.cc:95 src/libaudqt/prefs-pluginlist-model.cc:40
msgid "Input"
-msgstr "Ввід"
+msgstr "Вхід"
#: src/libaudgui/prefs-window.cc:97 src/libaudqt/prefs-pluginlist-model.cc:42
msgid "Transport"
@@ -882,15 +884,15 @@ msgstr "Виконавець альбому"
#: src/libaudgui/prefs-window.cc:105 src/libaudqt/prefs-window-qt.cc:150
msgid "Track number"
-msgstr "Номер стежки"
+msgstr "Номер доріжки"
#: src/libaudgui/prefs-window.cc:107 src/libaudqt/prefs-window-qt.cc:152
msgid "File name"
-msgstr "Назва файлу"
+msgstr "Ім’я файлу"
#: src/libaudgui/prefs-window.cc:108 src/libaudqt/prefs-window-qt.cc:153
msgid "File path"
-msgstr "Шлях до файлу"
+msgstr "Путь до файлу"
#: src/libaudgui/prefs-window.cc:109 src/libaudqt/prefs-window-qt.cc:154
msgid "Date"
@@ -988,7 +990,7 @@ msgstr "Вигляд:"
#: src/libaudgui/prefs-window.cc:180 src/libaudqt/prefs-window-qt.cc:216
msgid "Output plugin:"
-msgstr "Втулок виведення:"
+msgstr "Модуль виведення:"
#: src/libaudgui/prefs-window.cc:201 src/libaudqt/prefs-window-qt.cc:231
msgid "Amplify all files:"
@@ -1001,7 +1003,7 @@ msgstr "дБ"
#: src/libaudgui/prefs-window.cc:204 src/libaudqt/prefs-window-qt.cc:234
msgid "Amplify untagged files:"
-msgstr "Підсилювати непомічені файли:"
+msgstr "Підсилювати непозначені файли:"
#: src/libaudgui/prefs-window.cc:210 src/libaudqt/prefs-window-qt.cc:240
msgid "<b>Output Settings</b>"
@@ -1014,7 +1016,7 @@ msgstr "Амплітудна розрядність:"
#: src/libaudgui/prefs-window.cc:215 src/libaudgui/prefs-window.cc:260
#: src/libaudqt/prefs-window-qt.cc:245 src/libaudqt/prefs-window-qt.cc:290
msgid "Buffer size:"
-msgstr "Розмір буферу:"
+msgstr "Розмір буфера:"
#: src/libaudgui/prefs-window.cc:217 src/libaudqt/prefs-window-qt.cc:247
msgid "ms"
@@ -1054,7 +1056,7 @@ msgstr "Запобігати відсіканню (рекомендовано)"
#: src/libaudgui/prefs-window.cc:244 src/libaudqt/prefs-window-qt.cc:274
msgid "Proxy hostname:"
-msgstr "Адреса проксі-серверу:"
+msgstr "Адреса проксі-сервера:"
#: src/libaudgui/prefs-window.cc:246 src/libaudqt/prefs-window-qt.cc:276
msgid "Proxy port:"
@@ -1066,7 +1068,7 @@ msgstr "Ім'я користувача:"
#: src/libaudgui/prefs-window.cc:253 src/libaudqt/prefs-window-qt.cc:283
msgid "Proxy password:"
-msgstr "Гасло:"
+msgstr "Пароль:"
#: src/libaudgui/prefs-window.cc:259 src/libaudqt/prefs-window-qt.cc:289
msgid "<b>Network Settings</b>"
@@ -1138,11 +1140,11 @@ msgstr "Показувати розряд годин (1:30:00 замість 90:
#: src/libaudgui/prefs-window.cc:306 src/libaudqt/prefs-window-qt.cc:336
msgid "<b>Export</b>"
-msgstr "<b>Експортування</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:307 src/libaudqt/prefs-window-qt.cc:337
msgid "Use relative paths when possible"
-msgstr "За можливістю використовувати схожі шляхи"
+msgstr ""
#: src/libaudgui/prefs-window.cc:312 src/libaudqt/prefs-window-qt.cc:342
msgid "<b>Album Art</b>"
@@ -1194,15 +1196,15 @@ msgstr "Вважати \\ (обернену косу риску) розділю
#: src/libaudgui/prefs-window.cc:342 src/libaudqt/prefs-window-qt.cc:372
msgid "<b>Playlist</b>"
-msgstr "<b>Список відтворення</b>"
+msgstr ""
#: src/libaudgui/prefs-window.cc:343 src/libaudqt/prefs-window-qt.cc:373
msgid "Add folders recursively"
-msgstr "Додавати теки рекурсивно"
+msgstr ""
#: src/libaudgui/prefs-window.cc:345 src/libaudqt/prefs-window-qt.cc:375
msgid "Add folders nested within playlist files"
-msgstr "Додати теки, які вкладені поміж списків відтворення"
+msgstr ""
#: src/libaudgui/prefs-window.cc:347 src/libaudqt/prefs-window-qt.cc:377
msgid "<b>Metadata</b>"
@@ -1218,7 +1220,7 @@ msgstr "Не завантажувати метадані доріжок до в
#: src/libaudgui/prefs-window.cc:352 src/libaudqt/prefs-window-qt.cc:382
msgid "Probe content of files with no recognized file name extension"
-msgstr "Сканувати вміст файлів з невпізнаним розширенням"
+msgstr "Сканувати вміст файлу із невпізнаним розширенням"
#: src/libaudgui/prefs-window.cc:370 src/libaudqt/prefs-window-qt.cc:400
msgid "TITLE"
@@ -1242,11 +1244,11 @@ msgstr "ВИКОНАВЕЦЬ - АЛЬБОМ - НАЗВА"
#: src/libaudgui/prefs-window.cc:375 src/libaudqt/prefs-window-qt.cc:405
msgid "ARTIST - ALBUM - TRACK. TITLE"
-msgstr "ВИКОНАВЕЦЬ - АЛЬБОМ - СТЕЖКА. НАЗВА"
+msgstr "ВИКОНАВЕЦЬ - АЛЬБОМ - ДОРІЖКА. НАЗВА"
#: src/libaudgui/prefs-window.cc:376 src/libaudqt/prefs-window-qt.cc:406
msgid "ARTIST [ ALBUM ] - TRACK. TITLE"
-msgstr "ВИКОНАВЕЦЬ [ АЛЬБОМ ] СТЕЖКА. НАЗВА"
+msgstr "ВИКОНАВЕЦЬ [ АЛЬБОМ ] ДОРІЖКА. НАЗВА"
#: src/libaudgui/prefs-window.cc:377 src/libaudqt/prefs-window-qt.cc:407
msgid "ALBUM - TITLE"
@@ -1275,7 +1277,7 @@ msgstr "Увімкнено записування потоку з %s"
#: src/libaudgui/prefs-window.cc:765 src/libaudqt/prefs-window-qt.cc:730
msgid "No audio recording plugin available"
-msgstr "Немає втулків для запису авдіо"
+msgstr "Немає модулів для запису аудіо"
#: src/libaudgui/prefs-window.cc:825 src/libaudqt/prefs-window-qt.cc:607
msgid "Audacious Settings"
@@ -1299,7 +1301,7 @@ msgstr "Завантажити файл налаштувань"
#: src/libaudgui/preset-browser.cc:94
msgid "Load EQF File"
-msgstr "Завантажити файл налаштувань еквалайзеру"
+msgstr "Завантажити файл налаштувань еквалайзера"
#: src/libaudgui/preset-browser.cc:109
msgid "Save Preset File"
@@ -1307,15 +1309,15 @@ msgstr "Зберегти файл налаштувань"
#: src/libaudgui/preset-browser.cc:109
msgid "<name>.preset"
-msgstr "<name>.пресет"
+msgstr "<ім'я>.preset"
#: src/libaudgui/preset-browser.cc:127
msgid "Save EQF File"
-msgstr "Зберегти файл налаштувань еквалайзеру"
+msgstr "Зберегти файл налаштувань еквалайзера"
#: src/libaudgui/preset-browser.cc:127
msgid "<name>.eqf"
-msgstr "<name>.eqf"
+msgstr "<>.eqf"
#: src/libaudgui/preset-browser.cc:141
msgid "Import Winamp Presets"
@@ -1343,7 +1345,7 @@ msgstr "Інформація"
#: src/libaudgui/url-opener.cc:55 src/libaudqt/url-opener-qt.cc:39
msgid "_Save to history"
-msgstr "_Зберегти до історії"
+msgstr ""
#: src/libaudgui/url-opener.cc:63 src/libaudqt/url-opener-qt.cc:47
msgid "Open URL"
@@ -1355,7 +1357,7 @@ msgstr "Додати адресу"
#: src/libaudgui/url-opener.cc:92 src/libaudqt/url-opener-qt.cc:68
msgid "C_lear history"
-msgstr "О_чистити історію"
+msgstr ""
#: src/libaudgui/url-opener.cc:104 src/libaudqt/url-opener-qt.cc:62
msgid "Enter URL:"
@@ -1459,4 +1461,4 @@ msgid "Copy"
msgstr "Копіювати"
#~ msgid "Plugins ..."
-#~ msgstr "Втулки ..."
+#~ msgstr "Модулі ..."
diff --git a/src/audacious/Makefile b/src/audacious/Makefile
index e4678ba..79e86cd 100644
--- a/src/audacious/Makefile
+++ b/src/audacious/Makefile
@@ -28,7 +28,9 @@ CPPFLAGS := -I.. -I../.. \
${CPPFLAGS} \
${GLIB_CFLAGS}
-LIBS := -L../libaudcore -laudcore \
+LDFLAGS := -L../libaudcore $(LDFLAGS)
+
+LIBS := -laudcore \
${LIBS} -lm \
${LIBINTL} \
${GLIB_LIBS}
diff --git a/src/audacious/dbus-server.cc b/src/audacious/dbus-server.cc
index 20a6c58..10f3bba 100644
--- a/src/audacious/dbus-server.cc
+++ b/src/audacious/dbus-server.cc
@@ -86,14 +86,21 @@ static gboolean do_add_url (Obj * obj, Invoc * invoc, const char * url)
static gboolean do_advance (Obj * obj, Invoc * invoc)
{
- CURRENT.next_song (aud_get_bool (nullptr, "repeat"));
+ CURRENT.next_song (aud_get_bool ("repeat"));
FINISH (advance);
return true;
}
+static gboolean do_advance_album (Obj * obj, Invoc * invoc)
+{
+ CURRENT.next_album (aud_get_bool ("repeat"));
+ FINISH (advance_album);
+ return true;
+}
+
static gboolean do_auto_advance (Obj * obj, Invoc * invoc)
{
- FINISH2 (auto_advance, ! aud_get_bool (nullptr, "no_playlist_advance"));
+ FINISH2 (auto_advance, ! aud_get_bool ("no_playlist_advance"));
return true;
}
@@ -150,7 +157,7 @@ static gboolean do_eject (Obj * obj, Invoc * invoc)
static gboolean do_equalizer_activate (Obj * obj, Invoc * invoc, gboolean active)
{
- aud_set_bool (nullptr, "equalizer_active", active);
+ aud_set_bool ("equalizer_active", active);
FINISH (equalizer_activate);
return true;
}
@@ -170,7 +177,7 @@ static gboolean do_get_active_playlist_name (Obj * obj, Invoc * invoc)
static gboolean do_get_eq (Obj * obj, Invoc * invoc)
{
- double preamp = aud_get_double (nullptr, "equalizer_preamp");
+ double preamp = aud_get_double ("equalizer_preamp");
double bands[AUD_EQ_NBANDS];
aud_eq_get_bands (bands);
@@ -188,7 +195,7 @@ static gboolean do_get_eq_band (Obj * obj, Invoc * invoc, int band)
static gboolean do_get_eq_preamp (Obj * obj, Invoc * invoc)
{
- FINISH2 (get_eq_preamp, aud_get_double (nullptr, "equalizer_preamp"));
+ FINISH2 (get_eq_preamp, aud_get_double ("equalizer_preamp"));
return true;
}
@@ -423,7 +430,7 @@ static gboolean do_quit (Obj * obj, Invoc * invoc)
static gboolean do_record (Obj * obj, Invoc * invoc)
{
if (aud_drct_get_record_enabled ())
- aud_set_bool (nullptr, "record", ! aud_get_bool (nullptr, "record"));
+ aud_set_bool ("record", ! aud_get_bool ("record"));
FINISH (record);
return true;
@@ -433,7 +440,7 @@ static gboolean do_recording (Obj * obj, Invoc * invoc)
{
bool recording = false;
if (aud_drct_get_record_enabled ())
- recording = aud_get_bool (nullptr, "record");
+ recording = aud_get_bool ("record");
FINISH2 (recording, recording);
return true;
@@ -441,7 +448,7 @@ static gboolean do_recording (Obj * obj, Invoc * invoc)
static gboolean do_repeat (Obj * obj, Invoc * invoc)
{
- FINISH2 (repeat, aud_get_bool (nullptr, "repeat"));
+ FINISH2 (repeat, aud_get_bool ("repeat"));
return true;
}
@@ -452,6 +459,13 @@ static gboolean do_reverse (Obj * obj, Invoc * invoc)
return true;
}
+static gboolean do_reverse_album (Obj * obj, Invoc * invoc)
+{
+ CURRENT.prev_album ();
+ FINISH (reverse_album);
+ return true;
+}
+
static gboolean do_seek (Obj * obj, Invoc * invoc, unsigned pos)
{
aud_drct_seek (pos);
@@ -504,7 +518,7 @@ static gboolean do_set_eq (Obj * obj, Invoc * invoc, double preamp, GVariant * v
if (nbands != AUD_EQ_NBANDS)
return false;
- aud_set_double (nullptr, "equalizer_preamp", preamp);
+ aud_set_double ("equalizer_preamp", preamp);
aud_eq_set_bands (bands);
FINISH (set_eq);
return true;
@@ -519,7 +533,7 @@ static gboolean do_set_eq_band (Obj * obj, Invoc * invoc, int band, double value
static gboolean do_set_eq_preamp (Obj * obj, Invoc * invoc, double preamp)
{
- aud_set_double (nullptr, "equalizer_preamp", preamp);
+ aud_set_double ("equalizer_preamp", preamp);
FINISH (set_eq_preamp);
return true;
}
@@ -598,7 +612,7 @@ static gboolean do_show_prefs_box (Obj * obj, Invoc * invoc, gboolean show)
static gboolean do_shuffle (Obj * obj, Invoc * invoc)
{
- FINISH2 (shuffle, aud_get_bool (nullptr, "shuffle"));
+ FINISH2 (shuffle, aud_get_bool ("shuffle"));
return true;
}
@@ -689,7 +703,7 @@ static gboolean do_stop (Obj * obj, Invoc * invoc)
static gboolean do_stop_after (Obj * obj, Invoc * invoc)
{
- FINISH2 (stop_after, aud_get_bool (nullptr, "stop_after_current_song"));
+ FINISH2 (stop_after, aud_get_bool ("stop_after_current_song"));
return true;
}
@@ -707,28 +721,28 @@ static gboolean do_time (Obj * obj, Invoc * invoc)
static gboolean do_toggle_auto_advance (Obj * obj, Invoc * invoc)
{
- aud_toggle_bool (nullptr, "no_playlist_advance");
+ aud_toggle_bool ("no_playlist_advance");
FINISH (toggle_auto_advance);
return true;
}
static gboolean do_toggle_repeat (Obj * obj, Invoc * invoc)
{
- aud_toggle_bool (nullptr, "repeat");
+ aud_toggle_bool ("repeat");
FINISH (toggle_repeat);
return true;
}
static gboolean do_toggle_shuffle (Obj * obj, Invoc * invoc)
{
- aud_toggle_bool (nullptr, "shuffle");
+ aud_toggle_bool ("shuffle");
FINISH (toggle_shuffle);
return true;
}
static gboolean do_toggle_stop_after (Obj * obj, Invoc * invoc)
{
- aud_toggle_bool (nullptr, "stop_after_current_song");
+ aud_toggle_bool ("stop_after_current_song");
FINISH (toggle_stop_after);
return true;
}
@@ -757,6 +771,7 @@ handlers[] =
{"handle-add-list", (GCallback) do_add_list},
{"handle-add-url", (GCallback) do_add_url},
{"handle-advance", (GCallback) do_advance},
+ {"handle-advance-album", (GCallback) do_advance_album},
{"handle-auto-advance", (GCallback) do_auto_advance},
{"handle-balance", (GCallback) do_balance},
{"handle-clear", (GCallback) do_clear},
@@ -805,6 +820,7 @@ handlers[] =
{"handle-record", (GCallback) do_record},
{"handle-repeat", (GCallback) do_repeat},
{"handle-reverse", (GCallback) do_reverse},
+ {"handle-reverse-album", (GCallback) do_reverse_album},
{"handle-seek", (GCallback) do_seek},
{"handle-select-displayed-playlist", (GCallback) do_select_displayed_playlist},
{"handle-select-playing-playlist", (GCallback) do_select_playing_playlist},
diff --git a/src/audacious/main.cc b/src/audacious/main.cc
index 52ad234..1213a95 100644
--- a/src/audacious/main.cc
+++ b/src/audacious/main.cc
@@ -1,6 +1,6 @@
/*
* main.c
- * Copyright 2007-2013 William Pitcock and John Lindgren
+ * Copyright 2007-2013 Ariadne Conill and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -50,7 +50,7 @@ static struct {
int mainwin, show_jump_box;
int headless, quit_after_play;
int verbose;
- int qt;
+ int gtk;
} options;
static bool initted = false;
@@ -78,7 +78,7 @@ static const struct {
{"quit-after-play", 'q', & options.quit_after_play, N_("Quit on playback stop")},
{"verbose", 'V', & options.verbose, N_("Print debugging messages (may be used twice)")},
#if defined(USE_QT) && defined(USE_GTK)
- {"qt", 'Q', & options.qt, N_("Run in Qt mode")},
+ {"gtk", 'G', & options.gtk, N_("Run in GTK mode")},
#endif
};
@@ -171,8 +171,8 @@ static bool parse_options (int argc, char * * argv)
else if (options.verbose)
audlog::set_stderr_level (audlog::Info);
- if (options.qt)
- aud_set_mainloop_type (MainloopType::Qt);
+ if (options.gtk)
+ aud_set_mainloop_type (MainloopType::GLib);
return true;
}
@@ -199,9 +199,7 @@ static void do_remote ()
ObjAudacious * obj = nullptr;
GError * error = nullptr;
-#if ! GLIB_CHECK_VERSION (2, 36, 0)
g_type_init ();
-#endif
/* check whether the selected instance is running */
if (dbus_server_init () != StartupType::Client)
@@ -270,7 +268,7 @@ static void do_remote ()
static void do_commands ()
{
- bool resume = aud_get_bool (nullptr, "resume_playback_on_startup");
+ bool resume = aud_get_bool ("resume_playback_on_startup");
if (filenames.len ())
{
diff --git a/src/audacious/meson.build b/src/audacious/meson.build
new file mode 100644
index 0000000..d91ba79
--- /dev/null
+++ b/src/audacious/meson.build
@@ -0,0 +1,24 @@
+audacious_deps = [glib_dep]
+audacious_libs = [libaudcore_lib]
+
+audacious_sources = [
+ 'main.cc',
+ 'signals.cc',
+ 'util.cc'
+]
+
+
+if get_option('dbus')
+ audacious_sources += ['dbus-server.cc']
+ audacious_libs += [aud_dbus_lib]
+ audacious_deps += [aud_dbus_deps]
+endif
+
+
+audacious_exe = executable('audacious',
+ audacious_sources,
+ include_directories: [src_inc, aud_dbus_inc],
+ dependencies: audacious_deps,
+ link_with: audacious_libs,
+ install: true
+)
diff --git a/src/audacious/signals.cc b/src/audacious/signals.cc
index 35c1011..8ed1fec 100644
--- a/src/audacious/signals.cc
+++ b/src/audacious/signals.cc
@@ -19,23 +19,21 @@
#ifdef HAVE_SIGWAIT
-#include <pthread.h>
#include <signal.h>
#include <libaudcore/hook.h>
+#include <libaudcore/threads.h>
#include "main.h"
static sigset_t signal_set;
-static void * signal_thread (void * data)
+static void signal_thread ()
{
int signal;
while (! sigwait (& signal_set, & signal))
event_queue ("quit", nullptr);
-
- return nullptr;
}
/* Must be called before any threads are created. */
@@ -52,8 +50,7 @@ void signals_init_one ()
void signals_init_two ()
{
- pthread_t thread;
- pthread_create (& thread, nullptr, signal_thread, nullptr);
+ std::thread (signal_thread).detach ();
}
#endif /* HAVE_SIGWAIT */
diff --git a/src/audtool/audtool.h b/src/audtool/audtool.h
index b3aa711..7a1e3a9 100644
--- a/src/audtool/audtool.h
+++ b/src/audtool/audtool.h
@@ -1,6 +1,6 @@
/*
* audtool.h
- * Copyright 2005-2011 William Pitcock, George Averill, Giacomo Lozito,
+ * Copyright 2005-2011 Ariadne Conill, George Averill, Giacomo Lozito,
* Yoshiki Yazawa, Matti Hämäläinen, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
@@ -63,9 +63,11 @@ void select_displayed (int, char * *);
void select_playing (int, char * *);
void playlist_position (int, char * *);
void playlist_advance (int, char * *);
+void playlist_advance_album (int, char * *);
void playlist_auto_advance_status (int, char * *);
void playlist_auto_advance_toggle (int, char * *);
void playlist_reverse (int, char * *);
+void playlist_reverse_album (int, char * *);
void playlist_length (int, char * *);
void playlist_song (int, char * *);
void playlist_song_filename (int, char * *);
diff --git a/src/audtool/handlers_general.c b/src/audtool/handlers_general.c
index 886e7ac..d03c63b 100644
--- a/src/audtool/handlers_general.c
+++ b/src/audtool/handlers_general.c
@@ -1,6 +1,6 @@
/*
* handlers_general.c
- * Copyright 2005-2013 George Averill, William Pitcock, Giacomo Lozito,
+ * Copyright 2005-2013 George Averill, Ariadne Conill, Giacomo Lozito,
* Matti Hämäläinen, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
diff --git a/src/audtool/handlers_playback.c b/src/audtool/handlers_playback.c
index 8a812b7..c9ba722 100644
--- a/src/audtool/handlers_playback.c
+++ b/src/audtool/handlers_playback.c
@@ -1,6 +1,6 @@
/*
* handlers_playback.c
- * Copyright 2005-2013 George Averill, William Pitcock, Matti Hämäläinen, and
+ * Copyright 2005-2013 George Averill, Ariadne Conill, Matti Hämäläinen, and
* John Lindgren
*
* Redistribution and use in source and binary forms, with or without
diff --git a/src/audtool/handlers_playlist.c b/src/audtool/handlers_playlist.c
index e2362c9..e97d794 100644
--- a/src/audtool/handlers_playlist.c
+++ b/src/audtool/handlers_playlist.c
@@ -1,6 +1,6 @@
/*
* handlers_playlist.c
- * Copyright 2005-2013 George Averill, William Pitcock, Yoshiki Yazawa,
+ * Copyright 2005-2013 George Averill, Ariadne Conill, Yoshiki Yazawa,
* Matti Hämäläinen, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
@@ -39,11 +39,21 @@ void playlist_reverse (int argc, char * * argv)
obj_audacious_call_reverse_sync (dbus_proxy, NULL, NULL);
}
+void playlist_reverse_album (int argc, char * * argv)
+{
+ obj_audacious_call_reverse_album_sync (dbus_proxy, NULL, NULL);
+}
+
void playlist_advance (int argc, char * * argv)
{
obj_audacious_call_advance_sync (dbus_proxy, NULL, NULL);
}
+void playlist_advance_album (int argc, char * * argv)
+{
+ obj_audacious_call_advance_album_sync (dbus_proxy, NULL, NULL);
+}
+
void playlist_auto_advance_status (int argc, char * * argv)
{
gboolean advance = FALSE;
diff --git a/src/audtool/handlers_playqueue.c b/src/audtool/handlers_playqueue.c
index 1efdb37..56f5196 100644
--- a/src/audtool/handlers_playqueue.c
+++ b/src/audtool/handlers_playqueue.c
@@ -1,6 +1,6 @@
/*
* handlers_playqueue.c
- * Copyright 2005-2013 George Averill, William Pitcock, Yoshiki Yazawa,
+ * Copyright 2005-2013 George Averill, Ariadne Conill, Yoshiki Yazawa,
* Matti Hämäläinen, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
diff --git a/src/audtool/handlers_vitals.c b/src/audtool/handlers_vitals.c
index 68918dc..76f0eb3 100644
--- a/src/audtool/handlers_vitals.c
+++ b/src/audtool/handlers_vitals.c
@@ -1,6 +1,6 @@
/*
* handlers_vitals.c
- * Copyright 2005-2013 George Averill, William Pitcock, and John Lindgren
+ * Copyright 2005-2013 George Averill, Ariadne Conill, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
diff --git a/src/audtool/main.c b/src/audtool/main.c
index a09c6b8..5584ed3 100644
--- a/src/audtool/main.c
+++ b/src/audtool/main.c
@@ -1,6 +1,6 @@
/*
* main.c
- * Copyright 2005-2013 George Averill, William Pitcock, Yoshiki Yazawa, and
+ * Copyright 2005-2013 George Averill, Ariadne Conill, Yoshiki Yazawa, and
* John Lindgren
*
* Redistribution and use in source and binary forms, with or without
@@ -66,7 +66,9 @@ const struct commandhandler handlers[] =
{"select-displayed", select_displayed, "apply commands to displayed playlist", 0},
{"select-playing", select_playing, "apply commands to playing playlist", 0},
{"playlist-advance", playlist_advance, "skip to next song", 0},
+ {"playlist-advance-album", playlist_advance_album, "skip to next album", 0},
{"playlist-reverse", playlist_reverse, "skip to previous song", 0},
+ {"playlist-reverse-album", playlist_reverse_album, "skip to beginning of the previous album", 0},
{"playlist-addurl", playlist_add_url_string, "add URI at end of playlist", 1},
{"playlist-insurl", playlist_ins_url_string, "insert URI at given position", 2},
{"playlist-addurl-to-new-playlist", playlist_enqueue_to_temp, "open URI in \"Now Playing\" playlist", 1},
@@ -222,9 +224,7 @@ int main (int argc, char * * argv)
setlocale (LC_CTYPE, "");
-#if ! GLIB_CHECK_VERSION (2, 36, 0)
g_type_init();
-#endif
#ifdef _WIN32
g_set_print_handler (print_utf8);
diff --git a/src/audtool/meson.build b/src/audtool/meson.build
new file mode 100644
index 0000000..df7539f
--- /dev/null
+++ b/src/audtool/meson.build
@@ -0,0 +1,23 @@
+audtool_sources = [
+ 'main.c',
+ 'handlers_general.c',
+ 'handlers_playback.c',
+ 'handlers_playlist.c',
+ 'handlers_playqueue.c',
+ 'handlers_vitals.c',
+ 'handlers_equalizer.c',
+ 'report.c',
+ 'wrappers.c'
+]
+
+
+audtool_deps = aud_dbus_deps
+
+
+audtool_exe = executable('audtool',
+ audtool_sources,
+ link_with: aud_dbus_lib,
+ dependencies: audtool_deps,
+ include_directories: aud_dbus_inc,
+ install: true
+)
diff --git a/src/audtool/report.c b/src/audtool/report.c
index 2bc0298..0628756 100644
--- a/src/audtool/report.c
+++ b/src/audtool/report.c
@@ -1,6 +1,6 @@
/*
* report.c
- * Copyright 2007-2008 William Pitcock and Matti Hämäläinen
+ * Copyright 2007-2008 Ariadne Conill and Matti Hämäläinen
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
diff --git a/src/config.h.meson b/src/config.h.meson
new file mode 100644
index 0000000..51b89ff
--- /dev/null
+++ b/src/config.h.meson
@@ -0,0 +1,21 @@
+#mesondefine PACKAGE
+#mesondefine BUILDSTAMP
+#mesondefine VERSION
+#mesondefine COPYRIGHT
+#mesondefine EXPORT
+#mesondefine PLUGIN_SUFFIX
+
+#define PACKAGE_VERSION VERSION
+#define ICONV_CONST
+
+#mesondefine INSTALL_BINDIR
+#mesondefine INSTALL_DATADIR
+#mesondefine INSTALL_PLUGINDIR
+#mesondefine INSTALL_LOCALEDIR
+#mesondefine INSTALL_DESKTOPFILE
+#mesondefine INSTALL_ICONFILE
+
+#mesondefine USE_DBUS
+#mesondefine USE_QT
+
+#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_32
diff --git a/src/dbus/aud-dbus.xml b/src/dbus/aud-dbus.xml
index 960c910..b240d90 100644
--- a/src/dbus/aud-dbus.xml
+++ b/src/dbus/aud-dbus.xml
@@ -249,9 +249,15 @@
<!-- Skip ahead one song in the current playlist -->
<method name="Advance" />
+ <!-- Skip ahead one album in the current playlist -->
+ <method name="AdvanceAlbum" />
+
<!-- Skip backwards one song in the current playlist -->
<method name="Reverse" />
+ <!-- Skip backwards one album in the current playlist -->
+ <method name="ReverseAlbum" />
+
<!-- Playlist length -->
<method name="Length">
<!-- Return length of current playlist -->
diff --git a/src/dbus/meson.build b/src/dbus/meson.build
new file mode 100644
index 0000000..d1bbdf0
--- /dev/null
+++ b/src/dbus/meson.build
@@ -0,0 +1,29 @@
+gnome = import('gnome')
+
+
+gio_dep = dependency('gio-2.0', required: true)
+aud_dbus_deps = [gio_dep]
+
+
+if host_machine.system() != 'windows'
+ gio_unix_dep = dependency('gio-unix-2.0', required: true)
+ aud_dbus_deps += [gio_unix_dep]
+endif
+
+
+aud_dbus_src = gnome.gdbus_codegen('aud-dbus',
+ sources: 'aud-dbus.xml',
+ interface_prefix: 'org.atheme.',
+ namespace: 'Obj'
+)
+aud_dbus_deps += declare_dependency(sources: aud_dbus_src)
+
+
+aud_dbus_lib = static_library('aud-dbus',
+ aud_dbus_src,
+ dependencies: aud_dbus_deps,
+ pic: true
+)
+
+
+aud_dbus_inc = include_directories('.')
diff --git a/src/libaudcore/Makefile b/src/libaudcore/Makefile
index e969f93..4b1c383 100644
--- a/src/libaudcore/Makefile
+++ b/src/libaudcore/Makefile
@@ -1,6 +1,6 @@
SHARED_LIB = ${LIB_PREFIX}audcore${LIB_SUFFIX}
LIB_MAJOR = 5
-LIB_MINOR = 1
+LIB_MINOR = 2
SRCS = adder.cc \
art.cc \
@@ -78,6 +78,7 @@ INCLUDES = audio.h \
runtime.h \
templates.h \
tinylock.h \
+ threads.h \
tuple.h \
visualizer.h \
vfs.h \
diff --git a/src/libaudcore/adder.cc b/src/libaudcore/adder.cc
index 888b321..8ee3bb9 100644
--- a/src/libaudcore/adder.cc
+++ b/src/libaudcore/adder.cc
@@ -17,33 +17,37 @@
* the use of this software.
*/
-#include "playlist-internal.h"
#include "internal.h"
+#include "playlist-internal.h"
-#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include "audstrings.h"
#include "hook.h"
#include "i18n.h"
+#include "interface.h"
#include "list.h"
#include "mainloop.h"
#include "plugins-internal.h"
#include "probe.h"
#include "runtime.h"
+#include "threads.h"
#include "tuple.h"
-#include "interface.h"
#include "vfs.h"
// regrettably, strcmp_nocase can't be used directly as a
// callback for Index::sort due to taking a third argument;
// strcmp also triggers -Wnoexcept-type with GCC 7
-static int filename_compare (const char * a, const char * b)
+static int filename_compare(const char * a, const char * b)
#ifdef _WIN32
- { return strcmp_nocase (a, b); }
+{
+ return strcmp_nocase(a, b);
+}
#else
- { return strcmp (a, b); }
+{
+ return strcmp(a, b);
+}
#endif
struct AddTask : public ListNode
@@ -66,16 +70,15 @@ struct AddResult : public ListNode
bool saw_folder, filtered;
};
-static void * add_worker (void * unused);
+static void add_worker();
static List<AddTask> add_tasks;
static List<AddResult> add_results;
static Playlist current_playlist;
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-static bool add_thread_started = false;
+static aud::mutex mutex;
+static std::thread add_thread;
static bool add_thread_exited = false;
-static pthread_t add_thread;
static QueuedFunc queued_add;
static QueuedFunc status_timer;
@@ -83,63 +86,61 @@ static char status_path[512];
static int status_count;
static bool status_shown = false;
-static void status_cb (void * unused)
+static void status_cb(void * unused)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
char scratch[128];
- snprintf (scratch, sizeof scratch, dngettext (PACKAGE, "%d file found",
- "%d files found", status_count), status_count);
+ snprintf(
+ scratch, sizeof scratch,
+ dngettext(PACKAGE, "%d file found", "%d files found", status_count),
+ status_count);
- if (aud_get_headless_mode ())
+ if (aud_get_headless_mode())
{
- printf ("Searching, %s ...\r", scratch);
- fflush (stdout);
+ printf("Searching, %s ...\r", scratch);
+ fflush(stdout);
}
else
{
- hook_call ("ui show progress", status_path);
- hook_call ("ui show progress 2", scratch);
+ hook_call("ui show progress", status_path);
+ hook_call("ui show progress 2", scratch);
}
status_shown = true;
-
- pthread_mutex_unlock (& mutex);
}
-static void status_update (const char * filename, int found)
+static void status_update(const char * filename, int found)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- snprintf (status_path, sizeof status_path, "%s", filename);
+ snprintf(status_path, sizeof status_path, "%s", filename);
status_count = found;
- if (! status_timer.running ())
- status_timer.start (250, status_cb, nullptr);
-
- pthread_mutex_unlock (& mutex);
+ if (!status_timer.running())
+ status_timer.start(250, status_cb, nullptr);
}
-static void status_done_locked ()
+static void status_done_locked()
{
- status_timer.stop ();
+ status_timer.stop();
if (status_shown)
{
- if (aud_get_headless_mode ())
- printf ("\n");
+ if (aud_get_headless_mode())
+ printf("\n");
else
- hook_call ("ui hide progress", nullptr);
+ hook_call("ui hide progress", nullptr);
status_shown = false;
}
}
-static void add_file (PlaylistAddItem && item, Playlist::FilterFunc filter,
- void * user, AddResult * result, bool skip_invalid)
+static void add_file(PlaylistAddItem && item, Playlist::FilterFunc filter,
+ void * user, AddResult * result, bool skip_invalid)
{
- AUDINFO ("Adding file: %s\n", (const char *) item.filename);
- status_update (item.filename, result->items.len ());
+ AUDINFO("Adding file: %s\n", (const char *)item.filename);
+ status_update(item.filename, result->items.len());
/*
* If possible, we'll wait until the file is added to the playlist to probe
@@ -153,20 +154,22 @@ static void add_file (PlaylistAddItem && item, Playlist::FilterFunc filter,
* If we already have metadata, or the file is itself a subtune, then
* neither of these reasons apply.
*/
- if (! item.tuple.valid () && ! is_subtune (item.filename))
+ if (!item.tuple.valid() && !is_subtune(item.filename))
{
/* If we open the file to identify the decoder, we can re-use the same
* handle to read metadata. */
VFSFile file;
- if (! item.decoder)
+ if (!item.decoder)
{
- if (aud_get_bool (nullptr, "slow_probe"))
+ if (aud_get_bool("slow_probe"))
{
/* The slow path. User settings dictate that we should try to
- * find a decoder even if we don't recognize the file extension. */
- item.decoder = aud_file_find_decoder (item.filename, false, file);
- if (skip_invalid && ! item.decoder)
+ * find a decoder even if we don't recognize the file extension.
+ */
+ item.decoder =
+ aud_file_find_decoder(item.filename, false, file);
+ if (skip_invalid && !item.decoder)
return;
}
else
@@ -174,8 +177,8 @@ static void add_file (PlaylistAddItem && item, Playlist::FilterFunc filter,
/* The fast path. First see whether any plugins recognize the
* file extension. Note that it's possible for multiple plugins
* to recognize the same extension (.ogg, for example). */
- int flags = probe_by_filename (item.filename);
- if (skip_invalid && ! (flags & PROBE_FLAG_HAS_DECODER))
+ int flags = probe_by_filename(item.filename);
+ if (skip_invalid && !(flags & PROBE_FLAG_HAS_DECODER))
return;
if ((flags & PROBE_FLAG_MIGHT_HAVE_SUBTUNES))
@@ -183,8 +186,9 @@ static void add_file (PlaylistAddItem && item, Playlist::FilterFunc filter,
/* At least one plugin recognized the file extension and
* indicated that there might be subtunes. Figure out for
* sure which decoder we need to use for this file. */
- item.decoder = aud_file_find_decoder (item.filename, true, file);
- if (skip_invalid && ! item.decoder)
+ item.decoder =
+ aud_file_find_decoder(item.filename, true, file);
+ if (skip_invalid && !item.decoder)
return;
}
}
@@ -193,176 +197,186 @@ static void add_file (PlaylistAddItem && item, Playlist::FilterFunc filter,
/* At this point we've either identified the decoder or determined that
* the file doesn't have any subtunes. If the former, read the tag so
* so we can expand any subtunes we find. */
- if (item.decoder && input_plugin_has_subtunes (item.decoder))
- aud_file_read_tag (item.filename, item.decoder, file, item.tuple);
+ if (item.decoder && input_plugin_has_subtunes(item.decoder))
+ aud_file_read_tag(item.filename, item.decoder, file, item.tuple);
}
- int n_subtunes = item.tuple.get_n_subtunes ();
+ int n_subtunes = item.tuple.get_n_subtunes();
if (n_subtunes)
{
- for (int sub = 0; sub < n_subtunes; sub ++)
+ for (int sub = 0; sub < n_subtunes; sub++)
{
- StringBuf subname = str_printf ("%s?%d",
- (const char *) item.filename, item.tuple.get_nth_subtune (sub));
+ StringBuf subname = str_printf("%s?%d", (const char *)item.filename,
+ item.tuple.get_nth_subtune(sub));
- if (! filter || filter (subname, user))
- add_file ({String (subname), Tuple (), item.decoder}, filter, user, result, false);
+ if (!filter || filter(subname, user))
+ add_file({String(subname), Tuple(), item.decoder}, filter, user,
+ result, false);
else
result->filtered = true;
}
}
else
- result->items.append (std::move (item));
+ result->items.append(std::move(item));
}
/* To prevent infinite recursion, we currently allow adding a folder from within
* a playlist, but not a playlist from within a folder, nor a second playlist
* from within a playlist (this last rule is enforced by setting
* <from_playlist> to true from within add_playlist()). */
-static void add_generic (PlaylistAddItem && item, Playlist::FilterFunc filter,
- void * user, AddResult * result, bool save_title, bool from_playlist);
+static void add_generic(PlaylistAddItem && item, Playlist::FilterFunc filter,
+ void * user, AddResult * result, bool save_title,
+ bool from_playlist);
-static void add_playlist (const char * filename, Playlist::FilterFunc filter,
- void * user, AddResult * result, bool save_title)
+static void add_playlist(const char * filename, Playlist::FilterFunc filter,
+ void * user, AddResult * result, bool save_title)
{
- AUDINFO ("Adding playlist: %s\n", filename);
- status_update (filename, result->items.len ());
+ AUDINFO("Adding playlist: %s\n", filename);
+ status_update(filename, result->items.len());
String title;
Index<PlaylistAddItem> items;
- if (! playlist_load (filename, title, items))
+ if (!playlist_load(filename, title, items))
return;
if (save_title)
result->title = title;
for (auto & item : items)
- add_generic (std::move (item), filter, user, result, false, true);
+ add_generic(std::move(item), filter, user, result, false, true);
}
-static void add_cuesheets (Index<String> & files, Playlist::FilterFunc filter,
- void * user, AddResult * result)
+static void add_cuesheets(Index<String> & files, Playlist::FilterFunc filter,
+ void * user, AddResult * result)
{
Index<String> cuesheets;
- for (int i = 0; i < files.len ();)
+ for (int i = 0; i < files.len();)
{
- if (str_has_suffix_nocase (files[i], ".cue"))
- cuesheets.move_from (files, i, -1, 1, true, true);
+ if (str_has_suffix_nocase(files[i], ".cue"))
+ cuesheets.move_from(files, i, -1, 1, true, true);
else
- i ++;
+ i++;
}
- if (! cuesheets.len ())
+ if (!cuesheets.len())
return;
// sort cuesheet list in natural order
- cuesheets.sort (str_compare_encoded);
+ cuesheets.sort(str_compare_encoded);
// sort file list in system-dependent order for duplicate removal
- files.sort (filename_compare);
+ files.sort(filename_compare);
for (String & cuesheet : cuesheets)
{
- AUDINFO ("Adding cuesheet: %s\n", (const char *) cuesheet);
- status_update (cuesheet, result->items.len ());
+ AUDINFO("Adding cuesheet: %s\n", (const char *)cuesheet);
+ status_update(cuesheet, result->items.len());
String title; // ignored
Index<PlaylistAddItem> items;
- if (! playlist_load (cuesheet, title, items))
+ if (!playlist_load(cuesheet, title, items))
continue;
String prev_filename;
for (auto & item : items)
{
- String filename = item.tuple.get_str (Tuple::AudioFile);
- if (! filename)
+ String filename = item.tuple.get_str(Tuple::AudioFile);
+ if (!filename)
continue; // shouldn't happen
- if (! filter || filter (item.filename, user))
- add_file (std::move (item), filter, user, result, false);
+ if (!filter || filter(item.filename, user))
+ add_file(std::move(item), filter, user, result, false);
else
result->filtered = true;
// remove duplicates from file list
- if (prev_filename && ! filename_compare (filename, prev_filename))
+ if (prev_filename && !filename_compare(filename, prev_filename))
continue;
- int idx = files.bsearch ((const char *) filename, filename_compare);
+ int idx = files.bsearch((const char *)filename, filename_compare);
if (idx >= 0)
- files.remove (idx, 1);
+ files.remove(idx, 1);
- prev_filename = std::move (filename);
+ prev_filename = std::move(filename);
}
}
}
-static void add_folder (const char * filename, Playlist::FilterFunc filter,
- void * user, AddResult * result, bool save_title)
+static void add_folder(const char * filename, Playlist::FilterFunc filter,
+ void * user, AddResult * result, bool save_title)
{
- AUDINFO ("Adding folder: %s\n", filename);
- status_update (filename, result->items.len ());
+ AUDINFO("Adding folder: %s\n", filename);
+ status_update(filename, result->items.len());
String error;
- Index<String> files = VFSFile::read_folder (filename, error);
+ Index<String> files = VFSFile::read_folder(filename, error);
+ Index<String> folders;
if (error)
- aud_ui_show_error (str_printf (_("Error reading %s:\n%s"), filename, (const char *) error));
+ aud_ui_show_error(str_printf(_("Error reading %s:\n%s"), filename,
+ (const char *)error));
- if (! files.len ())
+ if (!files.len())
return;
if (save_title)
{
- const char * slash = strrchr (filename, '/');
+ const char * slash = strrchr(filename, '/');
if (slash)
- result->title = String (str_decode_percent (slash + 1));
+ result->title = String(str_decode_percent(slash + 1));
}
- add_cuesheets (files, filter, user, result);
+ add_cuesheets(files, filter, user, result);
// sort file list in natural order (must come after add_cuesheets)
- files.sort (str_compare_encoded);
+ files.sort(str_compare_encoded);
- for (const char * file : files)
+ for (const String & file : files)
{
- if (filter && ! filter (file, user))
+ if (filter && !filter(file, user))
{
result->filtered = true;
continue;
}
String error;
- VFSFileTest mode = VFSFile::test_file (file,
- VFSFileTest (VFS_IS_REGULAR | VFS_IS_SYMLINK | VFS_IS_DIR), error);
+ VFSFileTest mode = VFSFile::test_file(
+ file, VFSFileTest(VFS_IS_REGULAR | VFS_IS_SYMLINK | VFS_IS_DIR),
+ error);
if (error)
- AUDERR ("%s: %s\n", file, (const char *) error);
+ AUDERR("%s: %s\n", (const char *)file, (const char *)error);
if (mode & VFS_IS_SYMLINK)
continue;
if (mode & VFS_IS_REGULAR)
- add_file ({String (file)}, filter, user, result, true);
- else if ((mode & VFS_IS_DIR) && aud_get_bool (nullptr, "recurse_folders"))
- add_folder (file, filter, user, result, false);
+ add_file({file}, filter, user, result, true);
+ else if ((mode & VFS_IS_DIR) && aud_get_bool("recurse_folders"))
+ folders.append(file);
}
+
+ // add folders after files
+ for (const String & folder : folders)
+ add_folder(folder, filter, user, result, false);
}
-static void add_generic (PlaylistAddItem && item, Playlist::FilterFunc filter,
- void * user, AddResult * result, bool save_title, bool from_playlist)
+static void add_generic(PlaylistAddItem && item, Playlist::FilterFunc filter,
+ void * user, AddResult * result, bool save_title,
+ bool from_playlist)
{
- if (! strstr (item.filename, "://"))
+ if (!strstr(item.filename, "://"))
{
/* Let's not add random junk to the playlist. */
- AUDERR ("Invalid URI: %s\n", (const char *) item.filename);
+ AUDERR("Invalid URI: %s\n", (const char *)item.filename);
return;
}
- if (filter && ! filter (item.filename, user))
+ if (filter && !filter(item.filename, user))
{
result->filtered = true;
return;
@@ -370,263 +384,237 @@ static void add_generic (PlaylistAddItem && item, Playlist::FilterFunc filter,
/* If the item has a valid tuple or known decoder, or it's a subtune, then
* assume it's a playable file and skip some checks. */
- if (item.tuple.valid () || item.decoder || is_subtune (item.filename))
- add_file (std::move (item), filter, user, result, false);
+ if (item.tuple.valid() || item.decoder || is_subtune(item.filename))
+ add_file(std::move(item), filter, user, result, false);
else
{
int tests = 0;
- if (! from_playlist)
+ if (!from_playlist)
tests |= VFS_NO_ACCESS;
- if (! from_playlist || aud_get_bool (nullptr, "folders_in_playlist"))
+ if (!from_playlist || aud_get_bool("folders_in_playlist"))
tests |= VFS_IS_DIR;
String error;
- VFSFileTest mode = VFSFile::test_file (item.filename, (VFSFileTest) tests, error);
+ VFSFileTest mode =
+ VFSFile::test_file(item.filename, (VFSFileTest)tests, error);
if ((mode & VFS_NO_ACCESS))
- aud_ui_show_error (str_printf (_("Error reading %s:\n%s"),
- (const char *) item.filename, (const char *) error));
+ aud_ui_show_error(str_printf(_("Error reading %s:\n%s"),
+ (const char *)item.filename,
+ (const char *)error));
else if (mode & VFS_IS_DIR)
{
- add_folder (item.filename, filter, user, result, save_title);
+ add_folder(item.filename, filter, user, result, save_title);
result->saw_folder = true;
}
- else if ((! from_playlist) && Playlist::filename_is_playlist (item.filename))
- add_playlist (item.filename, filter, user, result, save_title);
+ else if ((!from_playlist) &&
+ Playlist::filename_is_playlist(item.filename))
+ add_playlist(item.filename, filter, user, result, save_title);
else
- add_file (std::move (item), filter, user, result, false);
+ add_file(std::move(item), filter, user, result, false);
}
}
-static void start_thread_locked ()
+static void start_thread_locked()
{
if (add_thread_exited)
{
- pthread_mutex_unlock (& mutex);
- pthread_join (add_thread, nullptr);
- pthread_mutex_lock (& mutex);
+ mutex.unlock();
+ add_thread.join();
+ mutex.lock();
}
- if (! add_thread_started || add_thread_exited)
+ if (!add_thread.joinable())
{
- pthread_create (& add_thread, nullptr, add_worker, nullptr);
- add_thread_started = true;
+ add_thread = std::thread(add_worker);
add_thread_exited = false;
}
}
-static void stop_thread_locked ()
+static void stop_thread_locked()
{
- if (add_thread_started)
+ if (add_thread.joinable())
{
- pthread_mutex_unlock (& mutex);
- pthread_join (add_thread, nullptr);
- pthread_mutex_lock (& mutex);
- add_thread_started = false;
+ mutex.unlock();
+ add_thread.join();
+ mutex.lock();
add_thread_exited = false;
}
}
-static void add_finish (void * unused)
+static void add_finish(void * unused)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- AddResult * result;
- while ((result = add_results.head ()))
+ for (SmartPtr<AddResult> result; result.capture(add_results.pop_head());)
{
- add_results.remove (result);
-
- PlaylistEx playlist;
- int count;
-
- if (! result->items.len ())
+ if (!result->items.len())
{
- if (result->saw_folder && ! result->filtered)
- aud_ui_show_error (_("No files found."));
- goto FREE;
+ if (result->saw_folder && !result->filtered)
+ aud_ui_show_error(_("No files found."));
+ continue;
}
- playlist = result->playlist;
- if (! playlist.exists ()) /* playlist deleted */
- goto FREE;
+ PlaylistEx playlist = result->playlist;
+ if (!playlist.exists()) /* playlist deleted */
+ continue;
if (result->play)
{
- if (aud_get_bool (nullptr, "clear_playlist"))
- playlist.remove_all_entries ();
+ if (aud_get_bool("clear_playlist"))
+ playlist.remove_all_entries();
else
- playlist.queue_remove_all ();
+ playlist.queue_remove_all();
}
- count = playlist.n_entries ();
+ int count = playlist.n_entries();
if (result->at < 0 || result->at > count)
result->at = count;
- if (result->title && ! count)
+ if (result->title && !count)
{
- if (! strcmp (playlist.get_title (), _("New Playlist")))
- playlist.set_title (result->title);
+ if (!strcmp(playlist.get_title(), _("New Playlist")))
+ playlist.set_title(result->title);
}
/* temporarily disable scanning this playlist; the intent is to avoid
* scanning until the currently playing entry is known, at which time it
* can be scanned more efficiently (album art read in the same pass). */
- playlist_enable_scan (false);
- playlist.insert_flat_items (result->at, std::move (result->items));
+ playlist_enable_scan(false);
+ playlist.insert_flat_items(result->at, std::move(result->items));
if (result->play)
{
- if (! aud_get_bool (0, "shuffle"))
- playlist.set_position (result->at);
+ if (!aud_get_bool("shuffle"))
+ playlist.set_position(result->at);
- playlist.start_playback ();
+ playlist.start_playback();
}
- playlist_enable_scan (true);
-
- FREE:
- delete result;
+ playlist_enable_scan(true);
}
if (add_thread_exited)
{
- stop_thread_locked ();
- status_done_locked ();
+ stop_thread_locked();
+ status_done_locked();
}
- pthread_mutex_unlock (& mutex);
+ mh.unlock(); // before calling hook
- hook_call ("playlist add complete", nullptr);
+ hook_call("playlist add complete", nullptr);
}
-static void * add_worker (void * unused)
+static void add_worker()
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- AddTask * task;
- while ((task = add_tasks.head ()))
+ for (SmartPtr<AddTask> task; task.capture(add_tasks.pop_head());)
{
- add_tasks.remove (task);
-
current_playlist = task->playlist;
- pthread_mutex_unlock (& mutex);
+ mh.unlock();
- playlist_cache_load (task->items);
+ playlist_cache_load(task->items);
- AddResult * result = new AddResult ();
+ AddResult * result = new AddResult();
result->playlist = task->playlist;
result->at = task->at;
result->play = task->play;
- bool save_title = (task->items.len () == 1);
+ bool save_title = (task->items.len() == 1);
for (auto & item : task->items)
- add_generic (std::move (item), task->filter, task->user, result, save_title, false);
+ add_generic(std::move(item), task->filter, task->user, result,
+ save_title, false);
- delete task;
+ mh.lock();
+ current_playlist = Playlist();
- pthread_mutex_lock (& mutex);
- current_playlist = Playlist ();
+ if (!add_results.head())
+ queued_add.queue(add_finish, nullptr);
- if (! add_results.head ())
- queued_add.queue (add_finish, nullptr);
-
- add_results.append (result);
+ add_results.append(result);
}
add_thread_exited = true;
- pthread_mutex_unlock (& mutex);
- return nullptr;
}
-void adder_cleanup ()
+void adder_cleanup()
{
- pthread_mutex_lock (& mutex);
-
- add_tasks.clear ();
+ auto mh = mutex.take();
- stop_thread_locked ();
- status_done_locked ();
+ add_tasks.clear();
- add_results.clear ();
+ stop_thread_locked();
+ status_done_locked();
- queued_add.stop ();
+ add_results.clear();
- pthread_mutex_unlock (& mutex);
+ queued_add.stop();
}
-EXPORT void Playlist::insert_entry (int at,
- const char * filename, Tuple && tuple, bool play) const
+EXPORT void Playlist::insert_entry(int at, const char * filename,
+ Tuple && tuple, bool play) const
{
Index<PlaylistAddItem> items;
- items.append (String (filename), std::move (tuple));
+ items.append(String(filename), std::move(tuple));
- insert_items (at, std::move (items), play);
+ insert_items(at, std::move(items), play);
}
-EXPORT void Playlist::insert_items (int at,
- Index<PlaylistAddItem> && items, bool play) const
+EXPORT void Playlist::insert_items(int at, Index<PlaylistAddItem> && items,
+ bool play) const
{
- insert_filtered (at, std::move (items), nullptr, nullptr, play);
+ insert_filtered(at, std::move(items), nullptr, nullptr, play);
}
-EXPORT void Playlist::insert_filtered (int at,
- Index<PlaylistAddItem> && items, Playlist::FilterFunc filter, void * user,
- bool play) const
+EXPORT void Playlist::insert_filtered(int at, Index<PlaylistAddItem> && items,
+ Playlist::FilterFunc filter, void * user,
+ bool play) const
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- AddTask * task = new AddTask ();
+ AddTask * task = new AddTask();
- task->playlist = * this;
+ task->playlist = *this;
task->at = at;
task->play = play;
- task->items = std::move (items);
+ task->items = std::move(items);
task->filter = filter;
task->user = user;
- add_tasks.append (task);
- start_thread_locked ();
-
- pthread_mutex_unlock (& mutex);
+ add_tasks.append(task);
+ start_thread_locked();
}
-EXPORT bool Playlist::add_in_progress () const
+EXPORT bool Playlist::add_in_progress() const
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- for (AddTask * task = add_tasks.head (); task; task = add_tasks.next (task))
+ for (AddTask * task = add_tasks.head(); task; task = add_tasks.next(task))
{
- if (task->playlist == * this)
- goto YES;
+ if (task->playlist == *this)
+ return true;
}
- if (current_playlist == * this)
- goto YES;
+ if (current_playlist == *this)
+ return true;
- for (AddResult * result = add_results.head (); result; result = add_results.next (result))
+ for (AddResult * result = add_results.head(); result;
+ result = add_results.next(result))
{
- if (result->playlist == * this)
- goto YES;
+ if (result->playlist == *this)
+ return true;
}
- pthread_mutex_unlock (& mutex);
return false;
-
-YES:
- pthread_mutex_unlock (& mutex);
- return true;
}
-EXPORT bool Playlist::add_in_progress_any ()
+EXPORT bool Playlist::add_in_progress_any()
{
- pthread_mutex_lock (& mutex);
-
- bool in_progress = (add_tasks.head () ||
- current_playlist != Playlist () ||
- add_results.head ());
+ auto mh = mutex.take();
- pthread_mutex_unlock (& mutex);
- return in_progress;
+ return (add_tasks.head() || current_playlist != Playlist() ||
+ add_results.head());
}
diff --git a/src/libaudcore/art-search.cc b/src/libaudcore/art-search.cc
index 0fe71e9..05f9723 100644
--- a/src/libaudcore/art-search.cc
+++ b/src/libaudcore/art-search.cc
@@ -21,132 +21,133 @@
#include <string.h>
-#include <glib.h> /* for g_dir_open, g_file_test */
+#include <glib.h> /* for g_dir_open, g_file_test */
#include "audstrings.h"
#include "index.h"
#include "runtime.h"
-struct SearchParams {
+struct SearchParams
+{
String filename;
Index<String> include, exclude;
};
-static bool has_front_cover_extension (const char * name)
+static bool has_front_cover_extension(const char * name)
{
- const char * ext = strrchr (name, '.');
- if (! ext)
+ const char * ext = strrchr(name, '.');
+ if (!ext)
return false;
- return ! strcmp_nocase (ext, ".jpg") || ! strcmp_nocase (ext, ".jpeg") ||
- ! strcmp_nocase (ext, ".png");
+ return !strcmp_nocase(ext, ".jpg") || !strcmp_nocase(ext, ".jpeg") ||
+ !strcmp_nocase(ext, ".png");
}
-static bool cover_name_filter (const char * name,
- const Index<String> & keywords, bool ret_on_empty)
+static bool cover_name_filter(const char * name, const Index<String> & keywords,
+ bool ret_on_empty)
{
- if (! keywords.len ())
+ if (!keywords.len())
return ret_on_empty;
for (const String & keyword : keywords)
{
- if (strstr_nocase (name, keyword))
+ if (strstr_nocase(name, keyword))
return true;
}
return false;
}
-static String fileinfo_recursive_get_image (const char * path,
- const SearchParams * params, int depth)
+static String fileinfo_recursive_get_image(const char * path,
+ const SearchParams * params,
+ int depth)
{
- GDir * d = g_dir_open (path, 0, nullptr);
- if (! d)
- return String ();
+ GDir * d = g_dir_open(path, 0, nullptr);
+ if (!d)
+ return String();
const char * name;
- if (aud_get_bool (nullptr, "use_file_cover") && ! depth)
+ if (aud_get_bool("use_file_cover") && !depth)
{
/* Look for images matching file name */
- while ((name = g_dir_read_name (d)))
+ while ((name = g_dir_read_name(d)))
{
- StringBuf newpath = filename_build ({path, name});
+ StringBuf newpath = filename_build({path, name});
- if (! g_file_test (newpath, G_FILE_TEST_IS_DIR) &&
- has_front_cover_extension (name) &&
- same_basename (name, params->filename))
+ if (has_front_cover_extension(name) &&
+ same_basename(name, params->filename) &&
+ !g_file_test(newpath, G_FILE_TEST_IS_DIR))
{
- g_dir_close (d);
- return String (newpath);
+ g_dir_close(d);
+ return String(newpath);
}
}
- g_dir_rewind (d);
+ g_dir_rewind(d);
}
/* Search for files using filter */
- while ((name = g_dir_read_name (d)))
+ while ((name = g_dir_read_name(d)))
{
- StringBuf newpath = filename_build ({path, name});
+ StringBuf newpath = filename_build({path, name});
- if (! g_file_test (newpath, G_FILE_TEST_IS_DIR) &&
- has_front_cover_extension (name) &&
- cover_name_filter (name, params->include, true) &&
- ! cover_name_filter (name, params->exclude, false))
+ if (has_front_cover_extension(name) &&
+ cover_name_filter(name, params->include, true) &&
+ !cover_name_filter(name, params->exclude, false) &&
+ !g_file_test(newpath, G_FILE_TEST_IS_DIR))
{
- g_dir_close (d);
- return String (newpath);
+ g_dir_close(d);
+ return String(newpath);
}
}
- g_dir_rewind (d);
+ g_dir_rewind(d);
- if (aud_get_bool (nullptr, "recurse_for_cover") && depth < aud_get_int (nullptr, "recurse_for_cover_depth"))
+ if (aud_get_bool("recurse_for_cover") &&
+ depth < aud_get_int("recurse_for_cover_depth"))
{
/* Descend into directories recursively. */
- while ((name = g_dir_read_name (d)))
+ while ((name = g_dir_read_name(d)))
{
- StringBuf newpath = filename_build ({path, name});
+ StringBuf newpath = filename_build({path, name});
- if (g_file_test (newpath, G_FILE_TEST_IS_DIR))
+ if (g_file_test(newpath, G_FILE_TEST_IS_DIR))
{
- String tmp = fileinfo_recursive_get_image (newpath, params, depth + 1);
+ String tmp =
+ fileinfo_recursive_get_image(newpath, params, depth + 1);
if (tmp)
{
- g_dir_close (d);
+ g_dir_close(d);
return tmp;
}
}
}
}
- g_dir_close (d);
- return String ();
+ g_dir_close(d);
+ return String();
}
-String art_search (const char * filename)
+String art_search(const char * filename)
{
- StringBuf local = uri_to_filename (filename);
- if (! local)
- return String ();
+ StringBuf local = uri_to_filename(filename);
+ if (!local)
+ return String();
- const char * elem = last_path_element (local);
- if (! elem)
- return String ();
+ const char * elem = last_path_element(local);
+ if (!elem)
+ return String();
- String include = aud_get_str (nullptr, "cover_name_include");
- String exclude = aud_get_str (nullptr, "cover_name_exclude");
+ String include = aud_get_str("cover_name_include");
+ String exclude = aud_get_str("cover_name_exclude");
- SearchParams params = {
- String (elem),
- str_list_to_index (include, ", "),
- str_list_to_index (exclude, ", ")
- };
+ SearchParams params = {String(elem), str_list_to_index(include, ", "),
+ str_list_to_index(exclude, ", ")};
- cut_path_element (local, elem - local);
+ cut_path_element(local, elem - local);
- String image_local = fileinfo_recursive_get_image (local, & params, 0);
- return image_local ? String (filename_to_uri (image_local)) : String ();
+ String image_local = fileinfo_recursive_get_image(local, &params, 0);
+ return image_local ? String(filename_to_uri(image_local)) : String();
}
diff --git a/src/libaudcore/art.cc b/src/libaudcore/art.cc
index e406eec..a0ea230 100644
--- a/src/libaudcore/art.cc
+++ b/src/libaudcore/art.cc
@@ -17,12 +17,11 @@
* the use of this software.
*/
-#include "probe.h"
#include "internal.h"
+#include "probe.h"
#include <assert.h>
#include <errno.h>
-#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -35,12 +34,14 @@
#include "multihash.h"
#include "runtime.h"
#include "scanner.h"
+#include "threads.h"
#include "vfs.h"
#define FLAG_DONE 1
#define FLAG_SENT 2
-struct AudArtItem {
+struct AudArtItem
+{
String filename;
int refcount;
int flag;
@@ -53,228 +54,222 @@ struct AudArtItem {
bool is_temp;
};
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-
+static aud::mutex mutex;
static SimpleHash<String, AudArtItem> art_items;
static AudArtItem * current_item;
static QueuedFunc queued_requests;
-static Index<AudArtItem *> get_queued ()
+static Index<AudArtItem *> get_queued()
{
+ auto mh = mutex.take();
Index<AudArtItem *> queued;
- pthread_mutex_lock (& mutex);
- art_items.iterate ([&] (const String &, AudArtItem & item)
- {
+ art_items.iterate([&](const String &, AudArtItem & item) {
if (item.flag == FLAG_DONE)
{
- queued.append (& item);
+ queued.append(&item);
item.flag = FLAG_SENT;
}
});
- queued_requests.stop ();
+ queued_requests.stop();
- pthread_mutex_unlock (& mutex);
return queued;
}
-static void send_requests (void *)
+static void send_requests(void *)
{
- auto queued = get_queued ();
+ auto queued = get_queued();
for (AudArtItem * item : queued)
{
- hook_call ("art ready", (void *) (const char *) item->filename);
- aud_art_unref (item); /* release temporary reference */
+ hook_call("art ready", (void *)(const char *)item->filename);
+ aud_art_unref(item); /* release temporary reference */
}
}
-static void finish_item_locked (AudArtItem * item, Index<char> && data, String && art_file)
+static void finish_item(aud::mutex::holder &, AudArtItem * item,
+ Index<char> && data, String && art_file)
{
/* already finished? */
if (item->flag)
return;
- item->data = std::move (data);
- item->art_file = std::move (art_file);
+ item->data = std::move(data);
+ item->art_file = std::move(art_file);
item->flag = FLAG_DONE;
- queued_requests.queue (send_requests, nullptr);
+ queued_requests.queue(send_requests, nullptr);
}
-static void request_callback (ScanRequest * request)
+static void request_callback(ScanRequest * request)
{
- pthread_mutex_lock (& mutex);
-
- AudArtItem * item = art_items.lookup (request->filename);
+ auto mh = mutex.take();
+ AudArtItem * item = art_items.lookup(request->filename);
if (item)
- finish_item_locked (item, std::move (request->image_data), std::move (request->image_file));
-
- pthread_mutex_unlock (& mutex);
+ finish_item(mh, item, std::move(request->image_data),
+ std::move(request->image_file));
}
-static AudArtItem * art_item_get_locked (const String & filename, bool * queued)
+static AudArtItem * art_item_get(aud::mutex::holder &, const String & filename,
+ bool * queued)
{
if (queued)
- * queued = false;
+ *queued = false;
// blacklist stdin
- if (! strncmp (filename, "stdin://", 8))
+ if (!strncmp(filename, "stdin://", 8))
return nullptr;
- AudArtItem * item = art_items.lookup (filename);
+ AudArtItem * item = art_items.lookup(filename);
if (item && item->flag)
{
- item->refcount ++;
+ item->refcount++;
return item;
}
- if (! item)
+ if (!item)
{
- item = art_items.add (filename, AudArtItem ());
+ item = art_items.add(filename, AudArtItem());
item->filename = filename;
item->refcount = 1; /* temporary reference */
- scanner_request (new ScanRequest (filename, SCAN_IMAGE, request_callback));
+ scanner_request(
+ new ScanRequest(filename, SCAN_IMAGE, request_callback));
}
if (queued)
- * queued = true;
+ *queued = true;
return nullptr;
}
-static void art_item_unref_locked (AudArtItem * item)
+static void art_item_unref(aud::mutex::holder &, AudArtItem * item)
{
- if (! -- item->refcount)
+ if (!--item->refcount)
{
/* delete temporary file */
if (item->art_file && item->is_temp)
{
- StringBuf local = uri_to_filename (item->art_file);
+ StringBuf local = uri_to_filename(item->art_file);
if (local)
- g_unlink (local);
+ g_unlink(local);
}
- art_items.remove (item->filename);
+ art_items.remove(item->filename);
}
}
-static void clear_current_locked ()
+static void clear_current(aud::mutex::holder & mh)
{
if (current_item)
{
- art_item_unref_locked (current_item);
+ art_item_unref(mh, current_item);
current_item = nullptr;
}
}
-void art_cache_current (const String & filename, Index<char> && data, String && art_file)
+void art_cache_current(const String & filename, Index<char> && data,
+ String && art_file)
{
- pthread_mutex_lock (& mutex);
-
- clear_current_locked ();
+ auto mh = mutex.take();
+ clear_current(mh);
- AudArtItem * item = art_items.lookup (filename);
+ AudArtItem * item = art_items.lookup(filename);
- if (! item)
+ if (!item)
{
- item = art_items.add (filename, AudArtItem ());
+ item = art_items.add(filename, AudArtItem());
item->filename = filename;
item->refcount = 1; /* temporary reference */
}
- finish_item_locked (item, std::move (data), std::move (art_file));
+ finish_item(mh, item, std::move(data), std::move(art_file));
- item->refcount ++;
+ item->refcount++;
current_item = item;
-
- pthread_mutex_unlock (& mutex);
}
-void art_clear_current ()
+void art_clear_current()
{
- pthread_mutex_lock (& mutex);
- clear_current_locked ();
- pthread_mutex_unlock (& mutex);
+ auto mh = mutex.take();
+ clear_current(mh);
}
-void art_cleanup ()
+void art_cleanup()
{
- auto queued = get_queued ();
+ auto queued = get_queued();
for (AudArtItem * item : queued)
- aud_art_unref (item); /* release temporary reference */
+ aud_art_unref(item); /* release temporary reference */
/* playback should already be stopped */
- assert (! current_item);
+ assert(!current_item);
- if (art_items.n_items ())
- AUDWARN ("Album art reference count not zero at exit!\n");
+ if (art_items.n_items())
+ AUDWARN("Album art reference count not zero at exit!\n");
}
-EXPORT AudArtPtr aud_art_request (const char * file, int format, bool * queued)
+EXPORT AudArtPtr aud_art_request(const char * file, int format, bool * queued)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
+ AudArtItem * item = art_item_get(mh, String(file), queued);
- String key (file);
- AudArtItem * item = art_item_get_locked (key, queued);
- bool good = true;
-
- if (! item)
- goto UNLOCK;
+ if (!item)
+ return AudArtPtr();
if (format & AUD_ART_DATA)
{
/* load data from external image file */
- if (! item->data.len () && item->art_file)
+ if (!item->data.len() && item->art_file)
{
- VFSFile file (item->art_file, "r");
+ VFSFile file(item->art_file, "r");
if (file)
- item->data = file.read_all ();
+ item->data = file.read_all();
}
- if (! item->data.len ())
- good = false;
+ if (!item->data.len())
+ {
+ art_item_unref(mh, item);
+ return AudArtPtr();
+ }
}
if (format & AUD_ART_FILE)
{
/* save data to temporary file */
- if (item->data.len () && ! item->art_file)
+ if (item->data.len() && !item->art_file)
{
- String local = write_temp_file (item->data.begin (), item->data.len ());
+ String local =
+ write_temp_file(item->data.begin(), item->data.len());
if (local)
{
- item->art_file = String (filename_to_uri (local));
+ item->art_file = String(filename_to_uri(local));
item->is_temp = true;
}
}
- if (! item->art_file)
- good = false;
- }
-
- if (! good)
- {
- art_item_unref_locked (item);
- item = nullptr;
+ if (!item->art_file)
+ {
+ art_item_unref(mh, item);
+ return AudArtPtr();
+ }
}
-UNLOCK:
- pthread_mutex_unlock (& mutex);
- return AudArtPtr (item);
+ return AudArtPtr(item);
}
-EXPORT const Index<char> * aud_art_data (const AudArtItem * item)
- { return & item->data; }
-EXPORT const char * aud_art_file (const AudArtItem * item)
- { return item->art_file; }
+EXPORT const Index<char> * aud_art_data(const AudArtItem * item)
+{
+ return &item->data;
+}
+EXPORT const char * aud_art_file(const AudArtItem * item)
+{
+ return item->art_file;
+}
-EXPORT void aud_art_unref (AudArtItem * item)
+EXPORT void aud_art_unref(AudArtItem * item)
{
- pthread_mutex_lock (& mutex);
- art_item_unref_locked (item);
- pthread_mutex_unlock (& mutex);
+ auto mh = mutex.take();
+ art_item_unref(mh, item);
}
diff --git a/src/libaudcore/audio.cc b/src/libaudcore/audio.cc
index b553864..524ae7f 100644
--- a/src/libaudcore/audio.cc
+++ b/src/libaudcore/audio.cc
@@ -27,106 +27,129 @@
#define SW_VOLUME_RANGE 40 /* decibels */
-struct packed24_t { uint8_t b[3]; };
-static_assert (sizeof (packed24_t) == 3, "invalid packed 24-bit type");
+struct packed24_t
+{
+ uint8_t b[3];
+};
+static_assert(sizeof(packed24_t) == 3, "invalid packed 24-bit type");
template<class Word>
-void interlace_loop (const void * const * in, int channels, void * out, int frames)
+void interlace_loop(const void * const * in, int channels, void * out,
+ int frames)
{
- for (int c = 0; c < channels; c ++)
+ for (int c = 0; c < channels; c++)
{
- auto get = (const Word *) in[c];
+ auto get = (const Word *)in[c];
auto end = get + frames;
- auto set = (Word *) out + c;
+ auto set = (Word *)out + c;
while (get < end)
{
- * set = * get ++;
+ *set = *get++;
set += channels;
}
}
}
template<class Word>
-void deinterlace_loop (const void * in, int channels, void * const * out, int frames)
+void deinterlace_loop(const void * in, int channels, void * const * out,
+ int frames)
{
- for (int c = 0; c < channels; c ++)
+ for (int c = 0; c < channels; c++)
{
- auto get = (const Word *) in + c;
- auto set = (Word *) out[c];
+ auto get = (const Word *)in + c;
+ auto set = (Word *)out[c];
auto end = set + frames;
while (set < end)
{
- * set ++ = * get;
+ *set++ = *get;
get += channels;
}
}
}
-EXPORT void audio_interlace (const void * const * in, int format, int channels,
- void * out, int frames)
+EXPORT void audio_interlace(const void * const * in, int format, int channels,
+ void * out, int frames)
{
switch (format)
{
case FMT_FLOAT:
- interlace_loop<float> (in, channels, out, frames);
+ interlace_loop<float>(in, channels, out, frames);
break;
- case FMT_S8: case FMT_U8:
- interlace_loop<int8_t> (in, channels, out, frames);
+ case FMT_S8:
+ case FMT_U8:
+ interlace_loop<int8_t>(in, channels, out, frames);
break;
- case FMT_S16_LE: case FMT_S16_BE:
- case FMT_U16_LE: case FMT_U16_BE:
- interlace_loop<int16_t> (in, channels, out, frames);
+ case FMT_S16_LE:
+ case FMT_S16_BE:
+ case FMT_U16_LE:
+ case FMT_U16_BE:
+ interlace_loop<int16_t>(in, channels, out, frames);
break;
- case FMT_S24_LE: case FMT_S24_BE:
- case FMT_U24_LE: case FMT_U24_BE:
- case FMT_S32_LE: case FMT_S32_BE:
- case FMT_U32_LE: case FMT_U32_BE:
- interlace_loop<int32_t> (in, channels, out, frames);
+ case FMT_S24_LE:
+ case FMT_S24_BE:
+ case FMT_U24_LE:
+ case FMT_U24_BE:
+ case FMT_S32_LE:
+ case FMT_S32_BE:
+ case FMT_U32_LE:
+ case FMT_U32_BE:
+ interlace_loop<int32_t>(in, channels, out, frames);
break;
- case FMT_S24_3LE: case FMT_S24_3BE:
- case FMT_U24_3LE: case FMT_U24_3BE:
- interlace_loop<packed24_t> (in, channels, out, frames);
+ case FMT_S24_3LE:
+ case FMT_S24_3BE:
+ case FMT_U24_3LE:
+ case FMT_U24_3BE:
+ interlace_loop<packed24_t>(in, channels, out, frames);
break;
}
}
-EXPORT void audio_deinterlace (const void * in, int format, int channels,
- void * const * out, int frames)
+EXPORT void audio_deinterlace(const void * in, int format, int channels,
+ void * const * out, int frames)
{
switch (format)
{
case FMT_FLOAT:
- deinterlace_loop<float> (in, channels, out, frames);
+ deinterlace_loop<float>(in, channels, out, frames);
break;
- case FMT_S8: case FMT_U8:
- deinterlace_loop<int8_t> (in, channels, out, frames);
+ case FMT_S8:
+ case FMT_U8:
+ deinterlace_loop<int8_t>(in, channels, out, frames);
break;
- case FMT_S16_LE: case FMT_S16_BE:
- case FMT_U16_LE: case FMT_U16_BE:
- deinterlace_loop<int16_t> (in, channels, out, frames);
+ case FMT_S16_LE:
+ case FMT_S16_BE:
+ case FMT_U16_LE:
+ case FMT_U16_BE:
+ deinterlace_loop<int16_t>(in, channels, out, frames);
break;
- case FMT_S24_LE: case FMT_S24_BE:
- case FMT_U24_LE: case FMT_U24_BE:
- case FMT_S32_LE: case FMT_S32_BE:
- case FMT_U32_LE: case FMT_U32_BE:
- deinterlace_loop<int32_t> (in, channels, out, frames);
+ case FMT_S24_LE:
+ case FMT_S24_BE:
+ case FMT_U24_LE:
+ case FMT_U24_BE:
+ case FMT_S32_LE:
+ case FMT_S32_BE:
+ case FMT_U32_LE:
+ case FMT_U32_BE:
+ deinterlace_loop<int32_t>(in, channels, out, frames);
break;
- case FMT_S24_3LE: case FMT_S24_3BE:
- case FMT_U24_3LE: case FMT_U24_3BE:
- deinterlace_loop<packed24_t> (in, channels, out, frames);
+ case FMT_S24_3LE:
+ case FMT_S24_3BE:
+ case FMT_U24_3LE:
+ case FMT_U24_3BE:
+ deinterlace_loop<packed24_t>(in, channels, out, frames);
break;
}
}
-static constexpr bool is_le (int format)
+static constexpr bool is_le(int format)
{
return format == FMT_S16_LE || format == FMT_U16_LE ||
format == FMT_S24_LE || format == FMT_U24_LE ||
@@ -134,33 +157,48 @@ static constexpr bool is_le (int format)
format == FMT_S24_3LE || format == FMT_U24_3LE;
}
-static constexpr bool is_signed (int format)
+static constexpr bool is_signed(int format)
{
- return (format == FMT_S8 ||
- format == FMT_S16_LE || format == FMT_S16_BE ||
+ return (format == FMT_S8 || format == FMT_S16_LE || format == FMT_S16_BE ||
format == FMT_S24_LE || format == FMT_S24_BE ||
format == FMT_S32_LE || format == FMT_S32_BE ||
format == FMT_S24_3LE || format == FMT_S24_3BE);
}
-static constexpr unsigned neg_range (int format)
+static constexpr unsigned neg_range(int format)
{
- return (format >= FMT_S32_LE && format < FMT_S24_3LE) ? 0x80000000 :
- (format >= FMT_S24_LE) ? 0x800000 :
- (format >= FMT_S16_LE) ? 0x8000 : 0x80;
+ return (format >= FMT_S32_LE && format < FMT_S24_3LE)
+ ? 0x80000000
+ : (format >= FMT_S24_LE)
+ ? 0x800000
+ : (format >= FMT_S16_LE) ? 0x8000 : 0x80;
}
// 0x7fffff80 = largest representable floating-point value before 2^31
-static constexpr unsigned pos_range (int format)
+static constexpr unsigned pos_range(int format)
{
- return (format >= FMT_S32_LE && format < FMT_S24_3LE) ? 0x7fffff80 :
- (format >= FMT_S24_LE) ? 0x7fffff :
- (format >= FMT_S16_LE) ? 0x7fff : 0x7f;
+ return (format >= FMT_S32_LE && format < FMT_S24_3LE)
+ ? 0x7fffff80
+ : (format >= FMT_S24_LE)
+ ? 0x7fffff
+ : (format >= FMT_S16_LE) ? 0x7fff : 0x7f;
}
-template<class T> T do_swap (T value) { return value; }
-template<> int16_t do_swap (int16_t value) { return bswap16 (value); }
-template<> int32_t do_swap (int32_t value) { return bswap32 (value); }
+template<class T>
+T do_swap(T value)
+{
+ return value;
+}
+template<>
+int16_t do_swap(int16_t value)
+{
+ return bswap16(value);
+}
+template<>
+int32_t do_swap(int32_t value)
+{
+ return bswap32(value);
+}
template<int format, class Word, class Int>
struct Convert
@@ -171,26 +209,26 @@ struct Convert
static constexpr bool native_le = true;
#endif
- static Int to_int (Word value)
+ static Int to_int(Word value)
{
- if (is_le (format) ^ native_le)
- value = do_swap (value);
- if (is_signed (format))
- value += neg_range (format);
+ if (is_le(format) ^ native_le)
+ value = do_swap(value);
+ if (is_signed(format))
+ value += neg_range(format);
if (format >= FMT_S24_LE && format <= FMT_U24_BE)
value &= 0xffffff; /* ignore high byte */
- return value - neg_range (format);
+ return value - neg_range(format);
}
- static Word to_word (Int value)
+ static Word to_word(Int value)
{
- if (! is_signed (format))
- value += neg_range (format);
+ if (!is_signed(format))
+ value += neg_range(format);
if (format >= FMT_S24_LE && format <= FMT_U24_BE)
value &= 0xffffff; /* zero high byte */
- if (is_le (format) ^ native_le)
- value = do_swap (value);
+ if (is_le(format) ^ native_le)
+ value = do_swap(value);
return value;
}
@@ -199,31 +237,30 @@ struct Convert
template<int format>
struct Convert<format, packed24_t, int32_t>
{
- static int32_t to_int (packed24_t value)
+ static int32_t to_int(packed24_t value)
{
uint8_t hi, mid, lo;
- if (is_le (format))
+ if (is_le(format))
hi = value.b[2], mid = value.b[1], lo = value.b[0];
else
hi = value.b[0], mid = value.b[1], lo = value.b[2];
- if (! is_signed (format))
+ if (!is_signed(format))
hi -= 0x80;
- return (int8_t (hi) << 16) | (mid << 8) | lo;
+ return (int8_t(hi) << 16) | (mid << 8) | lo;
}
- static packed24_t to_word (int32_t value)
+ static packed24_t to_word(int32_t value)
{
- auto hi = uint8_t (value >> 16),
- mid = uint8_t (value >> 8),
- lo = uint8_t (value);
+ auto hi = uint8_t(value >> 16), mid = uint8_t(value >> 8),
+ lo = uint8_t(value);
- if (! is_signed (format))
+ if (!is_signed(format))
hi += 0x80;
- if (is_le (format))
+ if (is_le(format))
return {{lo, mid, hi}};
else
return {{hi, mid, lo}};
@@ -231,109 +268,184 @@ struct Convert<format, packed24_t, int32_t>
};
template<int format, class Word, class Int = Word>
-void from_int_loop (const void * in_, float * out, int samples)
+void from_int_loop(const void * in_, float * out, int samples)
{
- auto in = (const Word *) in_;
+ auto in = (const Word *)in_;
auto end = in + samples;
while (in < end)
{
- Int value = Convert<format, Word, Int>::to_int (* in ++);
- * out ++ = value * (1.0f / neg_range (format));
+ Int value = Convert<format, Word, Int>::to_int(*in++);
+ *out++ = value * (1.0f / neg_range(format));
}
}
template<int format, class Word, class Int = Word>
-void to_int_loop (const float * in, void * out_, int samples)
+void to_int_loop(const float * in, void * out_, int samples)
{
auto end = in + samples;
- auto out = (Word *) out_;
+ auto out = (Word *)out_;
while (in < end)
{
- float f = (* in ++) * neg_range (format);
- f = aud::clamp (f, -(float) neg_range (format), (float) pos_range (format));
- * out ++ = Convert<format, Word, Int>::to_word (lrintf (f));
+ float f = (*in++) * neg_range(format);
+ f = aud::clamp(f, -(float)neg_range(format), (float)pos_range(format));
+ *out++ = Convert<format, Word, Int>::to_word(lrintf(f));
}
}
-EXPORT void audio_from_int (const void * in, int format, float * out, int samples)
+EXPORT void audio_from_int(const void * in, int format, float * out,
+ int samples)
{
switch (format)
{
- case FMT_S8: from_int_loop<FMT_S8, int8_t> (in, out, samples); break;
- case FMT_U8: from_int_loop<FMT_U8, int8_t> (in, out, samples); break;
-
- case FMT_S16_LE: from_int_loop<FMT_S16_LE, int16_t> (in, out, samples); break;
- case FMT_S16_BE: from_int_loop<FMT_S16_BE, int16_t> (in, out, samples); break;
- case FMT_U16_LE: from_int_loop<FMT_U16_LE, int16_t> (in, out, samples); break;
- case FMT_U16_BE: from_int_loop<FMT_U16_BE, int16_t> (in, out, samples); break;
-
- case FMT_S24_LE: from_int_loop<FMT_S24_LE, int32_t> (in, out, samples); break;
- case FMT_S24_BE: from_int_loop<FMT_S24_BE, int32_t> (in, out, samples); break;
- case FMT_U24_LE: from_int_loop<FMT_U24_LE, int32_t> (in, out, samples); break;
- case FMT_U24_BE: from_int_loop<FMT_U24_BE, int32_t> (in, out, samples); break;
-
- case FMT_S32_LE: from_int_loop<FMT_S32_LE, int32_t> (in, out, samples); break;
- case FMT_S32_BE: from_int_loop<FMT_S32_BE, int32_t> (in, out, samples); break;
- case FMT_U32_LE: from_int_loop<FMT_U32_LE, int32_t> (in, out, samples); break;
- case FMT_U32_BE: from_int_loop<FMT_U32_BE, int32_t> (in, out, samples); break;
-
- case FMT_S24_3LE: from_int_loop<FMT_S24_3LE, packed24_t, int32_t> (in, out, samples); break;
- case FMT_S24_3BE: from_int_loop<FMT_S24_3BE, packed24_t, int32_t> (in, out, samples); break;
- case FMT_U24_3LE: from_int_loop<FMT_U24_3LE, packed24_t, int32_t> (in, out, samples); break;
- case FMT_U24_3BE: from_int_loop<FMT_U24_3BE, packed24_t, int32_t> (in, out, samples); break;
+ case FMT_S8:
+ from_int_loop<FMT_S8, int8_t>(in, out, samples);
+ break;
+ case FMT_U8:
+ from_int_loop<FMT_U8, int8_t>(in, out, samples);
+ break;
+
+ case FMT_S16_LE:
+ from_int_loop<FMT_S16_LE, int16_t>(in, out, samples);
+ break;
+ case FMT_S16_BE:
+ from_int_loop<FMT_S16_BE, int16_t>(in, out, samples);
+ break;
+ case FMT_U16_LE:
+ from_int_loop<FMT_U16_LE, int16_t>(in, out, samples);
+ break;
+ case FMT_U16_BE:
+ from_int_loop<FMT_U16_BE, int16_t>(in, out, samples);
+ break;
+
+ case FMT_S24_LE:
+ from_int_loop<FMT_S24_LE, int32_t>(in, out, samples);
+ break;
+ case FMT_S24_BE:
+ from_int_loop<FMT_S24_BE, int32_t>(in, out, samples);
+ break;
+ case FMT_U24_LE:
+ from_int_loop<FMT_U24_LE, int32_t>(in, out, samples);
+ break;
+ case FMT_U24_BE:
+ from_int_loop<FMT_U24_BE, int32_t>(in, out, samples);
+ break;
+
+ case FMT_S32_LE:
+ from_int_loop<FMT_S32_LE, int32_t>(in, out, samples);
+ break;
+ case FMT_S32_BE:
+ from_int_loop<FMT_S32_BE, int32_t>(in, out, samples);
+ break;
+ case FMT_U32_LE:
+ from_int_loop<FMT_U32_LE, int32_t>(in, out, samples);
+ break;
+ case FMT_U32_BE:
+ from_int_loop<FMT_U32_BE, int32_t>(in, out, samples);
+ break;
+
+ case FMT_S24_3LE:
+ from_int_loop<FMT_S24_3LE, packed24_t, int32_t>(in, out, samples);
+ break;
+ case FMT_S24_3BE:
+ from_int_loop<FMT_S24_3BE, packed24_t, int32_t>(in, out, samples);
+ break;
+ case FMT_U24_3LE:
+ from_int_loop<FMT_U24_3LE, packed24_t, int32_t>(in, out, samples);
+ break;
+ case FMT_U24_3BE:
+ from_int_loop<FMT_U24_3BE, packed24_t, int32_t>(in, out, samples);
+ break;
}
}
-EXPORT void audio_to_int (const float * in, void * out, int format, int samples)
+EXPORT void audio_to_int(const float * in, void * out, int format, int samples)
{
- int save = fegetround ();
- fesetround (FE_TONEAREST);
+ int save = fegetround();
+ fesetround(FE_TONEAREST);
switch (format)
{
- case FMT_S8: to_int_loop<FMT_S8, int8_t> (in, out, samples); break;
- case FMT_U8: to_int_loop<FMT_U8, int8_t> (in, out, samples); break;
-
- case FMT_S16_LE: to_int_loop<FMT_S16_LE, int16_t> (in, out, samples); break;
- case FMT_S16_BE: to_int_loop<FMT_S16_BE, int16_t> (in, out, samples); break;
- case FMT_U16_LE: to_int_loop<FMT_U16_LE, int16_t> (in, out, samples); break;
- case FMT_U16_BE: to_int_loop<FMT_U16_BE, int16_t> (in, out, samples); break;
-
- case FMT_S24_LE: to_int_loop<FMT_S24_LE, int32_t> (in, out, samples); break;
- case FMT_S24_BE: to_int_loop<FMT_S24_BE, int32_t> (in, out, samples); break;
- case FMT_U24_LE: to_int_loop<FMT_U24_LE, int32_t> (in, out, samples); break;
- case FMT_U24_BE: to_int_loop<FMT_U24_BE, int32_t> (in, out, samples); break;
-
- case FMT_S32_LE: to_int_loop<FMT_S32_LE, int32_t> (in, out, samples); break;
- case FMT_S32_BE: to_int_loop<FMT_S32_BE, int32_t> (in, out, samples); break;
- case FMT_U32_LE: to_int_loop<FMT_U32_LE, int32_t> (in, out, samples); break;
- case FMT_U32_BE: to_int_loop<FMT_U32_BE, int32_t> (in, out, samples); break;
-
- case FMT_S24_3LE: to_int_loop<FMT_S24_3LE, packed24_t, int32_t> (in, out, samples); break;
- case FMT_S24_3BE: to_int_loop<FMT_S24_3BE, packed24_t, int32_t> (in, out, samples); break;
- case FMT_U24_3LE: to_int_loop<FMT_U24_3LE, packed24_t, int32_t> (in, out, samples); break;
- case FMT_U24_3BE: to_int_loop<FMT_U24_3BE, packed24_t, int32_t> (in, out, samples); break;
+ case FMT_S8:
+ to_int_loop<FMT_S8, int8_t>(in, out, samples);
+ break;
+ case FMT_U8:
+ to_int_loop<FMT_U8, int8_t>(in, out, samples);
+ break;
+
+ case FMT_S16_LE:
+ to_int_loop<FMT_S16_LE, int16_t>(in, out, samples);
+ break;
+ case FMT_S16_BE:
+ to_int_loop<FMT_S16_BE, int16_t>(in, out, samples);
+ break;
+ case FMT_U16_LE:
+ to_int_loop<FMT_U16_LE, int16_t>(in, out, samples);
+ break;
+ case FMT_U16_BE:
+ to_int_loop<FMT_U16_BE, int16_t>(in, out, samples);
+ break;
+
+ case FMT_S24_LE:
+ to_int_loop<FMT_S24_LE, int32_t>(in, out, samples);
+ break;
+ case FMT_S24_BE:
+ to_int_loop<FMT_S24_BE, int32_t>(in, out, samples);
+ break;
+ case FMT_U24_LE:
+ to_int_loop<FMT_U24_LE, int32_t>(in, out, samples);
+ break;
+ case FMT_U24_BE:
+ to_int_loop<FMT_U24_BE, int32_t>(in, out, samples);
+ break;
+
+ case FMT_S32_LE:
+ to_int_loop<FMT_S32_LE, int32_t>(in, out, samples);
+ break;
+ case FMT_S32_BE:
+ to_int_loop<FMT_S32_BE, int32_t>(in, out, samples);
+ break;
+ case FMT_U32_LE:
+ to_int_loop<FMT_U32_LE, int32_t>(in, out, samples);
+ break;
+ case FMT_U32_BE:
+ to_int_loop<FMT_U32_BE, int32_t>(in, out, samples);
+ break;
+
+ case FMT_S24_3LE:
+ to_int_loop<FMT_S24_3LE, packed24_t, int32_t>(in, out, samples);
+ break;
+ case FMT_S24_3BE:
+ to_int_loop<FMT_S24_3BE, packed24_t, int32_t>(in, out, samples);
+ break;
+ case FMT_U24_3LE:
+ to_int_loop<FMT_U24_3LE, packed24_t, int32_t>(in, out, samples);
+ break;
+ case FMT_U24_3BE:
+ to_int_loop<FMT_U24_3BE, packed24_t, int32_t>(in, out, samples);
+ break;
}
- fesetround (save);
+ fesetround(save);
}
-EXPORT void audio_amplify (float * data, int channels, int frames, const float * factors)
+EXPORT void audio_amplify(float * data, int channels, int frames,
+ const float * factors)
{
float * end = data + channels * frames;
int channel;
while (data < end)
{
- for (channel = 0; channel < channels; channel ++)
+ for (channel = 0; channel < channels; channel++)
{
- * data = * data * factors[channel];
- data ++;
+ *data = *data * factors[channel];
+ data++;
}
}
}
-EXPORT void audio_amplify (float * data, int channels, int frames, StereoVolume volume)
+EXPORT void audio_amplify(float * data, int channels, int frames,
+ StereoVolume volume)
{
if (channels < 1 || channels > AUD_MAX_CHANNELS)
return;
@@ -345,9 +457,11 @@ EXPORT void audio_amplify (float * data, int channels, int frames, StereoVolume
float factors[AUD_MAX_CHANNELS];
if (volume.left > 0)
- lfactor = powf (10, (float) SW_VOLUME_RANGE * (volume.left - 100) / 100 / 20);
+ lfactor =
+ powf(10, (float)SW_VOLUME_RANGE * (volume.left - 100) / 100 / 20);
if (volume.right > 0)
- rfactor = powf (10, (float) SW_VOLUME_RANGE * (volume.right - 100) / 100 / 20);
+ rfactor =
+ powf(10, (float)SW_VOLUME_RANGE * (volume.right - 100) / 100 / 20);
if (channels == 2)
{
@@ -356,37 +470,37 @@ EXPORT void audio_amplify (float * data, int channels, int frames, StereoVolume
}
else
{
- for (int c = 0; c < channels; c ++)
- factors[c] = aud::max (lfactor, rfactor);
+ for (int c = 0; c < channels; c++)
+ factors[c] = aud::max(lfactor, rfactor);
}
- audio_amplify (data, channels, frames, factors);
+ audio_amplify(data, channels, frames, factors);
}
/* linear approximation of y = sin(x) */
/* contributed by Anders Johansson */
-EXPORT void audio_soft_clip (float * data, int samples)
+EXPORT void audio_soft_clip(float * data, int samples)
{
float * end = data + samples;
while (data < end)
{
- float x = * data;
- float y = fabsf (x);
+ float x = *data;
+ float y = fabsf(x);
if (y <= 0.4)
- ; /* (0, 0.4) -> (0, 0.4) */
+ ; /* (0, 0.4) -> (0, 0.4) */
else if (y <= 0.7)
- y = 0.8 * y + 0.08; /* (0.4, 0.7) -> (0.4, 0.64) */
+ y = 0.8 * y + 0.08; /* (0.4, 0.7) -> (0.4, 0.64) */
else if (y <= 1.0)
- y = 0.7 * y + 0.15; /* (0.7, 1) -> (0.64, 0.85) */
+ y = 0.7 * y + 0.15; /* (0.7, 1) -> (0.64, 0.85) */
else if (y <= 1.3)
- y = 0.4 * y + 0.45; /* (1, 1.3) -> (0.85, 0.97) */
+ y = 0.4 * y + 0.45; /* (1, 1.3) -> (0.85, 0.97) */
else if (y <= 1.5)
- y = 0.15 * y + 0.775; /* (1.3, 1.5) -> (0.97, 1) */
+ y = 0.15 * y + 0.775; /* (1.3, 1.5) -> (0.97, 1) */
else
- y = 1.0; /* (1.5, inf) -> 1 */
+ y = 1.0; /* (1.5, inf) -> 1 */
- * data ++ = (x > 0) ? y : -y;
+ *data++ = (x > 0) ? y : -y;
}
}
diff --git a/src/libaudcore/audstrings.cc b/src/libaudcore/audstrings.cc
index a53f8e7..d0f2264 100644
--- a/src/libaudcore/audstrings.cc
+++ b/src/libaudcore/audstrings.cc
@@ -1,6 +1,6 @@
/*
* audstrings.c
- * Copyright 2009-2012 John Lindgren and William Pitcock
+ * Copyright 2009-2012 John Lindgren and Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -34,8 +34,8 @@
#include "runtime.h"
#define MAX_POW10 9
-static const unsigned int_pow10[MAX_POW10 + 1] =
- {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
+static const unsigned int_pow10[MAX_POW10 + 1] = {
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
static const char ascii_to_hex[256] =
"\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0"
@@ -47,20 +47,19 @@ static const char ascii_to_hex[256] =
"\x0\xa\xb\xc\xd\xe\xf\x0\x0\x0\x0\x0\x0\x0\x0\x0"
"\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0";
-static const char hex_to_ascii[16] = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-};
+static const char hex_to_ascii[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
static const char uri_legal_table[256] =
"\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0"
"\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0"
- "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x1\x1\x1" // '-' '.' '/'
+ "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x1\x1\x1" // '-' '.' '/'
#ifdef _WIN32
/* We assume ':' is used with a "reserved purpose" (i.e. drive letter).
* This assumption might need to be reconsidered for non-file URIs. */
- "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x0\x0\x0\x0\x0" // 0-9 ':'
+ "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x0\x0\x0\x0\x0" // 0-9 ':'
#else
- "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x0\x0\x0\x0\x0\x0" // 0-9
+ "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x0\x0\x0\x0\x0\x0" // 0-9
#endif
"\x0\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1" // A-O
"\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x0\x0\x0\x0\x1" // P-Z '_'
@@ -73,10 +72,10 @@ static const char swap_case[256] =
"\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0"
"\0ABCDEFGHIJKLMNOPQRSTUVWXYZ\0\0\0\0\0";
-#define FROM_HEX(c) (ascii_to_hex[(unsigned char) (c)])
-#define TO_HEX(i) (hex_to_ascii[(i) & 15])
-#define IS_LEGAL(c) (uri_legal_table[(unsigned char) (c)])
-#define SWAP_CASE(c) (swap_case[(unsigned char) (c)])
+#define FROM_HEX(c) (ascii_to_hex[(unsigned char)(c)])
+#define TO_HEX(i) (hex_to_ascii[(i)&15])
+#define IS_LEGAL(c) (uri_legal_table[(unsigned char)(c)])
+#define SWAP_CASE(c) (swap_case[(unsigned char)(c)])
#ifdef _WIN32
#define IS_SEP(c) ((c) == '/' || (c) == '\\')
@@ -85,119 +84,120 @@ static const char swap_case[256] =
#endif
/* strcmp() that handles nullptr safely */
-EXPORT int strcmp_safe (const char * a, const char * b, int len)
+EXPORT int strcmp_safe(const char * a, const char * b, int len)
{
- if (! a)
+ if (!a)
return b ? -1 : 0;
- if (! b)
+ if (!b)
return 1;
- return len < 0 ? strcmp (a, b) : strncmp (a, b, len);
+ return len < 0 ? strcmp(a, b) : strncmp(a, b, len);
}
/* ASCII version of strcasecmp, also handles nullptr safely */
-EXPORT int strcmp_nocase (const char * a, const char * b, int len)
+EXPORT int strcmp_nocase(const char * a, const char * b, int len)
{
- if (! a)
+ if (!a)
return b ? -1 : 0;
- if (! b)
+ if (!b)
return 1;
- return len < 0 ? g_ascii_strcasecmp (a, b) : g_ascii_strncasecmp (a, b, len);
+ return len < 0 ? g_ascii_strcasecmp(a, b) : g_ascii_strncasecmp(a, b, len);
}
/* strlen() if <len> is negative, otherwise strnlen() */
-EXPORT int strlen_bounded (const char * s, int len)
+EXPORT int strlen_bounded(const char * s, int len)
{
if (len < 0)
- return strlen (s);
+ return strlen(s);
- const char * nul = (const char *) memchr (s, 0, len);
+ const char * nul = (const char *)memchr(s, 0, len);
if (nul)
return nul - s;
return len;
}
-EXPORT StringBuf str_copy (const char * s, int len)
+EXPORT StringBuf str_copy(const char * s, int len)
{
if (len < 0)
- len = strlen (s);
+ len = strlen(s);
- StringBuf str (len);
- memcpy (str, s, len);
+ StringBuf str(len);
+ memcpy(str, s, len);
return str;
}
-EXPORT StringBuf str_concat (const std::initializer_list<const char *> & strings)
+EXPORT StringBuf str_concat(const std::initializer_list<const char *> & strings)
{
- StringBuf str (-1);
+ StringBuf str(-1);
char * set = str;
- int left = str.len ();
+ int left = str.len();
for (const char * s : strings)
{
- int len = strlen (s);
+ int len = strlen(s);
if (len > left)
- throw std::bad_alloc ();
+ throw std::bad_alloc();
- memcpy (set, s, len);
+ memcpy(set, s, len);
set += len;
left -= len;
}
- str.resize (set - str);
+ str.resize(set - str);
return str;
}
-EXPORT StringBuf str_printf (const char * format, ...)
+EXPORT StringBuf str_printf(const char * format, ...)
{
va_list args;
- va_start (args, format);
- StringBuf str = str_vprintf (format, args);
- va_end (args);
+ va_start(args, format);
+ StringBuf str = str_vprintf(format, args);
+ va_end(args);
return str;
}
-EXPORT void str_append_printf (StringBuf & str, const char * format, ...)
+EXPORT void str_append_printf(StringBuf & str, const char * format, ...)
{
va_list args;
- va_start (args, format);
- str_append_vprintf (str, format, args);
- va_end (args);
+ va_start(args, format);
+ str_append_vprintf(str, format, args);
+ va_end(args);
}
-EXPORT StringBuf str_vprintf (const char * format, va_list args)
+EXPORT StringBuf str_vprintf(const char * format, va_list args)
{
- StringBuf str (-1);
- int len = vsnprintf (str, str.len (), format, args);
- str.resize (len);
+ StringBuf str(-1);
+ int len = vsnprintf(str, str.len(), format, args);
+ str.resize(len);
return str;
}
-EXPORT void str_append_vprintf (StringBuf & str, const char * format, va_list args)
+EXPORT void str_append_vprintf(StringBuf & str, const char * format,
+ va_list args)
{
- int len0 = str.len ();
- str.resize (-1);
- int len1 = vsnprintf (str + len0, str.len () - len0, format, args);
- str.resize (len0 + len1);
+ int len0 = str.len();
+ str.resize(-1);
+ int len1 = vsnprintf(str + len0, str.len() - len0, format, args);
+ str.resize(len0 + len1);
}
-EXPORT bool str_has_prefix_nocase (const char * str, const char * prefix)
+EXPORT bool str_has_prefix_nocase(const char * str, const char * prefix)
{
- return ! g_ascii_strncasecmp (str, prefix, strlen (prefix));
+ return !g_ascii_strncasecmp(str, prefix, strlen(prefix));
}
-EXPORT bool str_has_suffix_nocase (const char * str, const char * suffix)
+EXPORT bool str_has_suffix_nocase(const char * str, const char * suffix)
{
- int len1 = strlen (str);
- int len2 = strlen (suffix);
+ int len1 = strlen(str);
+ int len2 = strlen(suffix);
if (len2 > len1)
return false;
- return ! g_ascii_strcasecmp (str + len1 - len2, suffix);
+ return !g_ascii_strcasecmp(str + len1 - len2, suffix);
}
/* Bernstein's hash function (unrolled version):
@@ -207,23 +207,18 @@ EXPORT bool str_has_suffix_nocase (const char * str, const char * suffix)
* This function is more than twice as fast as g_str_hash (a simpler version of
* Bernstein's hash) and even slightly faster than Murmur 3. */
-EXPORT unsigned str_calc_hash (const char * s)
+EXPORT unsigned str_calc_hash(const char * s)
{
unsigned h = 5381;
- int len = strlen (s);
+ int len = strlen(s);
while (len >= 8)
{
- h = h * 1954312449 +
- (unsigned) s[0] * 3963737313 +
- (unsigned) s[1] * 1291467969 +
- (unsigned) s[2] * 39135393 +
- (unsigned) s[3] * 1185921 +
- (unsigned) s[4] * 35937 +
- (unsigned) s[5] * 1089 +
- (unsigned) s[6] * 33 +
- s[7];
+ h = h * 1954312449 + (unsigned)s[0] * 3963737313 +
+ (unsigned)s[1] * 1291467969 + (unsigned)s[2] * 39135393 +
+ (unsigned)s[3] * 1185921 + (unsigned)s[4] * 35937 +
+ (unsigned)s[5] * 1089 + (unsigned)s[6] * 33 + s[7];
s += 8;
len -= 8;
@@ -231,11 +226,8 @@ EXPORT unsigned str_calc_hash (const char * s)
if (len >= 4)
{
- h = h * 1185921 +
- (unsigned) s[0] * 35937 +
- (unsigned) s[1] * 1089 +
- (unsigned) s[2] * 33 +
- s[3];
+ h = h * 1185921 + (unsigned)s[0] * 35937 + (unsigned)s[1] * 1089 +
+ (unsigned)s[2] * 33 + s[3];
s += 4;
len -= 4;
@@ -243,15 +235,18 @@ EXPORT unsigned str_calc_hash (const char * s)
switch (len)
{
- case 3: h = h * 33 + (* s ++);
- case 2: h = h * 33 + (* s ++);
- case 1: h = h * 33 + (* s ++);
+ case 3:
+ h = h * 33 + (*s++);
+ case 2:
+ h = h * 33 + (*s++);
+ case 1:
+ h = h * 33 + (*s++);
}
return h;
}
-EXPORT const char * strstr_nocase (const char * haystack, const char * needle)
+EXPORT const char * strstr_nocase(const char * haystack, const char * needle)
{
while (1)
{
@@ -260,23 +255,24 @@ EXPORT const char * strstr_nocase (const char * haystack, const char * needle)
while (1)
{
- char a = * ap ++;
- char b = * bp ++;
+ char a = *ap++;
+ char b = *bp++;
- if (! b) /* all of needle matched */
- return (char *) haystack;
- if (! a) /* end of haystack reached */
+ if (!b) /* all of needle matched */
+ return (char *)haystack;
+ if (!a) /* end of haystack reached */
return nullptr;
- if (a != b && a != SWAP_CASE (b))
+ if (a != b && a != SWAP_CASE(b))
break;
}
- haystack ++;
+ haystack++;
}
}
-EXPORT const char * strstr_nocase_utf8 (const char * haystack, const char * needle)
+EXPORT const char * strstr_nocase_utf8(const char * haystack,
+ const char * needle)
{
while (1)
{
@@ -285,112 +281,114 @@ EXPORT const char * strstr_nocase_utf8 (const char * haystack, const char * need
while (1)
{
- gunichar a = g_utf8_get_char (ap);
- gunichar b = g_utf8_get_char (bp);
+ gunichar a = g_utf8_get_char(ap);
+ gunichar b = g_utf8_get_char(bp);
- if (! b) /* all of needle matched */
- return (char *) haystack;
- if (! a) /* end of haystack reached */
+ if (!b) /* all of needle matched */
+ return (char *)haystack;
+ if (!a) /* end of haystack reached */
return nullptr;
- if (a != b && (a < 128 ? (gunichar) SWAP_CASE (a) != b :
- g_unichar_tolower (a) != g_unichar_tolower (b)))
+ if (a != b &&
+ (a < 128 ? (gunichar)SWAP_CASE(a) != b
+ : g_unichar_tolower(a) != g_unichar_tolower(b)))
break;
- ap = g_utf8_next_char (ap);
- bp = g_utf8_next_char (bp);
+ ap = g_utf8_next_char(ap);
+ bp = g_utf8_next_char(bp);
}
- haystack = g_utf8_next_char (haystack);
+ haystack = g_utf8_next_char(haystack);
}
}
-EXPORT StringBuf str_tolower (const char * str)
+EXPORT StringBuf str_tolower(const char * str)
{
- StringBuf buf (strlen (str));
+ StringBuf buf(strlen(str));
char * set = buf;
- while (* str)
- * set ++ = g_ascii_tolower (* str ++);
+ while (*str)
+ *set++ = g_ascii_tolower(*str++);
return buf;
}
-EXPORT StringBuf str_tolower_utf8 (const char * str)
+EXPORT StringBuf str_tolower_utf8(const char * str)
{
- StringBuf buf (6 * strlen (str));
+ StringBuf buf(6 * strlen(str));
char * set = buf;
gunichar c;
- while ((c = g_utf8_get_char (str)))
+ while ((c = g_utf8_get_char(str)))
{
if (c < 128)
- * set ++ = g_ascii_tolower (c);
+ *set++ = g_ascii_tolower(c);
else
- set += g_unichar_to_utf8 (g_unichar_tolower (c), set);
+ set += g_unichar_to_utf8(g_unichar_tolower(c), set);
- str = g_utf8_next_char (str);
+ str = g_utf8_next_char(str);
}
- buf.resize (set - buf);
+ buf.resize(set - buf);
return buf;
}
-EXPORT StringBuf str_toupper (const char * str)
+EXPORT StringBuf str_toupper(const char * str)
{
- StringBuf buf (strlen (str));
+ StringBuf buf(strlen(str));
char * set = buf;
- while (* str)
- * set ++ = g_ascii_toupper (* str ++);
+ while (*str)
+ *set++ = g_ascii_toupper(*str++);
return buf;
}
-EXPORT StringBuf str_toupper_utf8 (const char * str)
+EXPORT StringBuf str_toupper_utf8(const char * str)
{
- StringBuf buf (6 * strlen (str));
+ StringBuf buf(6 * strlen(str));
char * set = buf;
gunichar c;
- while ((c = g_utf8_get_char (str)))
+ while ((c = g_utf8_get_char(str)))
{
if (c < 128)
- * set ++ = g_ascii_toupper (c);
+ *set++ = g_ascii_toupper(c);
else
- set += g_unichar_to_utf8 (g_unichar_toupper (c), set);
+ set += g_unichar_to_utf8(g_unichar_toupper(c), set);
- str = g_utf8_next_char (str);
+ str = g_utf8_next_char(str);
}
- buf.resize (set - buf);
+ buf.resize(set - buf);
return buf;
}
-EXPORT void str_replace_char (char * string, char old_c, char new_c)
+EXPORT void str_replace_char(char * string, char old_c, char new_c)
{
- while ((string = strchr (string, old_c)))
- * string ++ = new_c;
+ while ((string = strchr(string, old_c)))
+ *string++ = new_c;
}
-/* Percent-decodes <len> bytes of <str>. If <len> is negative, decodes all of <str>. */
+/* Percent-decodes <len> bytes of <str>. If <len> is negative, decodes all of
+ * <str>. */
-EXPORT StringBuf str_decode_percent (const char * str, int len)
+EXPORT StringBuf str_decode_percent(const char * str, int len)
{
if (len < 0)
- len = strlen (str);
+ len = strlen(str);
- StringBuf buf (len);
+ StringBuf buf(len);
char * out = buf;
while (1)
{
- const char * p = (const char *) memchr (str, '%', len);
- if (! p)
+ const char * p = (const char *)memchr(str, '%', len);
+ if (!p)
break;
int block = p - str;
- memcpy (out, str, block);
+ memcpy(out, str, block);
str += block;
out += block;
@@ -399,181 +397,187 @@ EXPORT StringBuf str_decode_percent (const char * str, int len)
if (len < 3)
break;
- * out ++ = (FROM_HEX (str[1]) << 4) | FROM_HEX (str[2]);
+ *out++ = (FROM_HEX(str[1]) << 4) | FROM_HEX(str[2]);
str += 3;
len -= 3;
}
- memcpy (out, str, len);
- buf.resize (out + len - buf);
+ memcpy(out, str, len);
+ buf.resize(out + len - buf);
return buf;
}
-/* Percent-encodes <len> bytes of <str>. If <len> is negative, encodes all of <str>. */
+/* Percent-encodes <len> bytes of <str>. If <len> is negative, encodes all of
+ * <str>. */
-EXPORT StringBuf str_encode_percent (const char * str, int len)
+EXPORT StringBuf str_encode_percent(const char * str, int len)
{
if (len < 0)
- len = strlen (str);
+ len = strlen(str);
- StringBuf buf (3 * len);
+ StringBuf buf(3 * len);
char * out = buf;
- while (len --)
+ while (len--)
{
- char c = * str ++;
+ char c = *str++;
- if (IS_LEGAL (c))
- * out ++ = c;
+ if (IS_LEGAL(c))
+ *out++ = c;
else
{
- * out ++ = '%';
- * out ++ = TO_HEX ((unsigned char) c >> 4);
- * out ++ = TO_HEX (c & 0xF);
+ *out++ = '%';
+ *out++ = TO_HEX((unsigned char)c >> 4);
+ *out++ = TO_HEX(c & 0xF);
}
}
- buf.resize (out - buf);
+ buf.resize(out - buf);
return buf;
}
-EXPORT StringBuf filename_normalize (StringBuf && filename)
+EXPORT StringBuf filename_normalize(StringBuf && filename)
{
int len;
char * s;
#ifdef _WIN32
/* convert slash to backslash on Windows */
- str_replace_char (filename, '/', '\\');
+ str_replace_char(filename, '/', '\\');
#endif
/* remove current directory (".") elements */
- while ((len = filename.len ()) >= 2 &&
- (! strcmp ((s = filename + len - 2), G_DIR_SEPARATOR_S ".") ||
- (s = strstr (filename, G_DIR_SEPARATOR_S "." G_DIR_SEPARATOR_S))))
- filename.remove (s + 1 - filename, aud::min (s + 3, filename + len) - (s + 1));
+ while ((len = filename.len()) >= 2 &&
+ (!strcmp((s = filename + len - 2), G_DIR_SEPARATOR_S ".") ||
+ (s = strstr(filename, G_DIR_SEPARATOR_S "." G_DIR_SEPARATOR_S))))
+ filename.remove(s + 1 - filename,
+ aud::min(s + 3, filename + len) - (s + 1));
/* remove parent directory ("..") elements */
- while ((len = filename.len ()) >= 3 &&
- (! strcmp ((s = filename + len - 3), G_DIR_SEPARATOR_S "..") ||
- (s = strstr (filename, G_DIR_SEPARATOR_S ".." G_DIR_SEPARATOR_S))))
+ while ((len = filename.len()) >= 3 &&
+ (!strcmp((s = filename + len - 3), G_DIR_SEPARATOR_S "..") ||
+ (s = strstr(filename, G_DIR_SEPARATOR_S ".." G_DIR_SEPARATOR_S))))
{
- * s = 0;
- char * s2 = strrchr (filename, G_DIR_SEPARATOR);
- if (! s2)
- * (s2 = s) = G_DIR_SEPARATOR;
+ *s = 0;
+ char * s2 = strrchr(filename, G_DIR_SEPARATOR);
+ if (!s2)
+ *(s2 = s) = G_DIR_SEPARATOR;
- filename.remove (s2 + 1 - filename, aud::min (s + 4, filename + len) - (s2 + 1));
+ filename.remove(s2 + 1 - filename,
+ aud::min(s + 4, filename + len) - (s2 + 1));
}
/* remove trailing slash */
#ifdef _WIN32
- if ((len = filename.len ()) > 3 && filename[len - 1] == '\\') /* leave "C:\" */
+ if ((len = filename.len()) > 3 &&
+ filename[len - 1] == '\\') /* leave "C:\" */
#else
- if ((len = filename.len ()) > 1 && filename[len - 1] == '/') /* leave leading "/" */
+ if ((len = filename.len()) > 1 &&
+ filename[len - 1] == '/') /* leave leading "/" */
#endif
- filename.resize (len - 1);
+ filename.resize(len - 1);
- return std::move (filename);
+ return std::move(filename);
}
/* note #1: recommended order is filename_contract(filename_normalize(f)) */
/* note #2: currently assumes filename is UTF-8 (intended for display) */
-EXPORT StringBuf filename_contract (StringBuf && filename)
+EXPORT StringBuf filename_contract(StringBuf && filename)
{
/* replace home folder with '~' */
- const char * home = get_home_utf8 ();
- int homelen = home ? strlen (home) : 0;
+ const char * home = get_home_utf8();
+ int homelen = home ? strlen(home) : 0;
- if (homelen && ! strncmp (filename, home, homelen) &&
- (! filename[homelen] || IS_SEP (filename[homelen])))
+ if (homelen && !strncmp(filename, home, homelen) &&
+ (!filename[homelen] || IS_SEP(filename[homelen])))
{
filename[0] = '~';
- filename.remove (1, homelen - 1);
+ filename.remove(1, homelen - 1);
}
- return std::move (filename);
+ return std::move(filename);
}
/* note #1: recommended order is filename_normalize(filename_expand(f)) */
/* note #2: currently assumes filename is UTF-8 (intended for display) */
-EXPORT StringBuf filename_expand (StringBuf && filename)
+EXPORT StringBuf filename_expand(StringBuf && filename)
{
/* expand leading '~' */
- if (filename[0] == '~' && (! filename[1] || IS_SEP(filename[1])))
+ if (filename[0] == '~' && (!filename[1] || IS_SEP(filename[1])))
{
- const char * home = get_home_utf8 ();
+ const char * home = get_home_utf8();
if (home && home[0])
{
filename[0] = home[0];
- filename.insert (1, home + 1, -1);
+ filename.insert(1, home + 1, -1);
}
}
- return std::move (filename);
+ return std::move(filename);
}
-EXPORT StringBuf filename_get_parent (const char * filename)
+EXPORT StringBuf filename_get_parent(const char * filename)
{
- StringBuf buf = filename_normalize (str_copy (filename));
- const char * base = last_path_element (buf);
+ StringBuf buf = filename_normalize(str_copy(filename));
+ const char * base = last_path_element(buf);
- if (! base)
- return StringBuf ();
+ if (!base)
+ return StringBuf();
#ifdef _WIN32
if (base - buf > 3) /* leave "C:\" */
#else
- if (base - buf > 1) /* leave leading "/" */
+ if (base - buf > 1) /* leave leading "/" */
#endif
- buf.resize (base - buf - 1);
+ buf.resize(base - buf - 1);
else
- buf.resize (base - buf);
+ buf.resize(base - buf);
return buf;
}
-EXPORT StringBuf filename_get_base (const char * filename)
+EXPORT StringBuf filename_get_base(const char * filename)
{
- StringBuf buf = filename_normalize (str_copy (filename));
- const char * base = last_path_element (buf);
+ StringBuf buf = filename_normalize(str_copy(filename));
+ const char * base = last_path_element(buf);
if (base)
- buf.remove (0, base - buf);
+ buf.remove(0, base - buf);
return buf;
}
-EXPORT StringBuf filename_build (const std::initializer_list<const char *> & elems)
+EXPORT StringBuf
+filename_build(const std::initializer_list<const char *> & elems)
{
- StringBuf str (-1);
+ StringBuf str(-1);
char * set = str;
- int left = str.len ();
+ int left = str.len();
for (const char * s : elems)
{
- if (set > str && ! IS_SEP (set[-1]))
+ if (set > str && !IS_SEP(set[-1]))
{
- if (! left)
- throw std::bad_alloc ();
+ if (!left)
+ throw std::bad_alloc();
- * set ++ = G_DIR_SEPARATOR;
- left --;
+ *set++ = G_DIR_SEPARATOR;
+ left--;
}
- int len = strlen (s);
+ int len = strlen(s);
if (len > left)
- throw std::bad_alloc ();
+ throw std::bad_alloc();
- memcpy (set, s, len);
+ memcpy(set, s, len);
set += len;
left -= len;
}
- str.resize (set - str);
+ str.resize(set - str);
return str;
}
@@ -589,24 +593,24 @@ EXPORT StringBuf filename_build (const std::initializer_list<const char *> & ele
* UTF-8 before percent-encoding (except on Windows, where filenames are assumed
* to be UTF-8). On Windows, replaces '\' with '/' and adds a leading '/'. */
-EXPORT StringBuf filename_to_uri (const char * name)
+EXPORT StringBuf filename_to_uri(const char * name)
{
#ifdef _WIN32
- StringBuf buf = str_copy (name);
- str_replace_char (buf, '\\', '/');
+ StringBuf buf = str_copy(name);
+ str_replace_char(buf, '\\', '/');
#else
StringBuf buf;
/* convert from locale if:
* 1) system locale is not UTF-8, and
* 2) filename is not already valid UTF-8 */
- if (! g_get_charset (nullptr) && ! g_utf8_validate (name, -1, nullptr))
- buf = str_from_locale (name);
+ if (!g_get_charset(nullptr) && !g_utf8_validate(name, -1, nullptr))
+ buf = str_from_locale(name);
#endif
- buf = str_encode_percent (buf ? buf : name);
- buf.insert (0, URI_PREFIX);
- return buf.settle ();
+ buf = str_encode_percent(buf ? buf : name);
+ buf.insert(0, URI_PREFIX);
+ return buf.settle();
}
/* Like g_filename_from_uri, but optionally converts the filename from UTF-8 to
@@ -615,59 +619,60 @@ EXPORT StringBuf filename_to_uri (const char * name)
* '/' with '\'. If the input is not a valid URI, it is assumed to be a local
* filename already and is not percent-decoded. */
-EXPORT StringBuf uri_to_filename (const char * uri, bool use_locale)
+EXPORT StringBuf uri_to_filename(const char * uri, bool use_locale)
{
StringBuf buf;
- if (! strncmp (uri, URI_PREFIX, URI_PREFIX_LEN))
- buf = str_decode_percent (uri + URI_PREFIX_LEN);
- else if (! strstr (uri, "://")) /* already a local filename? */
- buf = str_copy (uri);
+ if (!strncmp(uri, URI_PREFIX, URI_PREFIX_LEN))
+ buf = str_decode_percent(uri + URI_PREFIX_LEN);
+ else if (!strstr(uri, "://")) /* already a local filename? */
+ buf = str_copy(uri);
else
- return StringBuf ();
+ return StringBuf();
#ifndef _WIN32
/* convert to locale if:
* 1) use_locale flag was not set to false, and
* 2) system locale is not UTF-8, and
* 3) decoded URI is valid UTF-8 */
- if (use_locale && ! g_get_charset (nullptr) && g_utf8_validate (buf, buf.len (), nullptr))
+ if (use_locale && !g_get_charset(nullptr) &&
+ g_utf8_validate(buf, buf.len(), nullptr))
{
- StringBuf locale = str_to_locale (buf);
+ StringBuf locale = str_to_locale(buf);
if (locale)
- buf = std::move (locale);
+ buf = std::move(locale);
}
#endif
/* if UTF-8 was requested, make sure the result is valid */
- if (! use_locale)
+ if (!use_locale)
{
- buf = str_to_utf8 (std::move (buf));
- if (! buf)
- return StringBuf ();
+ buf = str_to_utf8(std::move(buf));
+ if (!buf)
+ return StringBuf();
}
- return filename_normalize (buf.settle ());
+ return filename_normalize(buf.settle());
}
/* Formats a URI for human-readable display. Percent-decodes and, for file://
* URI's, converts to filename format, but in UTF-8. */
-EXPORT StringBuf uri_to_display (const char * uri)
+EXPORT StringBuf uri_to_display(const char * uri)
{
- if (! strncmp (uri, "stdin://", 8))
- return str_copy (_("Standard input"));
- if (! strncmp (uri, "cdda://?", 8))
- return str_printf (_("Audio CD, track %s"), uri + 8);
+ if (!strncmp(uri, "stdin://", 8))
+ return str_copy(_("Standard input"));
+ if (!strncmp(uri, "cdda://?", 8))
+ return str_printf(_("Audio CD, track %s"), uri + 8);
- StringBuf buf = str_to_utf8 (str_decode_percent (uri));
- if (! buf)
- return str_copy (_("(character encoding error)"));
+ StringBuf buf = str_to_utf8(str_decode_percent(uri));
+ if (!buf)
+ return str_copy(_("(character encoding error)"));
- if (! strncmp (buf, URI_PREFIX, URI_PREFIX_LEN))
+ if (!strncmp(buf, URI_PREFIX, URI_PREFIX_LEN))
{
- buf.remove (0, URI_PREFIX_LEN);
- return filename_contract (filename_normalize (std::move (buf)));
+ buf.remove(0, URI_PREFIX_LEN);
+ return filename_contract(filename_normalize(std::move(buf)));
}
return buf;
@@ -676,58 +681,69 @@ EXPORT StringBuf uri_to_display (const char * uri)
#undef URI_PREFIX
#undef URI_PREFIX_LEN
-EXPORT void uri_parse (const char * uri, const char * * base_p, const char * * ext_p,
- const char * * sub_p, int * isub_p)
+EXPORT void uri_parse(const char * uri, const char ** base_p,
+ const char ** ext_p, const char ** sub_p, int * isub_p)
{
- const char * end = uri + strlen (uri);
- const char * base, * ext, * sub, * c;
+ const char * end = uri + strlen(uri);
+ const char *base, *ext, *sub, *c;
int isub = 0;
char junk;
- if ((c = strrchr (uri, '/')))
+ if ((c = strrchr(uri, '/')))
base = c + 1;
else
base = end;
- if ((c = strrchr (base, '?')) && sscanf (c + 1, "%d%c", & isub, & junk) == 1)
+ if ((c = strrchr(base, '?')) && sscanf(c + 1, "%d%c", &isub, &junk) == 1)
sub = c;
else
sub = end;
- if ((c = strrchr (base, '.')) && c < sub)
+ if ((c = strrchr(base, '.')) && c < sub)
ext = c;
else
ext = sub;
if (base_p)
- * base_p = base;
+ *base_p = base;
if (ext_p)
- * ext_p = ext;
+ *ext_p = ext;
if (sub_p)
- * sub_p = sub;
+ *sub_p = sub;
if (isub_p)
- * isub_p = isub;
+ *isub_p = isub;
}
-EXPORT StringBuf uri_get_scheme (const char * uri)
+EXPORT StringBuf uri_get_scheme(const char * uri)
{
- const char * delim = strstr (uri, "://");
- return delim ? str_copy (uri, delim - uri) : StringBuf ();
+ const char * delim = strstr(uri, "://");
+ return delim ? str_copy(uri, delim - uri) : StringBuf();
}
-EXPORT StringBuf uri_get_extension (const char * uri)
+EXPORT StringBuf uri_get_extension(const char * uri)
{
const char * ext;
- uri_parse (uri, nullptr, & ext, nullptr, nullptr);
+ uri_parse(uri, nullptr, &ext, nullptr, nullptr);
if (ext[0] != '.')
- return StringBuf ();
+ return StringBuf();
- ext ++; // skip period
+ ext++; // skip period
// remove subtunes and HTTP query strings
- const char * qmark = strchr (ext, '?');
- return str_copy (ext, qmark ? qmark - ext : -1);
+ const char * qmark = strchr(ext, '?');
+ return str_copy(ext, qmark ? qmark - ext : -1);
+}
+
+EXPORT StringBuf uri_get_display_base(const char * uri)
+{
+ const char *base, *ext;
+ uri_parse(uri, &base, &ext, nullptr, nullptr);
+
+ if (ext > base)
+ return str_to_utf8(str_decode_percent(base, ext - base));
+
+ return StringBuf();
}
/* Constructs a full URI given:
@@ -737,35 +753,35 @@ EXPORT StringBuf uri_get_extension (const char * uri)
* c. a relative path (character set detected according to user settings)
* 2. reference: the full URI of the playlist containing <path> */
-EXPORT StringBuf uri_construct (const char * path, const char * reference)
+EXPORT StringBuf uri_construct(const char * path, const char * reference)
{
/* URI */
- if (strstr (path, "://"))
- return str_copy (path);
+ if (strstr(path, "://"))
+ return str_copy(path);
- /* absolute filename */
+ /* absolute filename */
#ifdef _WIN32
- if (path[0] && path[1] == ':' && IS_SEP (path[2]))
+ if (path[0] && path[1] == ':' && IS_SEP(path[2]))
#else
if (path[0] == '/')
#endif
- return filename_to_uri (path);
+ return filename_to_uri(path);
/* relative path */
- const char * slash = strrchr (reference, '/');
- if (! slash)
- return StringBuf ();
+ const char * slash = strrchr(reference, '/');
+ if (!slash)
+ return StringBuf();
- StringBuf buf = str_to_utf8 (path, -1);
- if (! buf)
- return StringBuf ();
+ StringBuf buf = str_to_utf8(path, -1);
+ if (!buf)
+ return StringBuf();
- if (aud_get_bool (nullptr, "convert_backslash"))
- str_replace_char (buf, '\\', '/');
+ if (aud_get_bool("convert_backslash"))
+ str_replace_char(buf, '\\', '/');
- buf = str_encode_percent (buf);
- buf.insert (0, reference, slash + 1 - reference);
- return buf.settle ();
+ buf = str_encode_percent(buf);
+ buf.insert(0, reference, slash + 1 - reference);
+ return buf.settle();
}
/* Basically the reverse of uri_construct().
@@ -779,39 +795,40 @@ EXPORT StringBuf uri_construct (const char * path, const char * reference)
* 1. uri: the full URI of a song file
* 2. reference: the full URI of the playlist being written */
-EXPORT StringBuf uri_deconstruct (const char * uri, const char * reference)
+EXPORT StringBuf uri_deconstruct(const char * uri, const char * reference)
{
- if (aud_get_bool (nullptr, "export_relative_paths"))
+ if (aud_get_bool("export_relative_paths"))
{
- const char * slash = strrchr (reference, '/');
- if (slash && ! strncmp (uri, reference, slash + 1 - reference))
+ const char * slash = strrchr(reference, '/');
+ if (slash && !strncmp(uri, reference, slash + 1 - reference))
{
- StringBuf path = str_to_utf8 (str_decode_percent (uri + (slash + 1 - reference)));
+ StringBuf path =
+ str_to_utf8(str_decode_percent(uri + (slash + 1 - reference)));
if (path)
return path;
}
}
- StringBuf filename = uri_to_filename (uri, false);
+ StringBuf filename = uri_to_filename(uri, false);
if (filename)
return filename;
- return str_copy (uri);
+ return str_copy(uri);
}
/* Like strcasecmp, but orders numbers correctly (2 before 10). */
/* Non-ASCII characters are treated exactly as is. */
/* Handles nullptr gracefully. */
-EXPORT int str_compare (const char * ap, const char * bp)
+EXPORT int str_compare(const char * ap, const char * bp)
{
- if (! ap)
+ if (!ap)
return bp ? -1 : 0;
- if (! bp)
+ if (!bp)
return 1;
- unsigned char a = * ap ++, b = * bp ++;
- for (; a || b; a = * ap ++, b = * bp ++)
+ unsigned char a = *ap++, b = *bp++;
+ for (; a || b; a = *ap++, b = *bp++)
{
if (a > '9' || b > '9' || a < '0' || b < '0')
{
@@ -828,11 +845,11 @@ EXPORT int str_compare (const char * ap, const char * bp)
else
{
int x = a - '0';
- for (; (a = * ap) <= '9' && a >= '0'; ap ++)
+ for (; (a = *ap) <= '9' && a >= '0'; ap++)
x = 10 * x + (a - '0');
int y = b - '0';
- for (; (b = * bp) >= '0' && b <= '9'; bp ++)
+ for (; (b = *bp) >= '0' && b <= '9'; bp++)
y = 10 * y + (b - '0');
if (x > y)
@@ -845,26 +862,26 @@ EXPORT int str_compare (const char * ap, const char * bp)
return 0;
}
-/* Decodes percent-encoded strings, then compares then with str_compare. */
+/* Decodes percent-encoded strings, then compares them with str_compare. */
-EXPORT int str_compare_encoded (const char * ap, const char * bp)
+EXPORT int str_compare_encoded(const char * ap, const char * bp)
{
- if (! ap)
+ if (!ap)
return bp ? -1 : 0;
- if (! bp)
+ if (!bp)
return 1;
- unsigned char a = * ap ++, b = * bp ++;
- for (; a || b; a = * ap ++, b = * bp ++)
+ unsigned char a = *ap++, b = *bp++;
+ for (; a || b; a = *ap++, b = *bp++)
{
if (a == '%' && ap[0] && ap[1])
{
- a = (FROM_HEX (ap[0]) << 4) | FROM_HEX (ap[1]);
+ a = (FROM_HEX(ap[0]) << 4) | FROM_HEX(ap[1]);
ap += 2;
}
if (b == '%' && bp[0] && bp[1])
{
- b = (FROM_HEX (bp[0]) << 4) | FROM_HEX (bp[1]);
+ b = (FROM_HEX(bp[0]) << 4) | FROM_HEX(bp[1]);
bp += 2;
}
@@ -883,11 +900,11 @@ EXPORT int str_compare_encoded (const char * ap, const char * bp)
else
{
int x = a - '0';
- for (; (a = * ap) <= '9' && a >= '0'; ap ++)
+ for (; (a = *ap) <= '9' && a >= '0'; ap++)
x = 10 * x + (a - '0');
int y = b - '0';
- for (; (b = * bp) >= '0' && b <= '9'; bp ++)
+ for (; (b = *bp) >= '0' && b <= '9'; bp++)
y = 10 * y + (b - '0');
if (x > y)
@@ -900,29 +917,29 @@ EXPORT int str_compare_encoded (const char * ap, const char * bp)
return 0;
}
-EXPORT Index<String> str_list_to_index (const char * list, const char * delims)
+EXPORT Index<String> str_list_to_index(const char * list, const char * delims)
{
char dmap[256] = {0};
- for (; * delims; delims ++)
- dmap[(unsigned char) (* delims)] = 1;
+ for (; *delims; delims++)
+ dmap[(unsigned char)(*delims)] = 1;
Index<String> index;
const char * word = nullptr;
- for (; * list; list ++)
+ for (; *list; list++)
{
- if (dmap[(unsigned char) (* list)])
+ if (dmap[(unsigned char)(*list)])
{
if (word)
{
- index.append (String (str_copy (word, list - word)));
+ index.append(String(str_copy(word, list - word)));
word = nullptr;
}
}
else
{
- if (! word)
+ if (!word)
{
word = list;
}
@@ -930,39 +947,40 @@ EXPORT Index<String> str_list_to_index (const char * list, const char * delims)
}
if (word)
- index.append (String (word));
+ index.append(String(word));
return index;
}
-EXPORT StringBuf index_to_str_list (const Index<String> & index, const char * sep)
+EXPORT StringBuf index_to_str_list(const Index<String> & index,
+ const char * sep)
{
- StringBuf str (-1);
+ StringBuf str(-1);
char * set = str;
- int left = str.len ();
- int seplen = strlen (sep);
+ int left = str.len();
+ int seplen = strlen(sep);
for (const String & s : index)
{
- int len = strlen (s);
+ int len = strlen(s);
if (len + seplen > left)
- throw std::bad_alloc ();
+ throw std::bad_alloc();
if (set > str)
{
- memcpy (set, sep, seplen);
+ memcpy(set, sep, seplen);
set += seplen;
left -= seplen;
}
- memcpy (set, s, len);
+ memcpy(set, s, len);
set += len;
left -= len;
}
- str.resize (set - str);
+ str.resize(set - str);
return str;
}
@@ -981,178 +999,178 @@ EXPORT StringBuf index_to_str_list (const Index<String> & index, const char * se
* have an accuracy of 6 decimal places.
*/
-static unsigned str_to_uint (const char * string, const char * * end = nullptr,
- const char * stop = nullptr)
+static unsigned str_to_uint(const char * string, const char ** end = nullptr,
+ const char * stop = nullptr)
{
unsigned val = 0;
- for (char c; string != stop && (c = * string) >= '0' && c <= '9'; string ++)
+ for (char c; string != stop && (c = *string) >= '0' && c <= '9'; string++)
val = val * 10 + (c - '0');
if (end)
- * end = string;
+ *end = string;
return val;
}
-static int digits_for (unsigned val)
+static int digits_for(unsigned val)
{
int digits = 1;
for (; val >= 1000; val /= 1000)
digits += 3;
for (; val >= 10; val /= 10)
- digits ++;
+ digits++;
return digits;
}
-static void uint_to_str (unsigned val, char * buf, int digits)
+static void uint_to_str(unsigned val, char * buf, int digits)
{
for (char * rev = buf + digits; rev > buf; val /= 10)
- * (-- rev) = '0' + val % 10;
+ *(--rev) = '0' + val % 10;
}
-EXPORT int str_to_int (const char * string)
+EXPORT int str_to_int(const char * string)
{
bool neg = (string[0] == '-');
if (neg || string[0] == '+')
- string ++;
+ string++;
- unsigned val = str_to_uint (string);
+ unsigned val = str_to_uint(string);
return neg ? -val : val;
}
-EXPORT double str_to_double (const char * string)
+EXPORT double str_to_double(const char * string)
{
bool neg = (string[0] == '-');
if (neg || string[0] == '+')
- string ++;
+ string++;
const char * p;
- double val = str_to_uint (string, & p);
+ double val = str_to_uint(string, &p);
- if (* (p ++) == '.')
+ if (*(p++) == '.')
{
const char * end;
- double decimal = str_to_uint (p, & end, p + MAX_POW10);
+ double decimal = str_to_uint(p, &end, p + MAX_POW10);
val += decimal / int_pow10[end - p];
}
return neg ? -val : val;
}
-EXPORT void str_insert_int (StringBuf & string, int pos, int val)
+EXPORT void str_insert_int(StringBuf & string, int pos, int val)
{
bool neg = (val < 0);
unsigned absval = neg ? -val : val;
- int digits = digits_for (absval);
+ int digits = digits_for(absval);
int len = (neg ? 1 : 0) + digits;
- char * set = string.insert (pos, nullptr, len);
+ char * set = string.insert(pos, nullptr, len);
if (neg)
- * (set ++) = '-';
+ *(set++) = '-';
- uint_to_str (absval, set, digits);
+ uint_to_str(absval, set, digits);
}
-EXPORT void str_insert_double (StringBuf & string, int pos, double val)
+EXPORT void str_insert_double(StringBuf & string, int pos, double val)
{
bool neg = (val < 0);
if (neg)
val = -val;
- unsigned i = floor (val);
- unsigned f = round ((val - i) * 1000000);
+ unsigned i = floor(val);
+ unsigned f = round((val - i) * 1000000);
if (f == 1000000)
{
- i ++;
+ i++;
f = 0;
}
int decimals = f ? 6 : 0;
- for (; decimals && ! (f % 10); f /= 10)
- decimals --;
+ for (; decimals && !(f % 10); f /= 10)
+ decimals--;
- int digits = digits_for (i);
+ int digits = digits_for(i);
int len = (neg ? 1 : 0) + digits + (decimals ? 1 : 0) + decimals;
- char * set = string.insert (pos, nullptr, len);
+ char * set = string.insert(pos, nullptr, len);
if (neg)
- * (set ++) = '-';
+ *(set++) = '-';
- uint_to_str (i, set, digits);
+ uint_to_str(i, set, digits);
if (decimals)
{
set += digits;
- * (set ++) = '.';
- uint_to_str (f, set, decimals);
+ *(set++) = '.';
+ uint_to_str(f, set, decimals);
}
}
-EXPORT StringBuf int_to_str (int val)
+EXPORT StringBuf int_to_str(int val)
{
StringBuf buf;
- str_insert_int (buf, 0, val);
+ str_insert_int(buf, 0, val);
return buf;
}
-EXPORT StringBuf double_to_str (double val)
+EXPORT StringBuf double_to_str(double val)
{
StringBuf buf;
- str_insert_double (buf, 0, val);
+ str_insert_double(buf, 0, val);
return buf;
}
-EXPORT bool str_to_int_array (const char * string, int * array, int count)
+EXPORT bool str_to_int_array(const char * string, int * array, int count)
{
- Index<String> index = str_list_to_index (string, ", ");
+ Index<String> index = str_list_to_index(string, ", ");
- if (index.len () != count)
+ if (index.len() != count)
return false;
- for (int i = 0; i < count; i ++)
- array[i] = str_to_int (index[i]);
+ for (int i = 0; i < count; i++)
+ array[i] = str_to_int(index[i]);
return true;
}
-EXPORT StringBuf int_array_to_str (const int * array, int count)
+EXPORT StringBuf int_array_to_str(const int * array, int count)
{
Index<String> index;
- for (int i = 0; i < count; i ++)
- index.append (String (int_to_str (array[i])));
+ for (int i = 0; i < count; i++)
+ index.append(String(int_to_str(array[i])));
- return index_to_str_list (index, ",");
+ return index_to_str_list(index, ",");
}
-EXPORT bool str_to_double_array (const char * string, double * array, int count)
+EXPORT bool str_to_double_array(const char * string, double * array, int count)
{
- Index<String> index = str_list_to_index (string, ", ");
+ Index<String> index = str_list_to_index(string, ", ");
- if (index.len () != count)
+ if (index.len() != count)
return false;
- for (int i = 0; i < count; i ++)
- array[i] = str_to_double (index[i]);
+ for (int i = 0; i < count; i++)
+ array[i] = str_to_double(index[i]);
return true;
}
-EXPORT StringBuf double_array_to_str (const double * array, int count)
+EXPORT StringBuf double_array_to_str(const double * array, int count)
{
Index<String> index;
- for (int i = 0; i < count; i ++)
- index.append (String (double_to_str (array[i])));
+ for (int i = 0; i < count; i++)
+ index.append(String(double_to_str(array[i])));
- return index_to_str_list (index, ",");
+ return index_to_str_list(index, ",");
}
-EXPORT StringBuf str_format_time (int64_t milliseconds)
+EXPORT StringBuf str_format_time(int64_t milliseconds)
{
bool neg = milliseconds < 0;
@@ -1163,11 +1181,13 @@ EXPORT StringBuf str_format_time (int64_t milliseconds)
int minutes = milliseconds / 60000;
int seconds = (milliseconds / 1000) % 60;
- if (hours && aud_get_bool (nullptr, "show_hours"))
- return str_printf ("%s%d:%02d:%02d", neg ? "- " : "", hours, minutes % 60, seconds);
+ if (hours && aud_get_bool("show_hours"))
+ return str_printf("%s%d:%02d:%02d", neg ? "- " : "", hours,
+ minutes % 60, seconds);
else
{
- bool zero = aud_get_bool (nullptr, "leading_zero");
- return str_printf (zero ? "%s%02d:%02d" : "%s%d:%02d", neg ? "- " : "", minutes, seconds);
+ bool zero = aud_get_bool("leading_zero");
+ return str_printf(zero ? "%s%02d:%02d" : "%s%d:%02d", neg ? "- " : "",
+ minutes, seconds);
}
}
diff --git a/src/libaudcore/audstrings.h b/src/libaudcore/audstrings.h
index e32f00a..ccd0439 100644
--- a/src/libaudcore/audstrings.h
+++ b/src/libaudcore/audstrings.h
@@ -1,6 +1,6 @@
/*
* audstrings.h
- * Copyright 2009-2012 John Lindgren and William Pitcock
+ * Copyright 2009-2012 John Lindgren and Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,92 +28,103 @@
#include <libaudcore/index.h>
#include <libaudcore/objects.h>
-int strcmp_safe (const char * a, const char * b, int len = -1);
-int strcmp_nocase (const char * a, const char * b, int len = -1);
-int strlen_bounded (const char * s, int len = -1);
+int strcmp_safe(const char * a, const char * b, int len = -1);
+int strcmp_nocase(const char * a, const char * b, int len = -1);
+int strlen_bounded(const char * s, int len = -1);
-StringBuf str_copy (const char * s, int len = -1);
-StringBuf str_concat (const std::initializer_list<const char *> & strings);
+StringBuf str_copy(const char * s, int len = -1);
+StringBuf str_concat(const std::initializer_list<const char *> & strings);
#ifdef _WIN32
-StringBuf str_printf (const char * format, ...) __attribute__ ((__format__ (gnu_printf, 1, 2)));
-void str_append_printf (StringBuf & str, const char * format, ...) __attribute__ ((__format__ (gnu_printf, 2, 3)));
+StringBuf str_printf(const char * format, ...)
+ __attribute__((__format__(gnu_printf, 1, 2)));
+void str_append_printf(StringBuf & str, const char * format, ...)
+ __attribute__((__format__(gnu_printf, 2, 3)));
#else
-StringBuf str_printf (const char * format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
-void str_append_printf (StringBuf & str, const char * format, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
+StringBuf str_printf(const char * format, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+void str_append_printf(StringBuf & str, const char * format, ...)
+ __attribute__((__format__(__printf__, 2, 3)));
#endif
-StringBuf str_vprintf (const char * format, va_list args);
-void str_append_vprintf (StringBuf & str, const char * format, va_list args);
+StringBuf str_vprintf(const char * format, va_list args);
+void str_append_vprintf(StringBuf & str, const char * format, va_list args);
-bool str_has_prefix_nocase (const char * str, const char * prefix);
-bool str_has_suffix_nocase (const char * str, const char * suffix);
+bool str_has_prefix_nocase(const char * str, const char * prefix);
+bool str_has_suffix_nocase(const char * str, const char * suffix);
-unsigned str_calc_hash (const char * str);
+unsigned str_calc_hash(const char * str);
-const char * strstr_nocase (const char * haystack, const char * needle);
-const char * strstr_nocase_utf8 (const char * haystack, const char * needle);
+const char * strstr_nocase(const char * haystack, const char * needle);
+const char * strstr_nocase_utf8(const char * haystack, const char * needle);
-static inline char * strstr_nocase (char * haystack, const char * needle)
- { return (char *) strstr_nocase ((const char *) haystack, needle); }
-static inline char * strstr_nocase_utf8 (char * haystack, const char * needle)
- { return (char *) strstr_nocase_utf8 ((const char *) haystack, needle); }
+static inline char * strstr_nocase(char * haystack, const char * needle)
+{
+ return (char *)strstr_nocase((const char *)haystack, needle);
+}
+static inline char * strstr_nocase_utf8(char * haystack, const char * needle)
+{
+ return (char *)strstr_nocase_utf8((const char *)haystack, needle);
+}
-StringBuf str_tolower (const char * str);
-StringBuf str_tolower_utf8 (const char * str);
-StringBuf str_toupper (const char * str);
-StringBuf str_toupper_utf8 (const char * str);
+StringBuf str_tolower(const char * str);
+StringBuf str_tolower_utf8(const char * str);
+StringBuf str_toupper(const char * str);
+StringBuf str_toupper_utf8(const char * str);
-void str_replace_char (char * string, char old_c, char new_c);
+void str_replace_char(char * string, char old_c, char new_c);
-StringBuf str_decode_percent (const char * str, int len = -1);
-StringBuf str_encode_percent (const char * str, int len = -1);
+StringBuf str_decode_percent(const char * str, int len = -1);
+StringBuf str_encode_percent(const char * str, int len = -1);
-StringBuf str_convert (const char * str, int len, const char * from_charset, const char * to_charset);
-StringBuf str_from_locale (const char * str, int len = -1);
-StringBuf str_to_locale (const char * str, int len = -1);
+StringBuf str_convert(const char * str, int len, const char * from_charset,
+ const char * to_charset);
+StringBuf str_from_locale(const char * str, int len = -1);
+StringBuf str_to_locale(const char * str, int len = -1);
/* Requires: aud_init() */
-StringBuf str_to_utf8 (const char * str, int len); // no "len = -1" to avoid ambiguity
-StringBuf str_to_utf8 (StringBuf && str);
+StringBuf str_to_utf8(const char * str,
+ int len); // no "len = -1" to avoid ambiguity
+StringBuf str_to_utf8(StringBuf && str);
-StringBuf filename_normalize (StringBuf && filename);
-StringBuf filename_contract (StringBuf && filename);
-StringBuf filename_expand (StringBuf && filename);
-StringBuf filename_get_parent (const char * filename);
-StringBuf filename_get_base (const char * filename);
-StringBuf filename_build (const std::initializer_list<const char *> & elems);
-StringBuf filename_to_uri (const char * filename);
-StringBuf uri_to_filename (const char * uri, bool use_locale = true);
-StringBuf uri_to_display (const char * uri);
+StringBuf filename_normalize(StringBuf && filename);
+StringBuf filename_contract(StringBuf && filename);
+StringBuf filename_expand(StringBuf && filename);
+StringBuf filename_get_parent(const char * filename);
+StringBuf filename_get_base(const char * filename);
+StringBuf filename_build(const std::initializer_list<const char *> & elems);
+StringBuf filename_to_uri(const char * filename);
+StringBuf uri_to_filename(const char * uri, bool use_locale = true);
-void uri_parse (const char * uri, const char * * base_p, const char * * ext_p,
- const char * * sub_p, int * isub_p);
+void uri_parse(const char * uri, const char ** base_p, const char ** ext_p,
+ const char ** sub_p, int * isub_p);
-StringBuf uri_get_scheme (const char * uri);
-StringBuf uri_get_extension (const char * uri);
+StringBuf uri_get_scheme(const char * uri);
+StringBuf uri_get_extension(const char * uri);
/* Requires: aud_init() */
-StringBuf uri_construct (const char * path, const char * reference);
-StringBuf uri_deconstruct (const char * uri, const char * reference);
+StringBuf uri_to_display(const char * uri);
+StringBuf uri_get_display_base(const char * uri);
+StringBuf uri_construct(const char * path, const char * reference);
+StringBuf uri_deconstruct(const char * uri, const char * reference);
-int str_compare (const char * a, const char * b);
-int str_compare_encoded (const char * a, const char * b);
+int str_compare(const char * a, const char * b);
+int str_compare_encoded(const char * a, const char * b);
-Index<String> str_list_to_index (const char * list, const char * delims);
-StringBuf index_to_str_list (const Index<String> & index, const char * sep);
+Index<String> str_list_to_index(const char * list, const char * delims);
+StringBuf index_to_str_list(const Index<String> & index, const char * sep);
-int str_to_int (const char * string);
-double str_to_double (const char * string);
-void str_insert_int (StringBuf & string, int pos, int val);
-void str_insert_double (StringBuf & string, int pos, double val);
-StringBuf int_to_str (int val);
-StringBuf double_to_str (double val);
+int str_to_int(const char * string);
+double str_to_double(const char * string);
+void str_insert_int(StringBuf & string, int pos, int val);
+void str_insert_double(StringBuf & string, int pos, double val);
+StringBuf int_to_str(int val);
+StringBuf double_to_str(double val);
-bool str_to_int_array (const char * string, int * array, int count);
-StringBuf int_array_to_str (const int * array, int count);
-bool str_to_double_array (const char * string, double * array, int count);
-StringBuf double_array_to_str (const double * array, int count);
+bool str_to_int_array(const char * string, int * array, int count);
+StringBuf int_array_to_str(const int * array, int count);
+bool str_to_double_array(const char * string, double * array, int count);
+StringBuf double_array_to_str(const double * array, int count);
/* Requires: aud_init() */
-StringBuf str_format_time (int64_t milliseconds);
+StringBuf str_format_time(int64_t milliseconds);
#endif /* LIBAUDCORE_STRINGS_H */
diff --git a/src/libaudcore/charset.cc b/src/libaudcore/charset.cc
index d77d38f..542225f 100644
--- a/src/libaudcore/charset.cc
+++ b/src/libaudcore/charset.cc
@@ -33,122 +33,125 @@
#include "hook.h"
#include "index.h"
#include "runtime.h"
-#include "tinylock.h"
+#include "threads.h"
-EXPORT StringBuf str_convert (const char * str, int len, const char * from_charset,
- const char * to_charset)
+EXPORT StringBuf str_convert(const char * str, int len,
+ const char * from_charset, const char * to_charset)
{
- iconv_t conv = iconv_open (to_charset, from_charset);
- if (conv == (iconv_t) -1)
- return StringBuf ();
+ iconv_t conv = iconv_open(to_charset, from_charset);
+ if (conv == (iconv_t)-1)
+ return StringBuf();
if (len < 0)
- len = strlen (str);
+ len = strlen(str);
- StringBuf buf (-1);
+ StringBuf buf(-1);
size_t inbytesleft = len;
- size_t outbytesleft = buf.len ();
- ICONV_CONST char * in = (ICONV_CONST char *) str;
+ size_t outbytesleft = buf.len();
+ ICONV_CONST char * in = (ICONV_CONST char *)str;
char * out = buf;
errno = 0;
- size_t ret = iconv (conv, & in, & inbytesleft, & out, & outbytesleft);
+ size_t ret = iconv(conv, &in, &inbytesleft, &out, &outbytesleft);
- if (ret == (size_t) -1 && errno == E2BIG)
- throw std::bad_alloc ();
+ if (ret == (size_t)-1 && errno == E2BIG)
+ throw std::bad_alloc();
- iconv_close (conv);
+ iconv_close(conv);
- if (ret == (size_t) -1 || inbytesleft)
- return StringBuf ();
+ if (ret == (size_t)-1 || inbytesleft)
+ return StringBuf();
- buf.resize (buf.len () - outbytesleft);
+ buf.resize(buf.len() - outbytesleft);
return buf;
}
-static void whine_locale (const char * str, int len, const char * dir, const char * charset)
+static void whine_locale(const char * str, int len, const char * dir,
+ const char * charset)
{
if (len < 0)
- AUDWARN ("Cannot convert %s locale (%s): %s\n", dir, charset, str);
+ AUDWARN("Cannot convert %s locale (%s): %s\n", dir, charset, str);
else
- AUDWARN ("Cannot convert %s locale (%s): %.*s\n", dir, charset, len, str);
+ AUDWARN("Cannot convert %s locale (%s): %.*s\n", dir, charset, len,
+ str);
}
-EXPORT StringBuf str_from_locale (const char * str, int len)
+EXPORT StringBuf str_from_locale(const char * str, int len)
{
const char * charset;
- if (g_get_charset (& charset))
+ if (g_get_charset(&charset))
{
/* locale is UTF-8 */
- if (! g_utf8_validate (str, len, nullptr))
+ if (!g_utf8_validate(str, len, nullptr))
{
- whine_locale (str, len, "from", "UTF-8");
- return StringBuf ();
+ whine_locale(str, len, "from", "UTF-8");
+ return StringBuf();
}
- return str_copy (str, len);
+ return str_copy(str, len);
}
else
{
- StringBuf utf8 = str_convert (str, len, charset, "UTF-8");
- if (! utf8)
- whine_locale (str, len, "from", charset);
+ StringBuf utf8 = str_convert(str, len, charset, "UTF-8");
+ if (!utf8)
+ whine_locale(str, len, "from", charset);
return utf8;
}
}
-EXPORT StringBuf str_to_locale (const char * str, int len)
+EXPORT StringBuf str_to_locale(const char * str, int len)
{
const char * charset;
- if (g_get_charset (& charset))
+ if (g_get_charset(&charset))
{
/* locale is UTF-8 */
- return str_copy (str, len);
+ return str_copy(str, len);
}
else
{
- StringBuf local = str_convert (str, len, "UTF-8", charset);
- if (! local)
- whine_locale (str, len, "to", charset);
+ StringBuf local = str_convert(str, len, "UTF-8", charset);
+ if (!local)
+ whine_locale(str, len, "to", charset);
return local;
}
}
-static TinyRWLock settings_lock;
+static aud::spinlock_rw settings_lock;
static String detect_region;
static Index<String> fallback_charsets;
-static void set_charsets (const char * region, const char * fallbacks)
+static void set_charsets(const char * region, const char * fallbacks)
{
- tiny_lock_write (& settings_lock);
+ auto wr = settings_lock.write();
- detect_region = String (region);
+ detect_region = String(region);
if (fallbacks)
- fallback_charsets = str_list_to_index (fallbacks, ", ");
+ fallback_charsets = str_list_to_index(fallbacks, ", ");
else
- fallback_charsets.clear ();
-
- tiny_unlock_write (& settings_lock);
+ fallback_charsets.clear();
}
-static StringBuf convert_to_utf8_locked (const char * str, int len)
+static StringBuf convert_to_utf8(const char * str, int len)
{
+ auto rd = settings_lock.read();
+
if (len < 0)
- len = strlen (str);
+ len = strlen(str);
if (detect_region)
{
/* prefer libguess-detected charset */
- const char * detected = libguess_determine_encoding (str, len, detect_region);
+ const char * detected =
+ libguess_determine_encoding(str, len, detect_region);
if (detected)
{
- StringBuf utf8 = str_convert (str, len, detected, "UTF-8");
+ StringBuf utf8 = str_convert(str, len, detected, "UTF-8");
if (utf8)
return utf8;
}
@@ -157,59 +160,54 @@ static StringBuf convert_to_utf8_locked (const char * str, int len)
/* try user-configured fallbacks */
for (const String & fallback : fallback_charsets)
{
- StringBuf utf8 = str_convert (str, len, fallback, "UTF-8");
+ StringBuf utf8 = str_convert(str, len, fallback, "UTF-8");
if (utf8)
return utf8;
}
/* try system locale last (this one will print a warning if it fails) */
- return str_from_locale (str, len);
+ return str_from_locale(str, len);
}
-EXPORT StringBuf str_to_utf8 (const char * str, int len)
+EXPORT StringBuf str_to_utf8(const char * str, int len)
{
/* check whether already UTF-8 */
- if (g_utf8_validate (str, len, nullptr))
- return str_copy (str, len);
+ if (g_utf8_validate(str, len, nullptr))
+ return str_copy(str, len);
- tiny_lock_read (& settings_lock);
- StringBuf utf8 = convert_to_utf8_locked (str, len);
- tiny_unlock_read (& settings_lock);
- return utf8;
+ return convert_to_utf8(str, len);
}
-EXPORT StringBuf str_to_utf8 (StringBuf && str)
+EXPORT StringBuf str_to_utf8(StringBuf && str)
{
/* check whether already UTF-8 */
- if (g_utf8_validate (str, str.len (), nullptr))
- return std::move (str);
+ if (g_utf8_validate(str, str.len(), nullptr))
+ return std::move(str);
- tiny_lock_read (& settings_lock);
- str = convert_to_utf8_locked (str, str.len ());
- tiny_unlock_read (& settings_lock);
- return str.settle ();
+ str = convert_to_utf8(str, str.len());
+ return str.settle();
}
-static void chardet_update (void * = nullptr, void * = nullptr)
+static void chardet_update(void * = nullptr, void * = nullptr)
{
- String region = aud_get_str (nullptr, "chardet_detector");
- String fallbacks = aud_get_str (nullptr, "chardet_fallback");
+ String region = aud_get_str("chardet_detector");
+ String fallbacks = aud_get_str("chardet_fallback");
- set_charsets (region[0] ? (const char *) region : nullptr, fallbacks);
+ set_charsets(region[0] ? (const char *)region : nullptr, fallbacks);
}
-void chardet_init ()
+void chardet_init()
{
- chardet_update ();
+ chardet_update();
- hook_associate ("set chardet_detector", chardet_update, nullptr);
- hook_associate ("set chardet_fallback", chardet_update, nullptr);
+ hook_associate("set chardet_detector", chardet_update, nullptr);
+ hook_associate("set chardet_fallback", chardet_update, nullptr);
}
-void chardet_cleanup ()
+void chardet_cleanup()
{
- hook_dissociate ("set chardet_detector", chardet_update);
- hook_dissociate ("set chardet_fallback", chardet_update);
+ hook_dissociate("set chardet_detector", chardet_update);
+ hook_dissociate("set chardet_fallback", chardet_update);
- set_charsets (nullptr, nullptr);
+ set_charsets(nullptr, nullptr);
}
diff --git a/src/libaudcore/config.cc b/src/libaudcore/config.cc
index 5046914..e39b4d5 100644
--- a/src/libaudcore/config.cc
+++ b/src/libaudcore/config.cc
@@ -17,8 +17,8 @@
* the use of this software.
*/
-#include "runtime.h"
#include "internal.h"
+#include "runtime.h"
#include <assert.h>
#include <string.h>
@@ -33,81 +33,86 @@
#define DEFAULT_SECTION "audacious"
static const char * const core_defaults[] = {
-
- /* general */
- "advance_on_delete", "FALSE",
- "always_resume_paused", "TRUE",
- "clear_playlist", "TRUE",
- "open_to_temporary", "TRUE",
- "recurse_folders", "TRUE",
- "resume_playback_on_startup", "TRUE",
- "show_interface", "TRUE",
-
- /* equalizer */
- "eqpreset_default_file", "",
- "eqpreset_extension", "",
- "equalizer_active", "FALSE",
- "equalizer_bands", "0,0,0,0,0,0,0,0,0,0",
- "equalizer_preamp", "0",
-
- /* info popup / info window */
- "cover_name_exclude", "back",
- "cover_name_include", "album,cover,front,folder",
- "filepopup_delay", "5",
- "filepopup_showprogressbar", "FALSE",
- "recurse_for_cover", "FALSE",
- "recurse_for_cover_depth", "0",
- "show_filepopup_for_tuple", "TRUE",
- "use_file_cover", "FALSE",
-
- /* network */
- "net_buffer_kb", "128",
- "save_url_history", "TRUE",
- "use_proxy", "FALSE",
- "use_proxy_auth", "FALSE",
-
- /* output */
- "default_gain", "0",
- "enable_replay_gain", "TRUE",
- "enable_clipping_prevention", "TRUE",
- "output_bit_depth", "-1",
- "output_buffer_size", "500",
- "record", "FALSE",
- "record_stream", aud::numeric_string<(int) OutputStream::AfterReplayGain>::str,
- "replay_gain_mode", aud::numeric_string<(int) ReplayGainMode::Track>::str,
- "replay_gain_preamp", "0",
- "soft_clipping", "FALSE",
- "software_volume_control", "FALSE",
- "sw_volume_left", "100",
- "sw_volume_right", "100",
-
- /* playback */
- "album_shuffle", "FALSE",
- "no_playlist_advance", "FALSE",
- "repeat", "FALSE",
- "shuffle", "FALSE",
- "stop_after_current_song", "FALSE",
-
- /* playlist */
- "chardet_fallback", "ISO-8859-1",
+ /* clang-format off */
+ /* general */
+ "advance_on_delete", "FALSE",
+ "always_resume_paused", "TRUE",
+ "clear_playlist", "TRUE",
+ "open_to_temporary", "TRUE",
+ "recurse_folders", "TRUE",
+ "resume_playback_on_startup", "TRUE",
+ "show_interface", "TRUE",
+
+ /* equalizer */
+ "eqpreset_default_file", "",
+ "eqpreset_extension", "",
+ "equalizer_active", "FALSE",
+ "equalizer_bands", "0,0,0,0,0,0,0,0,0,0",
+ "equalizer_preamp", "0",
+
+ /* info popup / info window */
+ "cover_name_exclude", "back",
+ "cover_name_include", "album,cover,front,folder",
+ "filepopup_delay", "5",
+ "filepopup_showprogressbar", "FALSE",
+ "recurse_for_cover", "FALSE",
+ "recurse_for_cover_depth", "0",
+ "show_filepopup_for_tuple", "TRUE",
+ "use_file_cover", "FALSE",
+
+ /* network */
+ "net_buffer_kb", "128",
+ "save_url_history", "TRUE",
+ "socks_proxy", "FALSE",
+ "socks_type", "0",
+ "use_proxy", "FALSE",
+ "use_proxy_auth", "FALSE",
+
+ /* output */
+ "default_gain", "0",
+ "enable_replay_gain", "TRUE",
+ "enable_clipping_prevention", "TRUE",
+ "output_bit_depth", "-1",
+ "output_buffer_size", "500",
+ "record", "FALSE",
+ "record_stream", aud::numeric_string<(int) OutputStream::AfterReplayGain>::str,
+ "replay_gain_mode", aud::numeric_string<(int) ReplayGainMode::Track>::str,
+ "replay_gain_preamp", "0",
+ "soft_clipping", "FALSE",
+ "software_volume_control", "FALSE",
+ "sw_volume_left", "100",
+ "sw_volume_right", "100",
+ "volume_delta", "5",
+
+ /* playback */
+ "album_shuffle", "FALSE",
+ "no_playlist_advance", "FALSE",
+ "repeat", "FALSE",
+ "shuffle", "FALSE",
+ "step_size", "5",
+ "stop_after_current_song", "FALSE",
+
+ /* playlist */
+ "chardet_fallback", "ISO-8859-1",
#ifdef _WIN32
- "convert_backslash", "TRUE",
+ "convert_backslash", "TRUE",
#else
- "convert_backslash", "FALSE",
+ "convert_backslash", "FALSE",
#endif
- "export_relative_paths", "TRUE",
- "folders_in_playlist", "FALSE",
- "generic_title_format", "${?artist:${artist} - }${?album:${album} - }${title}",
- "leading_zero", "FALSE",
- "show_hours", "TRUE",
- "metadata_fallbacks", "TRUE",
- "metadata_on_play", "FALSE",
- "show_numbers_in_pl", "FALSE",
- "slow_probe", "FALSE",
-
- nullptr};
-
-enum OpType {
+ "export_relative_paths", "TRUE",
+ "folders_in_playlist", "FALSE",
+ "generic_title_format", "${?artist:${artist} - }${?album:${album} - }${title}",
+ "leading_zero", "FALSE",
+ "show_hours", "TRUE",
+ "metadata_fallbacks", "TRUE",
+ "metadata_on_play", "FALSE",
+ "show_numbers_in_pl", "FALSE",
+ "slow_probe", "FALSE",
+ /* clang-format on */
+ nullptr};
+
+enum OpType
+{
OP_IS_DEFAULT,
OP_GET,
OP_SET,
@@ -116,7 +121,8 @@ enum OpType {
OP_CLEAR_NO_FLAG
};
-struct ConfigItem {
+struct ConfigItem
+{
String section;
String key;
String value;
@@ -134,14 +140,16 @@ struct ConfigOp
unsigned hash;
bool result;
- ConfigNode * add (const ConfigOp *);
- bool found (ConfigNode * node);
+ ConfigNode * add(const ConfigOp *);
+ bool found(ConfigNode * node);
};
struct ConfigNode : public MultiHash::Node, public ConfigItem
{
- bool match (const ConfigOp * op) const
- { return ! strcmp (section, op->section) && ! strcmp (key, op->key); }
+ bool match(const ConfigOp * op) const
+ {
+ return !strcmp(section, op->section) && !strcmp(key, op->key);
+ }
};
typedef MultiHash_T<ConfigNode, ConfigOp> ConfigTable;
@@ -149,12 +157,12 @@ typedef MultiHash_T<ConfigNode, ConfigOp> ConfigTable;
static ConfigTable s_defaults, s_config;
static volatile bool s_modified;
-ConfigNode * ConfigOp::add (const ConfigOp *)
+ConfigNode * ConfigOp::add(const ConfigOp *)
{
switch (type)
{
case OP_IS_DEFAULT:
- result = ! value[0]; /* empty string is default */
+ result = !value[0]; /* empty string is default */
return nullptr;
case OP_SET:
@@ -165,8 +173,8 @@ ConfigNode * ConfigOp::add (const ConfigOp *)
case OP_SET_NO_FLAG:
{
ConfigNode * node = new ConfigNode;
- node->section = String (section);
- node->key = String (key);
+ node->section = String(section);
+ node->key = String(key);
node->value = value;
return node;
}
@@ -176,12 +184,12 @@ ConfigNode * ConfigOp::add (const ConfigOp *)
}
}
-bool ConfigOp::found (ConfigNode * node)
+bool ConfigOp::found(ConfigNode * node)
{
switch (type)
{
case OP_IS_DEFAULT:
- result = ! strcmp (node->value, value);
+ result = !strcmp(node->value, value);
return false;
case OP_GET:
@@ -189,7 +197,7 @@ bool ConfigOp::found (ConfigNode * node)
return false;
case OP_SET:
- result = !! strcmp (node->value, value);
+ result = !!strcmp(node->value, value);
if (result)
s_modified = true;
// fall-through
@@ -212,13 +220,13 @@ bool ConfigOp::found (ConfigNode * node)
}
}
-static bool config_op_run (ConfigOp & op, ConfigTable & table)
+static bool config_op_run(ConfigOp & op, ConfigTable & table)
{
- if (! op.hash)
- op.hash = str_calc_hash (op.section) + str_calc_hash (op.key);
+ if (!op.hash)
+ op.hash = str_calc_hash(op.section) + str_calc_hash(op.key);
op.result = false;
- table.lookup (& op, op.hash, op);
+ table.lookup(&op, op.hash, op);
return op.result;
}
@@ -227,173 +235,191 @@ class ConfigParser : public IniParser
private:
String section;
- void handle_heading (const char * heading)
- { section = String (heading); }
+ void handle_heading(const char * heading) { section = String(heading); }
- void handle_entry (const char * key, const char * value)
+ void handle_entry(const char * key, const char * value)
{
- if (! section)
+ if (!section)
return;
- ConfigOp op = {OP_SET_NO_FLAG, section, key, String (value)};
- config_op_run (op, s_config);
+ ConfigOp op = {OP_SET_NO_FLAG, section, key, String(value)};
+ config_op_run(op, s_config);
}
};
-void config_load ()
+void config_load()
{
- StringBuf path = filename_build ({aud_get_path (AudPath::UserDir), "config"});
- if (VFSFile::test_file (path, VFS_EXISTS))
+ StringBuf path = filename_build({aud_get_path(AudPath::UserDir), "config"});
+ if (VFSFile::test_file(path, VFS_EXISTS))
{
- VFSFile file (path, "r");
+ VFSFile file(path, "r");
if (file)
- ConfigParser ().parse (file);
+ ConfigParser().parse(file);
}
- aud_config_set_defaults (nullptr, core_defaults);
+ aud_config_set_defaults(nullptr, core_defaults);
/* migrate from previous versions */
- if (aud_get_bool (0, "replay_gain_album"))
+ if (aud_get_bool("replay_gain_album"))
+ {
+ aud_set_str("replay_gain_album", "");
+ aud_set_int("replay_gain_mode", (int)ReplayGainMode::Album);
+ }
+
+ double step_size = aud_get_double("gtkui", "step_size");
+ if (step_size > 0)
+ {
+ aud_set_int("step_size", (int)step_size);
+ aud_set_str("gtkui", "step_size", "");
+ }
+
+ int volume_delta = aud_get_int("statusicon", "volume_delta");
+ if (volume_delta > 0)
{
- aud_set_str (0, "replay_gain_album", "");
- aud_set_int (0, "replay_gain_mode", (int) ReplayGainMode::Album);
+ aud_set_int("volume_delta", volume_delta);
+ aud_set_str("statusicon", "volume_delta", "");
}
}
-void config_save ()
+void config_save()
{
- if (! s_modified)
+ if (!s_modified)
return;
Index<ConfigItem> list;
- auto add_to_list = [&] (ConfigNode * node) {
- list.append (* node);
+ auto add_to_list = [&](ConfigNode * node) {
+ list.append(*node);
return false;
};
- auto finish = [] () {
- s_modified = false; // must be inside MultiHash lock
+ auto finish = []() {
+ s_modified = false; // must be inside MultiHash lock
};
- s_config.iterate (add_to_list, finish);
+ s_config.iterate(add_to_list, finish);
- list.sort ([] (const ConfigItem & a, const ConfigItem & b) {
+ list.sort([](const ConfigItem & a, const ConfigItem & b) {
if (a.section == b.section)
- return strcmp (a.key, b.key);
+ return strcmp(a.key, b.key);
else
- return strcmp (a.section, b.section);
+ return strcmp(a.section, b.section);
});
String current_heading;
- VFSFile file (filename_build ({aud_get_path (AudPath::UserDir), "config"}), "w");
- if (! file)
+ VFSFile file(filename_build({aud_get_path(AudPath::UserDir), "config"}),
+ "w");
+ if (!file)
goto FAILED;
for (const ConfigItem & item : list)
{
if (item.section != current_heading)
{
- if (! inifile_write_heading (file, item.section))
+ if (!inifile_write_heading(file, item.section))
goto FAILED;
current_heading = item.section;
}
- if (! inifile_write_entry (file, item.key, item.value))
+ if (!inifile_write_entry(file, item.key, item.value))
goto FAILED;
}
- if (file.fflush () < 0)
+ if (file.fflush() < 0)
goto FAILED;
return;
FAILED:
- AUDWARN ("Error saving configuration.\n");
+ AUDWARN("Error saving configuration.\n");
}
-EXPORT void aud_config_set_defaults (const char * section, const char * const * entries)
+EXPORT void aud_config_set_defaults(const char * section,
+ const char * const * entries)
{
- if (! section)
+ if (!section)
section = DEFAULT_SECTION;
while (1)
{
- const char * name = * entries ++;
- const char * value = * entries ++;
- if (! name || ! value)
+ const char * name = *entries++;
+ const char * value = *entries++;
+ if (!name || !value)
break;
- ConfigOp op = {OP_SET_NO_FLAG, section, name, String (value)};
- config_op_run (op, s_defaults);
+ ConfigOp op = {OP_SET_NO_FLAG, section, name, String(value)};
+ config_op_run(op, s_defaults);
}
}
-void config_cleanup ()
+void config_cleanup()
{
- s_config.clear ();
- s_defaults.clear ();
+ s_config.clear();
+ s_defaults.clear();
}
-EXPORT void aud_set_str (const char * section, const char * name, const char * value)
+EXPORT void aud_set_str(const char * section, const char * name,
+ const char * value)
{
- assert (name && value);
+ assert(name && value);
- ConfigOp op = {OP_IS_DEFAULT, section ? section : DEFAULT_SECTION, name, String (value)};
- bool is_default = config_op_run (op, s_defaults);
+ ConfigOp op = {OP_IS_DEFAULT, section ? section : DEFAULT_SECTION, name,
+ String(value)};
+ bool is_default = config_op_run(op, s_defaults);
op.type = is_default ? OP_CLEAR : OP_SET;
- bool changed = config_op_run (op, s_config);
+ bool changed = config_op_run(op, s_config);
- if (changed && ! section)
- event_queue (str_concat ({"set ", name}), nullptr);
+ if (changed && !section)
+ event_queue(str_concat({"set ", name}), nullptr);
}
-EXPORT String aud_get_str (const char * section, const char * name)
+EXPORT String aud_get_str(const char * section, const char * name)
{
- assert (name);
+ assert(name);
ConfigOp op = {OP_GET, section ? section : DEFAULT_SECTION, name};
- config_op_run (op, s_config);
+ config_op_run(op, s_config);
- if (! op.value)
- config_op_run (op, s_defaults);
+ if (!op.value)
+ config_op_run(op, s_defaults);
- return op.value ? op.value : String ("");
+ return op.value ? op.value : String("");
}
-EXPORT void aud_set_bool (const char * section, const char * name, bool value)
+EXPORT void aud_set_bool(const char * section, const char * name, bool value)
{
- aud_set_str (section, name, value ? "TRUE" : "FALSE");
+ aud_set_str(section, name, value ? "TRUE" : "FALSE");
}
-EXPORT bool aud_get_bool (const char * section, const char * name)
+EXPORT bool aud_get_bool(const char * section, const char * name)
{
- return ! strcmp (aud_get_str (section, name), "TRUE");
+ return !strcmp(aud_get_str(section, name), "TRUE");
}
-EXPORT void aud_toggle_bool (const char * section, const char * name)
+EXPORT void aud_toggle_bool(const char * section, const char * name)
{
- aud_set_bool (section, name, ! aud_get_bool (section, name));
+ aud_set_bool(section, name, !aud_get_bool(section, name));
}
-EXPORT void aud_set_int (const char * section, const char * name, int value)
+EXPORT void aud_set_int(const char * section, const char * name, int value)
{
- aud_set_str (section, name, int_to_str (value));
+ aud_set_str(section, name, int_to_str(value));
}
-EXPORT int aud_get_int (const char * section, const char * name)
+EXPORT int aud_get_int(const char * section, const char * name)
{
- return str_to_int (aud_get_str (section, name));
+ return str_to_int(aud_get_str(section, name));
}
-EXPORT void aud_set_double (const char * section, const char * name, double value)
+EXPORT void aud_set_double(const char * section, const char * name,
+ double value)
{
- aud_set_str (section, name, double_to_str (value));
+ aud_set_str(section, name, double_to_str(value));
}
-EXPORT double aud_get_double (const char * section, const char * name)
+EXPORT double aud_get_double(const char * section, const char * name)
{
- return str_to_double (aud_get_str (section, name));
+ return str_to_double(aud_get_str(section, name));
}
diff --git a/src/libaudcore/cue-cache.cc b/src/libaudcore/cue-cache.cc
index b821173..f568f7c 100644
--- a/src/libaudcore/cue-cache.cc
+++ b/src/libaudcore/cue-cache.cc
@@ -20,68 +20,68 @@
#include "cue-cache.h"
#include "multihash.h"
#include "playlist-internal.h"
+#include "threads.h"
-#include <pthread.h>
-
-enum NodeState {NotLoaded, Loading, Loaded};
+enum NodeState
+{
+ NotLoaded,
+ Loading,
+ Loaded
+};
-struct CueCacheNode {
+struct CueCacheNode
+{
Index<PlaylistAddItem> items;
NodeState state = NotLoaded;
int refcount = 0;
};
static SimpleHash<String, CueCacheNode> cache;
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static aud::mutex mutex;
+static aud::condvar cond;
-CueCacheRef::CueCacheRef (const char * filename) :
- m_filename (filename)
+CueCacheRef::CueCacheRef(const char * filename) : m_filename(filename)
{
- pthread_mutex_lock (& mutex);
-
- m_node = cache.lookup (m_filename);
- if (! m_node)
- m_node = cache.add (m_filename, CueCacheNode ());
+ auto mh = mutex.take();
- m_node->refcount ++;
+ m_node = cache.lookup(m_filename);
+ if (!m_node)
+ m_node = cache.add(m_filename, CueCacheNode());
- pthread_mutex_unlock (& mutex);
+ m_node->refcount++;
}
-CueCacheRef::~CueCacheRef ()
+CueCacheRef::~CueCacheRef()
{
- pthread_mutex_lock (& mutex);
-
- m_node->refcount --;
- if (! m_node->refcount)
- cache.remove (m_filename);
+ auto mh = mutex.take();
- pthread_mutex_unlock (& mutex);
+ m_node->refcount--;
+ if (!m_node->refcount)
+ cache.remove(m_filename);
}
-const Index<PlaylistAddItem> & CueCacheRef::load ()
+const Index<PlaylistAddItem> & CueCacheRef::load()
{
+ auto mh = mutex.take();
String title; // not used
- pthread_mutex_lock (& mutex);
switch (m_node->state)
{
case NotLoaded:
// load the cuesheet in this thread
m_node->state = Loading;
- pthread_mutex_unlock (& mutex);
- playlist_load (m_filename, title, m_node->items);
- pthread_mutex_lock (& mutex);
+ mh.unlock();
+ playlist_load(m_filename, title, m_node->items);
+ mh.lock();
m_node->state = Loaded;
- pthread_cond_broadcast (& cond);
+ cond.notify_all();
break;
case Loading:
// wait for cuesheet to load in another thread
while (m_node->state != Loaded)
- pthread_cond_wait (& cond, & mutex);
+ cond.wait(mh);
break;
@@ -90,6 +90,5 @@ const Index<PlaylistAddItem> & CueCacheRef::load ()
break;
}
- pthread_mutex_unlock (& mutex);
return m_node->items;
}
diff --git a/src/libaudcore/cue-cache.h b/src/libaudcore/cue-cache.h
index 84ab516..c5af486 100644
--- a/src/libaudcore/cue-cache.h
+++ b/src/libaudcore/cue-cache.h
@@ -28,10 +28,10 @@ struct CueCacheNode;
class CueCacheRef
{
public:
- CueCacheRef (const char * filename);
- ~CueCacheRef ();
+ CueCacheRef(const char * filename);
+ ~CueCacheRef();
- const Index<PlaylistAddItem> & load ();
+ const Index<PlaylistAddItem> & load();
private:
String m_filename;
diff --git a/src/libaudcore/drct.cc b/src/libaudcore/drct.cc
index 2ad76eb..592f8e8 100644
--- a/src/libaudcore/drct.cc
+++ b/src/libaudcore/drct.cc
@@ -30,44 +30,44 @@
/* --- PLAYBACK CONTROL --- */
-EXPORT void aud_drct_play ()
+EXPORT void aud_drct_play()
{
- if (aud_drct_get_playing ())
+ if (aud_drct_get_playing())
{
- if (aud_drct_get_paused ())
- aud_drct_pause ();
+ if (aud_drct_get_paused())
+ aud_drct_pause();
else
{
int a, b;
- aud_drct_get_ab_repeat (a, b);
- aud_drct_seek (aud::max (a, 0));
+ aud_drct_get_ab_repeat(a, b);
+ aud_drct_seek(aud::max(a, 0));
}
}
else
{
- auto playlist = Playlist::active_playlist ();
- playlist.set_position (playlist.get_position ());
- playlist.start_playback ();
+ auto playlist = Playlist::active_playlist();
+ playlist.set_position(playlist.get_position());
+ playlist.start_playback();
}
}
-EXPORT void aud_drct_play_pause ()
+EXPORT void aud_drct_play_pause()
{
- if (aud_drct_get_playing ())
- aud_drct_pause ();
+ if (aud_drct_get_playing())
+ aud_drct_pause();
else
- aud_drct_play ();
+ aud_drct_play();
}
-EXPORT int aud_drct_get_position ()
+EXPORT int aud_drct_get_position()
{
- return Playlist::playing_playlist ().get_position ();
+ return Playlist::playing_playlist().get_position();
}
-EXPORT String aud_drct_get_filename ()
+EXPORT String aud_drct_get_filename()
{
- auto playlist = Playlist::playing_playlist ();
- return playlist.entry_filename (playlist.get_position ());
+ auto playlist = Playlist::playing_playlist();
+ return playlist.entry_filename(playlist.get_position());
}
/* --- RECORDING CONTROL --- */
@@ -77,179 +77,203 @@ EXPORT String aud_drct_get_filename ()
static PluginHandle * record_plugin;
-static bool record_plugin_watcher (PluginHandle *, void *)
+static bool record_plugin_watcher(PluginHandle *, void *)
{
- if (! aud_drct_get_record_enabled ())
- aud_set_bool (nullptr, "record", false);
+ if (!aud_drct_get_record_enabled())
+ aud_set_bool("record", false);
- hook_call ("enable record", nullptr);
+ hook_call("enable record", nullptr);
return true;
}
-static void validate_record_setting (void *, void *)
+static void validate_record_setting(void *, void *)
{
- if (aud_get_bool (nullptr, "record") && ! aud_drct_get_record_enabled ())
+ if (aud_get_bool("record") && !aud_drct_get_record_enabled())
{
/* User attempted to start recording without a recording plugin enabled.
* This is probably not the best response, but better than nothing. */
- aud_set_bool (nullptr, "record", false);
- aud_ui_show_error (_("Stream recording must be configured in Audio "
- "Settings before it can be used."));
+ aud_set_bool("record", false);
+ aud_ui_show_error(_("Stream recording must be configured in Audio "
+ "Settings before it can be used."));
}
}
-void record_init ()
+void record_init()
{
- auto plugin = aud_plugin_lookup_basename ("filewriter");
- if (plugin && aud_plugin_get_type (plugin) == PluginType::Output)
+ // when building under Meson, the plugin may be libfilewriter.so.
+ auto plugin = aud_plugin_lookup_basename("filewriter");
+ if (!plugin)
+ plugin = aud_plugin_lookup_basename("libfilewriter");
+
+ if (plugin && aud_plugin_get_type(plugin) == PluginType::Output)
{
record_plugin = plugin;
- aud_plugin_add_watch (plugin, record_plugin_watcher, nullptr);
+ aud_plugin_add_watch(plugin, record_plugin_watcher, nullptr);
}
- if (! aud_drct_get_record_enabled ())
- aud_set_bool (nullptr, "record", false);
+ if (!aud_drct_get_record_enabled())
+ aud_set_bool("record", false);
- hook_associate ("set record", validate_record_setting, nullptr);
+ hook_associate("set record", validate_record_setting, nullptr);
}
-void record_cleanup ()
+void record_cleanup()
{
- hook_dissociate ("set record", validate_record_setting);
+ hook_dissociate("set record", validate_record_setting);
if (record_plugin)
{
- aud_plugin_remove_watch (record_plugin, record_plugin_watcher, nullptr);
+ aud_plugin_remove_watch(record_plugin, record_plugin_watcher, nullptr);
record_plugin = nullptr;
}
}
-EXPORT PluginHandle * aud_drct_get_record_plugin ()
+EXPORT PluginHandle * aud_drct_get_record_plugin()
{
/* recording is disabled when FileWriter is the primary output plugin */
- if (! record_plugin || plugin_get_enabled (record_plugin) == PluginEnabled::Primary)
+ if (!record_plugin ||
+ plugin_get_enabled(record_plugin) == PluginEnabled::Primary)
return nullptr;
return record_plugin;
}
-EXPORT bool aud_drct_get_record_enabled ()
+EXPORT bool aud_drct_get_record_enabled()
{
- return (record_plugin && plugin_get_enabled (record_plugin) == PluginEnabled::Secondary);
+ return (record_plugin &&
+ plugin_get_enabled(record_plugin) == PluginEnabled::Secondary);
}
-EXPORT bool aud_drct_enable_record (bool enable)
+EXPORT bool aud_drct_enable_record(bool enable)
{
- if (! record_plugin || plugin_get_enabled (record_plugin) == PluginEnabled::Primary)
+ if (!record_plugin ||
+ plugin_get_enabled(record_plugin) == PluginEnabled::Primary)
return false;
- return plugin_enable_secondary (record_plugin, enable);
+ return plugin_enable_secondary(record_plugin, enable);
}
/* --- VOLUME CONTROL --- */
-EXPORT int aud_drct_get_volume_main ()
+EXPORT int aud_drct_get_volume_main()
{
- StereoVolume volume = aud_drct_get_volume ();
- return aud::max (volume.left, volume.right);
+ StereoVolume volume = aud_drct_get_volume();
+ return aud::max(volume.left, volume.right);
}
-EXPORT void aud_drct_set_volume_main (int volume)
+EXPORT void aud_drct_set_volume_main(int volume)
{
- StereoVolume old = aud_drct_get_volume ();
- int main = aud::max (old.left, old.right);
+ StereoVolume old = aud_drct_get_volume();
+ int main = aud::max(old.left, old.right);
if (main > 0)
- aud_drct_set_volume ({
- aud::rescale (old.left, main, volume),
- aud::rescale (old.right, main, volume)
- });
+ aud_drct_set_volume({aud::rescale(old.left, main, volume),
+ aud::rescale(old.right, main, volume)});
else
- aud_drct_set_volume ({volume, volume});
+ aud_drct_set_volume({volume, volume});
}
-EXPORT int aud_drct_get_volume_balance ()
+EXPORT int aud_drct_get_volume_balance()
{
- StereoVolume volume = aud_drct_get_volume ();
+ StereoVolume volume = aud_drct_get_volume();
if (volume.left == volume.right)
return 0;
else if (volume.left > volume.right)
- return -100 + aud::rescale (volume.right, volume.left, 100);
+ return -100 + aud::rescale(volume.right, volume.left, 100);
else
- return 100 - aud::rescale (volume.left, volume.right, 100);
+ return 100 - aud::rescale(volume.left, volume.right, 100);
}
-EXPORT void aud_drct_set_volume_balance (int balance)
+EXPORT void aud_drct_set_volume_balance(int balance)
{
- int main = aud_drct_get_volume_main ();
+ int main = aud_drct_get_volume_main();
if (balance < 0)
- aud_drct_set_volume ({main, aud::rescale (main, 100, 100 + balance)});
+ aud_drct_set_volume({main, aud::rescale(main, 100, 100 + balance)});
else
- aud_drct_set_volume ({aud::rescale (main, 100, 100 - balance), main});
+ aud_drct_set_volume({aud::rescale(main, 100, 100 - balance), main});
}
/* --- PLAYLIST CONTROL --- */
-EXPORT void aud_drct_pl_next ()
+EXPORT void aud_drct_pl_next()
+{
+ PlaylistEx playlist = Playlist::playing_playlist();
+ if (playlist == Playlist())
+ playlist = Playlist::active_playlist();
+
+ playlist.next_song(aud_get_bool("repeat"));
+}
+
+EXPORT void aud_drct_pl_next_album()
+{
+ PlaylistEx playlist = Playlist::playing_playlist();
+ if (playlist == Playlist())
+ playlist = Playlist::active_playlist();
+
+ playlist.next_album(aud_get_bool("repeat"));
+}
+
+EXPORT void aud_drct_pl_prev()
{
- PlaylistEx playlist = Playlist::playing_playlist ();
- if (playlist == Playlist ())
- playlist = Playlist::active_playlist ();
+ PlaylistEx playlist = Playlist::playing_playlist();
+ if (playlist == Playlist())
+ playlist = Playlist::active_playlist();
- playlist.next_song (aud_get_bool (nullptr, "repeat"));
+ playlist.prev_song();
}
-EXPORT void aud_drct_pl_prev ()
+EXPORT void aud_drct_pl_prev_album()
{
- PlaylistEx playlist = Playlist::playing_playlist ();
- if (playlist == Playlist ())
- playlist = Playlist::active_playlist ();
+ PlaylistEx playlist = Playlist::playing_playlist();
+ if (playlist == Playlist())
+ playlist = Playlist::active_playlist();
- playlist.prev_song ();
+ playlist.prev_album();
}
-static void add_list (Index<PlaylistAddItem> && items, int at, bool to_temp, bool play)
+static void add_list(Index<PlaylistAddItem> && items, int at, bool to_temp,
+ bool play)
{
if (to_temp)
- Playlist::temporary_playlist ().activate ();
+ Playlist::temporary_playlist().activate();
- Playlist::active_playlist ().insert_items (at, std::move (items), play);
+ Playlist::active_playlist().insert_items(at, std::move(items), play);
}
-EXPORT void aud_drct_pl_add (const char * filename, int at)
+EXPORT void aud_drct_pl_add(const char * filename, int at)
{
Index<PlaylistAddItem> items;
- items.append (String (filename));
- add_list (std::move (items), at, false, false);
+ items.append(String(filename));
+ add_list(std::move(items), at, false, false);
}
-EXPORT void aud_drct_pl_add_list (Index<PlaylistAddItem> && items, int at)
+EXPORT void aud_drct_pl_add_list(Index<PlaylistAddItem> && items, int at)
{
- add_list (std::move (items), at, false, false);
+ add_list(std::move(items), at, false, false);
}
-EXPORT void aud_drct_pl_open (const char * filename)
+EXPORT void aud_drct_pl_open(const char * filename)
{
Index<PlaylistAddItem> items;
- items.append (String (filename));
- add_list (std::move (items), -1, aud_get_bool (nullptr, "open_to_temporary"), true);
+ items.append(String(filename));
+ add_list(std::move(items), -1, aud_get_bool("open_to_temporary"), true);
}
-EXPORT void aud_drct_pl_open_list (Index<PlaylistAddItem> && items)
+EXPORT void aud_drct_pl_open_list(Index<PlaylistAddItem> && items)
{
- add_list (std::move (items), -1, aud_get_bool (nullptr, "open_to_temporary"), true);
+ add_list(std::move(items), -1, aud_get_bool("open_to_temporary"), true);
}
-EXPORT void aud_drct_pl_open_temp (const char * filename)
+EXPORT void aud_drct_pl_open_temp(const char * filename)
{
Index<PlaylistAddItem> items;
- items.append (String (filename));
- add_list (std::move (items), -1, true, true);
+ items.append(String(filename));
+ add_list(std::move(items), -1, true, true);
}
-EXPORT void aud_drct_pl_open_temp_list (Index<PlaylistAddItem> && items)
+EXPORT void aud_drct_pl_open_temp_list(Index<PlaylistAddItem> && items)
{
- add_list (std::move (items), -1, true, true);
+ add_list(std::move(items), -1, true, true);
}
diff --git a/src/libaudcore/drct.h b/src/libaudcore/drct.h
index a486660..086a244 100644
--- a/src/libaudcore/drct.h
+++ b/src/libaudcore/drct.h
@@ -30,42 +30,42 @@ class PluginHandle;
/* --- PLAYBACK CONTROL --- */
-void aud_drct_play ();
-void aud_drct_play_pause ();
-void aud_drct_pause ();
-void aud_drct_stop ();
-bool aud_drct_get_playing ();
-bool aud_drct_get_ready ();
-bool aud_drct_get_paused ();
+void aud_drct_play();
+void aud_drct_play_pause();
+void aud_drct_pause();
+void aud_drct_stop();
+bool aud_drct_get_playing();
+bool aud_drct_get_ready();
+bool aud_drct_get_paused();
// returns entry number of playing song (zero-based)
-int aud_drct_get_position ();
+int aud_drct_get_position();
// returns filename of playing song
-String aud_drct_get_filename ();
+String aud_drct_get_filename();
// returns formatted title of playing song
// connect to the "title change" hook to be notified of changes
-String aud_drct_get_title ();
+String aud_drct_get_title();
// returns metadata of playing song
// connect to the "tuple change" hook to be notified of changes
-Tuple aud_drct_get_tuple ();
+Tuple aud_drct_get_tuple();
// returns some statistics of playing song
// connect to the "info change" hook to be notified of changes
-void aud_drct_get_info (int & bitrate, int & samplerate, int & channels);
+void aud_drct_get_info(int & bitrate, int & samplerate, int & channels);
-int aud_drct_get_time ();
-int aud_drct_get_length ();
-void aud_drct_seek (int time);
+int aud_drct_get_time();
+int aud_drct_get_length();
+void aud_drct_seek(int time);
/* "A-B repeat": when playback reaches point B, it returns to point A (where A
* and B are in milliseconds). The value -1 is interpreted as the beginning of
* the song (for A) or the end of the song (for B). A-B repeat is disabled
* entirely by setting both A and B to -1. */
-void aud_drct_set_ab_repeat (int a, int b);
-void aud_drct_get_ab_repeat (int & a, int & b);
+void aud_drct_set_ab_repeat(int a, int b);
+void aud_drct_get_ab_repeat(int & a, int & b);
/* --- RECORDING CONTROL --- */
@@ -75,35 +75,37 @@ void aud_drct_get_ab_repeat (int & a, int & b);
/* Returns the output plugin that will be used for recording, or null if none is
* available. Connect to the "enable record" hook to monitor changes. */
-PluginHandle * aud_drct_get_record_plugin ();
+PluginHandle * aud_drct_get_record_plugin();
/* Returns true if output recording is enabled, otherwise false. Connect to the
* "enable record" hook to monitor changes. */
-bool aud_drct_get_record_enabled ();
+bool aud_drct_get_record_enabled();
/* Enables or disables output recording (but does not actually start recording).
* Returns true on success, otherwise false. */
-bool aud_drct_enable_record (bool enable);
+bool aud_drct_enable_record(bool enable);
/* --- VOLUME CONTROL --- */
-StereoVolume aud_drct_get_volume ();
-void aud_drct_set_volume (StereoVolume volume);
-int aud_drct_get_volume_main ();
-void aud_drct_set_volume_main (int volume);
-int aud_drct_get_volume_balance ();
-void aud_drct_set_volume_balance (int balance);
+StereoVolume aud_drct_get_volume();
+void aud_drct_set_volume(StereoVolume volume);
+int aud_drct_get_volume_main();
+void aud_drct_set_volume_main(int volume);
+int aud_drct_get_volume_balance();
+void aud_drct_set_volume_balance(int balance);
/* --- PLAYLIST CONTROL --- */
-void aud_drct_pl_next ();
-void aud_drct_pl_prev ();
-
-void aud_drct_pl_add (const char * filename, int at);
-void aud_drct_pl_add_list (Index<PlaylistAddItem> && items, int at);
-void aud_drct_pl_open (const char * filename);
-void aud_drct_pl_open_list (Index<PlaylistAddItem> && items);
-void aud_drct_pl_open_temp (const char * filename);
-void aud_drct_pl_open_temp_list (Index<PlaylistAddItem> && items);
+void aud_drct_pl_next();
+void aud_drct_pl_next_album();
+void aud_drct_pl_prev();
+void aud_drct_pl_prev_album();
+
+void aud_drct_pl_add(const char * filename, int at);
+void aud_drct_pl_add_list(Index<PlaylistAddItem> && items, int at);
+void aud_drct_pl_open(const char * filename);
+void aud_drct_pl_open_list(Index<PlaylistAddItem> && items);
+void aud_drct_pl_open_temp(const char * filename);
+void aud_drct_pl_open_temp_list(Index<PlaylistAddItem> && items);
#endif
diff --git a/src/libaudcore/effect.cc b/src/libaudcore/effect.cc
index b0538d0..cd348b6 100644
--- a/src/libaudcore/effect.cc
+++ b/src/libaudcore/effect.cc
@@ -19,13 +19,12 @@
#include "internal.h"
-#include <pthread.h>
-
#include "drct.h"
#include "list.h"
#include "plugin.h"
#include "plugins.h"
#include "runtime.h"
+#include "threads.h"
struct Effect : public ListNode
{
@@ -36,135 +35,130 @@ struct Effect : public ListNode
bool remove_flag;
};
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static aud::mutex mutex;
static List<Effect> effects;
static int input_channels, input_rate;
-void effect_start (int & channels, int & rate)
+void effect_start(int & channels, int & rate)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- AUDDBG ("Starting effects.\n");
+ AUDDBG("Starting effects.\n");
- effects.clear ();
+ effects.clear();
input_channels = channels;
input_rate = rate;
- auto & list = aud_plugin_list (PluginType::Effect);
+ auto & list = aud_plugin_list(PluginType::Effect);
- for (int i = 0; i < list.len (); i ++)
+ for (int i = 0; i < list.len(); i++)
{
PluginHandle * plugin = list[i];
- if (! aud_plugin_get_enabled (plugin))
+ if (!aud_plugin_get_enabled(plugin))
continue;
- AUDINFO ("Starting %s at %d channels, %d Hz.\n",
- aud_plugin_get_name (plugin), channels, rate);
+ AUDINFO("Starting %s at %d channels, %d Hz.\n",
+ aud_plugin_get_name(plugin), channels, rate);
- EffectPlugin * header = (EffectPlugin *) aud_plugin_get_header (plugin);
- if (! header)
+ EffectPlugin * header = (EffectPlugin *)aud_plugin_get_header(plugin);
+ if (!header)
continue;
- header->start (channels, rate);
+ header->start(channels, rate);
- Effect * effect = new Effect ();
+ Effect * effect = new Effect();
effect->plugin = plugin;
effect->position = i;
effect->header = header;
effect->channels_returned = channels;
effect->rate_returned = rate;
- effects.append (effect);
+ effects.append(effect);
}
-
- pthread_mutex_unlock (& mutex);
}
-Index<float> & effect_process (Index<float> & data)
+Index<float> & effect_process(Index<float> & data)
{
- Index<float> * cur = & data;
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
+ Index<float> * cur = &data;
- Effect * e = effects.head ();
+ Effect * e = effects.head();
while (e)
{
- Effect * next = effects.next (e);
+ Effect * next = effects.next(e);
if (e->remove_flag)
{
- cur = & e->header->finish (* cur, false);
+ cur = &e->header->finish(*cur, false);
// simulate end-of-playlist call
// first save the current data
- Index<float> save = std::move (* cur);
- cur = & e->header->finish (* cur, true);
+ Index<float> save = std::move(*cur);
+ cur = &e->header->finish(*cur, true);
// combine the saved and new data
- save.move_from (* cur, 0, -1, -1, true, true);
- * cur = std::move (save);
+ save.move_from(*cur, 0, -1, -1, true, true);
+ *cur = std::move(save);
- effects.remove (e);
+ effects.remove(e);
delete e;
}
else
- cur = & e->header->process (* cur);
+ cur = &e->header->process(*cur);
e = next;
}
- pthread_mutex_unlock (& mutex);
- return * cur;
+ return *cur;
}
-bool effect_flush (bool force)
+bool effect_flush(bool force)
{
+ auto mh = mutex.take();
bool flushed = true;
- pthread_mutex_lock (& mutex);
- for (Effect * e = effects.head (); e; e = effects.next (e))
+ for (Effect * e = effects.head(); e; e = effects.next(e))
{
- if (! e->header->flush (force) && ! force)
+ if (!e->header->flush(force) && !force)
{
flushed = false;
break;
}
}
- pthread_mutex_unlock (& mutex);
return flushed;
}
-Index<float> & effect_finish (Index<float> & data, bool end_of_playlist)
+Index<float> & effect_finish(Index<float> & data, bool end_of_playlist)
{
- Index<float> * cur = & data;
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
+ Index<float> * cur = &data;
- for (Effect * e = effects.head (); e; e = effects.next (e))
- cur = & e->header->finish (* cur, end_of_playlist);
+ for (Effect * e = effects.head(); e; e = effects.next(e))
+ cur = &e->header->finish(*cur, end_of_playlist);
- pthread_mutex_unlock (& mutex);
- return * cur;
+ return *cur;
}
-int effect_adjust_delay (int delay)
+int effect_adjust_delay(int delay)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- for (Effect * e = effects.tail (); e; e = effects.prev (e))
- delay = e->header->adjust_delay (delay);
+ for (Effect * e = effects.tail(); e; e = effects.prev(e))
+ delay = e->header->adjust_delay(delay);
- pthread_mutex_unlock (& mutex);
return delay;
}
-static void effect_insert (PluginHandle * plugin, EffectPlugin * header)
+static void effect_insert(aud::mutex::holder &, PluginHandle * plugin,
+ EffectPlugin * header)
{
- int position = aud_plugin_list (PluginType::Effect).find (plugin);
+ int position = aud_plugin_list(PluginType::Effect).find(plugin);
Effect * prev = nullptr;
- for (Effect * e = effects.head (); e; e = effects.next (e))
+ for (Effect * e = effects.head(); e; e = effects.next(e))
{
if (e->plugin == plugin)
{
@@ -178,91 +172,90 @@ static void effect_insert (PluginHandle * plugin, EffectPlugin * header)
prev = e;
}
- AUDDBG ("Adding %s without reset.\n", aud_plugin_get_name (plugin));
+ AUDDBG("Adding %s without reset.\n", aud_plugin_get_name(plugin));
int channels, rate;
if (prev)
{
- AUDDBG ("Adding %s after %s.\n", aud_plugin_get_name (plugin),
- aud_plugin_get_name (prev->plugin));
+ AUDDBG("Adding %s after %s.\n", aud_plugin_get_name(plugin),
+ aud_plugin_get_name(prev->plugin));
channels = prev->channels_returned;
rate = prev->rate_returned;
}
else
{
- AUDDBG ("Adding %s as first effect.\n", aud_plugin_get_name (plugin));
+ AUDDBG("Adding %s as first effect.\n", aud_plugin_get_name(plugin));
channels = input_channels;
rate = input_rate;
}
- AUDINFO ("Starting %s at %d channels, %d Hz.\n", aud_plugin_get_name (plugin), channels, rate);
- header->start (channels, rate);
+ AUDINFO("Starting %s at %d channels, %d Hz.\n", aud_plugin_get_name(plugin),
+ channels, rate);
+ header->start(channels, rate);
- Effect * effect = new Effect ();
+ Effect * effect = new Effect();
effect->plugin = plugin;
effect->position = position;
effect->header = header;
effect->channels_returned = channels;
effect->rate_returned = rate;
- effects.insert_after (prev, effect);
+ effects.insert_after(prev, effect);
}
-static void effect_remove (PluginHandle * plugin)
+static void effect_remove(aud::mutex::holder &, PluginHandle * plugin)
{
- for (Effect * e = effects.head (); e; e = effects.next (e))
+ for (Effect * e = effects.head(); e; e = effects.next(e))
{
if (e->plugin == plugin)
{
- AUDDBG ("Removing %s without reset.\n", aud_plugin_get_name (plugin));
+ AUDDBG("Removing %s without reset.\n", aud_plugin_get_name(plugin));
e->remove_flag = true;
return;
}
}
}
-static void effect_enable (PluginHandle * plugin, EffectPlugin * ep, bool enable)
+static void effect_enable(PluginHandle * plugin, EffectPlugin * ep, bool enable)
{
if (ep->preserves_format)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
if (enable)
- effect_insert (plugin, ep);
+ effect_insert(mh, plugin, ep);
else
- effect_remove (plugin);
-
- pthread_mutex_unlock (& mutex);
+ effect_remove(mh, plugin);
}
else
{
- AUDDBG ("Reset to add/remove %s.\n", aud_plugin_get_name (plugin));
- aud_output_reset (OutputReset::EffectsOnly);
+ AUDDBG("Reset to add/remove %s.\n", aud_plugin_get_name(plugin));
+ aud_output_reset(OutputReset::EffectsOnly);
}
}
-bool effect_plugin_start (PluginHandle * plugin)
+bool effect_plugin_start(PluginHandle * plugin)
{
- if (aud_drct_get_playing ())
+ if (aud_drct_get_playing())
{
- EffectPlugin * ep = (EffectPlugin *) aud_plugin_get_header (plugin);
- if (! ep)
+ EffectPlugin * ep = (EffectPlugin *)aud_plugin_get_header(plugin);
+ if (!ep)
return false;
- effect_enable (plugin, ep, true);
+ effect_enable(plugin, ep, true);
}
return true;
}
-void effect_plugin_stop (PluginHandle * plugin)
+void effect_plugin_stop(PluginHandle * plugin)
{
- if (aud_drct_get_playing ())
+ if (aud_drct_get_playing())
{
- EffectPlugin * ep = (EffectPlugin *) aud_plugin_get_header (plugin);
- if (! ep)
+ EffectPlugin * ep = (EffectPlugin *)aud_plugin_get_header(plugin);
+ if (!ep)
return;
- effect_enable (plugin, ep, false);
+ effect_enable(plugin, ep, false);
}
}
diff --git a/src/libaudcore/equalizer-preset.cc b/src/libaudcore/equalizer-preset.cc
index 933148f..53e20e2 100644
--- a/src/libaudcore/equalizer-preset.cc
+++ b/src/libaudcore/equalizer-preset.cc
@@ -1,6 +1,6 @@
/*
* equalizer_preset.c
- * Copyright 2003-2013 Eugene Zagidullin, William Pitcock, John Lindgren, and
+ * Copyright 2003-2013 Eugene Zagidullin, Ariadne Conill, John Lindgren, and
* Thomas Lange
*
* Redistribution and use in source and binary forms, with or without
@@ -28,64 +28,73 @@
#include "runtime.h"
#include "vfs.h"
-EXPORT Index<EqualizerPreset> aud_eq_read_presets (const char * basename)
+EXPORT Index<EqualizerPreset> aud_eq_read_presets(const char * basename)
{
Index<EqualizerPreset> list;
- GKeyFile * rcfile = g_key_file_new ();
- StringBuf filename = filename_build ({aud_get_path (AudPath::UserDir), basename});
+ GKeyFile * rcfile = g_key_file_new();
+ StringBuf filename =
+ filename_build({aud_get_path(AudPath::UserDir), basename});
- if (! g_key_file_load_from_file (rcfile, filename, G_KEY_FILE_NONE, nullptr))
+ if (!g_key_file_load_from_file(rcfile, filename, G_KEY_FILE_NONE, nullptr))
{
- StringBuf filename2 = filename_build ({aud_get_path (AudPath::DataDir), basename});
+ StringBuf filename2 =
+ filename_build({aud_get_path(AudPath::DataDir), basename});
- if (! g_key_file_load_from_file (rcfile, filename2, G_KEY_FILE_NONE, nullptr))
+ if (!g_key_file_load_from_file(rcfile, filename2, G_KEY_FILE_NONE,
+ nullptr))
{
- g_key_file_free (rcfile);
+ g_key_file_free(rcfile);
return list;
}
}
- for (int p = 0;; p ++)
+ for (int p = 0;; p++)
{
- CharPtr name (g_key_file_get_string (rcfile, "Presets", str_printf ("Preset%d", p), nullptr));
- if (! name)
+ CharPtr name(g_key_file_get_string(rcfile, "Presets",
+ str_printf("Preset%d", p), nullptr));
+ if (!name || !name[0])
break;
- EqualizerPreset & preset = list.append (String (name));
- preset.preamp = g_key_file_get_double (rcfile, name, "Preamp", nullptr);
+ EqualizerPreset & preset = list.append(String(name));
+ preset.preamp = g_key_file_get_double(rcfile, name, "Preamp", nullptr);
for (int i = 0; i < AUD_EQ_NBANDS; i++)
- preset.bands[i] = g_key_file_get_double (rcfile, name, str_printf ("Band%d", i), nullptr);
+ preset.bands[i] = g_key_file_get_double(
+ rcfile, name, str_printf("Band%d", i), nullptr);
}
- g_key_file_free (rcfile);
+ g_key_file_free(rcfile);
return list;
}
-EXPORT bool aud_eq_write_presets (const Index<EqualizerPreset> & list, const char * basename)
+EXPORT bool aud_eq_write_presets(const Index<EqualizerPreset> & list,
+ const char * basename)
{
- GKeyFile * rcfile = g_key_file_new ();
+ GKeyFile * rcfile = g_key_file_new();
- for (int p = 0; p < list.len (); p ++)
+ for (int p = 0; p < list.len(); p++)
{
const EqualizerPreset & preset = list[p];
- g_key_file_set_string (rcfile, "Presets", str_printf ("Preset%d", p), preset.name);
- g_key_file_set_double (rcfile, preset.name, "Preamp", preset.preamp);
+ g_key_file_set_string(rcfile, "Presets", str_printf("Preset%d", p),
+ preset.name);
+ g_key_file_set_double(rcfile, preset.name, "Preamp", preset.preamp);
- for (int i = 0; i < AUD_EQ_NBANDS; i ++)
- g_key_file_set_double (rcfile, preset.name, str_printf ("Band%d", i), preset.bands[i]);
+ for (int i = 0; i < AUD_EQ_NBANDS; i++)
+ g_key_file_set_double(rcfile, preset.name, str_printf("Band%d", i),
+ preset.bands[i]);
}
size_t len;
- CharPtr data (g_key_file_to_data (rcfile, & len, nullptr));
+ CharPtr data(g_key_file_to_data(rcfile, &len, nullptr));
- StringBuf filename = filename_build ({aud_get_path (AudPath::UserDir), basename});
- bool success = g_file_set_contents (filename, data, len, nullptr);
+ StringBuf filename =
+ filename_build({aud_get_path(AudPath::UserDir), basename});
+ bool success = g_file_set_contents(filename, data, len, nullptr);
- g_key_file_free (rcfile);
+ g_key_file_free(rcfile);
return success;
}
@@ -98,7 +107,7 @@ EXPORT bool aud_eq_write_presets (const Index<EqualizerPreset> & list, const cha
* to represent 0 dB exactly (31 is +0.19 dB, 32 is -0.19 dB) but we
* mimic WinAmp in letting 31 mean 0 dB as a special case. */
-static float decode_winamp_val (int val)
+static float decode_winamp_val(int val)
{
if (val == 31)
return 0.0f;
@@ -106,15 +115,15 @@ static float decode_winamp_val (int val)
return (31.5f - val) * (12.0f / 31.5f);
}
-static int encode_winamp_val (float val)
+static int encode_winamp_val(float val)
{
if (val == 0.0f)
return 31;
- return lroundf (31.5f - val * (31.5f / 12.0f));
+ return lroundf(31.5f - val * (31.5f / 12.0f));
}
-EXPORT Index<EqualizerPreset> aud_import_winamp_presets (VFSFile & file)
+EXPORT Index<EqualizerPreset> aud_import_winamp_presets(VFSFile & file)
{
char header[31];
char bands[11];
@@ -122,95 +131,103 @@ EXPORT Index<EqualizerPreset> aud_import_winamp_presets (VFSFile & file)
Index<EqualizerPreset> list;
- if (file.fread (header, 1, sizeof header) != sizeof header ||
- strncmp (header, "Winamp EQ library file v1.1", 27))
+ if (file.fread(header, 1, sizeof header) != sizeof header ||
+ strncmp(header, "Winamp EQ library file v1.1", 27))
return list;
- while (file.fread (preset_name, 1, 180) == 180)
+ while (file.fread(preset_name, 1, 180) == 180 && preset_name[0])
{
preset_name[180] = 0; /* protect against buffer overflow */
- if (file.fseek (77, VFS_SEEK_CUR)) /* unknown crap --asphyx */
+ if (file.fseek(77, VFS_SEEK_CUR)) /* unknown crap --asphyx */
break;
- if (file.fread (bands, 1, 11) != 11)
+ if (file.fread(bands, 1, 11) != 11)
break;
- EqualizerPreset & preset = list.append (String (preset_name));
- preset.preamp = decode_winamp_val (bands[10]);
+ EqualizerPreset & preset = list.append(String(preset_name));
+ preset.preamp = decode_winamp_val(bands[10]);
- for (int i = 0; i < AUD_EQ_NBANDS; i ++)
- preset.bands[i] = decode_winamp_val (bands[i]);
+ for (int i = 0; i < AUD_EQ_NBANDS; i++)
+ preset.bands[i] = decode_winamp_val(bands[i]);
}
return list;
}
-EXPORT bool aud_export_winamp_preset (const EqualizerPreset & preset, VFSFile & file)
+EXPORT bool aud_export_winamp_preset(const EqualizerPreset & preset,
+ VFSFile & file)
{
char name[257];
char bands[11];
- if (file.fwrite ("Winamp EQ library file v1.1\x1a!--", 1, 31) != 31)
+ if (file.fwrite("Winamp EQ library file v1.1\x1a!--", 1, 31) != 31)
return false;
- strncpy (name, preset.name, 257);
+ strncpy(name, preset.name, 257);
- if (file.fwrite (name, 1, 257) != 257)
+ if (file.fwrite(name, 1, 257) != 257)
return false;
- for (int i = 0; i < AUD_EQ_NBANDS; i ++)
- bands[i] = encode_winamp_val (preset.bands[i]);
+ for (int i = 0; i < AUD_EQ_NBANDS; i++)
+ bands[i] = encode_winamp_val(preset.bands[i]);
- bands[10] = encode_winamp_val (preset.preamp);
+ bands[10] = encode_winamp_val(preset.preamp);
- if (file.fwrite (bands, 1, 11) != 11)
+ if (file.fwrite(bands, 1, 11) != 11)
return false;
return true;
}
-EXPORT bool aud_save_preset_file (const EqualizerPreset & preset, VFSFile & file)
+EXPORT bool aud_save_preset_file(const EqualizerPreset & preset, VFSFile & file)
{
- GKeyFile * rcfile = g_key_file_new ();
+ GKeyFile * rcfile = g_key_file_new();
- g_key_file_set_double (rcfile, "Equalizer preset", "Preamp", preset.preamp);
+ g_key_file_set_double(rcfile, "Equalizer preset", "Preamp", preset.preamp);
- for (int i = 0; i < AUD_EQ_NBANDS; i ++)
- g_key_file_set_double (rcfile, "Equalizer preset",
- str_printf ("Band%d", i), preset.bands[i]);
+ for (int i = 0; i < AUD_EQ_NBANDS; i++)
+ g_key_file_set_double(rcfile, "Equalizer preset",
+ str_printf("Band%d", i), preset.bands[i]);
size_t len;
- CharPtr data (g_key_file_to_data (rcfile, & len, nullptr));
+ CharPtr data(g_key_file_to_data(rcfile, &len, nullptr));
- bool success = (file.fwrite (data, 1, len) == (int64_t) len);
+ bool success = (file.fwrite(data, 1, len) == (int64_t)len);
- g_key_file_free (rcfile);
+ g_key_file_free(rcfile);
return success;
}
-EXPORT bool aud_load_preset_file (EqualizerPreset & preset, VFSFile & file)
+EXPORT bool aud_load_preset_file(EqualizerPreset & preset, VFSFile & file)
{
- GKeyFile * rcfile = g_key_file_new ();
+ /* get the preset name from the file name */
+ StringBuf name = uri_get_display_base(file.filename());
+ if (!name || !name[0])
+ return false;
+
+ GKeyFile * rcfile = g_key_file_new();
- Index<char> data = file.read_all ();
+ Index<char> data = file.read_all();
- if (! data.len () || ! g_key_file_load_from_data (rcfile, data.begin (),
- data.len (), G_KEY_FILE_NONE, nullptr))
+ if (!data.len() ||
+ !g_key_file_load_from_data(rcfile, data.begin(), data.len(),
+ G_KEY_FILE_NONE, nullptr))
{
- g_key_file_free (rcfile);
+ g_key_file_free(rcfile);
return false;
}
- preset.name = String ("");
- preset.preamp = g_key_file_get_double (rcfile, "Equalizer preset", "Preamp", nullptr);
+ preset.name = String(name);
+ preset.preamp =
+ g_key_file_get_double(rcfile, "Equalizer preset", "Preamp", nullptr);
- for (int i = 0; i < AUD_EQ_NBANDS; i ++)
- preset.bands[i] = g_key_file_get_double (rcfile, "Equalizer preset",
- str_printf ("Band%d", i), nullptr);
+ for (int i = 0; i < AUD_EQ_NBANDS; i++)
+ preset.bands[i] = g_key_file_get_double(
+ rcfile, "Equalizer preset", str_printf("Band%d", i), nullptr);
- g_key_file_free (rcfile);
+ g_key_file_free(rcfile);
return true;
}
diff --git a/src/libaudcore/equalizer.cc b/src/libaudcore/equalizer.cc
index d19c031..7cc6aa8 100644
--- a/src/libaudcore/equalizer.cc
+++ b/src/libaudcore/equalizer.cc
@@ -28,13 +28,13 @@
#include <assert.h>
#include <math.h>
-#include <pthread.h>
#include <string.h>
#include "audio.h"
#include "audstrings.h"
#include "hook.h"
#include "runtime.h"
+#include "threads.h"
/* Q value for band-pass filters 1.2247 = (3/2)^(1/2)
* Gives 4 dB suppression at Fc*2 and Fc/2 */
@@ -44,33 +44,35 @@
/* These are not the historical WinAmp frequencies, because the IIR filters used
* here are designed for each frequency to be twice the previous. Using WinAmp
* frequencies leads to too much gain in some bands and too little in others. */
-static const float CF[AUD_EQ_NBANDS] = {31.25f, 62.5f, 125, 250, 500, 1000,
- 2000, 4000, 8000, 16000};
+static const float CF[AUD_EQ_NBANDS] = {31.25f, 62.5f, 125, 250, 500,
+ 1000, 2000, 4000, 8000, 16000};
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static aud::mutex mutex;
static bool active;
static int channels, rate;
static float a[AUD_EQ_NBANDS][2]; /* A weights */
static float b[AUD_EQ_NBANDS][2]; /* B weights */
-static float wqv[AUD_MAX_CHANNELS][AUD_EQ_NBANDS][2]; /* Circular buffer for W data */
-static float gv[AUD_MAX_CHANNELS][AUD_EQ_NBANDS]; /* Gain factor for each channel and band */
-static int K; /* Number of used EQ bands */
+static float wqv[AUD_MAX_CHANNELS][AUD_EQ_NBANDS]
+ [2]; /* Circular buffer for W data */
+static float gv[AUD_MAX_CHANNELS]
+ [AUD_EQ_NBANDS]; /* Gain factor for each channel and band */
+static int K; /* Number of used EQ bands */
/* 2nd order band-pass filter design */
-static void bp2 (float *a, float *b, float fc)
+static void bp2(float * a, float * b, float fc)
{
float th = 2 * (float)M_PI * fc;
- float C = (1 - tanf (th * Q / 2)) / (1 + tanf (th * Q / 2));
+ float C = (1 - tanf(th * Q / 2)) / (1 + tanf(th * Q / 2));
- a[0] = (1 + C) * cosf (th);
+ a[0] = (1 + C) * cosf(th);
a[1] = -C;
b[0] = (1 - C) / 2;
b[1] = -1.005f;
}
-void eq_set_format (int new_channels, int new_rate)
+void eq_set_format(int new_channels, int new_rate)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
channels = new_channels;
rate = new_rate;
@@ -79,60 +81,52 @@ void eq_set_format (int new_channels, int new_rate)
* than rate/2Q to avoid singularities in the tangent used in bp2() */
K = AUD_EQ_NBANDS;
- while (K > 0 && CF[K - 1] > (float) rate / (2.005f * Q))
- K --;
+ while (K > 0 && CF[K - 1] > (float)rate / (2.005f * Q))
+ K--;
/* Generate filter taps */
- for (int k = 0; k < K; k ++)
- bp2 (a[k], b[k], CF[k] / (float) rate);
+ for (int k = 0; k < K; k++)
+ bp2(a[k], b[k], CF[k] / (float)rate);
/* Reset state */
- memset (wqv[0][0], 0, sizeof wqv);
-
- pthread_mutex_unlock (& mutex);
+ memset(wqv[0][0], 0, sizeof wqv);
}
-static void eq_set_bands_real (double preamp, double *values)
+static void eq_set_bands_real(aud::mutex::holder &, double preamp,
+ double * values)
{
float adj[AUD_EQ_NBANDS];
- for (int i = 0; i < AUD_EQ_NBANDS; i ++)
+ for (int i = 0; i < AUD_EQ_NBANDS; i++)
adj[i] = preamp + values[i];
- for (int c = 0; c < AUD_MAX_CHANNELS; c ++)
+ for (int c = 0; c < AUD_MAX_CHANNELS; c++)
{
- for (int i = 0; i < AUD_EQ_NBANDS; i ++)
- gv[c][i] = powf (10, adj[i] / 20) - 1;
+ for (int i = 0; i < AUD_EQ_NBANDS; i++)
+ gv[c][i] = powf(10, adj[i] / 20) - 1;
}
}
-void eq_filter (float *data, int samples)
+void eq_filter(float * data, int samples)
{
- int channel;
-
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- if (! active)
- {
- pthread_mutex_unlock (& mutex);
+ if (!active)
return;
- }
- for (channel = 0; channel < channels; channel ++)
+ for (int channel = 0; channel < channels; channel++)
{
- float *g = gv[channel]; /* Gain factor */
- float *end = data + samples;
- float *f;
+ float * g = gv[channel]; /* Gain factor */
+ float * end = data + samples;
- for (f = data + channel; f < end; f += channels)
+ for (float * f = data + channel; f < end; f += channels)
{
- int k; /* Frequency band index */
float yt = *f; /* Current input sample */
- for (k = 0; k < K; k ++)
+ for (int k = 0; k < K; k++)
{
/* Pointer to circular buffer wq */
- float *wq = wqv[channel][k];
+ float * wq = wqv[channel][k];
/* Calculate output from AR part of current filter */
float w = yt * b[k][0] + wq[0] * a[k][0] + wq[1] * a[k][1];
@@ -148,90 +142,86 @@ void eq_filter (float *data, int samples)
*f = yt;
}
}
-
- pthread_mutex_unlock (& mutex);
}
-static void eq_update (void *data, void *user)
+static void eq_update(void *, void *)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- active = aud_get_bool (nullptr, "equalizer_active");
+ active = aud_get_bool("equalizer_active");
double values[AUD_EQ_NBANDS];
- aud_eq_get_bands (values);
- eq_set_bands_real (aud_get_double (nullptr, "equalizer_preamp"), values);
-
- pthread_mutex_unlock (& mutex);
+ aud_eq_get_bands(values);
+ eq_set_bands_real(mh, aud_get_double("equalizer_preamp"), values);
}
-void eq_init ()
+void eq_init()
{
- eq_update (nullptr, nullptr);
- hook_associate ("set equalizer_active", eq_update, nullptr);
- hook_associate ("set equalizer_preamp", eq_update, nullptr);
- hook_associate ("set equalizer_bands", eq_update, nullptr);
+ eq_update(nullptr, nullptr);
+ hook_associate("set equalizer_active", eq_update, nullptr);
+ hook_associate("set equalizer_preamp", eq_update, nullptr);
+ hook_associate("set equalizer_bands", eq_update, nullptr);
}
-void eq_cleanup ()
+void eq_cleanup()
{
- hook_dissociate ("set equalizer_active", eq_update);
- hook_dissociate ("set equalizer_preamp", eq_update);
- hook_dissociate ("set equalizer_bands", eq_update);
+ hook_dissociate("set equalizer_active", eq_update);
+ hook_dissociate("set equalizer_preamp", eq_update);
+ hook_dissociate("set equalizer_bands", eq_update);
}
-EXPORT void aud_eq_set_bands (const double values[AUD_EQ_NBANDS])
+EXPORT void aud_eq_set_bands(const double values[AUD_EQ_NBANDS])
{
- StringBuf string = double_array_to_str (values, AUD_EQ_NBANDS);
- aud_set_str (nullptr, "equalizer_bands", string);
+ StringBuf string = double_array_to_str(values, AUD_EQ_NBANDS);
+ aud_set_str("equalizer_bands", string);
}
-EXPORT void aud_eq_get_bands (double values[AUD_EQ_NBANDS])
+EXPORT void aud_eq_get_bands(double values[AUD_EQ_NBANDS])
{
- memset (values, 0, sizeof (double) * AUD_EQ_NBANDS);
- String string = aud_get_str (nullptr, "equalizer_bands");
- str_to_double_array (string, values, AUD_EQ_NBANDS);
+ memset(values, 0, sizeof(double) * AUD_EQ_NBANDS);
+ String string = aud_get_str("equalizer_bands");
+ str_to_double_array(string, values, AUD_EQ_NBANDS);
}
-EXPORT void aud_eq_set_band (int band, double value)
+EXPORT void aud_eq_set_band(int band, double value)
{
- assert (band >= 0 && band < AUD_EQ_NBANDS);
+ assert(band >= 0 && band < AUD_EQ_NBANDS);
double values[AUD_EQ_NBANDS];
- aud_eq_get_bands (values);
+ aud_eq_get_bands(values);
values[band] = value;
- aud_eq_set_bands (values);
+ aud_eq_set_bands(values);
}
-EXPORT double aud_eq_get_band (int band)
+EXPORT double aud_eq_get_band(int band)
{
- assert (band >= 0 && band < AUD_EQ_NBANDS);
+ assert(band >= 0 && band < AUD_EQ_NBANDS);
double values[AUD_EQ_NBANDS];
- aud_eq_get_bands (values);
+ aud_eq_get_bands(values);
return values[band];
}
-EXPORT void aud_eq_apply_preset (const EqualizerPreset & preset)
+EXPORT void aud_eq_apply_preset(const EqualizerPreset & preset)
{
double bands[AUD_EQ_NBANDS];
/* convert float to double :( */
- for (int i = 0; i < AUD_EQ_NBANDS; i ++)
+ for (int i = 0; i < AUD_EQ_NBANDS; i++)
bands[i] = preset.bands[i];
- aud_eq_set_bands (bands);
- aud_set_double (nullptr, "equalizer_preamp", preset.preamp);
+ aud_eq_set_bands(bands);
+ aud_set_double("equalizer_preamp", preset.preamp);
}
-EXPORT void aud_eq_update_preset (EqualizerPreset & preset)
+EXPORT void aud_eq_update_preset(EqualizerPreset & preset)
{
double bands[AUD_EQ_NBANDS];
- aud_eq_get_bands (bands);
+ aud_eq_get_bands(bands);
/* convert double to float :( */
- for (int i = 0; i < AUD_EQ_NBANDS; i ++)
+ for (int i = 0; i < AUD_EQ_NBANDS; i++)
preset.bands[i] = bands[i];
- preset.preamp = aud_get_double (nullptr, "equalizer_preamp");
+ preset.preamp = aud_get_double("equalizer_preamp");
}
diff --git a/src/libaudcore/equalizer.h b/src/libaudcore/equalizer.h
index bfa8ab1..cf9441c 100644
--- a/src/libaudcore/equalizer.h
+++ b/src/libaudcore/equalizer.h
@@ -28,27 +28,29 @@ class VFSFile;
#define AUD_EQ_NBANDS 10
#define AUD_EQ_MAX_GAIN 12
-struct EqualizerPreset {
+struct EqualizerPreset
+{
String name;
float preamp;
float bands[AUD_EQ_NBANDS];
};
-void aud_eq_set_bands (const double values[AUD_EQ_NBANDS]);
-void aud_eq_get_bands (double values[AUD_EQ_NBANDS]);
-void aud_eq_set_band (int band, double value);
-double aud_eq_get_band (int band);
+void aud_eq_set_bands(const double values[AUD_EQ_NBANDS]);
+void aud_eq_get_bands(double values[AUD_EQ_NBANDS]);
+void aud_eq_set_band(int band, double value);
+double aud_eq_get_band(int band);
-void aud_eq_apply_preset (const EqualizerPreset & preset);
-void aud_eq_update_preset (EqualizerPreset & preset);
+void aud_eq_apply_preset(const EqualizerPreset & preset);
+void aud_eq_update_preset(EqualizerPreset & preset);
-Index<EqualizerPreset> aud_eq_read_presets (const char * basename);
-bool aud_eq_write_presets (const Index<EqualizerPreset> & list, const char * basename);
+Index<EqualizerPreset> aud_eq_read_presets(const char * basename);
+bool aud_eq_write_presets(const Index<EqualizerPreset> & list,
+ const char * basename);
-bool aud_load_preset_file (EqualizerPreset & preset, VFSFile & file);
-bool aud_save_preset_file (const EqualizerPreset & preset, VFSFile & file);
+bool aud_load_preset_file(EqualizerPreset & preset, VFSFile & file);
+bool aud_save_preset_file(const EqualizerPreset & preset, VFSFile & file);
-Index<EqualizerPreset> aud_import_winamp_presets (VFSFile & file);
-bool aud_export_winamp_preset (const EqualizerPreset & preset, VFSFile & file);
+Index<EqualizerPreset> aud_import_winamp_presets(VFSFile & file);
+bool aud_export_winamp_preset(const EqualizerPreset & preset, VFSFile & file);
#endif /* LIBAUDCORE_EQUALIZER_H */
diff --git a/src/libaudcore/eventqueue.cc b/src/libaudcore/eventqueue.cc
index c65a439..d084dc1 100644
--- a/src/libaudcore/eventqueue.cc
+++ b/src/libaudcore/eventqueue.cc
@@ -19,92 +19,86 @@
#include "hook.h"
-#include <pthread.h>
#include <string.h>
#include "internal.h"
#include "list.h"
#include "mainloop.h"
#include "objects.h"
+#include "threads.h"
struct Event : public ListNode
{
String name;
void * data;
- void (* destroy) (void *);
+ void (*destroy)(void *);
- Event (const char * name, void * data, EventDestroyFunc destroy) :
- name (name),
- data (data),
- destroy (destroy) {}
+ Event(const char * name, void * data, EventDestroyFunc destroy)
+ : name(name), data(data), destroy(destroy)
+ {
+ }
- ~Event ()
+ ~Event()
{
if (destroy)
- destroy (data);
+ destroy(data);
}
};
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static aud::mutex mutex;
static List<Event> events;
static QueuedFunc queued_events;
-static void events_execute (void *)
+static void events_execute(void *)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
Event * event;
- while ((event = events.head ()))
+ while ((event = events.head()))
{
- events.remove (event);
+ events.remove(event);
- pthread_mutex_unlock (& mutex);
+ mh.unlock();
- hook_call (event->name, event->data);
+ hook_call(event->name, event->data);
delete event;
- pthread_mutex_lock (& mutex);
+ mh.lock();
}
-
- pthread_mutex_unlock (& mutex);
}
-EXPORT void event_queue (const char * name, void * data, EventDestroyFunc destroy)
+EXPORT void event_queue(const char * name, void * data,
+ EventDestroyFunc destroy)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- if (! events.head ())
- queued_events.queue (events_execute, nullptr);
+ if (!events.head())
+ queued_events.queue(events_execute, nullptr);
- events.append (new Event (name, data, destroy));
-
- pthread_mutex_unlock (& mutex);
+ events.append(new Event(name, data, destroy));
}
-EXPORT void event_queue_cancel (const char * name, void * data)
+EXPORT void event_queue_cancel(const char * name, void * data)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- Event * event = events.head ();
+ Event * event = events.head();
while (event)
{
- Event * next = events.next (event);
+ Event * next = events.next(event);
- if (! strcmp (event->name, name) && (! data || event->data == data))
+ if (!strcmp(event->name, name) && (!data || event->data == data))
{
- events.remove (event);
+ events.remove(event);
delete event;
}
event = next;
}
-
- pthread_mutex_unlock (& mutex);
}
-void event_queue_cancel_all ()
+void event_queue_cancel_all()
{
- pthread_mutex_lock (& mutex);
- events.clear ();
- pthread_mutex_unlock (& mutex);
+ auto mh = mutex.take();
+ events.clear();
}
diff --git a/src/libaudcore/export.h b/src/libaudcore/export.h
index f91ed7c..f34332b 100644
--- a/src/libaudcore/export.h
+++ b/src/libaudcore/export.h
@@ -21,13 +21,13 @@
#define LIBAUDCORE_EXPORT_H
#ifdef _WIN32
- #ifdef LIBAUDCORE_BUILD
- #define LIBAUDCORE_PUBLIC __declspec(dllexport)
- #else
- #define LIBAUDCORE_PUBLIC __declspec(dllimport)
- #endif
+#ifdef LIBAUDCORE_BUILD
+#define LIBAUDCORE_PUBLIC __declspec(dllexport)
#else
- #define LIBAUDCORE_PUBLIC __attribute__ ((visibility ("default")))
+#define LIBAUDCORE_PUBLIC __declspec(dllimport)
+#endif
+#else
+#define LIBAUDCORE_PUBLIC __attribute__((visibility("default")))
#endif
#endif // LIBAUDCORE_EXPORT_H
diff --git a/src/libaudcore/fft.cc b/src/libaudcore/fft.cc
index c22d769..0587e7b 100644
--- a/src/libaudcore/fft.cc
+++ b/src/libaudcore/fft.cc
@@ -24,23 +24,23 @@
#define TWO_PI 6.2831853f
-#define N 512 /* size of the DFT */
-#define LOGN 9 /* log N (base 2) */
+#define N 512 /* size of the DFT */
+#define LOGN 9 /* log N (base 2) */
typedef std::complex<float> Complex;
-static float hamming[N]; /* hamming window, scaled to sum to 1 */
-static int reversed[N]; /* bit-reversal table */
-static Complex roots[N / 2]; /* N-th roots of unity */
-static char generated = 0; /* set if tables have been generated */
+static float hamming[N]; /* hamming window, scaled to sum to 1 */
+static int reversed[N]; /* bit-reversal table */
+static Complex roots[N / 2]; /* N-th roots of unity */
+static char generated = 0; /* set if tables have been generated */
/* Reverse the order of the lowest LOGN bits in an integer. */
-static int bit_reverse (int x)
+static int bit_reverse(int x)
{
int y = 0;
- for (int n = LOGN; n --; )
+ for (int n = LOGN; n--;)
{
y = (y << 1) | (x & 1);
x >>= 1;
@@ -51,17 +51,17 @@ static int bit_reverse (int x)
/* Generate lookup tables. */
-static void generate_tables ()
+static void generate_tables()
{
if (generated)
return;
- for (int n = 0; n < N; n ++)
- hamming[n] = 1 - 0.85f * cosf (n * (TWO_PI / N));
- for (int n = 0; n < N; n ++)
- reversed[n] = bit_reverse (n);
- for (int n = 0; n < N / 2; n ++)
- roots[n] = exp (Complex (0, n * (TWO_PI / N)));
+ for (int n = 0; n < N; n++)
+ hamming[n] = 1 - 0.85f * cosf(n * (TWO_PI / N));
+ for (int n = 0; n < N; n++)
+ reversed[n] = bit_reverse(n);
+ for (int n = 0; n < N / 2; n++)
+ roots[n] = exp(Complex(0, n * (TWO_PI / N)));
generated = 1;
}
@@ -69,12 +69,13 @@ static void generate_tables ()
/* Perform the DFT using the Cooley-Tukey algorithm. At each step s, where
* s=1..log N (base 2), there are N/(2^s) groups of intertwined butterfly
* operations. Each group contains (2^s)/2 butterflies, and each butterfly has
- * a span of (2^s)/2. The twiddle factors are nth roots of unity where n = 2^s. */
+ * a span of (2^s)/2. The twiddle factors are nth roots of unity where n = 2^s.
+ */
-static void do_fft (Complex a[N])
+static void do_fft(Complex a[N])
{
- int half = 1; /* (2^s)/2 */
- int inv = N / 2; /* N/(2^s) */
+ int half = 1; /* (2^s)/2 */
+ int inv = N / 2; /* N/(2^s) */
/* loop through steps */
while (inv)
@@ -83,7 +84,7 @@ static void do_fft (Complex a[N])
for (int g = 0; g < N; g += half << 1)
{
/* loop through butterflies */
- for (int b = 0, r = 0; b < half; b ++, r += inv)
+ for (int b = 0, r = 0; b < half; b++, r += inv)
{
Complex even = a[g + b];
Complex odd = roots[r] * a[g + half + b];
@@ -100,23 +101,23 @@ static void do_fft (Complex a[N])
/* Input is N=512 PCM samples.
* Output is intensity of frequencies from 1 to N/2=256. */
-void calc_freq (const float data[N], float freq[N / 2])
+void calc_freq(const float data[N], float freq[N / 2])
{
- generate_tables ();
+ generate_tables();
/* input is filtered by a Hamming window */
/* input values are in bit-reversed order */
Complex a[N];
- for (int n = 0; n < N; n ++)
+ for (int n = 0; n < N; n++)
a[reversed[n]] = data[n] * hamming[n];
- do_fft (a);
+ do_fft(a);
/* output values are divided by N */
/* frequencies from 1 to N/2-1 are doubled */
- for (int n = 0; n < N / 2 - 1; n ++)
- freq[n] = 2 * abs (a[1 + n]) / N;
+ for (int n = 0; n < N / 2 - 1; n++)
+ freq[n] = 2 * abs(a[1 + n]) / N;
/* frequency N/2 is not doubled */
- freq[N / 2 - 1] = abs (a[N / 2]) / N;
+ freq[N / 2 - 1] = abs(a[N / 2]) / N;
}
diff --git a/src/libaudcore/history.cc b/src/libaudcore/history.cc
index b8cfdbd..0f3c2b4 100644
--- a/src/libaudcore/history.cc
+++ b/src/libaudcore/history.cc
@@ -24,35 +24,35 @@
#define MAX_ENTRIES 30
-EXPORT String aud_history_get (int entry)
+EXPORT String aud_history_get(int entry)
{
- StringBuf name = str_printf ("entry%d", entry);
- String path = aud_get_str ("history", name);
- return (path[0] ? path : String ());
+ StringBuf name = str_printf("entry%d", entry);
+ String path = aud_get_str("history", name);
+ return (path[0] ? path : String());
}
-EXPORT void aud_history_add (const char * path)
+EXPORT void aud_history_add(const char * path)
{
- String add = String (path);
+ String add = String(path);
- for (int i = 0; i < MAX_ENTRIES; i ++)
+ for (int i = 0; i < MAX_ENTRIES; i++)
{
- StringBuf name = str_printf ("entry%d", i);
- String old = aud_get_str ("history", name);
- aud_set_str ("history", name, add);
+ StringBuf name = str_printf("entry%d", i);
+ String old = aud_get_str("history", name);
+ aud_set_str("history", name, add);
- if (! strcmp (old, path))
+ if (!strcmp(old, path))
break;
add = old;
}
}
-EXPORT void aud_history_clear ()
+EXPORT void aud_history_clear()
{
- for (int i = 0; i < MAX_ENTRIES; i ++)
+ for (int i = 0; i < MAX_ENTRIES; i++)
{
- StringBuf name = str_printf ("entry%d", i);
- aud_set_str ("history", name, "");
+ StringBuf name = str_printf("entry%d", i);
+ aud_set_str("history", name, "");
}
}
diff --git a/src/libaudcore/hook.cc b/src/libaudcore/hook.cc
index e9dd695..0364ced 100644
--- a/src/libaudcore/hook.cc
+++ b/src/libaudcore/hook.cc
@@ -19,15 +19,15 @@
#include "hook.h"
-#include <pthread.h>
-
#include "index.h"
#include "internal.h"
#include "multihash.h"
#include "objects.h"
#include "runtime.h"
+#include "threads.h"
-struct HookItem {
+struct HookItem
+{
HookFunction func;
void * user;
};
@@ -37,105 +37,95 @@ struct HookList
Index<HookItem> items;
int use_count;
- void compact ()
+ void compact()
{
- auto is_empty = [] (const HookItem & item)
- { return ! item.func; };
+ auto is_empty = [](const HookItem & item) { return !item.func; };
- items.remove_if (is_empty);
+ items.remove_if(is_empty);
}
};
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static aud::mutex mutex;
static SimpleHash<String, HookList> hooks;
-EXPORT void hook_associate (const char * name, HookFunction func, void * user)
+EXPORT void hook_associate(const char * name, HookFunction func, void * user)
{
- pthread_mutex_lock (& mutex);
-
- String key (name);
- HookList * list = hooks.lookup (key);
- if (! list)
- list = hooks.add (key, HookList ());
+ auto mh = mutex.take();
- list->items.append (func, user);
+ String key(name);
+ HookList * list = hooks.lookup(key);
+ if (!list)
+ list = hooks.add(key, HookList());
- pthread_mutex_unlock (& mutex);
+ list->items.append(func, user);
}
-EXPORT void hook_dissociate (const char * name, HookFunction func, void * user)
+EXPORT void hook_dissociate(const char * name, HookFunction func, void * user)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- String key (name);
- HookList * list = hooks.lookup (key);
- if (! list)
- goto DONE;
+ String key(name);
+ HookList * list = hooks.lookup(key);
+ if (!list)
+ return;
for (HookItem & item : list->items)
{
- if (item.func == func && (! user || item.user == user))
+ if (item.func == func && (!user || item.user == user))
item.func = nullptr;
}
- if (! list->use_count)
+ if (!list->use_count)
{
- list->compact ();
- if (! list->items.len ())
- hooks.remove (key);
+ list->compact();
+ if (!list->items.len())
+ hooks.remove(key);
}
-
-DONE:
- pthread_mutex_unlock (& mutex);
}
-EXPORT void hook_call (const char * name, void * data)
+EXPORT void hook_call(const char * name, void * data)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- String key (name);
- HookList * list = hooks.lookup (key);
- if (! list)
- goto DONE;
+ String key(name);
+ HookList * list = hooks.lookup(key);
+ if (!list)
+ return;
- list->use_count ++;
+ list->use_count++;
/* note: the list may grow (but not shrink) during the hook call */
- for (int i = 0; i < list->items.len (); i ++)
+ for (int i = 0; i < list->items.len(); i++)
{
/* copy locally to prevent race condition */
HookItem item = list->items[i];
if (item.func)
{
- pthread_mutex_unlock (& mutex);
- item.func (data, item.user);
- pthread_mutex_lock (& mutex);
+ mh.unlock();
+ item.func(data, item.user);
+ mh.lock();
}
}
- list->use_count --;
+ list->use_count--;
- if (! list->use_count)
+ if (!list->use_count)
{
- list->compact ();
- if (! list->items.len ())
- hooks.remove (key);
+ list->compact();
+ if (!list->items.len())
+ hooks.remove(key);
}
-
-DONE:
- pthread_mutex_unlock (& mutex);
}
-void hook_cleanup ()
+void hook_cleanup()
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- hooks.iterate ([] (const String & name, HookList & list) {
- AUDWARN ("Hook not disconnected: %s (%d)\n", (const char *) name, list.items.len ());
+ hooks.iterate([](const String & name, HookList & list) {
+ AUDWARN("Hook not disconnected: %s (%d)\n", (const char *)name,
+ list.items.len());
});
- hooks.clear ();
-
- pthread_mutex_unlock (& mutex);
+ hooks.clear();
}
diff --git a/src/libaudcore/hook.h b/src/libaudcore/hook.h
index 5772844..176076d 100644
--- a/src/libaudcore/hook.h
+++ b/src/libaudcore/hook.h
@@ -28,20 +28,25 @@
// reducing CPU wakeups.
// ========================================================================
-enum class TimerRate {
- Hz1, Hz4, Hz10, Hz30, count
+enum class TimerRate
+{
+ Hz1,
+ Hz4,
+ Hz10,
+ Hz30,
+ count
};
-typedef void (* TimerFunc) (void * data);
+typedef void (*TimerFunc)(void * data);
/* Adds <func> to the list of functions to be called at the given <rate>,
* unless it has already been added with the same <data>. */
-void timer_add (TimerRate rate, TimerFunc func, void * data = nullptr);
+void timer_add(TimerRate rate, TimerFunc func, void * data = nullptr);
/* Removes all instances matching <func> and <data> from the list of functions
* to be called at the given <rate>. If <data> is nullptr, all instances
* matching <func> are removed. */
-void timer_remove (TimerRate rate, TimerFunc func, void * data = nullptr);
+void timer_remove(TimerRate rate, TimerFunc func, void * data = nullptr);
/* Convenience wrapper for C++ classes. Allows non-static member functions to
* be used as timer callbacks. The Timer should be made a member of the class
@@ -51,31 +56,28 @@ template<class T>
class Timer
{
public:
- Timer (TimerRate rate, T * target, void (T::* func) ()) :
- rate (rate),
- target (target),
- func (func) {}
+ Timer(TimerRate rate, T * target, void (T::*func)())
+ : rate(rate), target(target), func(func)
+ {
+ }
- void start () const
- { timer_add (rate, run, (void *) this); }
- void stop () const
- { timer_remove (rate, run, (void *) this); }
+ void start() const { timer_add(rate, run, (void *)this); }
+ void stop() const { timer_remove(rate, run, (void *)this); }
- ~Timer ()
- { stop (); }
+ ~Timer() { stop(); }
- Timer (const Timer &) = delete;
- void operator= (const Timer &) = delete;
+ Timer(const Timer &) = delete;
+ void operator=(const Timer &) = delete;
private:
const TimerRate rate;
T * const target;
- void (T::* const func) ();
+ void (T::*const func)();
- static void run (void * timer_)
+ static void run(void * timer_)
{
- auto timer = (const Timer *) timer_;
- (timer->target->* timer->func) ();
+ auto timer = (const Timer *)timer_;
+ (timer->target->*timer->func)();
}
};
@@ -83,30 +85,32 @@ private:
// named event, or "hook", is called.
// =========================================================================
-typedef void (* HookFunction) (void * data, void * user);
+typedef void (*HookFunction)(void * data, void * user);
/* Adds <func> to the list of functions to be called when the hook <name> is
* triggered. */
-void hook_associate (const char * name, HookFunction func, void * user);
+void hook_associate(const char * name, HookFunction func, void * user);
/* Removes all instances matching <func> and <user> from the list of functions
* to be called when the hook <name> is triggered. If <user> is nullptr, all
* instances matching <func> are removed. */
-void hook_dissociate (const char * name, HookFunction func, void * user = nullptr);
+void hook_dissociate(const char * name, HookFunction func,
+ void * user = nullptr);
/* Triggers the hook <name>. */
-void hook_call (const char * name, void * data);
+void hook_call(const char * name, void * data);
-typedef void (* EventDestroyFunc) (void * data);
+typedef void (*EventDestroyFunc)(void * data);
/* Schedules a call of the hook <name> from the program's main loop.
* If <destroy> is not nullptr, it will be called on <data> after the
* hook is called. */
-void event_queue (const char * name, void * data, EventDestroyFunc destroy = nullptr);
+void event_queue(const char * name, void * data,
+ EventDestroyFunc destroy = nullptr);
/* Cancels pending hook calls matching <name> and <data>. If <data> is nullptr,
* all hook calls matching <name> are canceled. */
-void event_queue_cancel (const char * name, void * data = nullptr);
+void event_queue_cancel(const char * name, void * data = nullptr);
/* Convenience wrapper for C++ classes. Allows non-static member functions to
* be used as hook callbacks. The HookReceiver should be made a member of the
@@ -116,29 +120,26 @@ template<class T, class D = void>
class HookReceiver
{
public:
- HookReceiver (const char * hook, T * target, void (T::* func) (D)) :
- hook (hook),
- target (target),
- func (func)
+ HookReceiver(const char * hook, T * target, void (T::*func)(D))
+ : hook(hook), target(target), func(func)
{
- hook_associate (hook, run, this);
+ hook_associate(hook, run, this);
}
- ~HookReceiver ()
- { hook_dissociate (hook, run, this); }
+ ~HookReceiver() { hook_dissociate(hook, run, this); }
- HookReceiver (const HookReceiver &) = delete;
- void operator= (const HookReceiver &) = delete;
+ HookReceiver(const HookReceiver &) = delete;
+ void operator=(const HookReceiver &) = delete;
private:
const char * const hook;
T * const target;
- void (T::* const func) (D);
+ void (T::*const func)(D);
- static void run (void * d, void * recv_)
+ static void run(void * d, void * recv_)
{
- auto recv = (const HookReceiver *) recv_;
- (recv->target->* recv->func) (aud::from_ptr<D> (d));
+ auto recv = (const HookReceiver *)recv_;
+ (recv->target->*recv->func)(aud::from_ptr<D>(d));
}
};
@@ -147,29 +148,26 @@ template<class T>
class HookReceiver<T, void>
{
public:
- HookReceiver (const char * hook, T * target, void (T::* func) ()) :
- hook (hook),
- target (target),
- func (func)
+ HookReceiver(const char * hook, T * target, void (T::*func)())
+ : hook(hook), target(target), func(func)
{
- hook_associate (hook, run, this);
+ hook_associate(hook, run, this);
}
- ~HookReceiver ()
- { hook_dissociate (hook, run, this); }
+ ~HookReceiver() { hook_dissociate(hook, run, this); }
- HookReceiver (const HookReceiver &) = delete;
- void operator= (const HookReceiver &) = delete;
+ HookReceiver(const HookReceiver &) = delete;
+ void operator=(const HookReceiver &) = delete;
private:
const char * const hook;
T * const target;
- void (T::* const func) ();
+ void (T::*const func)();
- static void run (void *, void * recv_)
+ static void run(void *, void * recv_)
{
- auto recv = (const HookReceiver *) recv_;
- (recv->target->* recv->func) ();
+ auto recv = (const HookReceiver *)recv_;
+ (recv->target->*recv->func)();
}
};
diff --git a/src/libaudcore/i18n.h b/src/libaudcore/i18n.h
index 5b5205c..bbb48d7 100644
--- a/src/libaudcore/i18n.h
+++ b/src/libaudcore/i18n.h
@@ -1,6 +1,6 @@
/*
* i18n.h
- * Copyright 2007 William Pitcock
+ * Copyright 2007 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -20,13 +20,26 @@
#ifndef AUDACIOUS_I18N_H
#define AUDACIOUS_I18N_H
+#ifdef HAVE_GETTEXT
+
#include <libintl.h>
-#define _(String) dgettext (PACKAGE, String)
+#define _(String) dgettext(PACKAGE, String)
+
#ifdef gettext_noop
-#define N_(String) gettext_noop (String)
+#define N_(String) gettext_noop(String)
+#else
+#define N_(String) (String)
+#endif
+
#else
+
+#define _(String) (String)
#define N_(String) (String)
+#define dgettext(package, str) (str)
+#define dngettext(package, str1, str2, count) (count > 1 ? str2 : str1)
+#define ngettext(str1, str2, count) (count > 1 ? str2 : str1)
+
#endif
#endif /* AUDACIOUS_I18N_H */
diff --git a/src/libaudcore/index.cc b/src/libaudcore/index.cc
index 84ca64d..d33a0e0 100644
--- a/src/libaudcore/index.cc
+++ b/src/libaudcore/index.cc
@@ -24,52 +24,52 @@
#include <stdlib.h>
#include <string.h>
-#include <glib.h> /* for g_qsort_with_data */
+#include <glib.h> /* for g_qsort_with_data */
-static void do_fill (void * data, int len, aud::FillFunc fill_func)
+static void do_fill(void * data, int len, aud::FillFunc fill_func)
{
if (fill_func)
- fill_func (data, len);
+ fill_func(data, len);
else
- memset (data, 0, len);
+ memset(data, 0, len);
}
-static void do_erase (void * data, int len, aud::EraseFunc erase_func)
+static void do_erase(void * data, int len, aud::EraseFunc erase_func)
{
if (erase_func)
- erase_func (data, len);
+ erase_func(data, len);
}
-EXPORT void IndexBase::clear (aud::EraseFunc erase_func)
+EXPORT void IndexBase::clear(aud::EraseFunc erase_func)
{
- if (! m_data)
+ if (!m_data)
return;
- __sync_sub_and_fetch (& misc_bytes_allocated, m_size);
+ __sync_sub_and_fetch(&misc_bytes_allocated, m_size);
- do_erase (m_data, m_len, erase_func);
- free (m_data);
+ do_erase(m_data, m_len, erase_func);
+ free(m_data);
m_data = nullptr;
m_len = 0;
m_size = 0;
}
-EXPORT void * IndexBase::insert (int pos, int len)
+EXPORT void * IndexBase::insert(int pos, int len)
{
- assert (pos <= m_len);
- assert (len >= 0);
+ assert(pos <= m_len);
+ assert(len >= 0);
- if (! len)
+ if (!len)
goto out;
if (pos < 0)
- pos = m_len; /* insert at end */
+ pos = m_len; /* insert at end */
if (m_size < m_len + len)
{
/* never allocate less than 16 bytes */
- int new_size = aud::max (m_size, 16);
+ int new_size = aud::max(m_size, 16);
/* next try 4/3 current size, biased toward multiples of 4 */
if (new_size < m_len + len)
@@ -79,153 +79,160 @@ EXPORT void * IndexBase::insert (int pos, int len)
if (new_size < m_len + len)
new_size = m_len + len;
- void * new_data = realloc (m_data, new_size);
- if (! new_data)
- throw std::bad_alloc (); /* nothing changed yet */
+ void * new_data = realloc(m_data, new_size);
+ if (!new_data)
+ throw std::bad_alloc(); /* nothing changed yet */
- __sync_add_and_fetch (& misc_bytes_allocated, new_size - m_size);
+ __sync_add_and_fetch(&misc_bytes_allocated, new_size - m_size);
m_data = new_data;
m_size = new_size;
}
- memmove ((char *) m_data + pos + len, (char *) m_data + pos, m_len - pos);
+ memmove((char *)m_data + pos + len, (char *)m_data + pos, m_len - pos);
m_len += len;
out:
- return (char *) m_data + pos;
+ return (char *)m_data + pos;
}
-EXPORT void IndexBase::insert (int pos, int len, aud::FillFunc fill_func)
+EXPORT void IndexBase::insert(int pos, int len, aud::FillFunc fill_func)
{
- void * to = insert (pos, len);
+ void * to = insert(pos, len);
- if (! len)
+ if (!len)
return;
if (fill_func)
- fill_func (to, len);
+ fill_func(to, len);
else
- memset (to, 0, len);
+ memset(to, 0, len);
}
-EXPORT void IndexBase::insert (const void * from, int pos, int len, aud::CopyFunc copy_func)
+EXPORT void IndexBase::insert(const void * from, int pos, int len,
+ aud::CopyFunc copy_func)
{
- void * to = insert (pos, len);
+ void * to = insert(pos, len);
- if (! len)
+ if (!len)
return;
if (copy_func)
- copy_func (from, to, len);
+ copy_func(from, to, len);
else
- memcpy (to, from, len);
+ memcpy(to, from, len);
}
-EXPORT void IndexBase::remove (int pos, int len, aud::EraseFunc erase_func)
+EXPORT void IndexBase::remove(int pos, int len, aud::EraseFunc erase_func)
{
- assert (pos >= 0 && pos <= m_len);
- assert (len <= m_len - pos);
+ assert(pos >= 0 && pos <= m_len);
+ assert(len <= m_len - pos);
if (len < 0)
- len = m_len - pos; /* remove all following */
+ len = m_len - pos; /* remove all following */
- if (! len)
+ if (!len)
return;
- do_erase ((char *) m_data + pos, len, erase_func);
- memmove ((char *) m_data + pos, (char *) m_data + pos + len, m_len - pos - len);
+ do_erase((char *)m_data + pos, len, erase_func);
+ memmove((char *)m_data + pos, (char *)m_data + pos + len,
+ m_len - pos - len);
m_len -= len;
}
-EXPORT void IndexBase::erase (int pos, int len, aud::FillFunc fill_func, aud::EraseFunc erase_func)
+EXPORT void IndexBase::erase(int pos, int len, aud::FillFunc fill_func,
+ aud::EraseFunc erase_func)
{
- assert (pos >= 0 && pos <= m_len);
- assert (len <= m_len - pos);
+ assert(pos >= 0 && pos <= m_len);
+ assert(len <= m_len - pos);
if (len < 0)
- len = m_len - pos; /* erase all following */
+ len = m_len - pos; /* erase all following */
- if (! len)
+ if (!len)
return;
- do_erase ((char *) m_data + pos, len, erase_func);
- do_fill ((char *) m_data + pos, len, fill_func);
+ do_erase((char *)m_data + pos, len, erase_func);
+ do_fill((char *)m_data + pos, len, fill_func);
}
-EXPORT void IndexBase::shift (int from, int to, int len, aud::FillFunc fill_func, aud::EraseFunc erase_func)
+EXPORT void IndexBase::shift(int from, int to, int len, aud::FillFunc fill_func,
+ aud::EraseFunc erase_func)
{
- assert (len >= 0 && len <= m_len);
- assert (from >= 0 && from + len <= m_len);
- assert (to >= 0 && to + len <= m_len);
+ assert(len >= 0 && len <= m_len);
+ assert(from >= 0 && from + len <= m_len);
+ assert(to >= 0 && to + len <= m_len);
- if (! len)
+ if (!len)
return;
- int erase_len = aud::min (len, abs (to - from));
+ int erase_len = aud::min(len, abs(to - from));
if (to < from)
- do_erase ((char *) m_data + to, erase_len, erase_func);
+ do_erase((char *)m_data + to, erase_len, erase_func);
else
- do_erase ((char *) m_data + to + len - erase_len, erase_len, erase_func);
+ do_erase((char *)m_data + to + len - erase_len, erase_len, erase_func);
- memmove ((char *) m_data + to, (char *) m_data + from, len);
+ memmove((char *)m_data + to, (char *)m_data + from, len);
if (to < from)
- do_fill ((char *) m_data + from + len - erase_len, erase_len, fill_func);
+ do_fill((char *)m_data + from + len - erase_len, erase_len, fill_func);
else
- do_fill ((char *) m_data + from, erase_len, fill_func);
+ do_fill((char *)m_data + from, erase_len, fill_func);
}
-EXPORT void IndexBase::move_from (IndexBase & b, int from, int to, int len,
- bool expand, bool collapse, aud::FillFunc fill_func, aud::EraseFunc erase_func)
+EXPORT void IndexBase::move_from(IndexBase & b, int from, int to, int len,
+ bool expand, bool collapse,
+ aud::FillFunc fill_func,
+ aud::EraseFunc erase_func)
{
- assert (this != & b);
- assert (from >= 0 && from <= b.m_len);
- assert (len <= b.m_len - from);
+ assert(this != &b);
+ assert(from >= 0 && from <= b.m_len);
+ assert(len <= b.m_len - from);
if (len < 0)
- len = b.m_len - from; /* copy all following */
+ len = b.m_len - from; /* copy all following */
- if (! len)
+ if (!len)
return;
if (expand)
{
- assert (to <= m_len);
+ assert(to <= m_len);
if (to < 0)
- to = m_len; /* insert at end */
+ to = m_len; /* insert at end */
- insert (to, len);
+ insert(to, len);
}
else
{
- assert (to >= 0 && to <= m_len - len);
- do_erase ((char *) m_data + to, len, erase_func);
+ assert(to >= 0 && to <= m_len - len);
+ do_erase((char *)m_data + to, len, erase_func);
}
- memcpy ((char *) m_data + to, (char *) b.m_data + from, len);
+ memcpy((char *)m_data + to, (char *)b.m_data + from, len);
if (collapse)
{
- memmove ((char *) b.m_data + from, (char *) b.m_data + from + len, b.m_len - from - len);
+ memmove((char *)b.m_data + from, (char *)b.m_data + from + len,
+ b.m_len - from - len);
b.m_len -= len;
}
else
- do_fill ((char *) b.m_data + from, len, fill_func);
+ do_fill((char *)b.m_data + from, len, fill_func);
}
-EXPORT void IndexBase::sort (CompareFunc compare, int elemsize, void * userdata)
+EXPORT void IndexBase::sort(CompareFunc compare, int elemsize, void * userdata)
{
- if (! m_len)
+ if (!m_len)
return;
// since we require GLib >= 2.32, g_qsort_with_data performs a stable sort
- g_qsort_with_data (m_data, m_len / elemsize, elemsize, compare, userdata);
+ g_qsort_with_data(m_data, m_len / elemsize, elemsize, compare, userdata);
}
-EXPORT int IndexBase::bsearch (const void * key, CompareFunc compare,
- int elemsize, void * userdata) const
+EXPORT int IndexBase::bsearch(const void * key, CompareFunc compare,
+ int elemsize, void * userdata) const
{
int top = 0;
int bottom = m_len / elemsize;
@@ -233,7 +240,7 @@ EXPORT int IndexBase::bsearch (const void * key, CompareFunc compare,
while (top < bottom)
{
int middle = top + (bottom - top) / 2;
- int match = compare (key, (char *) m_data + middle * elemsize, userdata);
+ int match = compare(key, (char *)m_data + middle * elemsize, userdata);
if (match < 0)
bottom = middle;
diff --git a/src/libaudcore/index.h b/src/libaudcore/index.h
index a97a4b1..efc4ea7 100644
--- a/src/libaudcore/index.h
+++ b/src/libaudcore/index.h
@@ -34,49 +34,43 @@
class IndexBase
{
public:
- typedef int (* CompareFunc) (const void * a, const void * b, void * userdata);
+ typedef int (*CompareFunc)(const void * a, const void * b, void * userdata);
- constexpr IndexBase () :
- m_data (nullptr),
- m_len (0),
- m_size (0) {}
+ constexpr IndexBase() : m_data(nullptr), m_len(0), m_size(0) {}
- void clear (aud::EraseFunc erase_func); // use as destructor
+ void clear(aud::EraseFunc erase_func); // use as destructor
- IndexBase (IndexBase && b) :
- m_data (b.m_data),
- m_len (b.m_len),
- m_size (b.m_size)
+ IndexBase(IndexBase && b)
+ : m_data(b.m_data), m_len(b.m_len), m_size(b.m_size)
{
b.m_data = nullptr;
b.m_len = 0;
b.m_size = 0;
}
- void * begin ()
- { return m_data; }
- const void * begin () const
- { return m_data; }
- void * end ()
- { return (char *) m_data + m_len; }
- const void * end () const
- { return (char *) m_data + m_len; }
+ void * begin() { return m_data; }
+ const void * begin() const { return m_data; }
+ void * end() { return (char *)m_data + m_len; }
+ const void * end() const { return (char *)m_data + m_len; }
- int len () const
- { return m_len; }
+ int len() const { return m_len; }
- void * insert (int pos, int len); // no fill
- void insert (int pos, int len, aud::FillFunc fill_func);
- void insert (const void * from, int pos, int len, aud::CopyFunc copy_func);
- void remove (int pos, int len, aud::EraseFunc erase_func);
- void erase (int pos, int len, aud::FillFunc fill_func, aud::EraseFunc erase_func);
- void shift (int from, int to, int len, aud::FillFunc fill_func, aud::EraseFunc erase_func);
+ void * insert(int pos, int len); // no fill
+ void insert(int pos, int len, aud::FillFunc fill_func);
+ void insert(const void * from, int pos, int len, aud::CopyFunc copy_func);
+ void remove(int pos, int len, aud::EraseFunc erase_func);
+ void erase(int pos, int len, aud::FillFunc fill_func,
+ aud::EraseFunc erase_func);
+ void shift(int from, int to, int len, aud::FillFunc fill_func,
+ aud::EraseFunc erase_func);
- void move_from (IndexBase & b, int from, int to, int len, bool expand,
- bool collapse, aud::FillFunc fill_func, aud::EraseFunc erase_func);
+ void move_from(IndexBase & b, int from, int to, int len, bool expand,
+ bool collapse, aud::FillFunc fill_func,
+ aud::EraseFunc erase_func);
- void sort (CompareFunc compare, int elemsize, void * userdata);
- int bsearch (const void * key, CompareFunc search, int elemsize, void * userdata) const;
+ void sort(CompareFunc compare, int elemsize, void * userdata);
+ int bsearch(const void * key, CompareFunc search, int elemsize,
+ void * userdata) const;
private:
void * m_data;
@@ -89,74 +83,82 @@ class Index : private IndexBase
private:
// provides C-style callback to generic comparison functor
template<class Key, class F>
- struct WrapCompare {
- static int run (const void * key, const void * val, void * func)
- { return (* (F *) func) (* (const Key *) key, * (const T *) val); }
+ struct WrapCompare
+ {
+ static int run(const void * key, const void * val, void * func)
+ {
+ return (*(F *)func)(*(const Key *)key, *(const T *)val);
+ }
};
public:
- constexpr Index () :
- IndexBase () {}
+ constexpr Index() : IndexBase() {}
// use with care!
- IndexBase & base ()
- { return * this; }
-
- void clear ()
- { IndexBase::clear (aud::erase_func<T> ()); }
- ~Index ()
- { clear (); }
-
- Index (Index && b) :
- IndexBase (std::move (b)) {}
- Index & operator= (Index && b)
- { return aud::move_assign (* this, std::move (b)); }
-
- T * begin ()
- { return (T *) IndexBase::begin (); }
- const T * begin () const
- { return (const T *) IndexBase::begin (); }
- T * end ()
- { return (T *) IndexBase::end (); }
- const T * end () const
- { return (const T *) IndexBase::end (); }
-
- int len () const
- { return cooked (IndexBase::len ()); }
-
- T & operator[] (int i)
- { return begin ()[i]; }
- const T & operator[] (int i) const
- { return begin ()[i]; }
-
- void insert (int pos, int len)
- { IndexBase::insert (raw (pos), raw (len), aud::fill_func<T> ()); }
- void insert (const T * from, int pos, int len)
- { IndexBase::insert (from, raw (pos), raw (len), aud::copy_func<T> ()); }
- void remove (int pos, int len)
- { IndexBase::remove (raw (pos), raw (len), aud::erase_func<T> ()); }
- void erase (int pos, int len)
- { IndexBase::erase (raw (pos), raw (len), aud::fill_func<T> (), aud::erase_func<T> ()); }
- void shift (int from, int to, int len)
- { IndexBase::shift (raw (from), raw (to), raw (len), aud::fill_func<T> (), aud::erase_func<T> ()); }
-
- void move_from (Index<T> & b, int from, int to, int len, bool expand, bool collapse)
- { IndexBase::move_from (b, raw (from), raw (to), raw (len), expand,
- collapse, aud::fill_func<T> (), aud::erase_func<T> ()); }
-
- template<class ... Args>
- T & append (Args && ... args)
+ IndexBase & base() { return *this; }
+
+ void clear() { IndexBase::clear(aud::erase_func<T>()); }
+ ~Index() { clear(); }
+
+ Index(Index && b) : IndexBase(std::move(b)) {}
+ Index & operator=(Index && b)
{
- return * aud::construct<T>::make (IndexBase::insert (-1, sizeof (T)),
- std::forward<Args> (args) ...);
+ return aud::move_assign(*this, std::move(b));
}
- int find (const T & val) const
+ T * begin() { return (T *)IndexBase::begin(); }
+ const T * begin() const { return (const T *)IndexBase::begin(); }
+ T * end() { return (T *)IndexBase::end(); }
+ const T * end() const { return (const T *)IndexBase::end(); }
+
+ int len() const { return cooked(IndexBase::len()); }
+
+ T & operator[](int i) { return begin()[i]; }
+ const T & operator[](int i) const { return begin()[i]; }
+
+ void insert(int pos, int len)
{
- for (const T * iter = begin (); iter != end (); iter ++)
+ IndexBase::insert(raw(pos), raw(len), aud::fill_func<T>());
+ }
+ void insert(const T * from, int pos, int len)
+ {
+ IndexBase::insert(from, raw(pos), raw(len), aud::copy_func<T>());
+ }
+ void remove(int pos, int len)
+ {
+ IndexBase::remove(raw(pos), raw(len), aud::erase_func<T>());
+ }
+ void erase(int pos, int len)
+ {
+ IndexBase::erase(raw(pos), raw(len), aud::fill_func<T>(),
+ aud::erase_func<T>());
+ }
+ void shift(int from, int to, int len)
+ {
+ IndexBase::shift(raw(from), raw(to), raw(len), aud::fill_func<T>(),
+ aud::erase_func<T>());
+ }
+
+ void move_from(Index<T> & b, int from, int to, int len, bool expand,
+ bool collapse)
+ {
+ IndexBase::move_from(b, raw(from), raw(to), raw(len), expand, collapse,
+ aud::fill_func<T>(), aud::erase_func<T>());
+ }
+
+ template<class... Args>
+ T & append(Args &&... args)
+ {
+ return *aud::construct<T>::make(IndexBase::insert(-1, sizeof(T)),
+ std::forward<Args>(args)...);
+ }
+
+ int find(const T & val) const
+ {
+ for (const T * iter = begin(); iter != end(); iter++)
{
- if (* iter == val)
- return iter - begin ();
+ if (*iter == val)
+ return iter - begin();
}
return -1;
@@ -164,54 +166,57 @@ public:
// func(val) returns true to remove val, false to keep it
template<class F>
- bool remove_if (F func, bool clear_if_empty = false)
+ bool remove_if(F func, bool clear_if_empty = false)
{
- T * iter = begin ();
+ T * iter = begin();
bool changed = false;
- while (iter != end ())
+ while (iter != end())
{
- if (func (* iter))
+ if (func(*iter))
{
- remove (iter - begin (), 1);
+ remove(iter - begin(), 1);
changed = true;
}
else
- iter ++;
+ iter++;
}
- if (clear_if_empty && ! len ())
- clear ();
+ if (clear_if_empty && !len())
+ clear();
return changed;
}
// compare(a, b) returns <0 if a<b, 0 if a=b, >0 if a>b
template<class F>
- void sort (F compare)
- { IndexBase::sort (WrapCompare<T, F>::run, sizeof (T), & compare); }
+ void sort(F compare)
+ {
+ IndexBase::sort(WrapCompare<T, F>::run, sizeof(T), &compare);
+ }
// compare(key, val) returns <0 if key<val, 0 if key=val, >0 if key>val
template<class Key, class F>
- int bsearch (const Key & key, F compare)
- { return IndexBase::bsearch (& key, WrapCompare<Key, F>::run, sizeof (T), & compare); }
+ int bsearch(const Key & key, F compare)
+ {
+ return IndexBase::bsearch(&key, WrapCompare<Key, F>::run, sizeof(T),
+ &compare);
+ }
// for use of Index as a raw data buffer
// unlike insert(), does not zero-fill any added space
- void resize (int size)
+ void resize(int size)
{
- static_assert (std::is_trivial<T>::value, "for basic types only");
- int diff = size - len ();
+ static_assert(std::is_trivial<T>::value, "for basic types only");
+ int diff = size - len();
if (diff > 0)
- IndexBase::insert (-1, raw (diff));
+ IndexBase::insert(-1, raw(diff));
else if (diff < 0)
- IndexBase::remove (raw (size), -1, nullptr);
+ IndexBase::remove(raw(size), -1, nullptr);
}
private:
- static constexpr int raw (int len)
- { return len * sizeof (T); }
- static constexpr int cooked (int len)
- { return len / sizeof (T); }
+ static constexpr int raw(int len) { return len * sizeof(T); }
+ static constexpr int cooked(int len) { return len / sizeof(T); }
};
#endif // LIBAUDCORE_INDEX_H
diff --git a/src/libaudcore/inifile.cc b/src/libaudcore/inifile.cc
index 046c14a..c7f5da8 100644
--- a/src/libaudcore/inifile.cc
+++ b/src/libaudcore/inifile.cc
@@ -21,32 +21,32 @@
#include <string.h>
-#include <glib.h> /* for g_ascii_isspace */
+#include <glib.h> /* for g_ascii_isspace */
#include "audstrings.h"
#include "vfs.h"
-static char * strskip (char * str, char * end)
+static char * strskip(char * str, char * end)
{
- while (str < end && g_ascii_isspace (* str))
- str ++;
+ while (str < end && g_ascii_isspace(*str))
+ str++;
return str;
}
-static char * strtrim (char * str, char * end)
+static char * strtrim(char * str, char * end)
{
- while (end > str && g_ascii_isspace (end[-1]))
- end --;
+ while (end > str && g_ascii_isspace(end[-1]))
+ end--;
- * end = 0;
+ *end = 0;
return str;
}
-EXPORT void IniParser::parse (VFSFile & file)
+EXPORT void IniParser::parse(VFSFile & file)
{
int size = 512;
- StringBuf buf (size);
+ StringBuf buf(size);
char * pos = buf;
int len = 0;
@@ -54,55 +54,56 @@ EXPORT void IniParser::parse (VFSFile & file)
while (1)
{
- char * newline = (char *) memchr (pos, '\n', len);
+ char * newline = (char *)memchr(pos, '\n', len);
- while (! newline && ! eof)
+ while (!newline && !eof)
{
- memmove (buf, pos, len);
+ memmove(buf, pos, len);
pos = buf;
if (len >= size - 1)
{
size <<= 1;
- buf.resize (size);
+ buf.resize(size);
pos = buf;
}
- len += file.fread (buf + len, 1, size - 1 - len);
+ len += file.fread(buf + len, 1, size - 1 - len);
if (len < size - 1)
eof = true;
- newline = (char *) memchr (pos, '\n', len);
+ newline = (char *)memchr(pos, '\n', len);
}
char * end = newline ? newline : pos + len;
- char * start = strskip (pos, end);
+ char * start = strskip(pos, end);
char * sep;
if (start < end)
{
- switch (* start)
+ switch (*start)
{
case '#':
case ';':
break;
case '[':
- if ((end = (char *) memchr (start, ']', end - start)))
- handle_heading (strtrim (strskip (start + 1, end), end));
+ if ((end = (char *)memchr(start, ']', end - start)))
+ handle_heading(strtrim(strskip(start + 1, end), end));
break;
default:
- if ((sep = (char *) memchr (start, '=', end - start)))
- handle_entry (strtrim (start, sep), strtrim (strskip (sep + 1, end), end));
+ if ((sep = (char *)memchr(start, '=', end - start)))
+ handle_entry(strtrim(start, sep),
+ strtrim(strskip(sep + 1, end), end));
break;
}
}
- if (! newline)
+ if (!newline)
break;
len -= newline + 1 - pos;
@@ -110,14 +111,15 @@ EXPORT void IniParser::parse (VFSFile & file)
}
}
-EXPORT bool inifile_write_heading (VFSFile & file, const char * heading)
+EXPORT bool inifile_write_heading(VFSFile & file, const char * heading)
{
- StringBuf line = str_concat ({"\n[", heading, "]\n"});
- return (file.fwrite (line, 1, line.len ()) == line.len ());
+ StringBuf line = str_concat({"\n[", heading, "]\n"});
+ return (file.fwrite(line, 1, line.len()) == line.len());
}
-EXPORT bool inifile_write_entry (VFSFile & file, const char * key, const char * value)
+EXPORT bool inifile_write_entry(VFSFile & file, const char * key,
+ const char * value)
{
- StringBuf line = str_concat ({key, "=", value, "\n"});
- return (file.fwrite (line, 1, line.len ()) == line.len ());
+ StringBuf line = str_concat({key, "=", value, "\n"});
+ return (file.fwrite(line, 1, line.len()) == line.len());
}
diff --git a/src/libaudcore/inifile.h b/src/libaudcore/inifile.h
index 273d2c6..aa28794 100644
--- a/src/libaudcore/inifile.h
+++ b/src/libaudcore/inifile.h
@@ -27,18 +27,18 @@ class VFSFile;
class LIBAUDCORE_PUBLIC IniParser
{
public:
- virtual ~IniParser () {}
+ virtual ~IniParser() {}
- void parse (VFSFile & file);
+ void parse(VFSFile & file);
protected:
- virtual void handle_heading (const char * heading) = 0;
- virtual void handle_entry (const char * key, const char * value) = 0;
+ virtual void handle_heading(const char * heading) = 0;
+ virtual void handle_entry(const char * key, const char * value) = 0;
};
-bool inifile_write_heading (VFSFile & file, const char * heading)
- __attribute__ ((warn_unused_result));
-bool inifile_write_entry (VFSFile & file, const char * key, const char * value)
- __attribute__ ((warn_unused_result));
+bool inifile_write_heading(VFSFile & file, const char * heading)
+ __attribute__((warn_unused_result));
+bool inifile_write_entry(VFSFile & file, const char * key, const char * value)
+ __attribute__((warn_unused_result));
#endif /* LIBAUDCORE_INIFILE_H */
diff --git a/src/libaudcore/interface.cc b/src/libaudcore/interface.cc
index ae44093..ce4e5b2 100644
--- a/src/libaudcore/interface.cc
+++ b/src/libaudcore/interface.cc
@@ -30,10 +30,11 @@
#include "plugins.h"
#include "runtime.h"
-struct MenuItem {
+struct MenuItem
+{
const char * name;
const char * icon;
- void (* func) ();
+ void (*func)();
};
static PluginHandle * current_plugin;
@@ -41,205 +42,203 @@ static IfacePlugin * current_interface;
static aud::array<AudMenuID, Index<MenuItem>> menu_items;
-static void add_menu_items ()
+static void add_menu_items()
{
- for (AudMenuID id : aud::range<AudMenuID> ())
+ for (AudMenuID id : aud::range<AudMenuID>())
{
for (MenuItem & item : menu_items[id])
- current_interface->plugin_menu_add (id, item.func, item.name, item.icon);
+ current_interface->plugin_menu_add(id, item.func, item.name,
+ item.icon);
}
}
-static void remove_menu_items ()
+static void remove_menu_items()
{
- for (AudMenuID id : aud::range<AudMenuID> ())
+ for (AudMenuID id : aud::range<AudMenuID>())
{
for (MenuItem & item : menu_items[id])
- current_interface->plugin_menu_remove (id, item.func);
+ current_interface->plugin_menu_remove(id, item.func);
}
}
-static bool interface_load (PluginHandle * plugin)
+static bool interface_load(PluginHandle * plugin)
{
- auto i = (IfacePlugin *) aud_plugin_get_header (plugin);
- if (! i)
+ auto i = (IfacePlugin *)aud_plugin_get_header(plugin);
+ if (!i)
return false;
- AUDINFO ("Loading %s.\n", aud_plugin_get_name (plugin));
+ AUDINFO("Loading %s.\n", aud_plugin_get_name(plugin));
- if (! i->init ())
+ if (!i->init())
return false;
current_interface = i;
- add_menu_items ();
+ add_menu_items();
- if (aud_get_bool (0, "show_interface"))
- current_interface->show (true);
+ if (aud_get_bool("show_interface"))
+ current_interface->show(true);
return true;
}
-static void interface_unload ()
+static void interface_unload()
{
- AUDINFO ("Unloading %s.\n", aud_plugin_get_name (current_plugin));
+ AUDINFO("Unloading %s.\n", aud_plugin_get_name(current_plugin));
// call before unloading interface
- hook_call ("config save", nullptr);
+ hook_call("config save", nullptr);
- if (aud_get_bool (0, "show_interface"))
- current_interface->show (false);
+ if (aud_get_bool("show_interface"))
+ current_interface->show(false);
- remove_menu_items ();
+ remove_menu_items();
- current_interface->cleanup ();
+ current_interface->cleanup();
current_interface = nullptr;
}
-EXPORT void aud_ui_show (bool show)
+EXPORT void aud_ui_show(bool show)
{
- if (! current_interface)
+ if (!current_interface)
return;
- aud_set_bool (0, "show_interface", show);
+ aud_set_bool("show_interface", show);
- current_interface->show (show);
+ current_interface->show(show);
- vis_activate (show);
+ vis_activate(show);
}
-EXPORT bool aud_ui_is_shown ()
+EXPORT bool aud_ui_is_shown()
{
- if (! current_interface)
+ if (!current_interface)
return false;
- return aud_get_bool (0, "show_interface");
+ return aud_get_bool("show_interface");
}
-EXPORT void aud_ui_startup_notify (const char * id)
+EXPORT void aud_ui_startup_notify(const char * id)
{
if (current_interface)
- current_interface->startup_notify (id);
+ current_interface->startup_notify(id);
}
-EXPORT void aud_ui_show_error (const char * message)
+EXPORT void aud_ui_show_error(const char * message)
{
- if (aud_get_headless_mode ())
- AUDERR ("%s\n", message);
+ if (aud_get_headless_mode())
+ AUDERR("%s\n", message);
else
- event_queue ("ui show error", g_strdup (message), g_free);
+ event_queue("ui show error", g_strdup(message), g_free);
}
-PluginHandle * iface_plugin_get_current ()
-{
- return current_plugin;
-}
+PluginHandle * iface_plugin_get_current() { return current_plugin; }
-bool iface_plugin_set_current (PluginHandle * plugin)
+bool iface_plugin_set_current(PluginHandle * plugin)
{
if (current_interface)
- interface_unload ();
+ interface_unload();
- if (! interface_load (plugin))
+ if (!interface_load(plugin))
return false;
current_plugin = plugin;
return true;
}
-void interface_run ()
+void interface_run()
{
- if (aud_get_headless_mode ())
+ if (aud_get_headless_mode())
{
- mainloop_run ();
+ mainloop_run();
// call before shutting down
- hook_call ("config save", nullptr);
+ hook_call("config save", nullptr);
}
else if (current_interface)
{
- vis_activate (aud_get_bool (0, "show_interface"));
+ vis_activate(aud_get_bool("show_interface"));
- current_interface->run ();
- interface_unload ();
+ current_interface->run();
+ interface_unload();
}
}
-EXPORT void aud_quit ()
+EXPORT void aud_quit()
{
// Qt is very sensitive to things being deleted in the correct order
// to avoid upsetting it, we'll stop all queued callbacks right now
- QueuedFunc::inhibit_all ();
+ QueuedFunc::inhibit_all();
if (current_interface)
- current_interface->quit ();
+ current_interface->quit();
else
- mainloop_quit ();
+ mainloop_quit();
}
-EXPORT void aud_plugin_menu_add (AudMenuID id, void (* func) (), const char * name, const char * icon)
+EXPORT void aud_plugin_menu_add(AudMenuID id, void (*func)(), const char * name,
+ const char * icon)
{
- menu_items[id].append (name, icon, func);
+ menu_items[id].append(name, icon, func);
if (current_interface)
- current_interface->plugin_menu_add (id, func, name, icon);
+ current_interface->plugin_menu_add(id, func, name, icon);
}
-EXPORT void aud_plugin_menu_remove (AudMenuID id, void (* func) ())
+EXPORT void aud_plugin_menu_remove(AudMenuID id, void (*func)())
{
if (current_interface)
- current_interface->plugin_menu_remove (id, func);
+ current_interface->plugin_menu_remove(id, func);
- auto is_match = [=] (const MenuItem & item)
- { return item.func == func; };
+ auto is_match = [=](const MenuItem & item) { return item.func == func; };
- menu_items[id].remove_if (is_match, true);
+ menu_items[id].remove_if(is_match, true);
}
-EXPORT void aud_ui_show_about_window ()
+EXPORT void aud_ui_show_about_window()
{
if (current_interface)
- current_interface->show_about_window ();
+ current_interface->show_about_window();
}
-EXPORT void aud_ui_hide_about_window ()
+EXPORT void aud_ui_hide_about_window()
{
if (current_interface)
- current_interface->hide_about_window ();
+ current_interface->hide_about_window();
}
-EXPORT void aud_ui_show_filebrowser (bool open)
+EXPORT void aud_ui_show_filebrowser(bool open)
{
if (current_interface)
- current_interface->show_filebrowser (open);
+ current_interface->show_filebrowser(open);
}
-EXPORT void aud_ui_hide_filebrowser ()
+EXPORT void aud_ui_hide_filebrowser()
{
if (current_interface)
- current_interface->hide_filebrowser ();
+ current_interface->hide_filebrowser();
}
-EXPORT void aud_ui_show_jump_to_song ()
+EXPORT void aud_ui_show_jump_to_song()
{
if (current_interface)
- current_interface->show_jump_to_song ();
+ current_interface->show_jump_to_song();
}
-EXPORT void aud_ui_hide_jump_to_song ()
+EXPORT void aud_ui_hide_jump_to_song()
{
if (current_interface)
- current_interface->hide_jump_to_song ();
+ current_interface->hide_jump_to_song();
}
-EXPORT void aud_ui_show_prefs_window ()
+EXPORT void aud_ui_show_prefs_window()
{
if (current_interface)
- current_interface->show_prefs_window ();
+ current_interface->show_prefs_window();
}
-EXPORT void aud_ui_hide_prefs_window ()
+EXPORT void aud_ui_hide_prefs_window()
{
if (current_interface)
- current_interface->hide_prefs_window ();
+ current_interface->hide_prefs_window();
}
diff --git a/src/libaudcore/interface.h b/src/libaudcore/interface.h
index b918a38..0a8821d 100644
--- a/src/libaudcore/interface.h
+++ b/src/libaudcore/interface.h
@@ -22,7 +22,8 @@
#include <libaudcore/visualizer.h>
-enum class AudMenuID {
+enum class AudMenuID
+{
Main,
Playlist,
PlaylistAdd,
@@ -30,25 +31,26 @@ enum class AudMenuID {
count
};
-void aud_ui_show (bool show);
-bool aud_ui_is_shown ();
+void aud_ui_show(bool show);
+bool aud_ui_is_shown();
-void aud_ui_startup_notify (const char * id);
-void aud_ui_show_error (const char * message); /* thread-safe */
+void aud_ui_startup_notify(const char * id);
+void aud_ui_show_error(const char * message); /* thread-safe */
-void aud_ui_show_about_window ();
-void aud_ui_hide_about_window ();
-void aud_ui_show_filebrowser (bool open);
-void aud_ui_hide_filebrowser ();
-void aud_ui_show_jump_to_song ();
-void aud_ui_hide_jump_to_song ();
-void aud_ui_show_prefs_window ();
-void aud_ui_hide_prefs_window ();
+void aud_ui_show_about_window();
+void aud_ui_hide_about_window();
+void aud_ui_show_filebrowser(bool open);
+void aud_ui_hide_filebrowser();
+void aud_ui_show_jump_to_song();
+void aud_ui_hide_jump_to_song();
+void aud_ui_show_prefs_window();
+void aud_ui_hide_prefs_window();
-void aud_plugin_menu_add (AudMenuID id, void (* func) (), const char * name, const char * icon);
-void aud_plugin_menu_remove (AudMenuID id, void (* func) ());
+void aud_plugin_menu_add(AudMenuID id, void (*func)(), const char * name,
+ const char * icon);
+void aud_plugin_menu_remove(AudMenuID id, void (*func)());
-void aud_visualizer_add (Visualizer * vis);
-void aud_visualizer_remove (Visualizer * vis);
+void aud_visualizer_add(Visualizer * vis);
+void aud_visualizer_remove(Visualizer * vis);
#endif
diff --git a/src/libaudcore/internal.h b/src/libaudcore/internal.h
index 7035a20..2a79bef 100644
--- a/src/libaudcore/internal.h
+++ b/src/libaudcore/internal.h
@@ -32,130 +32,131 @@ class PluginHandle;
class VFSFile;
class Tuple;
-typedef bool (* DirForeachFunc) (const char * path, const char * basename, void * user);
+typedef bool (*DirForeachFunc)(const char * path, const char * basename,
+ void * user);
/* adder.cc */
-void adder_cleanup ();
+void adder_cleanup();
/* art.cc */
-void art_cache_current (const String & filename, Index<char> && data, String && art_file);
-void art_clear_current ();
-void art_cleanup ();
+void art_cache_current(const String & filename, Index<char> && data,
+ String && art_file);
+void art_clear_current();
+void art_cleanup();
/* art-search.cc */
-String art_search (const char * filename);
+String art_search(const char * filename);
/* charset.cc */
-void chardet_init ();
-void chardet_cleanup ();
+void chardet_init();
+void chardet_cleanup();
/* config.cc */
-void config_load ();
-void config_save ();
-void config_cleanup ();
+void config_load();
+void config_save();
+void config_cleanup();
/* drct.cc */
-void record_init ();
-void record_cleanup ();
+void record_init();
+void record_cleanup();
/* effect.cc */
-void effect_start (int & channels, int & rate);
-Index<float> & effect_process (Index<float> & data);
-bool effect_flush (bool force);
-Index<float> & effect_finish (Index<float> & data, bool end_of_playlist);
-int effect_adjust_delay (int delay);
+void effect_start(int & channels, int & rate);
+Index<float> & effect_process(Index<float> & data);
+bool effect_flush(bool force);
+Index<float> & effect_finish(Index<float> & data, bool end_of_playlist);
+int effect_adjust_delay(int delay);
-bool effect_plugin_start (PluginHandle * plugin);
-void effect_plugin_stop (PluginHandle * plugin);
+bool effect_plugin_start(PluginHandle * plugin);
+void effect_plugin_stop(PluginHandle * plugin);
/* equalizer.cc */
-void eq_init ();
-void eq_cleanup ();
-void eq_set_format (int new_channels, int new_rate);
-void eq_filter (float * data, int samples);
+void eq_init();
+void eq_cleanup();
+void eq_set_format(int new_channels, int new_rate);
+void eq_filter(float * data, int samples);
/* eventqueue.cc */
-void event_queue_cancel_all ();
+void event_queue_cancel_all();
/* fft.cc */
-void calc_freq (const float data[512], float freq[256]);
+void calc_freq(const float data[512], float freq[256]);
/* hook.cc */
-void hook_cleanup ();
+void hook_cleanup();
/* interface.cc */
-PluginHandle * iface_plugin_probe ();
-PluginHandle * iface_plugin_get_current ();
-bool iface_plugin_set_current (PluginHandle * plugin);
+PluginHandle * iface_plugin_probe();
+PluginHandle * iface_plugin_get_current();
+bool iface_plugin_set_current(PluginHandle * plugin);
-void interface_run ();
+void interface_run();
/* playback.cc */
/* do not call these; use aud_drct_play/stop() instead */
-void playback_play (int seek_time, bool pause);
-void playback_stop (bool exiting = false);
+void playback_play(int seek_time, bool pause);
+void playback_stop(bool exiting = false);
-bool playback_check_serial (int serial);
-void playback_set_info (int entry, Tuple && tuple);
+bool playback_check_serial(int serial);
+void playback_set_info(int entry, Tuple && tuple);
/* probe.cc */
-bool open_input_file (const char * filename, const char * mode,
- InputPlugin * ip, VFSFile & file, String * error = nullptr);
-InputPlugin * load_input_plugin (PluginHandle * decoder, String * error = nullptr);
+bool open_input_file(const char * filename, const char * mode, InputPlugin * ip,
+ VFSFile & file, String * error = nullptr);
+InputPlugin * load_input_plugin(PluginHandle * decoder,
+ String * error = nullptr);
-#define PROBE_FLAG_HAS_DECODER (1 << 0)
+#define PROBE_FLAG_HAS_DECODER (1 << 0)
#define PROBE_FLAG_MIGHT_HAVE_SUBTUNES (1 << 1)
-int probe_by_filename (const char * filename);
+int probe_by_filename(const char * filename);
/* runtime.cc */
extern size_t misc_bytes_allocated;
/* strpool.cc */
-void string_leak_check ();
+void string_leak_check();
/* timer.cc */
-void timer_cleanup ();
+void timer_cleanup();
/* util.cc */
-const char * get_home_utf8 ();
-bool dir_foreach (const char * path, DirForeachFunc func, void * user_data);
-String write_temp_file (const void * data, int64_t len);
+const char * get_home_utf8();
+bool dir_foreach(const char * path, DirForeachFunc func, void * user_data);
+String write_temp_file(const void * data, int64_t len);
-bool same_basename (const char * a, const char * b);
-const char * last_path_element (const char * path);
-void cut_path_element (char * path, int pos);
+bool same_basename(const char * a, const char * b);
+const char * last_path_element(const char * path);
+void cut_path_element(char * path, int pos);
-bool is_cuesheet_entry (const char * filename);
-bool is_subtune (const char * filename);
-StringBuf strip_subtune (const char * filename);
+bool is_cuesheet_entry(const char * filename);
+bool is_subtune(const char * filename);
+StringBuf strip_subtune(const char * filename);
-unsigned int32_hash (unsigned val);
-unsigned ptr_hash (const void * ptr);
+unsigned int32_hash(unsigned val);
+unsigned ptr_hash(const void * ptr);
struct IntHashKey
{
int val;
- constexpr IntHashKey (int val) :
- val (val) {}
- operator int () const
- { return val; }
- unsigned hash () const
- { return int32_hash (val); }
+ constexpr IntHashKey(int val) : val(val) {}
+ operator int() const { return val; }
+ unsigned hash() const { return int32_hash(val); }
};
/* vis-runner.cc */
-void vis_runner_start_stop (bool playing, bool paused);
-void vis_runner_pass_audio (int time, const Index<float> & data, int channels, int rate);
-void vis_runner_flush ();
-void vis_runner_enable (bool enable);
+void vis_runner_start_stop(bool playing, bool paused);
+void vis_runner_pass_audio(int time, const Index<float> & data, int channels,
+ int rate);
+void vis_runner_flush();
+void vis_runner_enable(bool enable);
/* visualization.cc */
-void vis_activate (bool activate);
-void vis_send_clear ();
-void vis_send_audio (const float * data, int channels);
+void vis_activate(bool activate);
+void vis_send_clear();
+void vis_send_audio(const float * data, int channels);
-bool vis_plugin_start (PluginHandle * plugin);
-void vis_plugin_stop (PluginHandle * plugin);
+bool vis_plugin_start(PluginHandle * plugin);
+void vis_plugin_stop(PluginHandle * plugin);
#endif
diff --git a/src/libaudcore/list.cc b/src/libaudcore/list.cc
index f2b7a5e..f5a64e2 100644
--- a/src/libaudcore/list.cc
+++ b/src/libaudcore/list.cc
@@ -19,7 +19,7 @@
#include "list.h"
-EXPORT void ListBase::insert_after (ListNode * prev, ListNode * node)
+EXPORT void ListBase::insert_after(ListNode * prev, ListNode * node)
{
ListNode * next;
@@ -43,7 +43,7 @@ EXPORT void ListBase::insert_after (ListNode * prev, ListNode * node)
tail = node;
}
-EXPORT void ListBase::remove (ListNode * node)
+EXPORT void ListBase::remove(ListNode * node)
{
ListNode * prev = node->prev;
ListNode * next = node->next;
@@ -62,13 +62,13 @@ EXPORT void ListBase::remove (ListNode * node)
tail = prev;
}
-EXPORT void ListBase::clear (DestroyFunc destroy)
+EXPORT void ListBase::clear(DestroyFunc destroy)
{
ListNode * node = head;
while (node)
{
ListNode * next = node->next;
- destroy (node);
+ destroy(node);
node = next;
}
diff --git a/src/libaudcore/list.h b/src/libaudcore/list.h
index a3551f1..90ef9af 100644
--- a/src/libaudcore/list.h
+++ b/src/libaudcore/list.h
@@ -32,54 +32,54 @@ private:
class ListBase
{
protected:
- typedef void (* DestroyFunc) (ListNode *);
+ typedef void (*DestroyFunc)(ListNode *);
ListNode * head = nullptr;
ListNode * tail = nullptr;
- void insert_after (ListNode * prev, ListNode * node);
- void remove (ListNode * node);
- void clear (DestroyFunc destroy);
+ void insert_after(ListNode * prev, ListNode * node);
+ void remove(ListNode * node);
+ void clear(DestroyFunc destroy);
- static ListNode * prev (ListNode * node)
- { return node->prev; }
- static ListNode * next (ListNode * node)
- { return node->next; }
+ static ListNode * prev(ListNode * node) { return node->prev; }
+ static ListNode * next(ListNode * node) { return node->next; }
};
template<class C>
class List : private ListBase
{
public:
- C * head () const
- { return (C *) ListBase::head; }
- C * tail () const
- { return (C *) ListBase::tail; }
+ C * head() const { return (C *)ListBase::head; }
+ C * tail() const { return (C *)ListBase::tail; }
- static C * prev (C * node)
- { return (C *) ListBase::prev (node); }
- static C * next (C * node)
- { return (C *) ListBase::next (node); }
+ static C * prev(C * node) { return (C *)ListBase::prev(node); }
+ static C * next(C * node) { return (C *)ListBase::next(node); }
- void insert_after (C * prev, C * node)
- { ListBase::insert_after (prev, node); }
- void remove (C * node)
- { ListBase::remove (node); }
+ void insert_after(C * prev, C * node)
+ {
+ ListBase::insert_after(prev, node);
+ }
+ void remove(C * node) { ListBase::remove(node); }
+
+ void prepend(C * node) { insert_after(nullptr, node); }
+ void append(C * node) { insert_after(tail(), node); }
- void prepend (C * node)
- { insert_after (nullptr, node); }
- void append (C * node)
- { insert_after (tail (), node); }
+ void clear() { ListBase::clear(destroy); }
- void clear ()
- { ListBase::clear (destroy); }
+ C * pop_head()
+ {
+ C * node = head();
+ if (node)
+ remove(node);
+ return node;
+ }
template<class MatchFunc>
- C * find (MatchFunc match)
+ C * find(MatchFunc match)
{
- for (C * node = head (); node; node = next (node))
+ for (C * node = head(); node; node = next(node))
{
- if (match (* node))
+ if (match(*node))
return node;
}
@@ -87,8 +87,7 @@ public:
}
private:
- static void destroy (ListNode * node)
- { delete (C *) node; }
+ static void destroy(ListNode * node) { delete (C *)node; }
};
#endif // LIBAUDCORE_LIST_H
diff --git a/src/libaudcore/logger.cc b/src/libaudcore/logger.cc
index 5fa300b..d00a5af 100644
--- a/src/libaudcore/logger.cc
+++ b/src/libaudcore/logger.cc
@@ -1,6 +1,6 @@
/*
* logger.cc
- * Copyright 2014 John Lindgren and William Pitcock
+ * Copyright 2014 John Lindgren and Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -20,26 +20,27 @@
#include "audstrings.h"
#include "index.h"
#include "runtime.h"
-#include "tinylock.h"
+#include "threads.h"
#include <stdio.h>
-namespace audlog {
+namespace audlog
+{
-struct HandlerData {
+struct HandlerData
+{
Handler handler;
Level level;
};
-static TinyRWLock lock;
+static aud::spinlock_rw lock;
static Index<HandlerData> handlers;
static Level stderr_level = Warning;
static Level min_level = Warning;
-EXPORT void set_stderr_level (Level level)
+EXPORT void set_stderr_level(Level level)
{
- tiny_lock_write (& lock);
-
+ auto wr = lock.write();
min_level = stderr_level = level;
for (const HandlerData & h : handlers)
@@ -47,31 +48,25 @@ EXPORT void set_stderr_level (Level level)
if (h.level < min_level)
min_level = h.level;
}
-
- tiny_unlock_write (& lock);
}
-EXPORT void subscribe (Handler handler, Level level)
+EXPORT void subscribe(Handler handler, Level level)
{
- tiny_lock_write (& lock);
-
- handlers.append (handler, level);
+ auto wr = lock.write();
+ handlers.append(handler, level);
if (level < min_level)
min_level = level;
-
- tiny_unlock_write (& lock);
}
-EXPORT void unsubscribe (Handler handler)
+EXPORT void unsubscribe(Handler handler)
{
- tiny_lock_write (& lock);
-
- auto is_match = [=] (const HandlerData & data)
- { return data.handler == handler; };
-
- handlers.remove_if (is_match, true);
+ auto is_match = [handler](const HandlerData & data) {
+ return data.handler == handler;
+ };
+ auto wr = lock.write();
+ handlers.remove_if(is_match, true);
min_level = stderr_level;
for (const HandlerData & h : handlers)
@@ -79,47 +74,47 @@ EXPORT void unsubscribe (Handler handler)
if (h.level < min_level)
min_level = h.level;
}
-
- tiny_unlock_write (& lock);
}
-EXPORT const char * get_level_name (Level level)
+EXPORT const char * get_level_name(Level level)
{
switch (level)
{
- case Debug: return "DEBUG";
- case Info: return "INFO";
- case Warning: return "WARNING";
- case Error: return "ERROR";
+ case Debug:
+ return "DEBUG";
+ case Info:
+ return "INFO";
+ case Warning:
+ return "WARNING";
+ case Error:
+ return "ERROR";
};
return nullptr;
}
-EXPORT void log (Level level, const char * file, int line, const char * func,
- const char * format, ...)
+EXPORT void log(Level level, const char * file, int line, const char * func,
+ const char * format, ...)
{
- tiny_lock_read (& lock);
+ auto rd = lock.read();
if (level >= min_level)
{
va_list args;
- va_start (args, format);
- StringBuf message = str_vprintf (format, args);
- va_end (args);
+ va_start(args, format);
+ StringBuf message = str_vprintf(format, args);
+ va_end(args);
if (level >= stderr_level)
- fprintf (stderr, "%s %s:%d [%s]: %s", get_level_name (level), file,
- line, func, (const char *) message);
+ fprintf(stderr, "%s %s:%d [%s]: %s", get_level_name(level), file,
+ line, func, (const char *)message);
for (const HandlerData & h : handlers)
{
if (level >= h.level)
- h.handler (level, file, line, func, message);
+ h.handler(level, file, line, func, message);
}
}
-
- tiny_unlock_read (& lock);
}
} // namespace audlog
diff --git a/src/libaudcore/mainloop.cc b/src/libaudcore/mainloop.cc
index 090aeca..359e561 100644
--- a/src/libaudcore/mainloop.cc
+++ b/src/libaudcore/mainloop.cc
@@ -29,7 +29,8 @@
#include "multihash.h"
#include "runtime.h"
-struct QueuedFuncParams {
+struct QueuedFuncParams
+{
QueuedFunc::Func func;
void * data;
int interval_ms;
@@ -47,22 +48,24 @@ struct QueuedFuncHelper
// Creates an appropriate helper subclass for the given parameters and
// schedules it to run the QueuedFunc
- static QueuedFuncHelper * create (QueuedFunc * queued, const QueuedFuncParams & params);
+ static QueuedFuncHelper * create(QueuedFunc * queued,
+ const QueuedFuncParams & params);
// Callback which runs the QueuedFunc, if still active
- void run ();
+ void run();
// Cancels any scheduled run of the QueuedFunc and marks the helper for
// deletion (it may not deleted immediately, but should not be accessed
// again after calling this function)
- virtual void cancel () = 0;
+ virtual void cancel() = 0;
- virtual ~QueuedFuncHelper () {}
+ virtual ~QueuedFuncHelper() {}
protected:
- QueuedFuncHelper (QueuedFunc * queued, const QueuedFuncParams & params) :
- queued (queued), params (params) {}
-
+ QueuedFuncHelper(QueuedFunc * queued, const QueuedFuncParams & params)
+ : queued(queued), params(params)
+ {
+ }
};
// The following hash table implements a thread-safe "registry" of active
@@ -73,27 +76,32 @@ protected:
struct QueuedFuncNode : public MultiHash::Node
{
// Creates a helper to be registered in the hash
- QueuedFuncNode (QueuedFunc * queued, const QueuedFuncParams & params) :
- helper (QueuedFuncHelper::create (queued, params)) {}
+ QueuedFuncNode(QueuedFunc * queued, const QueuedFuncParams & params)
+ : helper(QueuedFuncHelper::create(queued, params))
+ {
+ }
// Cancels a helper when it is unregistered from the hash
- ~QueuedFuncNode ()
- { helper->cancel (); }
+ ~QueuedFuncNode() { helper->cancel(); }
// Replaces the registration of one helper with another
- void reset (QueuedFunc * queued, const QueuedFuncParams & params)
+ void reset(QueuedFunc * queued, const QueuedFuncParams & params)
{
- helper->cancel ();
- helper = QueuedFuncHelper::create (queued, params);
+ helper->cancel();
+ helper = QueuedFuncHelper::create(queued, params);
}
// Checks whether a helper is still registered
- bool is_current (QueuedFuncHelper * test_helper) const
- { return test_helper == helper; }
+ bool is_current(QueuedFuncHelper * test_helper) const
+ {
+ return test_helper == helper;
+ }
// Hash comparison function
- bool match (const QueuedFunc * queued) const
- { return queued == helper->queued; }
+ bool match(const QueuedFunc * queued) const
+ {
+ return queued == helper->queued;
+ }
private:
QueuedFuncHelper * helper;
@@ -112,14 +120,13 @@ struct RunCheck
// Called if the QueuedFunc is not registered in the hash
// This indicates a "stale" event that should not be processed
- QueuedFuncNode * add (const QueuedFunc *)
- { return nullptr; }
+ QueuedFuncNode * add(const QueuedFunc *) { return nullptr; }
- bool found (const QueuedFuncNode * node)
+ bool found(const QueuedFuncNode * node)
{
// Check whether a different helper has been registered
// This also indicates a "stale" event that should not be processed
- if (! node->is_current (helper))
+ if (!node->is_current(helper))
return false;
// We are still registered and good to go
@@ -135,15 +142,15 @@ struct RunCheck
}
};
-void QueuedFuncHelper::run ()
+void QueuedFuncHelper::run()
{
// Check whether it's okay to run. The actual check is performed within
// the MultiHash lock to eliminate race conditions.
RunCheck r = {this, false};
- func_table.lookup (queued, ptr_hash (queued), r);
+ func_table.lookup(queued, ptr_hash(queued), r);
if (r.okay_to_run)
- params.func (params.data);
+ params.func(params.data);
}
// GLib implementation -- simple wrapper around g_timeout_add_full()
@@ -151,30 +158,30 @@ void QueuedFuncHelper::run ()
class HelperGLib : public QueuedFuncHelper
{
public:
- HelperGLib (QueuedFunc * queued, const QueuedFuncParams & params) :
- QueuedFuncHelper (queued, params)
+ HelperGLib(QueuedFunc * queued, const QueuedFuncParams & params)
+ : QueuedFuncHelper(queued, params)
{
- glib_source = g_timeout_add_full (G_PRIORITY_HIGH, params.interval_ms,
- run_cb, this, aud::delete_obj<HelperGLib>);
+ glib_source =
+ g_timeout_add_full(G_PRIORITY_HIGH, params.interval_ms, run_cb,
+ this, aud::delete_obj<HelperGLib>);
}
- void cancel ()
+ void cancel()
{
// GLib will delete the helper after we return to the main loop
- g_source_remove (glib_source);
+ g_source_remove(glib_source);
}
private:
- static gboolean run_cb (void * me)
+ static gboolean run_cb(void * me)
{
- (static_cast<HelperGLib *> (me))->run ();
+ (static_cast<HelperGLib *>(me))->run();
return G_SOURCE_CONTINUE;
}
int glib_source = 0;
};
-
#ifdef USE_QT
// Qt implementation -- rather more complicated
@@ -190,7 +197,7 @@ private:
class EventRouter : public QObject
{
protected:
- void customEvent (QEvent * event);
+ void customEvent(QEvent * event);
};
static EventRouter router;
@@ -198,18 +205,19 @@ static EventRouter router;
class HelperQEvent : public QueuedFuncHelper, public QEvent
{
public:
- HelperQEvent (QueuedFunc * queued, const QueuedFuncParams & params) :
- QueuedFuncHelper (queued, params),
- QEvent (User)
+ HelperQEvent(QueuedFunc * queued, const QueuedFuncParams & params)
+ : QueuedFuncHelper(queued, params), QEvent(User)
{
- QCoreApplication::postEvent (& router, this, Qt::HighEventPriority);
+ QCoreApplication::postEvent(&router, this, Qt::HighEventPriority);
}
- void cancel () {} // Qt will delete the event after it fires
+ void cancel() {} // Qt will delete the event after it fires
};
-void EventRouter::customEvent (QEvent * event)
- { dynamic_cast<HelperQEvent *> (event)->run (); }
+void EventRouter::customEvent(QEvent * event)
+{
+ dynamic_cast<HelperQEvent *>(event)->run();
+}
// Periodic callbacks are implemented through QObject's timer capability. In
// this case, the QueuedFuncHelper is a QObject that is re-associated with the
@@ -223,39 +231,38 @@ void EventRouter::customEvent (QEvent * event)
class HelperQTimer : public QueuedFuncHelper, public QObject
{
public:
- HelperQTimer (QueuedFunc * queued, const QueuedFuncParams & params) :
- QueuedFuncHelper (queued, params)
+ HelperQTimer(QueuedFunc * queued, const QueuedFuncParams & params)
+ : QueuedFuncHelper(queued, params)
{
- moveToThread (router.thread ()); // main thread
- QCoreApplication::postEvent (this, new QEvent (QEvent::User), Qt::HighEventPriority);
+ moveToThread(router.thread()); // main thread
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User),
+ Qt::HighEventPriority);
}
- void cancel ()
- { deleteLater (); }
+ void cancel() { deleteLater(); }
protected:
- void customEvent (QEvent *)
- { startTimer (params.interval_ms); }
- void timerEvent (QTimerEvent *)
- { run (); }
+ void customEvent(QEvent *) { startTimer(params.interval_ms); }
+ void timerEvent(QTimerEvent *) { run(); }
};
#endif // USE_QT
// creates the appropriate helper subclass
-QueuedFuncHelper * QueuedFuncHelper::create (QueuedFunc * queued, const QueuedFuncParams & params)
+QueuedFuncHelper * QueuedFuncHelper::create(QueuedFunc * queued,
+ const QueuedFuncParams & params)
{
#ifdef USE_QT
- if (aud_get_mainloop_type () == MainloopType::Qt)
+ if (aud_get_mainloop_type() == MainloopType::Qt)
{
if (params.interval_ms > 0)
- return new HelperQTimer (queued, params);
+ return new HelperQTimer(queued, params);
else
- return new HelperQEvent (queued, params);
+ return new HelperQEvent(queued, params);
}
#endif
- return new HelperGLib (queued, params);
+ return new HelperGLib(queued, params);
}
// "start" logic executed within the hash table lock
@@ -265,38 +272,43 @@ struct Starter
const QueuedFuncParams & params;
// register a new helper for this QueuedFunc
- QueuedFuncNode * add (const QueuedFunc *)
- { return in_lockdown ? nullptr : new QueuedFuncNode (queued, params); }
+ QueuedFuncNode * add(const QueuedFunc *)
+ {
+ return in_lockdown ? nullptr : new QueuedFuncNode(queued, params);
+ }
// cancel the old helper and register a replacement
- bool found (QueuedFuncNode * node)
- { node->reset (queued, params); return false; }
+ bool found(QueuedFuncNode * node)
+ {
+ node->reset(queued, params);
+ return false;
+ }
};
// common entry point used by all queue() and start() variants
-static void start_func (QueuedFunc * queued, const QueuedFuncParams & params)
+static void start_func(QueuedFunc * queued, const QueuedFuncParams & params)
{
Starter s = {queued, params};
- func_table.lookup (queued, ptr_hash (queued), s);
+ func_table.lookup(queued, ptr_hash(queued), s);
}
-EXPORT void QueuedFunc::queue (Func func, void * data)
+EXPORT void QueuedFunc::queue(Func func, void * data)
{
- start_func (this, {func, data, 0, false});
+ start_func(this, {func, data, 0, false});
_running = false;
}
-EXPORT void QueuedFunc::queue (int delay_ms, Func func, void * data)
+EXPORT void QueuedFunc::queue(int delay_ms, Func func, void * data)
{
- g_return_if_fail (delay_ms >= 0);
- start_func (this, {func, data, delay_ms, false});
+ g_return_if_fail(delay_ms >= 0);
+ start_func(this, {func, data, delay_ms, false});
_running = false;
}
-EXPORT void QueuedFunc::start (int interval_ms, Func func, void * data)
+EXPORT void QueuedFunc::start(int interval_ms, Func func, void * data)
{
- g_return_if_fail (interval_ms > 0);
- start_func (this, {func, data, interval_ms, true});
+ g_return_if_fail(interval_ms > 0);
+ start_func(this, {func, data, interval_ms, true});
_running = true;
}
@@ -304,68 +316,72 @@ EXPORT void QueuedFunc::start (int interval_ms, Func func, void * data)
struct Stopper
{
// not registered, do nothing
- QueuedFuncNode * add (const QueuedFunc *)
- { return nullptr; }
+ QueuedFuncNode * add(const QueuedFunc *) { return nullptr; }
// unregister and cancel helper
- bool found (QueuedFuncNode * node)
- { delete node; return true; }
+ bool found(QueuedFuncNode * node)
+ {
+ delete node;
+ return true;
+ }
};
-EXPORT void QueuedFunc::stop ()
+EXPORT void QueuedFunc::stop()
{
Stopper s;
- func_table.lookup (this, ptr_hash (this), s);
+ func_table.lookup(this, ptr_hash(this), s);
_running = false;
}
// unregister a pending callback at shutdown
-static bool cleanup_node (QueuedFuncNode * node)
- { delete node; return true; }
+static bool cleanup_node(QueuedFuncNode * node)
+{
+ delete node;
+ return true;
+}
// inhibit all future callbacks at shutdown
-static void enter_lockdown ()
- { in_lockdown = true; }
+static void enter_lockdown() { in_lockdown = true; }
-EXPORT void QueuedFunc::inhibit_all ()
+EXPORT void QueuedFunc::inhibit_all()
{
- func_table.iterate (cleanup_node, enter_lockdown);
+ func_table.iterate(cleanup_node, enter_lockdown);
}
// main loop implementation follows
static GMainLoop * glib_mainloop;
-EXPORT void mainloop_run ()
+EXPORT void mainloop_run()
{
#ifdef USE_QT
- if (aud_get_mainloop_type () == MainloopType::Qt)
+ if (aud_get_mainloop_type() == MainloopType::Qt)
{
static char app_name[] = "audacious";
static int dummy_argc = 1;
static char * dummy_argv[] = {app_name, nullptr};
- QCoreApplication (dummy_argc, dummy_argv).exec ();
+ QCoreApplication(dummy_argc, dummy_argv).exec();
}
else
#endif
{
- glib_mainloop = g_main_loop_new (nullptr, true);
- g_main_loop_run (glib_mainloop);
- g_main_loop_unref (glib_mainloop);
+ glib_mainloop = g_main_loop_new(nullptr, true);
+ g_main_loop_run(glib_mainloop);
+ g_main_loop_unref(glib_mainloop);
glib_mainloop = nullptr;
}
}
-EXPORT void mainloop_quit ()
+EXPORT void mainloop_quit()
{
#ifdef USE_QT
- if (aud_get_mainloop_type () == MainloopType::Qt)
+ if (aud_get_mainloop_type() == MainloopType::Qt)
{
- qApp->quit ();
+ qApp->quit();
}
else
#endif
{
- g_main_loop_quit (glib_mainloop);
+ g_main_loop_quit(glib_mainloop);
}
}
diff --git a/src/libaudcore/mainloop.h b/src/libaudcore/mainloop.h
index 4c38eba..2d74e28 100644
--- a/src/libaudcore/mainloop.h
+++ b/src/libaudcore/mainloop.h
@@ -27,43 +27,41 @@
class QueuedFunc
{
public:
- typedef void (* Func) (void * data);
+ typedef void (*Func)(void * data);
// one-time idle callback
- void queue (Func func, void * data);
+ void queue(Func func, void * data);
// one-time delayed callback
- void queue (int delay_ms, Func func, void * data);
+ void queue(int delay_ms, Func func, void * data);
// periodic timer callback
- void start (int interval_ms, Func func, void * data);
+ void start(int interval_ms, Func func, void * data);
// stops any type of callback
// note that queue() and start() also stop any previous callback
- void stop ();
+ void stop();
// true if a periodic timer is running
// does not apply to one-time callbacks
- bool running () const
- { return _running; }
+ bool running() const { return _running; }
- constexpr QueuedFunc () = default;
- QueuedFunc (const QueuedFunc &) = delete;
- void operator= (const QueuedFunc &) = delete;
+ constexpr QueuedFunc() = default;
+ QueuedFunc(const QueuedFunc &) = delete;
+ void operator=(const QueuedFunc &) = delete;
- ~QueuedFunc ()
- { stop (); }
+ ~QueuedFunc() { stop(); }
// cancels any pending callbacks
// inhibits all future callbacks
// needed to allow safe shutdown of some (Qt!) main loops
- static void inhibit_all ();
+ static void inhibit_all();
private:
bool _running = false;
};
-void mainloop_run ();
-void mainloop_quit ();
+void mainloop_run();
+void mainloop_quit();
#endif // LIBAUDCORE_MAINLOOP_H
diff --git a/src/libaudcore/meson.build b/src/libaudcore/meson.build
new file mode 100644
index 0000000..9c04bb3
--- /dev/null
+++ b/src/libaudcore/meson.build
@@ -0,0 +1,126 @@
+libaudcore_inc = include_directories('.')
+
+
+libaudcore_sources = [
+ 'adder.cc',
+ 'art.cc',
+ 'art-search.cc',
+ 'audio.cc',
+ 'audstrings.cc',
+ 'charset.cc',
+ 'config.cc',
+ 'cue-cache.cc',
+ 'drct.cc',
+ 'effect.cc',
+ 'equalizer.cc',
+ 'equalizer-preset.cc',
+ 'eventqueue.cc',
+ 'fft.cc',
+ 'history.cc',
+ 'hook.cc',
+ 'index.cc',
+ 'inifile.cc',
+ 'interface.cc',
+ 'list.cc',
+ 'logger.cc',
+ 'mainloop.cc',
+ 'multihash.cc',
+ 'output.cc',
+ 'parse.cc',
+ 'playback.cc',
+ 'playlist.cc',
+ 'playlist-cache.cc',
+ 'playlist-data.cc',
+ 'playlist-files.cc',
+ 'playlist-utils.cc',
+ 'plugin-init.cc',
+ 'plugin-load.cc',
+ 'plugin-registry.cc',
+ 'preferences.cc',
+ 'probe.cc',
+ 'probe-buffer.cc',
+ 'ringbuf.cc',
+ 'runtime.cc',
+ 'scanner.cc',
+ 'stringbuf.cc',
+ 'strpool.cc',
+ 'tinylock.cc',
+ 'timer.cc',
+ 'tuple.cc',
+ 'tuple-compiler.cc',
+ 'util.cc',
+ 'vfs.cc',
+ 'vfs_async.cc',
+ 'vfs_local.cc',
+ 'vis-runner.cc',
+ 'visualization.cc'
+]
+
+
+libaudcore_headers = [
+ 'audstrings.h',
+ 'drct.h',
+ 'equalizer.h',
+ 'export.h',
+ 'hook.h',
+ 'i18n.h',
+ 'index.h',
+ 'inifile.h',
+ 'interface.h',
+ 'list.h',
+ 'mainloop.h',
+ 'multihash.h',
+ 'objects.h',
+ 'playlist.h',
+ 'plugin.h',
+ 'plugins.h',
+ 'preferences.h',
+ 'probe.h',
+ 'ringbuf.h',
+ 'runtime.h',
+ 'templates.h',
+ 'tinylock.h',
+ 'threads.h',
+ 'tuple.h',
+ 'visualizer.h',
+ 'vfs.h',
+ 'vfs_async.h'
+]
+
+
+audio_h = configure_file(input: 'audio.h.in',
+ output: 'audio.h',
+ configuration: conf,
+ install: true,
+ install_dir: join_paths(get_option('includedir'), 'libaudcore'))
+
+
+libaudcore_deps = [glib_dep, gmodule_dep]
+
+if get_option('qt')
+ libaudcore_deps += [qt_dep]
+endif
+
+
+if cc.has_function('iconv')
+ iconv_dep = []
+else
+ iconv_dep = cc.find_library('iconv', required: true)
+endif
+
+libaudcore_deps += [iconv_dep]
+
+
+libaudcore_lib = library('audcore',
+ libaudcore_sources,
+ cpp_args: ['-DLIBAUDCORE_BUILD'],
+ include_directories: src_inc,
+ dependencies: libaudcore_deps,
+ link_with: libguess_lib,
+ version: '5.1.0',
+ soversion: '5',
+ install: true
+)
+
+
+install_headers(libaudcore_headers, subdir: 'libaudcore')
diff --git a/src/libaudcore/multihash.cc b/src/libaudcore/multihash.cc
index 81f9c83..2068a6c 100644
--- a/src/libaudcore/multihash.cc
+++ b/src/libaudcore/multihash.cc
@@ -19,9 +19,9 @@
#include "multihash.h"
-EXPORT void HashBase::add (Node * node, unsigned hash)
+EXPORT void HashBase::add(Node * node, unsigned hash)
{
- if (! buckets)
+ if (!buckets)
{
buckets = new Node *[InitialSize]();
size = InitialSize;
@@ -32,31 +32,31 @@ EXPORT void HashBase::add (Node * node, unsigned hash)
node->hash = hash;
buckets[b] = node;
- used ++;
+ used++;
if (used > size)
- resize (size << 1);
+ resize(size << 1);
}
-EXPORT HashBase::Node * HashBase::lookup (MatchFunc match, const void * data,
- unsigned hash, NodeLoc * loc) const
+EXPORT HashBase::Node * HashBase::lookup(MatchFunc match, const void * data,
+ unsigned hash, NodeLoc * loc) const
{
- if (! buckets)
+ if (!buckets)
return nullptr;
unsigned b = hash & (size - 1);
- Node * * node_ptr = & buckets[b];
- Node * node = * node_ptr;
+ Node ** node_ptr = &buckets[b];
+ Node * node = *node_ptr;
while (1)
{
- if (! node)
+ if (!node)
return nullptr;
- if (node->hash == hash && match (node, data))
+ if (node->hash == hash && match(node, data))
break;
- node_ptr = & node->next;
- node = * node_ptr;
+ node_ptr = &node->next;
+ node = *node_ptr;
}
if (loc)
@@ -68,47 +68,47 @@ EXPORT HashBase::Node * HashBase::lookup (MatchFunc match, const void * data,
return node;
}
-EXPORT void HashBase::remove (const NodeLoc & loc)
+EXPORT void HashBase::remove(const NodeLoc & loc)
{
- * loc.ptr = loc.next;
+ *loc.ptr = loc.next;
- used --;
- if (used < size >> 2 && size > InitialSize)
- resize (size >> 1);
+ used--;
+ if (used<size>> 2 && size > InitialSize)
+ resize(size >> 1);
}
-EXPORT void HashBase::iterate (FoundFunc func, void * state)
+EXPORT void HashBase::iterate(FoundFunc func, void * state)
{
- for (unsigned b = 0; b < size; b ++)
+ for (unsigned b = 0; b < size; b++)
{
- Node * * ptr = & buckets[b];
- Node * node = * ptr;
+ Node ** ptr = &buckets[b];
+ Node * node = *ptr;
while (node)
{
Node * next = node->next;
- if (func (node, state))
+ if (func(node, state))
{
- * ptr = next;
- used --;
+ *ptr = next;
+ used--;
}
else
- ptr = & node->next;
+ ptr = &node->next;
node = next;
}
}
- if (used < size >> 2 && size > InitialSize)
- resize (size >> 1);
+ if (used<size>> 2 && size > InitialSize)
+ resize(size >> 1);
}
-void HashBase::resize (unsigned new_size)
+void HashBase::resize(unsigned new_size)
{
- Node * * new_buckets = new Node *[new_size]();
+ Node ** new_buckets = new Node *[new_size]();
- for (unsigned b1 = 0; b1 < size; b1 ++)
+ for (unsigned b1 = 0; b1 < size; b1++)
{
Node * node = buckets[b1];
@@ -129,53 +129,51 @@ void HashBase::resize (unsigned new_size)
size = new_size;
}
-EXPORT int MultiHash::lookup (const void * data, unsigned hash, AddFunc add,
- FoundFunc found, void * state)
+EXPORT int MultiHash::lookup(const void * data, unsigned hash, AddFunc add,
+ FoundFunc found, void * state)
{
const unsigned c = (hash >> Shift) & (Channels - 1);
HashBase & channel = channels[c];
int status = 0;
- tiny_lock (& locks[c]);
+ auto lh = locks[c].take();
HashBase::NodeLoc loc;
- Node * node = channel.lookup (match, data, hash, & loc);
+ Node * node = channel.lookup(match, data, hash, &loc);
if (node)
{
status |= Found;
- if (found && found (node, state))
+ if (found && found(node, state))
{
status |= Removed;
- channel.remove (loc);
+ channel.remove(loc);
}
}
- else if (add && (node = add (data, state)))
+ else if (add && (node = add(data, state)))
{
status |= Added;
- channel.add (node, hash);
+ channel.add(node, hash);
}
- tiny_unlock (& locks[c]);
return status;
}
-EXPORT void MultiHash::iterate (FoundFunc func, void * state)
+EXPORT void MultiHash::iterate(FoundFunc func, void * state)
{
- iterate (func, state, nullptr, nullptr);
+ iterate(func, state, nullptr, nullptr);
}
-EXPORT void MultiHash::iterate (FoundFunc func, void * state, FinalFunc final, void * fstate)
+EXPORT void MultiHash::iterate(FoundFunc func, void * state, FinalFunc final,
+ void * fstate)
{
- for (TinyLock & lock : locks)
- tiny_lock (& lock);
+ aud::spinlock::holder lh[Channels];
+ for (int i = 0; i < Channels; i++)
+ lh[i] = locks[i].take();
for (HashBase & channel : channels)
- channel.iterate (func, state);
+ channel.iterate(func, state);
if (final)
- final (fstate);
-
- for (TinyLock & lock : locks)
- tiny_unlock (& lock);
+ final(fstate);
}
diff --git a/src/libaudcore/multihash.h b/src/libaudcore/multihash.h
index e5bf35b..d370a27 100644
--- a/src/libaudcore/multihash.h
+++ b/src/libaudcore/multihash.h
@@ -20,8 +20,8 @@
#ifndef LIBAUDCORE_MULTIHASH_H
#define LIBAUDCORE_MULTIHASH_H
+#include <libaudcore/threads.h>
#include <utility>
-#include <libaudcore/tinylock.h>
/* HashBase is a low-level hash table implementation. It is used as a backend
* for SimpleHash as well as for a single channel of MultiHash. */
@@ -32,60 +32,58 @@ public:
/* Skeleton structure containing internal members of a hash node (except for
* "refs", which is not used internally and included here only to fill an
* alignment gap). Actual node structures should subclass Node. */
- struct Node {
+ struct Node
+ {
Node * next;
unsigned hash;
unsigned refs;
};
/* Represents the location of a node within the table. */
- struct NodeLoc {
- Node * * ptr;
+ struct NodeLoc
+ {
+ Node ** ptr;
Node * next;
};
/* Callback. Returns true if <node> matches <data>, otherwise false. */
- typedef bool (* MatchFunc) (const Node * node, const void * data);
+ typedef bool (*MatchFunc)(const Node * node, const void * data);
/* Callback. Called when a node is found. Returns true if <node> is to be
* removed, otherwise false. */
- typedef bool (* FoundFunc) (Node * node, void * state);
+ typedef bool (*FoundFunc)(Node * node, void * state);
- constexpr HashBase () :
- buckets (nullptr),
- size (0),
- used (0) {}
+ constexpr HashBase() : buckets(nullptr), size(0), used(0) {}
- void clear () // use as destructor
+ void clear() // use as destructor
{
delete[] buckets;
- * this = HashBase ();
+ *this = HashBase();
}
- int n_items () const
- { return used; }
+ int n_items() const { return used; }
/* Adds a node. Does not check for duplicates. */
- void add (Node * node, unsigned hash);
+ void add(Node * node, unsigned hash);
/* Locates the node matching <data>. Returns null if no node is found. If
* <loc> is not null, also returns the location of the node, which can be
* used to remove it from the table. */
- Node * lookup (MatchFunc match, const void * data, unsigned hash,
- NodeLoc * loc = nullptr) const;
+ Node * lookup(MatchFunc match, const void * data, unsigned hash,
+ NodeLoc * loc = nullptr) const;
/* Removes a node, given a location returned by lookup_full(). */
- void remove (const NodeLoc & loc);
+ void remove(const NodeLoc & loc);
/* Iterates over all nodes in the table, removing them as desired. */
- void iterate (FoundFunc func, void * state);
+ void iterate(FoundFunc func, void * state);
private:
static constexpr unsigned InitialSize = 16;
- void resize (unsigned new_size);
+ void resize(unsigned new_size);
- Node * * buckets;
+ Node ** buckets;
unsigned size, used;
};
@@ -107,16 +105,13 @@ public:
typedef HashBase::Node Node;
typedef HashBase::MatchFunc MatchFunc;
typedef HashBase::FoundFunc FoundFunc;
- typedef void (* FinalFunc) (void * state);
+ typedef void (*FinalFunc)(void * state);
/* Callback. May create a new node representing <data> to be added to the
* table. Returns the new node or null. */
- typedef Node * (* AddFunc) (const void * data, void * state);
+ typedef Node * (*AddFunc)(const void * data, void * state);
- MultiHash (MatchFunc match) :
- match (match),
- locks (),
- channels () {}
+ MultiHash(MatchFunc match) : match(match), locks(), channels() {}
/* There is no destructor. In some instances, such as the string pool, it
* is never safe to destroy the hash table, since it can be referenced from
@@ -129,25 +124,26 @@ public:
* the table. <found> is called if a matching node is found, and may return
* true to remove the node from the table. Returns the status of the lookup
* as a bitmask of Found, Added, and Removed. */
- int lookup (const void * data, unsigned hash, AddFunc add, FoundFunc found, void * state);
+ int lookup(const void * data, unsigned hash, AddFunc add, FoundFunc found,
+ void * state);
/* All-purpose iteration function. All channels of the table are locked
* simultaneously during the iteration to freeze the table in a consistent
* state. <func> is called on each node in order, and may return true to
* remove the node from the table. */
- void iterate (FoundFunc func, void * state);
+ void iterate(FoundFunc func, void * state);
/* Variant of iterate() which runs a second callback after the iteration
* is complete, while the table is still locked. This is useful when some
* operation needs to be performed with the table in a known state. */
- void iterate (FoundFunc func, void * state, FinalFunc final, void * fstate);
+ void iterate(FoundFunc func, void * state, FinalFunc final, void * fstate);
private:
- static constexpr int Channels = 16; /* must be a power of two */
- static constexpr int Shift = 24; /* bit shift for channel selection */
+ static constexpr int Channels = 16; /* must be a power of two */
+ static constexpr int Shift = 24; /* bit shift for channel selection */
const MatchFunc match;
- TinyLock locks[Channels];
+ aud::spinlock locks[Channels];
HashBase channels[Channels];
};
@@ -170,55 +166,70 @@ public:
// bool found (Node_T * node);
// };
- MultiHash_T () : MultiHash (match_cb) {}
+ MultiHash_T() : MultiHash(match_cb) {}
- void clear ()
- { MultiHash::iterate (remove_cb, nullptr); }
+ void clear() { MultiHash::iterate(remove_cb, nullptr); }
template<class Op>
- int lookup (const Data_T * data, unsigned hash, Op & op)
- { return MultiHash::lookup (data, hash, WrapOp<Op>::add, WrapOp<Op>::found, & op); }
+ int lookup(const Data_T * data, unsigned hash, Op & op)
+ {
+ return MultiHash::lookup(data, hash, WrapOp<Op>::add, WrapOp<Op>::found,
+ &op);
+ }
template<class F>
- void iterate (F func)
- { MultiHash::iterate (WrapIterate<F>::run, & func); }
+ void iterate(F func)
+ {
+ MultiHash::iterate(WrapIterate<F>::run, &func);
+ }
template<class F, class Final>
- void iterate (F func, Final final)
- { MultiHash::iterate (WrapIterate<F>::run, & func, WrapFinal<Final>::run, & final); }
+ void iterate(F func, Final final)
+ {
+ MultiHash::iterate(WrapIterate<F>::run, &func, WrapFinal<Final>::run,
+ &final);
+ }
private:
- static bool match_cb (const Node * node, const void * data)
- { return (static_cast<const Node_T *> (node))->match
- (static_cast<const Data_T *> (data)); }
+ static bool match_cb(const Node * node, const void * data)
+ {
+ return (static_cast<const Node_T *>(node))
+ ->match(static_cast<const Data_T *>(data));
+ }
- static bool remove_cb (Node * node, void *)
+ static bool remove_cb(Node * node, void *)
{
- delete static_cast<Node_T *> (node);
+ delete static_cast<Node_T *>(node);
return true;
}
template<class Op>
- struct WrapOp {
- static Node * add (const void * data, void * op)
- { return (static_cast<Op *> (op))->add
- (static_cast<const Data_T *> (data)); }
- static bool found (Node * node, void * op)
- { return (static_cast<Op *> (op))->found
- (static_cast<Node_T *> (node)); }
+ struct WrapOp
+ {
+ static Node * add(const void * data, void * op)
+ {
+ return (static_cast<Op *>(op))
+ ->add(static_cast<const Data_T *>(data));
+ }
+ static bool found(Node * node, void * op)
+ {
+ return (static_cast<Op *>(op))->found(static_cast<Node_T *>(node));
+ }
};
template<class F>
- struct WrapIterate {
- static bool run (Node * node, void * func)
- { return (* static_cast<F *> (func))
- (static_cast<Node_T *> (node)); }
+ struct WrapIterate
+ {
+ static bool run(Node * node, void * func)
+ {
+ return (*static_cast<F *>(func))(static_cast<Node_T *>(node));
+ }
};
template<class Final>
- struct WrapFinal {
- static void run (void * func)
- { (* static_cast<Final *> (func)) (); }
+ struct WrapFinal
+ {
+ static void run(void * func) { (*static_cast<Final *>(func))(); }
};
};
@@ -228,80 +239,87 @@ template<class Key, class Value>
class SimpleHash : private HashBase
{
public:
- typedef void (* IterFunc) (const Key & key, Value & value, void * state);
+ typedef void (*IterFunc)(const Key & key, Value & value, void * state);
- ~SimpleHash ()
- { clear (); }
+ ~SimpleHash() { clear(); }
using HashBase::n_items;
- Value * lookup (const Key & key)
+ Value * lookup(const Key & key)
{
- auto node = static_cast<Node *> (HashBase::lookup (match_cb, & key, key.hash ()));
- return node ? & node->value : nullptr;
+ auto node =
+ static_cast<Node *>(HashBase::lookup(match_cb, &key, key.hash()));
+ return node ? &node->value : nullptr;
}
- Value * add (const Key & key, Value && value)
+ Value * add(const Key & key, Value && value)
{
- unsigned hash = key.hash ();
- auto node = static_cast<Node *> (HashBase::lookup (match_cb, & key, hash));
+ unsigned hash = key.hash();
+ auto node = static_cast<Node *>(HashBase::lookup(match_cb, &key, hash));
if (node)
- node->value = std::move (value);
+ node->value = std::move(value);
else
{
- node = new Node (key, std::move (value));
- HashBase::add (node, hash);
+ node = new Node(key, std::move(value));
+ HashBase::add(node, hash);
}
- return & node->value;
+ return &node->value;
}
- void remove (const Key & key)
+ void remove(const Key & key)
{
NodeLoc loc;
- auto node = static_cast<Node *> (HashBase::lookup (match_cb, & key, key.hash (), & loc));
+ auto node = static_cast<Node *>(
+ HashBase::lookup(match_cb, &key, key.hash(), &loc));
if (node)
{
delete node;
- HashBase::remove (loc);
+ HashBase::remove(loc);
}
}
- void clear ()
+ void clear()
{
- HashBase::iterate (remove_cb, nullptr);
- HashBase::clear ();
+ HashBase::iterate(remove_cb, nullptr);
+ HashBase::clear();
}
template<class F>
- void iterate (F func)
- { HashBase::iterate (WrapIterate<F>::run, & func); }
+ void iterate(F func)
+ {
+ HashBase::iterate(WrapIterate<F>::run, &func);
+ }
private:
struct Node : public HashBase::Node
{
- Node (const Key & key, Value && value) :
- key (key),
- value (std::move (value)) {}
+ Node(const Key & key, Value && value)
+ : key(key), value(std::move(value))
+ {
+ }
Key key;
Value value;
};
- struct IterData {
+ struct IterData
+ {
IterFunc func;
void * state;
};
- static bool match_cb (const HashBase::Node * node, const void * data)
- { return (static_cast<const Node *> (node))->key ==
- * static_cast<const Key *> (data); }
+ static bool match_cb(const HashBase::Node * node, const void * data)
+ {
+ return (static_cast<const Node *>(node))->key ==
+ *static_cast<const Key *>(data);
+ }
- static bool remove_cb (HashBase::Node * node, void *)
+ static bool remove_cb(HashBase::Node * node, void *)
{
- delete static_cast<Node *> (node);
+ delete static_cast<Node *>(node);
return true;
}
@@ -309,10 +327,10 @@ private:
template<class F>
struct WrapIterate
{
- static bool run (HashBase::Node * node_, void * func)
+ static bool run(HashBase::Node * node_, void * func)
{
- auto node = static_cast<Node *> (node_);
- (* static_cast<F *> (func)) (node->key, node->value);
+ auto node = static_cast<Node *>(node_);
+ (*static_cast<F *>(func))(node->key, node->value);
return false;
}
};
diff --git a/src/libaudcore/objects.h b/src/libaudcore/objects.h
index 214254a..7b79ac6 100644
--- a/src/libaudcore/objects.h
+++ b/src/libaudcore/objects.h
@@ -34,89 +34,76 @@ struct ArrayRef
const T * data;
int len;
- constexpr ArrayRef (decltype (nullptr) = nullptr) :
- data (nullptr),
- len (0) {}
+ constexpr ArrayRef(decltype(nullptr) = nullptr) : data(nullptr), len(0) {}
template<int N>
- constexpr ArrayRef (const T (& array) [N]) :
- data (array),
- len (N) {}
-
- constexpr ArrayRef (const T * data, int len) :
- data (data),
- len (len) {}
-
- const T * begin () const
- { return data; }
- const T * end () const
- { return data + len; }
+ constexpr ArrayRef(const T (&array)[N]) : data(array), len(N)
+ {
+ }
+
+ constexpr ArrayRef(const T * data, int len) : data(data), len(len) {}
+
+ const T * begin() const { return data; }
+ const T * end() const { return data + len; }
};
// Smart pointer. Deletes object pointed to when the pointer goes out of scope.
-template<class T, void (* deleter) (T *) = aud::delete_typed>
+template<class T, void (*deleter)(T *) = aud::delete_typed>
class SmartPtr
{
public:
- constexpr SmartPtr () :
- ptr (nullptr) {}
- explicit constexpr SmartPtr (T * ptr) :
- ptr (ptr) {}
+ constexpr SmartPtr() : ptr(nullptr) {}
+ explicit constexpr SmartPtr(T * ptr) : ptr(ptr) {}
- ~SmartPtr ()
- { if (ptr) deleter (ptr); }
+ ~SmartPtr()
+ {
+ if (ptr)
+ deleter(ptr);
+ }
- void capture (T * ptr2)
+ bool capture(T * ptr2)
{
- if (ptr) deleter (ptr);
+ if (ptr)
+ deleter(ptr);
ptr = ptr2;
+ return (bool)ptr;
}
- T * release ()
+ T * release()
{
T * ptr2 = ptr;
ptr = nullptr;
return ptr2;
}
- void clear ()
- { capture (nullptr); }
+ void clear() { capture(nullptr); }
- SmartPtr (SmartPtr && b) :
- ptr (b.ptr)
+ SmartPtr(SmartPtr && b) : ptr(b.ptr) { b.ptr = nullptr; }
+
+ SmartPtr & operator=(SmartPtr && b)
{
- b.ptr = nullptr;
+ return aud::move_assign(*this, std::move(b));
}
- SmartPtr & operator= (SmartPtr && b)
- { return aud::move_assign (* this, std::move (b)); }
-
- explicit operator bool () const
- { return (bool) ptr; }
-
- T * get ()
- { return ptr; }
- const T * get () const
- { return ptr; }
- T & operator* ()
- { return (* ptr); }
- const T & operator* () const
- { return (* ptr); }
- T * operator-> ()
- { return ptr; }
- const T * operator-> () const
- { return ptr; }
+ explicit operator bool() const { return (bool)ptr; }
+
+ T * get() { return ptr; }
+ const T * get() const { return ptr; }
+ T & operator*() { return (*ptr); }
+ const T & operator*() const { return (*ptr); }
+ T * operator->() { return ptr; }
+ const T * operator->() const { return ptr; }
private:
T * ptr;
};
-template<class T, class ... Args>
-SmartPtr<T> SmartNew (Args && ... args)
+template<class T, class... Args>
+SmartPtr<T> SmartNew(Args &&... args)
{
- return SmartPtr<T> (aud::construct<T>::make (operator new (sizeof (T)),
- std::forward<Args> (args) ...));
+ return SmartPtr<T>(aud::construct<T>::make(operator new(sizeof(T)),
+ std::forward<Args>(args)...));
}
// Convenience wrapper for a GLib-style string (char *).
@@ -125,12 +112,11 @@ SmartPtr<T> SmartNew (Args && ... args)
class CharPtr : public SmartPtr<char, aud::typed_func<char, g_free>>
{
public:
- CharPtr () : SmartPtr () {}
- explicit CharPtr (char * ptr) : SmartPtr (ptr) {}
+ CharPtr() : SmartPtr() {}
+ explicit CharPtr(char * ptr) : SmartPtr(ptr) {}
// non-const operator omitted to prevent "CharPtr s; g_free(s);"
- operator const char * () const
- { return get (); }
+ operator const char *() const { return get(); }
};
#endif
@@ -139,54 +125,49 @@ public:
class String
{
public:
- constexpr String () :
- raw (nullptr) {}
+ constexpr String() : raw(nullptr) {}
- ~String ()
- { raw_unref (raw); }
+ ~String()
+ {
+ if (raw)
+ raw_unref(raw);
+ }
- String (const String & b) :
- raw (raw_ref (b.raw)) {}
+ String(const String & b) : raw(raw_ref(b.raw)) {}
- String & operator= (const String & b)
+ String & operator=(const String & b)
{
- if (this != & b)
+ if (this != &b)
{
- raw_unref (raw);
- raw = raw_ref (b.raw);
+ raw_unref(raw);
+ raw = raw_ref(b.raw);
}
- return * this;
+ return *this;
}
- String (String && b) :
- raw (b.raw)
+ String(String && b) : raw(b.raw) { b.raw = nullptr; }
+
+ String & operator=(String && b)
{
- b.raw = nullptr;
+ return aud::move_assign(*this, std::move(b));
}
- String & operator= (String && b)
- { return aud::move_assign (* this, std::move (b)); }
-
- bool operator== (const String & b) const
- { return raw_equal (raw, b.raw); }
+ bool operator==(const String & b) const { return raw_equal(raw, b.raw); }
- explicit String (const char * str) :
- raw (raw_get (str)) {}
+ explicit String(const char * str) : raw(raw_get(str)) {}
- String (decltype (nullptr)) = delete;
+ String(decltype(nullptr)) = delete;
- operator const char * () const
- { return raw; }
+ operator const char *() const { return raw; }
- unsigned hash () const
- { return raw_hash (raw); }
+ unsigned hash() const { return raw_hash(raw); }
private:
- static char * raw_get (const char * str);
- static char * raw_ref (const char * str);
- static void raw_unref (char * str);
- static unsigned raw_hash (const char * str);
- static bool raw_equal (const char * str1, const char * str2);
+ static char * raw_get(const char * str);
+ static char * raw_ref(const char * str);
+ static void raw_unref(char * str);
+ static unsigned raw_hash(const char * str);
+ static bool raw_equal(const char * str1, const char * str2);
char * raw;
};
@@ -212,33 +193,27 @@ struct StringStack;
class StringBuf
{
public:
- constexpr StringBuf () :
- stack (nullptr),
- m_data (nullptr),
- m_len (0) {}
-
- explicit StringBuf (int len) :
- stack (nullptr),
- m_data (nullptr),
- m_len (0)
+ constexpr StringBuf() : stack(nullptr), m_data(nullptr), m_len(0) {}
+
+ explicit StringBuf(int len) : stack(nullptr), m_data(nullptr), m_len(0)
{
- resize (len);
+ resize(len);
}
- StringBuf (StringBuf && other) :
- stack (other.stack),
- m_data (other.m_data),
- m_len (other.m_len)
+ StringBuf(StringBuf && other)
+ : stack(other.stack), m_data(other.m_data), m_len(other.m_len)
{
other.stack = nullptr;
other.m_data = nullptr;
other.m_len = 0;
}
- StringBuf & operator= (StringBuf && other)
- { return aud::move_assign (* this, std::move (other)); }
+ StringBuf & operator=(StringBuf && other)
+ {
+ return aud::move_assign(*this, std::move(other));
+ }
- ~StringBuf ();
+ ~StringBuf();
// Resizes to <len> bytes (not counting the terminating null byte) by
// appended uninitialized bytes or truncating. The resized string will be
@@ -246,33 +221,31 @@ public:
// string as large as possible. This can be useful when the required length
// is not known in advance. However, it will be impossible to create any
// further StringBufs until resize() is called again.
- void resize (int len);
+ void resize(int len);
// Inserts the substring <s> at the given position, or appends it if <pos>
// is -1. If <len> is -1, <s> is assumed to be null-terminated; otherwise,
// <len> indicates the number of bytes to insert. If <s> is a null pointer,
// uninitialized bytes are inserted and <len> must not be -1. A pointer to
// the inserted substring is returned for convenience.
- char * insert (int pos, const char * s, int len = -1);
+ char * insert(int pos, const char * s, int len = -1);
// Removes <len> bytes at the given position.
- void remove (int pos, int len);
+ void remove(int pos, int len);
// Collapses any unused space preceding this string.
// Judicious use can combat memory fragmentation.
// Returns a move reference to allow e.g. "return str.settle();"
- StringBuf && settle ();
+ StringBuf && settle();
- int len () const
- { return m_len; }
+ int len() const { return m_len; }
- operator char * ()
- { return m_data; }
+ operator char *() { return m_data; }
// deprecated, use assignment
- void steal (StringBuf && other) __attribute__((deprecated));
+ void steal(StringBuf && other) __attribute__((deprecated));
// deprecated, use insert()
- void combine (StringBuf && other) __attribute__((deprecated));
+ void combine(StringBuf && other) __attribute__((deprecated));
private:
StringStack * stack;
diff --git a/src/libaudcore/output.cc b/src/libaudcore/output.cc
index bb861e5..53931de 100644
--- a/src/libaudcore/output.cc
+++ b/src/libaudcore/output.cc
@@ -19,8 +19,8 @@
#include "output.h"
+#include <assert.h>
#include <math.h>
-#include <pthread.h>
#include <stdlib.h>
#include <string.h>
@@ -32,6 +32,7 @@
#include "plugin.h"
#include "plugins.h"
#include "runtime.h"
+#include "threads.h"
/* With Audacious 3.7, there is some support for secondary output plugins.
* Notes and limitations:
@@ -45,39 +46,101 @@
* - The secondary's write_audio() is called in a tight loop until it has
* caught up to the primary, and should never return a zero byte count. */
-static pthread_mutex_t mutex_major = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t mutex_minor = PTHREAD_MUTEX_INITIALIZER;
+/* Locking in this module is complicated by the fact that some of the
+ * output plugin functions (specifically period_wait() and drain()) are
+ * blocking calls. Various other functions are designed to be called
+ * in parallel with period_wait() and drain().
+ *
+ * A two-mutex scheme is used to ensure that safe operations are allowed
+ * while a blocking call is in progress, and unsafe operations are
+ * prevented. The "major" mutex is locked before an unsafe operations;
+ * only the "minor" mutex is locked before a safe one. The "minor" mutex
+ * protects all changes to state data.
+ *
+ * The thread performing a blocking call (i.e. the input thread) must
+ * perform the following sequence:
+ *
+ * 1. Lock the major mutex
+ * 2. Lock the minor mutex
+ * 3. Check whether state data is correct for the call
+ * 4. Unlock the minor mutex
+ * 5. Call the blocking function
+ * 6. Unlock the major mutex
+ *
+ * The following classes attempt to enforce some of the rules regarding
+ * locking and state data. */
+
+/* locks held for a "safe" operation */
+struct SafeLock
+{
+ aud::mutex::holder minor;
+};
+
+/* locks held for an "unsafe" operation */
+struct UnsafeLock : SafeLock
+{
+ aud::mutex::holder major;
+};
+
+class OutputState
+{
+public:
+ bool input() const { return (m_flags & INPUT); }
+ bool output() const { return (m_flags & OUTPUT); }
+ bool secondary() const { return (m_flags & SECONDARY); }
+ bool paused() const { return (m_flags & PAUSED); }
+ bool flushed() const { return (m_flags & FLUSHED); }
+ bool resetting() const { return (m_flags & RESETTING); }
+
+ SafeLock lock_safe() { return {mutex_minor.take()}; }
+
+ UnsafeLock lock_unsafe()
+ {
+ UnsafeLock lock;
+ lock.major = mutex_major.take();
+ lock.minor = mutex_minor.take();
+ return lock;
+ }
-#define LOCK_MAJOR pthread_mutex_lock (& mutex_major)
-#define UNLOCK_MAJOR pthread_mutex_unlock (& mutex_major)
-#define LOCK_MINOR pthread_mutex_lock (& mutex_minor)
-#define UNLOCK_MINOR pthread_mutex_unlock (& mutex_minor)
-#define LOCK_ALL do { LOCK_MAJOR; LOCK_MINOR; } while (0)
-#define UNLOCK_ALL do { UNLOCK_MINOR; UNLOCK_MAJOR; } while (0)
+ /* safe state changes */
+ void set_secondary(SafeLock &, bool on) { set_flag(SECONDARY, on); }
+ void set_paused(SafeLock &, bool on) { set_flag(PAUSED, on); }
+ void set_flushed(SafeLock &, bool on) { set_flag(FLUSHED, on); }
+ void set_resetting(SafeLock &, bool on) { set_flag(RESETTING, on); }
-/* State variables. State changes that are allowed between LOCK_MINOR and
- * UNLOCK_MINOR (all others must take place between LOCK_ALL and UNLOCK_ALL):
- * s_paused -> true or false, s_flushed -> true, s_resetting -> true,
- * s_secondary -> true or false */
+ /* unsafe state changes */
+ void set_input(UnsafeLock &, bool on) { set_flag(INPUT, on); }
+ void set_output(UnsafeLock &, bool on) { set_flag(OUTPUT, on); }
-static bool s_input; /* input plugin connected */
-static bool s_output; /* primary output plugin connected */
-static bool s_secondary; /* secondary output plugin connected */
-static bool s_gain; /* replay gain info set */
-static bool s_paused; /* paused */
-static bool s_flushed; /* flushed, writes ignored until resume */
-static bool s_resetting; /* resetting output system */
+ void await_change(SafeLock & lock) { cond.wait(lock.minor); }
-/* Condition variable linked to LOCK_MINOR.
- * The input thread will wait if the following is true:
- * ((! s_output || s_paused || s_resetting) && ! s_flushed)
- * Hence you must signal if you cause the inverse to be true:
- * ((s_output && ! s_paused && ! s_resetting) || s_flushed) */
+private:
+ static constexpr int INPUT = (1 << 0); /* input plugin connected */
+ static constexpr int OUTPUT =
+ (1 << 1); /* primary output plugin connected */
+ static constexpr int SECONDARY =
+ (1 << 2); /* secondary output plugin connected */
+ static constexpr int PAUSED = (1 << 3); /* paused */
+ static constexpr int FLUSHED =
+ (1 << 4); /* flushed, writes ignored until resume */
+ static constexpr int RESETTING = (1 << 5); /* resetting output system */
-static pthread_cond_t cond_minor = PTHREAD_COND_INITIALIZER;
+ int m_flags = 0;
+
+ aud::mutex mutex_major;
+ aud::mutex mutex_minor;
+
+ aud::condvar cond;
+
+ void set_flag(int flag, bool on)
+ {
+ m_flags = on ? (m_flags | flag) : (m_flags & ~flag);
+ /* wake any thread waiting for a state change */
+ cond.notify_all();
+ }
+};
-#define SIGNAL_MINOR pthread_cond_broadcast (& cond_minor)
-#define WAIT_MINOR pthread_cond_wait (& cond_minor, & mutex_minor)
+static OutputState state;
static OutputPlugin * cop; /* current (primary) output plugin */
static OutputPlugin * sop; /* secondary output plugin */
@@ -94,138 +157,164 @@ static int out_format, out_channels, out_rate;
static int out_bytes_per_sec, out_bytes_held;
static int64_t in_frames, out_bytes_written;
static ReplayGainInfo gain_info;
+static bool gain_info_valid;
static Index<float> buffer1;
static Index<char> buffer2;
-static inline int get_format (bool & automatic)
+static inline int get_format(bool & automatic)
{
automatic = false;
- switch (aud_get_int (0, "output_bit_depth"))
+ switch (aud_get_int("output_bit_depth"))
{
- case 16: return FMT_S16_NE;
- case 24: return FMT_S24_3NE;
- case 32: return FMT_S32_NE;
-
- // return FMT_FLOAT for "auto" as well
- case -1: automatic = true;
- default: return FMT_FLOAT;
+ case 16:
+ return FMT_S16_NE;
+ case 24:
+ return FMT_S24_3NE;
+ case 32:
+ return FMT_S32_NE;
+
+ // return FMT_FLOAT for "auto" as well
+ case -1:
+ automatic = true;
+ default:
+ return FMT_FLOAT;
}
}
-/* assumes LOCK_ALL, s_input */
-static void setup_effects ()
+static void setup_effects(SafeLock &)
{
+ assert(state.input());
+
effect_channels = in_channels;
effect_rate = in_rate;
- effect_start (effect_channels, effect_rate);
- eq_set_format (effect_channels, effect_rate);
+ effect_start(effect_channels, effect_rate);
+ eq_set_format(effect_channels, effect_rate);
}
-/* assumes LOCK_ALL */
-static void cleanup_output ()
+static void cleanup_output(UnsafeLock & lock)
{
- if (! s_output)
+ if (!state.output())
return;
- if (! s_paused && ! s_flushed && ! s_resetting)
+ // avoid locking up if the input thread reaches close_audio() while
+ // paused (unlikely but possible with perfect timing)
+ if (out_bytes_written && !state.paused())
{
- UNLOCK_MINOR;
- cop->drain ();
- LOCK_MINOR;
+ lock.minor.unlock();
+ cop->drain();
+ lock.minor.lock();
}
- s_output = false;
+ state.set_output(lock, false);
- buffer1.clear ();
- buffer2.clear ();
+ buffer1.clear();
+ buffer2.clear();
- cop->close_audio ();
- vis_runner_start_stop (false, false);
+ cop->close_audio();
+ vis_runner_start_stop(false, false);
}
-/* assumes LOCK_MINOR */
-static void cleanup_secondary ()
+static void cleanup_secondary(SafeLock & lock)
{
- if (! s_secondary)
+ if (!state.secondary())
return;
- s_secondary = false;
- sop->close_audio ();
+ state.set_secondary(lock, false);
+ sop->close_audio();
+}
+
+static void apply_pause(SafeLock & lock, bool pause, bool new_output = false)
+{
+ if (state.output())
+ {
+ // assume output plugin is unpaused after open_audio()
+ if (pause != (new_output ? false : state.paused()))
+ cop->pause(pause);
+
+ vis_runner_start_stop(true, pause);
+ }
+
+ state.set_paused(lock, pause);
}
-/* assumes LOCK_MINOR, s_output */
-static void apply_pause ()
+static bool open_audio_with_info(OutputPlugin * op, const char * filename,
+ const Tuple & tuple, int format, int rate,
+ int chans, String & error)
{
- cop->pause (s_paused);
- vis_runner_start_stop (true, s_paused);
+ op->set_info(filename, tuple);
+ return op->open_audio(format, rate, chans, error);
}
-/* assumes LOCK_ALL, s_input */
-static void setup_output (bool new_input)
+static void setup_output(UnsafeLock & lock, bool new_input, bool pause)
{
- if (! cop)
+ assert(state.input());
+
+ if (!cop)
return;
bool automatic;
- int format = get_format (automatic);
+ int format = get_format(automatic);
- if (s_output && effect_channels == out_channels &&
- effect_rate == out_rate && ! (new_input && cop->force_reopen))
+ if (state.output() && effect_channels == out_channels &&
+ effect_rate == out_rate && !(new_input && cop->force_reopen))
{
- AUDINFO ("Reuse output, %d channels, %d Hz.\n", effect_channels, effect_rate);
+ AUDINFO("Reuse output, %d channels, %d Hz.\n", effect_channels,
+ effect_rate);
+ apply_pause(lock, pause);
return;
}
- AUDINFO ("Setup output, format %d, %d channels, %d Hz.\n", format, effect_channels, effect_rate);
+ AUDINFO("Setup output, format %d, %d channels, %d Hz.\n", format,
+ effect_channels, effect_rate);
- cleanup_output ();
- cop->set_info (in_filename, in_tuple);
+ cleanup_output(lock);
String error;
- while (! cop->open_audio (format, effect_rate, effect_channels, error))
+ while (!open_audio_with_info(cop, in_filename, in_tuple, format,
+ effect_rate, effect_channels, error))
{
if (automatic && format == FMT_FLOAT)
format = FMT_S32_NE;
else if (automatic && format == FMT_S32_NE)
format = FMT_S16_NE;
else if (format == FMT_S24_3NE)
- format = FMT_S24_NE; /* some output plugins support only padded 24-bit */
+ format =
+ FMT_S24_NE; /* some output plugins support only padded 24-bit */
else
{
- aud_ui_show_error (error ? (const char *) error : _("Error opening output stream"));
+ aud_ui_show_error(error ? (const char *)error
+ : _("Error opening output stream"));
return;
}
- AUDINFO ("Falling back to format %d.\n", format);
+ AUDINFO("Falling back to format %d.\n", format);
}
- s_output = true;
+ state.set_output(lock, true);
out_format = format;
out_channels = effect_channels;
out_rate = effect_rate;
- out_bytes_per_sec = FMT_SIZEOF (format) * out_channels * out_rate;
+ out_bytes_per_sec = FMT_SIZEOF(format) * out_channels * out_rate;
out_bytes_held = 0;
out_bytes_written = 0;
- apply_pause ();
-
- if (! s_paused && ! s_flushed && ! s_resetting)
- SIGNAL_MINOR;
+ apply_pause(lock, pause, true);
}
-/* assumes LOCK_MINOR, s_input */
-static void setup_secondary (bool new_input)
+static void setup_secondary(SafeLock & lock, bool new_input)
{
- if (! sop)
+ assert(state.input());
+
+ if (!sop)
return;
int rate, channels;
- record_stream = (OutputStream) aud_get_int (0, "record_stream");
+ record_stream = (OutputStream)aud_get_int("record_stream");
if (record_stream < OutputStream::AfterEffects)
{
@@ -238,145 +327,166 @@ static void setup_secondary (bool new_input)
channels = effect_channels;
}
- if (s_secondary && channels == sec_channels && rate == sec_rate &&
- ! (new_input && sop->force_reopen))
+ if (state.secondary() && channels == sec_channels && rate == sec_rate &&
+ !(new_input && sop->force_reopen))
return;
- cleanup_secondary ();
- sop->set_info (in_filename, in_tuple);
+ cleanup_secondary(lock);
String error;
- if (! sop->open_audio (FMT_FLOAT, rate, channels, error))
+ if (!open_audio_with_info(sop, in_filename, in_tuple, FMT_FLOAT, rate,
+ channels, error))
{
- aud_ui_show_error (error ? (const char *) error : _("Error recording output stream"));
+ aud_ui_show_error(error ? (const char *)error
+ : _("Error recording output stream"));
return;
}
- s_secondary = true;
+ state.set_secondary(lock, true);
sec_channels = channels;
sec_rate = rate;
}
-/* assumes LOCK_MINOR, s_output */
-static void flush_output ()
+static void flush_output(SafeLock &)
{
+ assert(state.output());
+
out_bytes_held = 0;
out_bytes_written = 0;
- cop->flush ();
- vis_runner_flush ();
+ cop->flush();
+ vis_runner_flush();
}
-static void apply_replay_gain (Index<float> & data)
+static void apply_replay_gain(SafeLock &, Index<float> & data)
{
- if (! aud_get_bool (0, "enable_replay_gain"))
+ if (!aud_get_bool("enable_replay_gain"))
return;
- float factor = powf (10, aud_get_double (0, "replay_gain_preamp") / 20);
+ float factor = powf(10, aud_get_double("replay_gain_preamp") / 20);
- if (s_gain)
+ if (gain_info_valid)
{
float peak;
- auto mode = (ReplayGainMode) aud_get_int (0, "replay_gain_mode");
+ auto mode = (ReplayGainMode)aud_get_int("replay_gain_mode");
if ((mode == ReplayGainMode::Album) ||
(mode == ReplayGainMode::Automatic &&
- (! aud_get_bool (0, "shuffle") || aud_get_bool (0, "album_shuffle"))))
+ (!aud_get_bool("shuffle") || aud_get_bool("album_shuffle"))))
{
- factor *= powf (10, gain_info.album_gain / 20);
+ factor *= powf(10, gain_info.album_gain / 20);
peak = gain_info.album_peak;
}
else
{
- factor *= powf (10, gain_info.track_gain / 20);
+ factor *= powf(10, gain_info.track_gain / 20);
peak = gain_info.track_peak;
}
- if (aud_get_bool (0, "enable_clipping_prevention") && peak * factor > 1)
+ if (aud_get_bool("enable_clipping_prevention") && peak * factor > 1)
factor = 1 / peak;
}
else
- factor *= powf (10, aud_get_double (0, "default_gain") / 20);
+ factor *= powf(10, aud_get_double("default_gain") / 20);
if (factor < 0.99 || factor > 1.01)
- audio_amplify (data.begin (), 1, data.len (), & factor);
+ audio_amplify(data.begin(), 1, data.len(), &factor);
}
-/* assumes LOCK_MINOR, s_secondary */
-static void write_secondary (const Index<float> & data)
+static void write_secondary(SafeLock &, const Index<float> & data)
{
- auto begin = (const char *) data.begin ();
- auto end = (const char *) data.end ();
+ assert(state.secondary());
+
+ auto begin = (const char *)data.begin();
+ auto end = (const char *)data.end();
while (begin < end)
- begin += sop->write_audio (begin, end - begin);
+ begin += sop->write_audio(begin, end - begin);
}
-/* assumes LOCK_ALL, s_output */
-static void write_output (Index<float> & data)
+static void write_output(UnsafeLock & lock, Index<float> & data)
{
- if (! data.len ())
+ assert(state.output());
+
+ if (!data.len())
return;
- if (s_secondary && record_stream == OutputStream::AfterEffects)
- write_secondary (data);
+ if (state.secondary() && record_stream == OutputStream::AfterEffects)
+ write_secondary(lock, data);
- int out_time = aud::rescale<int64_t> (out_bytes_written, out_bytes_per_sec, 1000);
- vis_runner_pass_audio (out_time, data, out_channels, out_rate);
+ int out_time =
+ aud::rescale<int64_t>(out_bytes_written, out_bytes_per_sec, 1000);
+ vis_runner_pass_audio(out_time, data, out_channels, out_rate);
- eq_filter (data.begin (), data.len ());
+ eq_filter(data.begin(), data.len());
- if (s_secondary && record_stream == OutputStream::AfterEqualizer)
- write_secondary (data);
+ if (state.secondary() && record_stream == OutputStream::AfterEqualizer)
+ write_secondary(lock, data);
- if (aud_get_bool (0, "software_volume_control"))
+ if (aud_get_bool("software_volume_control"))
{
- StereoVolume v = {aud_get_int (0, "sw_volume_left"), aud_get_int (0, "sw_volume_right")};
- audio_amplify (data.begin (), out_channels, data.len () / out_channels, v);
+ StereoVolume v = {aud_get_int("sw_volume_left"),
+ aud_get_int("sw_volume_right")};
+ audio_amplify(data.begin(), out_channels, data.len() / out_channels, v);
}
- if (aud_get_bool (0, "soft_clipping"))
- audio_soft_clip (data.begin (), data.len ());
+ if (aud_get_bool("soft_clipping"))
+ audio_soft_clip(data.begin(), data.len());
- const void * out_data = data.begin ();
+ const void * out_data = data.begin();
if (out_format != FMT_FLOAT)
{
- buffer2.resize (FMT_SIZEOF (out_format) * data.len ());
- audio_to_int (data.begin (), buffer2.begin (), out_format, data.len ());
- out_data = buffer2.begin ();
+ buffer2.resize(FMT_SIZEOF(out_format) * data.len());
+ audio_to_int(data.begin(), buffer2.begin(), out_format, data.len());
+ out_data = buffer2.begin();
}
- out_bytes_held = FMT_SIZEOF (out_format) * data.len ();
+ out_bytes_held = FMT_SIZEOF(out_format) * data.len();
- while (! s_paused && ! s_flushed && ! s_resetting)
+ while (out_bytes_held && !state.resetting())
{
- int written = cop->write_audio (out_data, out_bytes_held);
+ if (state.paused())
+ {
+ // avoid locking up if the input thread reaches close_audio() while
+ // paused (unlikely but possible with perfect timing)
+ if (!state.input())
+ break;
+
+ state.await_change(lock);
+ continue;
+ }
+
+ int written = cop->write_audio(out_data, out_bytes_held);
- out_data = (const char *) out_data + written;
+ out_data = (const char *)out_data + written;
out_bytes_held -= written;
out_bytes_written += written;
- if (! out_bytes_held)
+ if (!out_bytes_held)
break;
- UNLOCK_MINOR;
- cop->period_wait ();
- LOCK_MINOR;
+ lock.minor.unlock();
+ cop->period_wait();
+ lock.minor.lock();
}
}
-/* assumes LOCK_ALL, s_input, s_output */
-static bool process_audio (const void * data, int size, int stop_time)
+static bool process_audio(UnsafeLock & lock, const void * data, int size,
+ int stop_time)
{
- int samples = size / FMT_SIZEOF (in_format);
+ assert(state.input() && state.output());
+
+ int samples = size / FMT_SIZEOF(in_format);
bool stopped = false;
if (stop_time != -1)
{
- int64_t frames_left = aud::rescale<int64_t> (stop_time - seek_time, 1000, in_rate) - in_frames;
- int64_t samples_left = in_channels * aud::max ((int64_t) 0, frames_left);
+ int64_t frames_left =
+ aud::rescale<int64_t>(stop_time - seek_time, 1000, in_rate) -
+ in_frames;
+ int64_t samples_left = in_channels * aud::max((int64_t)0, frames_left);
if (samples >= samples_left)
{
@@ -387,403 +497,346 @@ static bool process_audio (const void * data, int size, int stop_time)
in_frames += samples / in_channels;
- buffer1.resize (samples);
+ buffer1.resize(samples);
if (in_format == FMT_FLOAT)
- memcpy (buffer1.begin (), data, sizeof (float) * samples);
+ memcpy(buffer1.begin(), data, sizeof(float) * samples);
else
- audio_from_int (data, in_format, buffer1.begin (), samples);
+ audio_from_int(data, in_format, buffer1.begin(), samples);
- if (s_secondary && record_stream == OutputStream::AsDecoded)
- write_secondary (buffer1);
+ if (state.secondary() && record_stream == OutputStream::AsDecoded)
+ write_secondary(lock, buffer1);
- apply_replay_gain (buffer1);
+ apply_replay_gain(lock, buffer1);
- if (s_secondary && record_stream == OutputStream::AfterReplayGain)
- write_secondary (buffer1);
+ if (state.secondary() && record_stream == OutputStream::AfterReplayGain)
+ write_secondary(lock, buffer1);
- write_output (effect_process (buffer1));
+ write_output(lock, effect_process(buffer1));
- return ! stopped;
+ return !stopped;
}
-/* assumes LOCK_ALL, s_output */
-static void finish_effects (bool end_of_playlist)
+static void finish_effects(UnsafeLock & lock, bool end_of_playlist)
{
- buffer1.resize (0);
- write_output (effect_finish (buffer1, end_of_playlist));
+ assert(state.output());
+
+ buffer1.resize(0);
+ write_output(lock, effect_finish(buffer1, end_of_playlist));
}
-bool output_open_audio (const String & filename, const Tuple & tuple,
- int format, int rate, int channels, int start_time)
+bool output_open_audio(const String & filename, const Tuple & tuple, int format,
+ int rate, int channels, int start_time, bool pause)
{
/* prevent division by zero */
if (rate < 1 || channels < 1 || channels > AUD_MAX_CHANNELS)
return false;
- LOCK_ALL;
+ auto lock = state.lock_unsafe();
- if (s_output && s_paused)
- {
- effect_flush (true);
- cleanup_output ();
- }
+ state.set_input(lock, true);
+ state.set_flushed(lock, false);
- s_input = true;
- s_gain = s_paused = s_flushed = false;
seek_time = start_time;
+ gain_info_valid = false;
in_filename = filename;
- in_tuple = tuple.ref ();
+ in_tuple = tuple.ref();
in_format = format;
in_channels = channels;
in_rate = rate;
in_frames = 0;
- setup_effects ();
- setup_output (true);
+ setup_effects(lock);
+ setup_output(lock, true, pause);
- if (aud_get_bool (0, "record"))
- setup_secondary (true);
+ if (aud_get_bool("record"))
+ setup_secondary(lock, true);
- UNLOCK_ALL;
return true;
}
-void output_set_tuple (const Tuple & tuple)
+void output_set_tuple(const Tuple & tuple)
{
- LOCK_MINOR;
-
- if (s_input)
- in_tuple = tuple.ref ();
+ auto lock = state.lock_safe();
- UNLOCK_MINOR;
+ if (state.input())
+ in_tuple = tuple.ref();
}
-void output_set_replay_gain (const ReplayGainInfo & info)
+void output_set_replay_gain(const ReplayGainInfo & info)
{
- LOCK_ALL;
+ auto lock = state.lock_safe();
- if (s_input)
+ if (state.input())
{
gain_info = info;
- s_gain = true;
+ gain_info_valid = true;
- AUDINFO ("Replay Gain info:\n");
- AUDINFO (" album gain: %f dB\n", info.album_gain);
- AUDINFO (" album peak: %f\n", info.album_peak);
- AUDINFO (" track gain: %f dB\n", info.track_gain);
- AUDINFO (" track peak: %f\n", info.track_peak);
+ AUDINFO("Replay Gain info:\n");
+ AUDINFO(" album gain: %f dB\n", info.album_gain);
+ AUDINFO(" album peak: %f\n", info.album_peak);
+ AUDINFO(" track gain: %f dB\n", info.track_gain);
+ AUDINFO(" track peak: %f\n", info.track_peak);
}
-
- UNLOCK_ALL;
}
/* returns false if stop_time is reached */
-bool output_write_audio (const void * data, int size, int stop_time)
+bool output_write_audio(const void * data, int size, int stop_time)
{
-RETRY:
- LOCK_ALL;
- bool good = false;
-
- if (s_input && ! s_flushed)
+ while (1)
{
- if (! s_output || s_paused || s_resetting)
- {
- UNLOCK_MAJOR;
- WAIT_MINOR;
- UNLOCK_MINOR;
- goto RETRY;
- }
+ auto lock = state.lock_unsafe();
+ if (!state.input() || state.flushed())
+ return false;
- good = process_audio (data, size, stop_time);
- }
+ if (state.output() && !state.resetting())
+ return process_audio(lock, data, size, stop_time);
- UNLOCK_ALL;
- return good;
+ lock.major.unlock();
+ state.await_change(lock);
+ }
}
-void output_flush (int time, bool force)
+void output_flush(int time, bool force)
{
- LOCK_MINOR;
+ auto lock = state.lock_safe();
- if (s_input && ! s_flushed)
+ if (state.input() || state.output())
{
- if (s_output && ! s_resetting)
- {
- // allow effect plugins to prevent the flush, but
- // always flush if paused to prevent locking up
- if (effect_flush (s_paused || force))
- {
- flush_output ();
- s_flushed = true;
- if (s_paused)
- SIGNAL_MINOR;
- }
- }
- else
- {
- s_flushed = true;
- SIGNAL_MINOR;
- }
+ // allow effect plugins to prevent the flush, but
+ // always flush if paused to prevent locking up
+ bool flush = effect_flush(state.paused() || force);
+ if (flush && state.output())
+ flush_output(lock);
}
- if (s_input)
+ if (state.input())
{
+ state.set_flushed(lock, true);
seek_time = time;
in_frames = 0;
}
-
- UNLOCK_MINOR;
}
-void output_resume ()
+void output_resume()
{
- LOCK_ALL;
+ auto lock = state.lock_safe();
- if (s_input)
- s_flushed = false;
-
- UNLOCK_ALL;
+ if (state.input())
+ state.set_flushed(lock, false);
}
-void output_pause (bool pause)
+void output_pause(bool pause)
{
- LOCK_MINOR;
-
- if (s_input && s_paused != pause)
- {
- s_paused = pause;
-
- if (s_output)
- {
- apply_pause ();
- if (! s_paused && ! s_flushed && ! s_resetting)
- SIGNAL_MINOR;
- }
- }
+ auto lock = state.lock_safe();
- UNLOCK_MINOR;
+ if (state.input())
+ apply_pause(lock, pause);
}
-int output_get_time ()
+int output_get_time()
{
- LOCK_MINOR;
+ auto lock = state.lock_safe();
int time = 0, delay = 0;
- if (s_input)
+ if (state.input())
{
- if (s_output)
+ if (state.output())
{
- delay = cop->get_delay ();
- delay += aud::rescale<int64_t> (out_bytes_held, out_bytes_per_sec, 1000);
+ delay = cop->get_delay();
+ delay +=
+ aud::rescale<int64_t>(out_bytes_held, out_bytes_per_sec, 1000);
}
- delay = effect_adjust_delay (delay);
- time = aud::rescale<int64_t> (in_frames, in_rate, 1000);
- time = seek_time + aud::max (time - delay, 0);
+ delay = effect_adjust_delay(delay);
+ time = aud::rescale<int64_t>(in_frames, in_rate, 1000);
+ time = seek_time + aud::max(time - delay, 0);
}
- UNLOCK_MINOR;
return time;
}
-int output_get_raw_time ()
+int output_get_raw_time()
{
- LOCK_MINOR;
+ auto lock = state.lock_safe();
int time = 0;
- if (s_output)
+ if (state.output())
{
- time = aud::rescale<int64_t> (out_bytes_written, out_bytes_per_sec, 1000);
- time = aud::max (time - cop->get_delay (), 0);
+ time =
+ aud::rescale<int64_t>(out_bytes_written, out_bytes_per_sec, 1000);
+ time = aud::max(time - cop->get_delay(), 0);
}
- UNLOCK_MINOR;
return time;
}
-void output_close_audio ()
+void output_close_audio()
{
- LOCK_ALL;
+ auto lock = state.lock_unsafe();
- if (s_input)
+ if (state.input())
{
- s_input = false;
- in_filename = String ();
- in_tuple = Tuple ();
+ state.set_input(lock, false);
+ in_filename = String();
+ in_tuple = Tuple();
- if (s_output && ! (s_paused || s_flushed || s_resetting))
- finish_effects (false); /* first time for end of song */
+ if (state.output())
+ finish_effects(lock, false); /* first time for end of song */
}
-
- UNLOCK_ALL;
}
-void output_drain ()
+void output_drain()
{
- LOCK_ALL;
+ auto lock = state.lock_unsafe();
- if (! s_input)
+ if (!state.input())
{
- if (s_output)
- finish_effects (true); /* second time for end of playlist */
+ if (state.output())
+ finish_effects(lock, true); /* second time for end of playlist */
- cleanup_output ();
- cleanup_secondary ();
+ cleanup_output(lock);
+ cleanup_secondary(lock);
}
-
- UNLOCK_ALL;
}
-static void output_reset (OutputReset type, OutputPlugin * op)
+static void output_reset(OutputReset type, OutputPlugin * op)
{
- LOCK_MINOR;
+ auto lock1 = state.lock_safe();
- s_resetting = true;
+ state.set_resetting(lock1, true);
- if (s_output && ! s_flushed)
- flush_output ();
+ if (state.output())
+ flush_output(lock1);
- UNLOCK_MINOR;
- LOCK_ALL;
+ lock1.minor.unlock();
+ auto lock2 = state.lock_unsafe();
if (type != OutputReset::EffectsOnly)
- cleanup_output ();
+ cleanup_output(lock2);
/* this does not reset the secondary plugin */
if (type == OutputReset::ResetPlugin)
{
if (cop)
- cop->cleanup ();
+ cop->cleanup();
if (op)
{
/* secondary plugin may become primary */
if (op == sop)
{
- cleanup_secondary ();
+ cleanup_secondary(lock2);
sop = nullptr;
}
- else if (! op->init ())
+ else if (!op->init())
op = nullptr;
}
cop = op;
}
- if (s_input)
+ if (state.input())
{
if (type == OutputReset::EffectsOnly)
- setup_effects ();
+ setup_effects(lock2);
- setup_output (false);
+ setup_output(lock2, false, state.paused());
- if (aud_get_bool (0, "record"))
- setup_secondary (false);
+ if (aud_get_bool("record"))
+ setup_secondary(lock2, false);
}
- s_resetting = false;
-
- if (s_output && ! s_paused && ! s_flushed)
- SIGNAL_MINOR;
-
- UNLOCK_ALL;
+ state.set_resetting(lock2, false);
}
-EXPORT void aud_output_reset (OutputReset type)
-{
- output_reset (type, cop);
-}
+EXPORT void aud_output_reset(OutputReset type) { output_reset(type, cop); }
-EXPORT StereoVolume aud_drct_get_volume ()
+EXPORT StereoVolume aud_drct_get_volume()
{
+ auto lock = state.lock_safe();
StereoVolume volume = {0, 0};
- LOCK_MINOR;
- if (aud_get_bool (0, "software_volume_control"))
- volume = {aud_get_int (0, "sw_volume_left"), aud_get_int (0, "sw_volume_right")};
+ if (aud_get_bool("software_volume_control"))
+ volume = {aud_get_int("sw_volume_left"),
+ aud_get_int("sw_volume_right")};
else if (cop)
- volume = cop->get_volume ();
+ volume = cop->get_volume();
- UNLOCK_MINOR;
return volume;
}
-EXPORT void aud_drct_set_volume (StereoVolume volume)
+EXPORT void aud_drct_set_volume(StereoVolume volume)
{
- LOCK_MINOR;
+ auto lock = state.lock_safe();
- volume.left = aud::clamp (volume.left, 0, 100);
- volume.right = aud::clamp (volume.right, 0, 100);
+ volume.left = aud::clamp(volume.left, 0, 100);
+ volume.right = aud::clamp(volume.right, 0, 100);
- if (aud_get_bool (0, "software_volume_control"))
+ if (aud_get_bool("software_volume_control"))
{
- aud_set_int (0, "sw_volume_left", volume.left);
- aud_set_int (0, "sw_volume_right", volume.right);
+ aud_set_int("sw_volume_left", volume.left);
+ aud_set_int("sw_volume_right", volume.right);
}
else if (cop)
- cop->set_volume (volume);
-
- UNLOCK_MINOR;
+ cop->set_volume(volume);
}
-PluginHandle * output_plugin_get_current ()
+PluginHandle * output_plugin_get_current()
{
- return cop ? aud_plugin_by_header (cop) : nullptr;
+ return cop ? aud_plugin_by_header(cop) : nullptr;
}
-PluginHandle * output_plugin_get_secondary ()
+PluginHandle * output_plugin_get_secondary()
{
- return sop ? aud_plugin_by_header (sop) : nullptr;
+ return sop ? aud_plugin_by_header(sop) : nullptr;
}
-bool output_plugin_set_current (PluginHandle * plugin)
+bool output_plugin_set_current(PluginHandle * plugin)
{
- output_reset (OutputReset::ResetPlugin, plugin ?
- (OutputPlugin *) aud_plugin_get_header (plugin) : nullptr);
- return (! plugin || cop);
+ output_reset(OutputReset::ResetPlugin,
+ plugin ? (OutputPlugin *)aud_plugin_get_header(plugin)
+ : nullptr);
+ return (!plugin || cop);
}
-bool output_plugin_set_secondary (PluginHandle * plugin)
+bool output_plugin_set_secondary(PluginHandle * plugin)
{
- LOCK_MINOR;
+ auto lock = state.lock_safe();
- cleanup_secondary ();
+ cleanup_secondary(lock);
if (sop)
- sop->cleanup ();
+ sop->cleanup();
- sop = plugin ? (OutputPlugin *) aud_plugin_get_header (plugin) : nullptr;
- if (sop && ! sop->init ())
+ sop = plugin ? (OutputPlugin *)aud_plugin_get_header(plugin) : nullptr;
+ if (sop && !sop->init())
sop = nullptr;
- if (s_input && aud_get_bool (0, "record"))
- setup_secondary (false);
+ if (state.input() && aud_get_bool("record"))
+ setup_secondary(lock, false);
- UNLOCK_MINOR;
- return (! plugin || sop);
+ return (!plugin || sop);
}
-static void record_settings_changed (void *, void *)
+static void record_settings_changed(void *, void *)
{
- LOCK_MINOR;
+ auto lock = state.lock_safe();
- if (s_input && aud_get_bool (0, "record"))
- setup_secondary (false);
+ if (state.input() && aud_get_bool("record"))
+ setup_secondary(lock, false);
else
- cleanup_secondary ();
-
- UNLOCK_MINOR;
+ cleanup_secondary(lock);
}
-void output_init ()
+void output_init()
{
- hook_associate ("set record", record_settings_changed, nullptr);
- hook_associate ("set record_stream", record_settings_changed, nullptr);
+ hook_associate("set record", record_settings_changed, nullptr);
+ hook_associate("set record_stream", record_settings_changed, nullptr);
}
-void output_cleanup ()
+void output_cleanup()
{
- hook_dissociate ("set record", record_settings_changed);
- hook_dissociate ("set record_stream", record_settings_changed);
+ hook_dissociate("set record", record_settings_changed);
+ hook_dissociate("set record_stream", record_settings_changed);
}
diff --git a/src/libaudcore/output.h b/src/libaudcore/output.h
index a9fafee..7f6e06f 100644
--- a/src/libaudcore/output.h
+++ b/src/libaudcore/output.h
@@ -26,26 +26,26 @@
class PluginHandle;
class Tuple;
-void output_init ();
-void output_cleanup ();
-
-bool output_open_audio (const String & filename, const Tuple & tuple,
- int format, int rate, int channels, int start_time);
-void output_set_tuple (const Tuple & tuple);
-void output_set_replay_gain (const ReplayGainInfo & info);
-bool output_write_audio (const void * data, int size, int stop_time);
-void output_flush (int time, bool force = false);
-void output_resume ();
-void output_pause (bool pause);
-
-int output_get_time ();
-int output_get_raw_time ();
-void output_close_audio ();
-void output_drain ();
-
-PluginHandle * output_plugin_get_current ();
-PluginHandle * output_plugin_get_secondary ();
-bool output_plugin_set_current (PluginHandle * plugin);
-bool output_plugin_set_secondary (PluginHandle * plugin);
+void output_init();
+void output_cleanup();
+
+bool output_open_audio(const String & filename, const Tuple & tuple, int format,
+ int rate, int channels, int start_time, bool pause);
+void output_set_tuple(const Tuple & tuple);
+void output_set_replay_gain(const ReplayGainInfo & info);
+bool output_write_audio(const void * data, int size, int stop_time);
+void output_flush(int time, bool force = false);
+void output_resume();
+void output_pause(bool pause);
+
+int output_get_time();
+int output_get_raw_time();
+void output_close_audio();
+void output_drain();
+
+PluginHandle * output_plugin_get_current();
+PluginHandle * output_plugin_get_secondary();
+bool output_plugin_set_current(PluginHandle * plugin);
+bool output_plugin_set_secondary(PluginHandle * plugin);
#endif
diff --git a/src/libaudcore/parse.cc b/src/libaudcore/parse.cc
index 9450e72..ab6c5f3 100644
--- a/src/libaudcore/parse.cc
+++ b/src/libaudcore/parse.cc
@@ -20,32 +20,31 @@
#include "parse.h"
#include <string.h>
-void TextParser::next ()
+void TextParser::next()
{
m_val = nullptr;
- if (! fgets (m_key, sizeof m_key, m_file))
+ if (!fgets(m_key, sizeof m_key, m_file))
return;
- char * space = strchr (m_key, ' ');
- if (! space)
+ char * space = strchr(m_key, ' ');
+ if (!space)
return;
- * space = 0;
+ *space = 0;
m_val = space + 1;
- char * newline = strchr (m_val, '\n');
+ char * newline = strchr(m_val, '\n');
if (newline)
- * newline = 0;
+ *newline = 0;
}
-bool TextParser::get_int (const char * key, int & val) const
+bool TextParser::get_int(const char * key, int & val) const
{
- return (m_val && ! strcmp (m_key, key) && sscanf (m_val, "%d", & val) == 1);
+ return (m_val && !strcmp(m_key, key) && sscanf(m_val, "%d", &val) == 1);
}
-String TextParser::get_str (const char * key) const
+String TextParser::get_str(const char * key) const
{
- return (m_val && ! strcmp (m_key, key)) ? String (m_val) : String ();
+ return (m_val && !strcmp(m_key, key)) ? String(m_val) : String();
}
-
diff --git a/src/libaudcore/parse.h b/src/libaudcore/parse.h
index 0dc63e4..c1f96b3 100644
--- a/src/libaudcore/parse.h
+++ b/src/libaudcore/parse.h
@@ -20,24 +20,21 @@
#ifndef LIBAUDCORE_PARSE_H
#define LIBAUDCORE_PARSE_H
-#include <stdio.h>
#include "objects.h"
+#include <stdio.h>
// simplistic key-value file parser
// used for playlist-state and plugin-registry files
class TextParser
{
public:
- TextParser (FILE * file) :
- m_file (file)
- { next (); }
+ TextParser(FILE * file) : m_file(file) { next(); }
- void next ();
- bool eof () const
- { return ! m_val; }
+ void next();
+ bool eof() const { return !m_val; }
- bool get_int (const char * key, int & val) const;
- String get_str (const char * key) const;
+ bool get_int(const char * key, int & val) const;
+ String get_str(const char * key) const;
private:
FILE * m_file;
diff --git a/src/libaudcore/playback.cc b/src/libaudcore/playback.cc
index ce8be6c..321db52 100644
--- a/src/libaudcore/playback.cc
+++ b/src/libaudcore/playback.cc
@@ -38,7 +38,6 @@
#include "internal.h"
#include <assert.h>
-#include <pthread.h>
#include "audstrings.h"
#include "hook.h"
@@ -48,25 +47,29 @@
#include "output.h"
#include "playlist-internal.h"
#include "plugin.h"
-#include "plugins.h"
#include "plugins-internal.h"
+#include "plugins.h"
#include "runtime.h"
+#include "threads.h"
-struct PlaybackState {
+struct PlaybackState
+{
bool playing = false;
bool thread_running = false;
int control_serial = 0;
int playback_serial = 0;
};
-struct PlaybackControl {
+struct PlaybackControl
+{
bool paused = false;
int seek = -1;
int repeat_a = -1;
int repeat_b = -1;
};
-struct PlaybackInfo {
+struct PlaybackInfo
+{
// set by playback_set_info
int entry = -1;
Tuple tuple;
@@ -78,7 +81,7 @@ struct PlaybackInfo {
int time_offset = 0;
int stop_time = -1;
- ReplayGainInfo gain {};
+ ReplayGainInfo gain{};
bool gain_valid = false;
int bitrate = 0;
@@ -91,8 +94,8 @@ struct PlaybackInfo {
String error_s;
};
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static aud::mutex mutex;
+static aud::condvar cond;
static PlaybackState pb_state;
static PlaybackControl pb_control;
@@ -102,258 +105,261 @@ static QueuedFunc end_queue;
static bool song_finished = false;
static int failed_entries = 0;
-static void lock ()
- { pthread_mutex_lock (& mutex); }
-static void unlock ()
- { pthread_mutex_unlock (& mutex); }
-
-static bool lock_if (bool (* test) ())
+// check that the playback thread is not lagging
+static bool in_sync(aud::mutex::holder &)
{
- lock ();
- if (test ())
- return true;
-
- unlock ();
- return false;
+ return pb_state.playing &&
+ pb_state.control_serial == pb_state.playback_serial;
}
-// check that the playback thread is not lagging
-static bool in_sync ()
- { return pb_state.playing && pb_state.control_serial == pb_state.playback_serial; }
-
// check that the playback thread is not lagging and playback is "ready"
-static bool is_ready ()
- { return in_sync () && pb_info.ready; }
+static bool is_ready(aud::mutex::holder & mh)
+{
+ return in_sync(mh) && pb_info.ready;
+}
// called by playback_entry_set_tuple() to ensure that the tuple still applies
// to the current song from the perspective of the main/playlist thread; the
// check is necessary because playback_entry_set_tuple() is itself called from
// the playback thread
-bool playback_check_serial (int serial)
+bool playback_check_serial(int serial)
{
- lock ();
- bool okay = (pb_state.playing && pb_state.control_serial == serial);
- unlock ();
- return okay;
+ auto mh = mutex.take();
+ return pb_state.playing && pb_state.control_serial == serial;
}
// called from the playlist to update the tuple for the current song
-void playback_set_info (int entry, Tuple && tuple)
+void playback_set_info(int entry, Tuple && tuple)
{
// do nothing if the playback thread is lagging behind;
// in that case, playback_set_info() will get called again anyway
- if (! lock_if (in_sync))
+ auto mh = mutex.take();
+ if (!in_sync(mh))
return;
- if (tuple.valid () && tuple != pb_info.tuple)
+ if (tuple.valid() && tuple != pb_info.tuple)
{
- pb_info.tuple = std::move (tuple);
+ pb_info.tuple = std::move(tuple);
// don't call "tuple change" before "playback ready"
- if (is_ready ())
+ if (is_ready(mh))
{
- event_queue ("tuple change", nullptr);
- output_set_tuple (pb_info.tuple);
+ event_queue("tuple change", nullptr);
+ output_set_tuple(pb_info.tuple);
}
}
- String title = pb_info.tuple.get_str (Tuple::FormattedTitle);
+ String title = pb_info.tuple.get_str(Tuple::FormattedTitle);
if (entry != pb_info.entry || title != pb_info.title)
{
pb_info.entry = entry;
pb_info.title = title;
// don't call "title change" before "playback ready"
- if (is_ready ())
- event_queue ("title change", nullptr);
+ if (is_ready(mh))
+ event_queue("title change", nullptr);
}
-
- unlock ();
}
// cleanup common to both playback_play() and playback_stop()
-static void playback_cleanup_locked ()
+static void playback_cleanup(aud::mutex::holder &)
{
pb_state.playing = false;
- pb_control = PlaybackControl ();
-
- // discard audio buffer if the song did not end on its own
- if (! song_finished)
- output_flush (0);
+ pb_control = PlaybackControl();
// miscellaneous cleanup
- end_queue.stop ();
+ end_queue.stop();
song_finished = false;
- event_queue_cancel ("playback ready");
- event_queue_cancel ("playback pause");
- event_queue_cancel ("playback unpause");
- event_queue_cancel ("playback seek");
- event_queue_cancel ("info change");
- event_queue_cancel ("title change");
- event_queue_cancel ("tuple change");
+ event_queue_cancel("playback ready");
+ event_queue_cancel("playback pause");
+ event_queue_cancel("playback unpause");
+ event_queue_cancel("playback seek");
+ event_queue_cancel("info change");
+ event_queue_cancel("title change");
+ event_queue_cancel("tuple change");
- aud_set_bool (nullptr, "stop_after_current_song", false);
+ aud_set_bool("stop_after_current_song", false);
}
// main thread: stops playback when no more songs are to be played
-void playback_stop (bool exiting)
+void playback_stop(bool exiting)
{
- if (! pb_state.playing && ! exiting)
+ if (!pb_state.playing && !exiting)
return;
- lock ();
+ auto mh = mutex.take();
+
+ // discard audio buffer on a user-initiated stop
+ if (!song_finished || exiting)
+ output_flush(0, exiting);
if (pb_state.playing)
- playback_cleanup_locked ();
+ playback_cleanup(mh);
if (pb_state.thread_running)
{
- // discard audio buffer if exiting
- if (exiting)
- output_flush (0, true);
-
// signal playback thread to drain audio buffer
- pb_state.control_serial ++;
- pthread_cond_broadcast (& cond);
+ pb_state.control_serial++;
+ cond.notify_all();
// wait for playback thread to finish if exiting
while (exiting && pb_state.thread_running)
- pthread_cond_wait (& cond, & mutex);
+ cond.wait(mh);
}
- unlock ();
-
// miscellaneous cleanup
failed_entries = 0;
}
// called from top-level event loop after playback finishes
-static void end_cb (void *)
+static void end_cb(void *)
{
song_finished = true;
- hook_call ("playback end", nullptr);
+ hook_call("playback end", nullptr);
- PlaylistEx playlist = Playlist::playing_playlist ();
+ PlaylistEx playlist = Playlist::playing_playlist();
- auto do_stop = [playlist] ()
- {
- aud_drct_stop ();
- playlist.set_position (playlist.get_position ());
+ auto do_stop = [playlist]() {
+ aud_drct_stop();
+ playlist.set_position(playlist.get_position());
};
- auto do_next = [playlist] ()
- {
- if (! playlist.next_song (aud_get_bool (nullptr, "repeat")))
+ auto do_next = [playlist]() {
+ if (!playlist.next_song(aud_get_bool("repeat")))
{
- playlist.set_position (-1);
- hook_call ("playlist end reached", nullptr);
+ playlist.set_position(-1);
+ hook_call("playlist end reached", nullptr);
}
};
- if (aud_get_bool (nullptr, "no_playlist_advance"))
+ if (aud_get_bool("no_playlist_advance"))
{
// we assume here that repeat is not enabled;
// single-song repeats are handled in run_playback()
- do_stop ();
+ do_stop();
}
- else if (aud_get_bool (nullptr, "stop_after_current_song"))
+ else if (aud_get_bool("stop_after_current_song"))
{
- do_stop ();
- do_next ();
+ do_stop();
+ do_next();
}
else
{
// if 10 songs in a row have failed, or if the entire playlist
// (for playlists less than 10 songs) has failed, stop trying
- if (failed_entries < aud::min (playlist.n_entries (), 10))
- do_next ();
+ if (failed_entries < aud::min(playlist.n_entries(), 10))
+ do_next();
else
- do_stop ();
+ do_stop();
}
}
// helper, can be called from either main or playback thread
-static void request_seek_locked (int time)
+static void request_seek(aud::mutex::holder & mh, int time)
{
// set up "seek" command whether ready or not;
// if not ready, it will take effect upon open_audio()
- pb_control.seek = aud::max (0, time);
+ pb_control.seek = aud::max(0, time);
// trigger seek immediately if ready
- if (is_ready () && pb_info.length > 0)
+ if (is_ready(mh) && pb_info.length > 0)
{
- output_flush (aud::clamp (time, 0, pb_info.length));
- event_queue ("playback seek", nullptr);
+ output_flush(aud::clamp(time, 0, pb_info.length));
+ event_queue("playback seek", nullptr);
}
}
// playback thread helper
-static void run_playback ()
+static bool setup_playback(const DecodeInfo & dec)
{
- // due to mutex ordering, we cannot call into the playlist while locked
- DecodeInfo dec = playback_entry_read (pb_state.playback_serial);
-
- if (! lock_if (in_sync))
- return;
+ auto mh = mutex.take();
+ if (!in_sync(mh))
+ return false;
// for a cuesheet entry, determine the source filename
- pb_info.filename = pb_info.tuple.get_str (Tuple::AudioFile);
- if (! pb_info.filename)
- pb_info.filename = std::move (dec.filename);
+ pb_info.filename = pb_info.tuple.get_str(Tuple::AudioFile);
+ if (!pb_info.filename)
+ pb_info.filename = std::move(dec.filename);
// check that we have all the necessary data
- if (! pb_info.filename || ! pb_info.tuple.valid () || ! dec.ip ||
- (! dec.ip->input_info.keys[InputKey::Scheme] && ! dec.file))
+ if (!pb_info.filename || !pb_info.tuple.valid() || !dec.ip ||
+ (!dec.ip->input_info.keys[InputKey::Scheme] && !dec.file))
{
pb_info.error = true;
- pb_info.error_s = std::move (dec.error);
- unlock ();
- return;
+ pb_info.error_s = std::move(dec.error);
+ return false;
}
// get various other bits of info from the tuple
- pb_info.length = pb_info.tuple.get_int (Tuple::Length);
- pb_info.time_offset = aud::max (0, pb_info.tuple.get_int (Tuple::StartTime));
- pb_info.stop_time = aud::max (-1, pb_info.tuple.get_int (Tuple::EndTime) - pb_info.time_offset);
- pb_info.gain = pb_info.tuple.get_replay_gain ();
- pb_info.gain_valid = pb_info.tuple.has_replay_gain ();
+ pb_info.length = pb_info.tuple.get_int(Tuple::Length);
+ pb_info.time_offset = aud::max(0, pb_info.tuple.get_int(Tuple::StartTime));
+ pb_info.stop_time = aud::max(-1, pb_info.tuple.get_int(Tuple::EndTime) -
+ pb_info.time_offset);
+ pb_info.gain = pb_info.tuple.get_replay_gain();
+ pb_info.gain_valid = pb_info.tuple.has_replay_gain();
// force initial seek if we are playing a segmented track
if (pb_info.time_offset > 0 && pb_control.seek < 0)
pb_control.seek = 0;
- unlock ();
+ return true;
+}
+
+// playback thread helper
+static bool check_playback_repeat()
+{
+ auto mh = mutex.take();
+ if (!is_ready(mh))
+ return false;
+
+ // check whether we need to repeat
+ if (pb_control.repeat_a >= 0 ||
+ (aud_get_bool("repeat") && aud_get_bool("no_playlist_advance")))
+ {
+ // treat the repeat as a seek (takes effect at open_audio())
+ pb_control.seek = pb_control.repeat_a;
+
+ // force initial seek if we are playing a segmented track
+ if (pb_info.time_offset > 0 && pb_control.seek < 0)
+ pb_control.seek = 0;
+
+ event_queue("playback seek", nullptr);
+ pb_info.ended = false;
+ return true;
+ }
+
+ pb_info.ended = true;
+ return false;
+}
+
+// playback thread helper
+static void run_playback()
+{
+ // due to mutex ordering, we cannot call into the playlist while locked
+ DecodeInfo dec = playback_entry_read(pb_state.playback_serial);
+
+ if (!setup_playback(dec))
+ return;
while (1)
{
// hand off control to input plugin
- if (! dec.ip->play (pb_info.filename, dec.file))
+ if (!dec.ip->play(pb_info.filename, dec.file))
pb_info.error = true;
// close audio (no-op if it wasn't opened)
- output_close_audio ();
+ output_close_audio();
if (pb_info.error || pb_info.length <= 0)
break;
- if (! lock_if (in_sync))
- break;
-
- // check whether we need to repeat
- pb_info.ended = (pb_control.repeat_a < 0 && ! (aud_get_bool (nullptr,
- "repeat") && aud_get_bool (nullptr, "no_playlist_advance")));
-
- if (! pb_info.ended)
- request_seek_locked (pb_control.repeat_a);
-
- unlock ();
-
- if (pb_info.ended)
+ if (!check_playback_repeat())
break;
// rewind file pointer before repeating
- if (! open_input_file (pb_info.filename, "r", dec.ip, dec.file, & pb_info.error_s))
+ if (!open_input_file(pb_info.filename, "r", dec.ip, dec.file,
+ &pb_info.error_s))
{
pb_info.error = true;
break;
@@ -362,36 +368,37 @@ static void run_playback ()
}
// playback thread helper
-static void finish_playback_locked ()
+static void finish_playback(aud::mutex::holder &)
{
// record any playback error that occurred
if (pb_info.error)
{
- failed_entries ++;
+ failed_entries++;
if (pb_info.error_s)
- aud_ui_show_error (str_printf (_("Error playing %s:\n%s"),
- (const char *) pb_info.filename, (const char *) pb_info.error_s));
+ aud_ui_show_error(str_printf(_("Error playing %s:\n%s"),
+ (const char *)pb_info.filename,
+ (const char *)pb_info.error_s));
else
- AUDERR ("Playback finished with error.\n");
+ AUDERR("Playback finished with error.\n");
}
else
failed_entries = 0;
// queue up function to start next song (or perform cleanup)
- end_queue.queue (end_cb, nullptr);
+ end_queue.queue(end_cb, nullptr);
}
// playback thread
-static void * playback_thread (void *)
+static void playback_thread()
{
- lock ();
+ auto mh = mutex.take();
while (1)
{
// wait for a command
while (pb_state.control_serial == pb_state.playback_serial)
- pthread_cond_wait (& cond, & mutex);
+ cond.wait(mh);
// fetch the command (either "play" or "drain")
bool play = pb_state.playing;
@@ -399,22 +406,23 @@ static void * playback_thread (void *)
// update playback thread serial number
pb_state.playback_serial = pb_state.control_serial;
- unlock ();
+ mh.unlock();
if (play)
- run_playback ();
+ run_playback();
else
- output_drain ();
+ output_drain();
- lock ();
+ mh.lock();
if (play)
{
- // don't report errors or queue next song if another command is pending
- if (in_sync ())
- finish_playback_locked ();
+ // don't report errors or queue next song if another command is
+ // pending
+ if (in_sync(mh))
+ finish_playback(mh);
- pb_info = PlaybackInfo ();
+ pb_info = PlaybackInfo();
}
else
{
@@ -426,135 +434,129 @@ static void * playback_thread (void *)
// signal the main thread that we are quitting
pb_state.thread_running = false;
- pthread_cond_broadcast (& cond);
- unlock ();
- return nullptr;
+ cond.notify_all();
}
// main thread: starts playback of a new song
-void playback_play (int seek_time, bool pause)
+void playback_play(int seek_time, bool pause)
{
- lock ();
+ auto mh = mutex.take();
+
+ // discard audio buffer unless progressing to the next song
+ if (!song_finished)
+ output_flush(0);
if (pb_state.playing)
- playback_cleanup_locked ();
+ playback_cleanup(mh);
// set up "play" command
pb_state.playing = true;
- pb_state.control_serial ++;
+ pb_state.control_serial++;
pb_control.paused = pause;
pb_control.seek = (seek_time > 0) ? seek_time : -1;
// start playback thread (or signal it if it's already running)
if (pb_state.thread_running)
- pthread_cond_broadcast (& cond);
+ cond.notify_all();
else
{
- pthread_t thread;
- pthread_create (& thread, nullptr, playback_thread, nullptr);
- pthread_detach (thread);
+ std::thread(playback_thread).detach();
pb_state.thread_running = true;
}
-
- unlock ();
}
// main thread
-EXPORT void aud_drct_pause ()
+EXPORT void aud_drct_pause()
{
- if (! pb_state.playing)
+ if (!pb_state.playing)
return;
- lock ();
+ auto mh = mutex.take();
// set up "pause" command whether ready or not;
// if not ready, it will take effect upon open_audio()
- bool pause = ! pb_control.paused;
+ bool pause = !pb_control.paused;
pb_control.paused = pause;
// apply pause immediately if ready
- if (is_ready ())
- output_pause (pause);
-
- event_queue (pause ? "playback pause" : "playback unpause", nullptr);
+ if (is_ready(mh))
+ output_pause(pause);
- unlock ();
+ event_queue(pause ? "playback pause" : "playback unpause", nullptr);
}
// main thread
-EXPORT void aud_drct_seek (int time)
+EXPORT void aud_drct_seek(int time)
{
- if (! pb_state.playing)
+ if (!pb_state.playing)
return;
- lock ();
- request_seek_locked (time);
- unlock ();
+ auto mh = mutex.take();
+ request_seek(mh, time);
}
-EXPORT void InputPlugin::open_audio (int format, int rate, int channels)
+EXPORT void InputPlugin::open_audio(int format, int rate, int channels)
{
// don't open audio if playback thread is lagging
- if (! lock_if (in_sync))
+ auto mh = mutex.take();
+ if (!in_sync(mh))
return;
- if (! output_open_audio (pb_info.filename, pb_info.tuple, format, rate,
- channels, aud::max (0, pb_control.seek)))
+ if (!output_open_audio(pb_info.filename, pb_info.tuple, format, rate,
+ channels, aud::max(0, pb_control.seek),
+ pb_control.paused))
{
pb_info.error = true;
- pb_info.error_s = String (_("Invalid audio format"));
- unlock ();
+ pb_info.error_s = String(_("Invalid audio format"));
return;
}
if (pb_info.gain_valid)
- output_set_replay_gain (pb_info.gain);
- if (pb_control.paused)
- output_pause (true);
+ output_set_replay_gain(pb_info.gain);
pb_info.samplerate = rate;
pb_info.channels = channels;
if (pb_info.ready)
- event_queue ("info change", nullptr);
+ event_queue("info change", nullptr);
else
- event_queue ("playback ready", nullptr);
+ event_queue("playback ready", nullptr);
pb_info.ready = true;
-
- unlock ();
}
-EXPORT void InputPlugin::set_replay_gain (const ReplayGainInfo & gain)
+EXPORT void InputPlugin::set_replay_gain(const ReplayGainInfo & gain)
{
- lock ();
+ auto mh = mutex.take();
+
pb_info.gain = gain;
pb_info.gain_valid = true;
- if (is_ready ())
- output_set_replay_gain (gain);
-
- unlock ();
+ if (is_ready(mh))
+ output_set_replay_gain(gain);
}
-EXPORT void InputPlugin::write_audio (const void * data, int length)
+EXPORT void InputPlugin::write_audio(const void * data, int length)
{
- if (! lock_if (in_sync))
+ auto mh = mutex.take();
+ if (!in_sync(mh))
return;
// fetch A-B repeat settings
int a = pb_control.repeat_a;
int b = pb_control.repeat_b;
- unlock ();
+ mh.unlock();
// it's okay to call output_write_audio() even if we are no longer in sync,
// since it will return immediately if output_flush() has been called
int stop_time = (b >= 0) ? b : pb_info.stop_time;
- if (output_write_audio (data, length, stop_time))
+ if (output_write_audio(data, length, stop_time))
return;
- if (! lock_if (in_sync))
+ mh.lock();
+
+ if (!in_sync(mh))
return;
// if we are still in sync, then one of the following happened:
@@ -564,179 +566,152 @@ EXPORT void InputPlugin::write_audio (const void * data, int length)
if (pb_control.seek < 0)
{
if (b >= 0)
- request_seek_locked (a);
+ request_seek(mh, a);
else
pb_info.ended = true;
}
-
- unlock ();
}
-EXPORT Tuple InputPlugin::get_playback_tuple ()
+EXPORT Tuple InputPlugin::get_playback_tuple()
{
- lock ();
- Tuple tuple = pb_info.tuple.ref ();
- unlock ();
+ auto mh = mutex.take();
+ Tuple tuple = pb_info.tuple.ref();
// tuples passed to us from input plugins do not have fallback fields
// generated; for consistency, tuples passed back should not either
- tuple.delete_fallbacks ();
+ tuple.delete_fallbacks();
return tuple;
}
-EXPORT void InputPlugin::set_playback_tuple (Tuple && tuple)
+EXPORT void InputPlugin::set_playback_tuple(Tuple && tuple)
{
// due to mutex ordering, we cannot call into the playlist while locked;
// instead, playback_entry_set_tuple() calls back into first
// playback_check_serial() and then eventually playback_set_info()
- playback_entry_set_tuple (pb_state.playback_serial, std::move (tuple));
+ playback_entry_set_tuple(pb_state.playback_serial, std::move(tuple));
}
-EXPORT void InputPlugin::set_stream_bitrate (int bitrate)
+EXPORT void InputPlugin::set_stream_bitrate(int bitrate)
{
- lock ();
+ auto mh = mutex.take();
pb_info.bitrate = bitrate;
- if (is_ready ())
- event_queue ("info change", nullptr);
-
- unlock ();
+ if (is_ready(mh))
+ event_queue("info change", nullptr);
}
-EXPORT bool InputPlugin::check_stop ()
+EXPORT bool InputPlugin::check_stop()
{
- lock ();
- bool stop = ! is_ready () || pb_info.ended || pb_info.error;
- unlock ();
- return stop;
+ auto mh = mutex.take();
+ return !is_ready(mh) || pb_info.ended || pb_info.error;
}
-EXPORT int InputPlugin::check_seek ()
+EXPORT int InputPlugin::check_seek()
{
- lock ();
+ auto mh = mutex.take();
int seek = -1;
- if (is_ready () && pb_control.seek >= 0 && pb_info.length > 0)
+ if (is_ready(mh) && pb_control.seek >= 0 && pb_info.length > 0)
{
- seek = pb_info.time_offset + aud::min (pb_control.seek, pb_info.length);
+ seek = pb_info.time_offset + aud::min(pb_control.seek, pb_info.length);
pb_control.seek = -1;
- output_resume ();
+ output_resume();
}
- unlock ();
return seek;
}
// thread-safe
-EXPORT bool aud_drct_get_playing ()
+EXPORT bool aud_drct_get_playing()
{
- lock ();
- bool playing = pb_state.playing;
- unlock ();
- return playing;
+ auto mh = mutex.take();
+ return pb_state.playing;
}
// thread-safe
-EXPORT bool aud_drct_get_ready ()
+EXPORT bool aud_drct_get_ready()
{
- lock ();
- bool ready = is_ready ();
- unlock ();
- return ready;
+ auto mh = mutex.take();
+ return is_ready(mh);
}
// thread-safe
-EXPORT bool aud_drct_get_paused ()
+EXPORT bool aud_drct_get_paused()
{
- lock ();
- bool paused = pb_control.paused;
- unlock ();
- return paused;
+ auto mh = mutex.take();
+ return pb_control.paused;
}
// thread-safe
-EXPORT String aud_drct_get_title ()
+EXPORT String aud_drct_get_title()
{
- if (! lock_if (is_ready))
- return String ();
-
- String title = pb_info.title;
- int entry = pb_info.entry;
- int length = pb_info.length;
-
- unlock ();
+ auto mh = mutex.take();
+ if (!is_ready(mh))
+ return String();
- StringBuf prefix = aud_get_bool (nullptr, "show_numbers_in_pl") ?
- str_printf ("%d. ", 1 + entry) : StringBuf (0);
+ StringBuf prefix = aud_get_bool("show_numbers_in_pl")
+ ? str_printf("%d. ", 1 + pb_info.entry)
+ : StringBuf(0);
- StringBuf time = (length > 0) ? str_format_time (length) : StringBuf ();
- StringBuf suffix = time ? str_concat ({" (", time, ")"}) : StringBuf (0);
+ StringBuf time =
+ (pb_info.length > 0) ? str_format_time(pb_info.length) : StringBuf();
+ StringBuf suffix = time ? str_concat({" (", time, ")"}) : StringBuf(0);
- return String (str_concat ({prefix, title, suffix}));
+ return String(str_concat({prefix, pb_info.title, suffix}));
}
// thread-safe
-EXPORT Tuple aud_drct_get_tuple ()
+EXPORT Tuple aud_drct_get_tuple()
{
- lock ();
- Tuple tuple = is_ready () ? pb_info.tuple.ref () : Tuple ();
- unlock ();
- return tuple;
+ auto mh = mutex.take();
+ return is_ready(mh) ? pb_info.tuple.ref() : Tuple();
}
// thread-safe
-EXPORT void aud_drct_get_info (int & bitrate, int & samplerate, int & channels)
+EXPORT void aud_drct_get_info(int & bitrate, int & samplerate, int & channels)
{
- lock ();
+ auto mh = mutex.take();
+ bool ready = is_ready(mh);
- bool ready = is_ready ();
bitrate = ready ? pb_info.bitrate : 0;
samplerate = ready ? pb_info.samplerate : 0;
channels = ready ? pb_info.channels : 0;
-
- unlock ();
}
// thread-safe
-EXPORT int aud_drct_get_time ()
+EXPORT int aud_drct_get_time()
{
- lock ();
- int time = is_ready () ? output_get_time () : 0;
- unlock ();
- return time;
+ auto mh = mutex.take();
+ return is_ready(mh) ? output_get_time() : 0;
}
// thread-safe
-EXPORT int aud_drct_get_length ()
+EXPORT int aud_drct_get_length()
{
- lock ();
- int length = is_ready () ? pb_info.length : -1;
- unlock ();
- return length;
+ auto mh = mutex.take();
+ return is_ready(mh) ? pb_info.length : -1;
}
// main thread
-EXPORT void aud_drct_set_ab_repeat (int a, int b)
+EXPORT void aud_drct_set_ab_repeat(int a, int b)
{
- if (! pb_state.playing)
+ if (!pb_state.playing)
return;
- lock ();
+ auto mh = mutex.take();
pb_control.repeat_a = a;
pb_control.repeat_b = b;
- if (b >= 0 && is_ready () && output_get_time () >= b)
- request_seek_locked (a);
-
- unlock ();
+ if (b >= 0 && is_ready(mh) && output_get_time() >= b)
+ request_seek(mh, a);
}
// thread-safe
-EXPORT void aud_drct_get_ab_repeat (int & a, int & b)
+EXPORT void aud_drct_get_ab_repeat(int & a, int & b)
{
- lock ();
+ auto mh = mutex.take();
+
a = pb_control.repeat_a;
b = pb_control.repeat_b;
- unlock ();
}
diff --git a/src/libaudcore/playlist-cache.cc b/src/libaudcore/playlist-cache.cc
index fe371ac..1cf8035 100644
--- a/src/libaudcore/playlist-cache.cc
+++ b/src/libaudcore/playlist-cache.cc
@@ -17,72 +17,63 @@
* the use of this software.
*/
-#include "playlist-internal.h"
#include "mainloop.h"
#include "multihash.h"
-
-#include <pthread.h>
+#include "playlist-internal.h"
+#include "threads.h"
static SimpleHash<String, PlaylistAddItem> cache;
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static aud::mutex mutex;
static QueuedFunc clear_timer;
-EXPORT void Playlist::cache_selected () const
+EXPORT void Playlist::cache_selected() const
{
- pthread_mutex_lock (& mutex);
-
- int entries = n_entries ();
+ auto mh = mutex.take();
+ int entries = n_entries();
- for (int i = 0; i < entries; i ++)
+ for (int i = 0; i < entries; i++)
{
- if (! entry_selected (i))
+ if (!entry_selected(i))
continue;
- String filename = entry_filename (i);
- Tuple tuple = entry_tuple (i, NoWait);
- PluginHandle * decoder = entry_decoder (i, NoWait);
+ String filename = entry_filename(i);
+ Tuple tuple = entry_tuple(i, NoWait);
+ PluginHandle * decoder = entry_decoder(i, NoWait);
- if (tuple.valid () || decoder)
- cache.add (filename, {filename, std::move (tuple), decoder});
+ if (tuple.valid() || decoder)
+ cache.add(filename, {filename, std::move(tuple), decoder});
}
- clear_timer.queue (30000, playlist_cache_clear, nullptr);
-
- pthread_mutex_unlock (& mutex);
+ clear_timer.queue(30000, playlist_cache_clear, nullptr);
}
-void playlist_cache_load (Index<PlaylistAddItem> & items)
+void playlist_cache_load(Index<PlaylistAddItem> & items)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- if (! cache.n_items ())
- goto out;
+ if (!cache.n_items())
+ return;
for (auto & item : items)
{
- if (item.tuple.valid () && item.decoder)
+ if (item.tuple.valid() && item.decoder)
continue;
- auto node = cache.lookup (item.filename);
- if (! node)
+ auto node = cache.lookup(item.filename);
+ if (!node)
continue;
- if (! item.tuple.valid () && node->tuple.valid ())
- item.tuple = node->tuple.ref ();
- if (! item.decoder && node->decoder)
+ if (!item.tuple.valid() && node->tuple.valid())
+ item.tuple = node->tuple.ref();
+ if (!item.decoder && node->decoder)
item.decoder = node->decoder;
}
-
-out:
- pthread_mutex_unlock (& mutex);
}
-void playlist_cache_clear (void *)
+void playlist_cache_clear(void *)
{
- pthread_mutex_lock (& mutex);
-
- cache.clear ();
- clear_timer.stop ();
+ auto mh = mutex.take();
- pthread_mutex_unlock (& mutex);
+ cache.clear();
+ clear_timer.stop();
}
diff --git a/src/libaudcore/playlist-data.cc b/src/libaudcore/playlist-data.cc
index dd3a3d5..923e6f1 100644
--- a/src/libaudcore/playlist-data.cc
+++ b/src/libaudcore/playlist-data.cc
@@ -26,16 +26,21 @@
#include "scanner.h"
#include "tuple-compiler.h"
+#define NO_POS \
+ { \
+ -1, false \
+ }
+
static TupleCompiler s_tuple_formatter;
static bool s_use_tuple_fallbacks = false;
struct PlaylistEntry
{
- PlaylistEntry (PlaylistAddItem && item);
- ~PlaylistEntry ();
+ PlaylistEntry(PlaylistAddItem && item);
+ ~PlaylistEntry();
- void format ();
- void set_tuple (Tuple && new_tuple);
+ void format();
+ void set_tuple(Tuple && new_tuple);
String filename;
PluginHandle * decoder;
@@ -47,207 +52,202 @@ struct PlaylistEntry
bool selected, queued;
};
-void PlaylistEntry::format ()
+void PlaylistEntry::format()
{
- tuple.delete_fallbacks ();
+ tuple.delete_fallbacks();
if (s_use_tuple_fallbacks)
- tuple.generate_fallbacks ();
+ tuple.generate_fallbacks();
else
- tuple.generate_title ();
+ tuple.generate_title();
- s_tuple_formatter.format (tuple);
+ s_tuple_formatter.format(tuple);
}
-void PlaylistEntry::set_tuple (Tuple && new_tuple)
+void PlaylistEntry::set_tuple(Tuple && new_tuple)
{
/* Since 3.8, cuesheet entries are handled differently. The entry filename
* points to the .cue file, and the path to the actual audio file is stored
* in the Tuple::AudioFile. If Tuple::AudioFile is not set, then assume
* that the playlist was created by an older version of Audacious, and
* revert to the former behavior (don't refresh this entry). */
- if (tuple.is_set (Tuple::StartTime) && ! tuple.is_set (Tuple::AudioFile))
+ if (tuple.is_set(Tuple::StartTime) && !tuple.is_set(Tuple::AudioFile))
return;
- error = String ();
+ error = String();
- if (! new_tuple.valid ())
- new_tuple.set_filename (filename);
+ if (!new_tuple.valid())
+ new_tuple.set_filename(filename);
- length = aud::max (0, new_tuple.get_int (Tuple::Length));
- tuple = std::move (new_tuple);
+ length = aud::max(0, new_tuple.get_int(Tuple::Length));
+ tuple = std::move(new_tuple);
- format ();
+ format();
}
-PlaylistEntry::PlaylistEntry (PlaylistAddItem && item) :
- filename (item.filename),
- decoder (item.decoder),
- number (-1),
- length (0),
- shuffle_num (0),
- selected (false),
- queued (false)
+PlaylistEntry::PlaylistEntry(PlaylistAddItem && item)
+ : filename(item.filename), decoder(item.decoder), number(-1), length(0),
+ shuffle_num(0), selected(false), queued(false)
{
- set_tuple (std::move (item.tuple));
+ set_tuple(std::move(item.tuple));
}
-PlaylistEntry::~PlaylistEntry ()
+PlaylistEntry::~PlaylistEntry() { pl_signal_entry_deleted(this); }
+
+void PlaylistData::update_formatter() // static
{
- pl_signal_entry_deleted (this);
+ s_tuple_formatter.compile(aud_get_str("generic_title_format"));
+ s_use_tuple_fallbacks = aud_get_bool("metadata_fallbacks");
}
-void PlaylistData::update_formatter () // static
+void PlaylistData::cleanup_formatter() // static
{
- s_tuple_formatter.compile (aud_get_str (nullptr, "generic_title_format"));
- s_use_tuple_fallbacks = aud_get_bool (nullptr, "metadata_fallbacks");
+ s_tuple_formatter.reset();
}
-void PlaylistData::cleanup_formatter () // static
- { s_tuple_formatter.reset (); }
-
-void PlaylistData::delete_entry (PlaylistEntry * entry) // static
- { delete entry; }
-
-PlaylistData::PlaylistData (Playlist::ID * id, const char * title) :
- modified (true),
- scan_status (NotScanning),
- title (title),
- resume_time (0),
- m_id (id),
- m_position (nullptr),
- m_focus (nullptr),
- m_selected_count (0),
- m_last_shuffle_num (0),
- m_total_length (0),
- m_selected_length (0),
- m_last_update (),
- m_next_update (),
- m_position_changed (false) {}
+void PlaylistData::delete_entry(PlaylistEntry * entry) // static
+{
+ delete entry;
+}
-PlaylistData::~PlaylistData ()
+PlaylistData::PlaylistData(Playlist::ID * id, const char * title)
+ : modified(true), scan_status(NotScanning), title(title), resume_time(0),
+ m_id(id), m_position(nullptr), m_focus(nullptr), m_selected_count(0),
+ m_last_shuffle_num(0), m_total_length(0), m_selected_length(0),
+ m_last_update(), m_next_update(), m_position_changed(false)
{
- pl_signal_playlist_deleted (m_id);
}
-void PlaylistData::number_entries (int at, int length)
+PlaylistData::~PlaylistData() { pl_signal_playlist_deleted(m_id); }
+
+void PlaylistData::number_entries(int at, int length)
{
- for (int i = at; i < at + length; i ++)
+ for (int i = at; i < at + length; i++)
m_entries[i]->number = i;
}
-PlaylistEntry * PlaylistData::entry_at (int i)
+PlaylistEntry * PlaylistData::entry_at(int i)
{
- return (i >= 0 && i < m_entries.len ()) ? m_entries[i].get () : nullptr;
+ return (i >= 0 && i < m_entries.len()) ? m_entries[i].get() : nullptr;
}
-const PlaylistEntry * PlaylistData::entry_at (int i) const
+const PlaylistEntry * PlaylistData::entry_at(int i) const
{
- return (i >= 0 && i < m_entries.len ()) ? m_entries[i].get () : nullptr;
+ return (i >= 0 && i < m_entries.len()) ? m_entries[i].get() : nullptr;
}
-String PlaylistData::entry_filename (int i) const
+String PlaylistData::entry_filename(int i) const
{
- auto entry = entry_at (i);
- return entry ? entry->filename : String ();
+ auto entry = entry_at(i);
+ return entry ? entry->filename : String();
}
-PluginHandle * PlaylistData::entry_decoder (int i, String * error) const
+PluginHandle * PlaylistData::entry_decoder(int i, String * error) const
{
- auto entry = entry_at (i);
- if (error) * error = entry ? entry->error : String ();
+ auto entry = entry_at(i);
+ if (error)
+ *error = entry ? entry->error : String();
return entry ? entry->decoder : nullptr;
}
-Tuple PlaylistData::entry_tuple (int i, String * error) const
+Tuple PlaylistData::entry_tuple(int i, String * error) const
{
- auto entry = entry_at (i);
- if (error) * error = entry ? entry->error : String ();
- return entry ? entry->tuple.ref () : Tuple ();
+ auto entry = entry_at(i);
+ if (error)
+ *error = entry ? entry->error : String();
+ return entry ? entry->tuple.ref() : Tuple();
}
-void PlaylistData::set_entry_tuple (PlaylistEntry * entry, Tuple && tuple)
+static bool same_album(const Tuple & a, const Tuple & b)
+{
+ String album = a.get_str(Tuple::Album);
+ return (album && album == b.get_str(Tuple::Album));
+}
+
+void PlaylistData::set_entry_tuple(PlaylistEntry * entry, Tuple && tuple)
{
m_total_length -= entry->length;
if (entry->selected)
m_selected_length -= entry->length;
- entry->set_tuple (std::move (tuple));
+ entry->set_tuple(std::move(tuple));
m_total_length += entry->length;
if (entry->selected)
m_selected_length += entry->length;
}
-void PlaylistData::queue_update (Playlist::UpdateLevel level, int at, int count, int flags)
+void PlaylistData::queue_update(Playlist::UpdateLevel level, int at, int count,
+ int flags)
{
if (m_next_update.level)
{
- m_next_update.level = aud::max (m_next_update.level, level);
- m_next_update.before = aud::min (m_next_update.before, at);
- m_next_update.after = aud::min (m_next_update.after, m_entries.len () - at - count);
+ m_next_update.level = aud::max(m_next_update.level, level);
+ m_next_update.before = aud::min(m_next_update.before, at);
+ m_next_update.after =
+ aud::min(m_next_update.after, m_entries.len() - at - count);
}
else
{
m_next_update.level = level;
m_next_update.before = at;
- m_next_update.after = m_entries.len () - at - count;
+ m_next_update.after = m_entries.len() - at - count;
}
if ((flags & QueueChanged))
m_next_update.queue_changed = true;
- pl_signal_update_queued (m_id, level, flags);
+ pl_signal_update_queued(m_id, level, flags);
}
-void PlaylistData::queue_position_change ()
+void PlaylistData::queue_position_change()
{
m_position_changed = true;
- pl_signal_position_changed (m_id);
+ pl_signal_position_changed(m_id);
}
-void PlaylistData::cancel_updates ()
+void PlaylistData::cancel_updates()
{
- m_last_update = Playlist::Update ();
- m_next_update = Playlist::Update ();
+ m_last_update = Playlist::Update();
+ m_next_update = Playlist::Update();
m_position_changed = false;
}
-void PlaylistData::swap_updates (bool & position_changed)
+void PlaylistData::swap_updates(bool & position_changed)
{
m_last_update = m_next_update;
- m_next_update = Playlist::Update ();
+ m_next_update = Playlist::Update();
position_changed = m_position_changed;
m_position_changed = false;
}
-void PlaylistData::insert_items (int at, Index<PlaylistAddItem> && items)
+void PlaylistData::insert_items(int at, Index<PlaylistAddItem> && items)
{
- int n_entries = m_entries.len ();
- int n_items = items.len ();
+ int n_entries = m_entries.len();
+ int n_items = items.len();
if (at < 0 || at > n_entries)
at = n_entries;
- m_entries.insert (at, n_items);
+ m_entries.insert(at, n_items);
int i = at;
for (auto & item : items)
{
- auto entry = new PlaylistEntry (std::move (item));
- m_entries[i ++].capture (entry);
+ auto entry = new PlaylistEntry(std::move(item));
+ m_entries[i++].capture(entry);
m_total_length += entry->length;
}
- items.clear ();
+ items.clear();
- number_entries (at, n_entries + n_items - at);
- queue_update (Playlist::Structure, at, n_items);
+ number_entries(at, n_entries + n_items - at);
+ queue_update(Playlist::Structure, at, n_items);
}
-void PlaylistData::remove_entries (int at, int number)
+void PlaylistData::remove_entries(int at, int number)
{
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
bool position_changed = false;
int update_flags = 0;
@@ -256,74 +256,72 @@ void PlaylistData::remove_entries (int at, int number)
if (number < 0 || number > n_entries - at)
number = n_entries - at;
- if (m_position && m_position->number >= at && m_position->number < at + number)
+ if (m_position && m_position->number >= at &&
+ m_position->number < at + number)
{
- set_position (nullptr, false);
+ change_position(NO_POS);
position_changed = true;
}
if (m_focus && m_focus->number >= at && m_focus->number < at + number)
{
if (at + number < n_entries)
- m_focus = m_entries[at + number].get ();
+ m_focus = m_entries[at + number].get();
else if (at > 0)
- m_focus = m_entries[at - 1].get ();
+ m_focus = m_entries[at - 1].get();
else
m_focus = nullptr;
}
- for (int i = 0; i < number; i ++)
+ for (int i = 0; i < number; i++)
{
- PlaylistEntry * entry = m_entries [at + i].get ();
+ PlaylistEntry * entry = m_entries[at + i].get();
if (entry->queued)
{
- m_queued.remove (m_queued.find (entry), 1);
+ m_queued.remove(m_queued.find(entry), 1);
update_flags |= QueueChanged;
}
if (entry->selected)
{
- m_selected_count --;
+ m_selected_count--;
m_selected_length -= entry->length;
}
m_total_length -= entry->length;
}
- m_entries.remove (at, number);
+ m_entries.remove(at, number);
- number_entries (at, n_entries - at - number);
- queue_update (Playlist::Structure, at, 0, update_flags);
+ number_entries(at, n_entries - at - number);
+ queue_update(Playlist::Structure, at, 0, update_flags);
if (position_changed)
{
- if (aud_get_bool (nullptr, "advance_on_delete"))
- next_song_with_hint (aud_get_bool (nullptr, "repeat"), at);
+ if (aud_get_bool("advance_on_delete"))
+ change_position_to_next(aud_get_bool("repeat"), at);
- queue_position_change ();
+ queue_position_change();
}
}
-int PlaylistData::position () const
+int PlaylistData::position() const
{
return m_position ? m_position->number : -1;
}
-int PlaylistData::focus () const
-{
- return m_focus ? m_focus->number : -1;
-}
+int PlaylistData::focus() const { return m_focus ? m_focus->number : -1; }
-bool PlaylistData::entry_selected (int entry_num) const
+bool PlaylistData::entry_selected(int entry_num) const
{
- auto entry = entry_at (entry_num);
+ auto entry = entry_at(entry_num);
return entry ? entry->selected : false;
}
-int PlaylistData::n_selected (int at, int number) const
+int PlaylistData::n_selected(int at, int number) const
{
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
if (at < 0 || at > n_entries)
at = n_entries;
@@ -336,68 +334,68 @@ int PlaylistData::n_selected (int at, int number) const
n_selected = m_selected_count;
else
{
- for (int i = 0; i < number; i ++)
+ for (int i = 0; i < number; i++)
{
if (m_entries[at + i]->selected)
- n_selected ++;
+ n_selected++;
}
}
return n_selected;
}
-void PlaylistData::set_focus (int entry_num)
+void PlaylistData::set_focus(int entry_num)
{
- auto new_focus = entry_at (entry_num);
+ auto new_focus = entry_at(entry_num);
if (new_focus == m_focus)
return;
- int first = m_entries.len ();
+ int first = m_entries.len();
int last = -1;
if (m_focus)
{
- first = aud::min (first, m_focus->number);
- last = aud::max (last, m_focus->number);
+ first = aud::min(first, m_focus->number);
+ last = aud::max(last, m_focus->number);
}
m_focus = new_focus;
if (m_focus)
{
- first = aud::min (first, m_focus->number);
- last = aud::max (last, m_focus->number);
+ first = aud::min(first, m_focus->number);
+ last = aud::max(last, m_focus->number);
}
if (first <= last)
- queue_update (Playlist::Selection, first, last + 1 - first);
+ queue_update(Playlist::Selection, first, last + 1 - first);
}
-void PlaylistData::select_entry (int entry_num, bool selected)
+void PlaylistData::select_entry(int entry_num, bool selected)
{
- auto entry = entry_at (entry_num);
- if (! entry || entry->selected == selected)
+ auto entry = entry_at(entry_num);
+ if (!entry || entry->selected == selected)
return;
entry->selected = selected;
if (selected)
{
- m_selected_count ++;
+ m_selected_count++;
m_selected_length += entry->length;
}
else
{
- m_selected_count --;
+ m_selected_count--;
m_selected_length -= entry->length;
}
- queue_update (Playlist::Selection, entry_num, 1);
+ queue_update(Playlist::Selection, entry_num, 1);
}
-void PlaylistData::select_all (bool selected)
+void PlaylistData::select_all(bool selected)
{
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
int first = n_entries, last = 0;
for (auto & entry : m_entries)
@@ -405,7 +403,7 @@ void PlaylistData::select_all (bool selected)
if (entry->selected != selected)
{
entry->selected = selected;
- first = aud::min (first, entry->number);
+ first = aud::min(first, entry->number);
last = entry->number;
}
}
@@ -422,44 +420,44 @@ void PlaylistData::select_all (bool selected)
}
if (first < n_entries)
- queue_update (Playlist::Selection, first, last + 1 - first);
+ queue_update(Playlist::Selection, first, last + 1 - first);
}
-int PlaylistData::shift_entries (int entry_num, int distance)
+int PlaylistData::shift_entries(int entry_num, int distance)
{
- PlaylistEntry * entry = entry_at (entry_num);
- if (! entry || ! entry->selected || ! distance)
+ PlaylistEntry * entry = entry_at(entry_num);
+ if (!entry || !entry->selected || !distance)
return 0;
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
int shift = 0, center, top, bottom;
if (distance < 0)
{
- for (center = entry_num; center > 0 && shift > distance; )
+ for (center = entry_num; center > 0 && shift > distance;)
{
- if (! m_entries[-- center]->selected)
- shift --;
+ if (!m_entries[--center]->selected)
+ shift--;
}
}
else
{
- for (center = entry_num + 1; center < n_entries && shift < distance; )
+ for (center = entry_num + 1; center < n_entries && shift < distance;)
{
- if (! m_entries[center ++]->selected)
- shift ++;
+ if (!m_entries[center++]->selected)
+ shift++;
}
}
top = bottom = center;
- for (int i = 0; i < top; i ++)
+ for (int i = 0; i < top; i++)
{
if (m_entries[i]->selected)
top = i;
}
- for (int i = n_entries; i > bottom; i --)
+ for (int i = n_entries; i > bottom; i--)
{
if (m_entries[i - 1]->selected)
bottom = i;
@@ -467,66 +465,66 @@ int PlaylistData::shift_entries (int entry_num, int distance)
Index<EntryPtr> temp;
- for (int i = top; i < center; i ++)
+ for (int i = top; i < center; i++)
{
- if (! m_entries[i]->selected)
- temp.append (std::move (m_entries[i]));
+ if (!m_entries[i]->selected)
+ temp.append(std::move(m_entries[i]));
}
- for (int i = top; i < bottom; i ++)
+ for (int i = top; i < bottom; i++)
{
if (m_entries[i] && m_entries[i]->selected)
- temp.append (std::move (m_entries[i]));
+ temp.append(std::move(m_entries[i]));
}
- for (int i = center; i < bottom; i ++)
+ for (int i = center; i < bottom; i++)
{
- if (m_entries[i] && ! m_entries[i]->selected)
- temp.append (std::move (m_entries[i]));
+ if (m_entries[i] && !m_entries[i]->selected)
+ temp.append(std::move(m_entries[i]));
}
- m_entries.move_from (temp, 0, top, bottom - top, false, true);
+ m_entries.move_from(temp, 0, top, bottom - top, false, true);
- number_entries (top, bottom - top);
- queue_update (Playlist::Structure, top, bottom - top);
+ number_entries(top, bottom - top);
+ queue_update(Playlist::Structure, top, bottom - top);
return shift;
}
-void PlaylistData::remove_selected ()
+void PlaylistData::remove_selected()
{
- if (! m_selected_count)
+ if (!m_selected_count)
return;
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
bool position_changed = false;
int update_flags = 0;
if (m_position && m_position->selected)
{
- set_position (nullptr, false);
+ change_position(NO_POS);
position_changed = true;
}
- m_focus = find_unselected_focus ();
+ m_focus = find_unselected_focus();
- int before = 0; // number of entries before first selected
- int after = 0; // number of entries after last selected
+ int before = 0; // number of entries before first selected
+ int after = 0; // number of entries after last selected
- while (before < n_entries && ! m_entries[before]->selected)
- before ++;
+ while (before < n_entries && !m_entries[before]->selected)
+ before++;
int to = before;
- for (int from = before; from < n_entries; from ++)
+ for (int from = before; from < n_entries; from++)
{
- PlaylistEntry * entry = m_entries[from].get ();
+ PlaylistEntry * entry = m_entries[from].get();
if (entry->selected)
{
if (entry->queued)
{
- m_queued.remove (m_queued.find (entry), 1);
+ m_queued.remove(m_queued.find(entry), 1);
update_flags |= QueueChanged;
}
@@ -535,374 +533,431 @@ void PlaylistData::remove_selected ()
}
else
{
- m_entries[to ++] = std::move (m_entries[from]);
- after ++;
+ m_entries[to++] = std::move(m_entries[from]);
+ after++;
}
}
n_entries = to;
- m_entries.remove (n_entries, -1);
+ m_entries.remove(n_entries, -1);
m_selected_count = 0;
m_selected_length = 0;
- number_entries (before, n_entries - before);
- queue_update (Playlist::Structure, before, n_entries - after - before, update_flags);
+ number_entries(before, n_entries - before);
+ queue_update(Playlist::Structure, before, n_entries - after - before,
+ update_flags);
if (position_changed)
{
- if (aud_get_bool (nullptr, "advance_on_delete"))
- next_song_with_hint (aud_get_bool (nullptr, "repeat"), n_entries - after);
+ if (aud_get_bool("advance_on_delete"))
+ change_position_to_next(aud_get_bool("repeat"), n_entries - after);
- queue_position_change ();
+ queue_position_change();
}
}
-void PlaylistData::sort_entries (Index<EntryPtr> & entries, const CompareData & data) // static
+void PlaylistData::sort_entries(Index<EntryPtr> & entries,
+ const CompareData & data) // static
{
- entries.sort ([data] (const EntryPtr & a, const EntryPtr & b) {
+ entries.sort([data](const EntryPtr & a, const EntryPtr & b) {
if (data.filename_compare)
- return data.filename_compare (a->filename, b->filename);
+ return data.filename_compare(a->filename, b->filename);
else
- return data.tuple_compare (a->tuple, b->tuple);
+ return data.tuple_compare(a->tuple, b->tuple);
});
}
-void PlaylistData::sort (const CompareData & data)
+void PlaylistData::sort(const CompareData & data)
{
- sort_entries (m_entries, data);
+ sort_entries(m_entries, data);
- number_entries (0, m_entries.len ());
- queue_update (Playlist::Structure, 0, m_entries.len ());
+ number_entries(0, m_entries.len());
+ queue_update(Playlist::Structure, 0, m_entries.len());
}
-void PlaylistData::sort_selected (const CompareData & data)
+void PlaylistData::sort_selected(const CompareData & data)
{
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
Index<EntryPtr> selected;
for (auto & entry : m_entries)
{
if (entry->selected)
- selected.append (std::move (entry));
+ selected.append(std::move(entry));
}
- sort_entries (selected, data);
+ sort_entries(selected, data);
int i = 0;
for (auto & entry : m_entries)
{
- if (! entry)
- entry = std::move (selected[i ++]);
+ if (!entry)
+ entry = std::move(selected[i++]);
}
- number_entries (0, n_entries);
- queue_update (Playlist::Structure, 0, n_entries);
+ number_entries(0, n_entries);
+ queue_update(Playlist::Structure, 0, n_entries);
}
-void PlaylistData::reverse_order ()
+void PlaylistData::reverse_order()
{
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
- for (int i = 0; i < n_entries / 2; i ++)
- std::swap (m_entries[i], m_entries[n_entries - 1 - i]);
+ for (int i = 0; i < n_entries / 2; i++)
+ std::swap(m_entries[i], m_entries[n_entries - 1 - i]);
- number_entries (0, n_entries);
- queue_update (Playlist::Structure, 0, n_entries);
+ number_entries(0, n_entries);
+ queue_update(Playlist::Structure, 0, n_entries);
}
-void PlaylistData::reverse_selected ()
+void PlaylistData::reverse_selected()
{
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
int top = 0;
int bottom = n_entries - 1;
while (1)
{
- while (top < bottom && ! m_entries[top]->selected)
- top ++;
- while (top < bottom && ! m_entries[bottom]->selected)
- bottom --;
+ while (top < bottom && !m_entries[top]->selected)
+ top++;
+ while (top < bottom && !m_entries[bottom]->selected)
+ bottom--;
if (top >= bottom)
break;
- std::swap (m_entries[top ++], m_entries[bottom --]);
+ std::swap(m_entries[top++], m_entries[bottom--]);
}
- number_entries (0, n_entries);
- queue_update (Playlist::Structure, 0, n_entries);
+ number_entries(0, n_entries);
+ queue_update(Playlist::Structure, 0, n_entries);
}
-void PlaylistData::randomize_order ()
+void PlaylistData::randomize_order()
{
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
- for (int i = 0; i < n_entries; i ++)
- std::swap (m_entries[i], m_entries[rand () % n_entries]);
+ for (int i = 0; i < n_entries; i++)
+ std::swap(m_entries[i], m_entries[rand() % n_entries]);
- number_entries (0, n_entries);
- queue_update (Playlist::Structure, 0, n_entries);
+ number_entries(0, n_entries);
+ queue_update(Playlist::Structure, 0, n_entries);
}
-void PlaylistData::randomize_selected ()
+void PlaylistData::randomize_selected()
{
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
Index<PlaylistEntry *> selected;
for (auto & entry : m_entries)
{
if (entry->selected)
- selected.append (entry.get ());
+ selected.append(entry.get());
}
- int n_selected = selected.len ();
+ int n_selected = selected.len();
- for (int i = 0; i < n_selected; i ++)
+ for (int i = 0; i < n_selected; i++)
{
int a = selected[i]->number;
- int b = selected[rand () % n_selected]->number;
- std::swap (m_entries[a], m_entries[b]);
+ int b = selected[rand() % n_selected]->number;
+ std::swap(m_entries[a], m_entries[b]);
}
- number_entries (0, n_entries);
- queue_update (Playlist::Structure, 0, n_entries);
+ number_entries(0, n_entries);
+ queue_update(Playlist::Structure, 0, n_entries);
}
-int PlaylistData::queue_get_entry (int at) const
+int PlaylistData::queue_get_entry(int at) const
{
- return (at >= 0 && at < m_queued.len ()) ? m_queued[at]->number : -1;
+ return (at >= 0 && at < m_queued.len()) ? m_queued[at]->number : -1;
}
-int PlaylistData::queue_find_entry (int entry_num) const
+int PlaylistData::queue_find_entry(int entry_num) const
{
- auto entry = entry_at (entry_num);
- return (entry && entry->queued) ? m_queued.find ((PlaylistEntry *) entry) : -1;
+ auto entry = entry_at(entry_num);
+ return (entry && entry->queued) ? m_queued.find((PlaylistEntry *)entry)
+ : -1;
}
-void PlaylistData::queue_insert (int at, int entry_num)
+void PlaylistData::queue_insert(int at, int entry_num)
{
- auto entry = entry_at (entry_num);
- if (! entry || entry->queued)
+ auto entry = entry_at(entry_num);
+ if (!entry || entry->queued)
return;
- if (at < 0 || at > m_queued.len ())
- m_queued.append (entry);
+ if (at < 0 || at > m_queued.len())
+ m_queued.append(entry);
else
{
- m_queued.insert (at, 1);
+ m_queued.insert(at, 1);
m_queued[at] = entry;
}
entry->queued = true;
- queue_update (Playlist::Selection, entry_num, 1, QueueChanged);
+ queue_update(Playlist::Selection, entry_num, 1, QueueChanged);
}
-void PlaylistData::queue_insert_selected (int at)
+void PlaylistData::queue_insert_selected(int at)
{
- if (at < 0 || at > m_queued.len ())
- at = m_queued.len ();
+ if (at < 0 || at > m_queued.len())
+ at = m_queued.len();
Index<PlaylistEntry *> add;
- int first = m_entries.len ();
+ int first = m_entries.len();
int last = 0;
for (auto & entry : m_entries)
{
- if (! entry->selected || entry->queued)
+ if (!entry->selected || entry->queued)
continue;
- add.append (entry.get ());
+ add.append(entry.get());
entry->queued = true;
- first = aud::min (first, entry->number);
+ first = aud::min(first, entry->number);
last = entry->number;
}
- m_queued.move_from (add, 0, at, -1, true, true);
+ m_queued.move_from(add, 0, at, -1, true, true);
- if (first < m_entries.len ())
- queue_update (Playlist::Selection, first, last + 1 - first, QueueChanged);
+ if (first < m_entries.len())
+ queue_update(Playlist::Selection, first, last + 1 - first,
+ QueueChanged);
}
-void PlaylistData::queue_remove (int at, int number)
+void PlaylistData::queue_remove(int at, int number)
{
- int queue_len = m_queued.len ();
+ int queue_len = m_queued.len();
if (at < 0 || at > queue_len)
at = queue_len;
if (number < 0 || number > queue_len - at)
number = queue_len - at;
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
int first = n_entries, last = 0;
- for (int i = at; i < at + number; i ++)
+ for (int i = at; i < at + number; i++)
{
PlaylistEntry * entry = m_queued[i];
entry->queued = false;
- first = aud::min (first, entry->number);
+ first = aud::min(first, entry->number);
last = entry->number;
}
- m_queued.remove (at, number);
+ m_queued.remove(at, number);
if (first < n_entries)
- queue_update (Playlist::Selection, first, last + 1 - first, QueueChanged);
+ queue_update(Playlist::Selection, first, last + 1 - first,
+ QueueChanged);
}
-void PlaylistData::queue_remove_selected ()
+void PlaylistData::queue_remove_selected()
{
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
int first = n_entries, last = 0;
- for (int i = 0; i < m_queued.len ();)
+ for (int i = 0; i < m_queued.len();)
{
PlaylistEntry * entry = m_queued[i];
if (entry->selected)
{
- m_queued.remove (i, 1);
+ m_queued.remove(i, 1);
entry->queued = false;
- first = aud::min (first, entry->number);
+ first = aud::min(first, entry->number);
last = entry->number;
}
else
- i ++;
+ i++;
}
if (first < n_entries)
- queue_update (Playlist::Selection, first, last + 1 - first, QueueChanged);
+ queue_update(Playlist::Selection, first, last + 1 - first,
+ QueueChanged);
}
-void PlaylistData::set_position (PlaylistEntry * entry, bool update_shuffle)
+int PlaylistData::shuffle_pos_before(int ref_pos) const
{
- m_position = entry;
- resume_time = 0;
+ auto ref_entry = entry_at(ref_pos);
+ if (!ref_entry)
+ return -1;
- /* move entry to top of shuffle list */
- if (entry && update_shuffle)
- entry->shuffle_num = ++ m_last_shuffle_num;
+ const PlaylistEntry * found = nullptr;
+ for (auto & entry : m_entries)
+ {
+ if (entry->shuffle_num > 0 &&
+ entry->shuffle_num < ref_entry->shuffle_num &&
+ (!found || entry->shuffle_num > found->shuffle_num))
+ {
+ found = entry.get();
+ }
+ }
+
+ return found ? found->number : -1;
}
-void PlaylistData::set_position (int entry_num)
+PlaylistData::PosChange PlaylistData::shuffle_pos_after(int ref_pos,
+ bool by_album) const
{
- set_position (entry_at (entry_num), true);
- queue_position_change ();
+ auto ref_entry = entry_at(ref_pos);
+ if (!ref_entry)
+ return NO_POS;
+
+ // the reference entry can be beyond the end of the shuffle list
+ // if we are looking ahead multiple entries, as in next_album()
+ if (ref_entry->shuffle_num > 0)
+ {
+ // look for the next entry in the existing shuffle order
+ const PlaylistEntry * next = nullptr;
+ for (auto & entry : m_entries)
+ {
+ if (entry->shuffle_num > ref_entry->shuffle_num &&
+ (!next || entry->shuffle_num < next->shuffle_num))
+ {
+ next = entry.get();
+ }
+ }
+
+ if (next)
+ return {next->number, false};
+ }
+
+ if (by_album)
+ {
+ // look for the next entry in the album
+ auto next = entry_at(ref_pos + 1);
+ if (next && same_album(next->tuple, ref_entry->tuple))
+ return {ref_pos + 1, true};
+ }
+
+ return NO_POS;
}
-bool PlaylistData::shuffle_prev ()
+PlaylistData::PosChange PlaylistData::shuffle_pos_random(bool repeat,
+ bool by_album) const
{
- PlaylistEntry * found = nullptr;
+ Index<const PlaylistEntry *> choices;
+ const PlaylistEntry * prev_entry = nullptr;
for (auto & entry : m_entries)
{
- if (entry->shuffle_num &&
- (! m_position || entry->shuffle_num < m_position->shuffle_num) &&
- (! found || entry->shuffle_num > found->shuffle_num))
+ // skip already played entries (unless repeating)
+ // optionally skip all but first entry in album
+ if ((entry->shuffle_num == 0 || repeat) &&
+ !(by_album && prev_entry &&
+ same_album(entry->tuple, prev_entry->tuple)))
{
- found = entry.get ();
+ choices.append(entry.get());
}
+
+ prev_entry = entry.get();
}
- if (! found)
- return false;
+ if (choices.len())
+ return {choices[rand() % choices.len()]->number, true};
- set_position (found, false);
- return true;
+ return NO_POS;
}
-bool PlaylistData::shuffle_next ()
+int PlaylistData::pos_before(int ref_pos, bool shuffle) const
{
- bool by_album = aud_get_bool (nullptr, "album_shuffle");
+ if (shuffle)
+ return shuffle_pos_before(ref_pos);
- // helper #1: determine whether two entries are in the same album
- auto same_album = [] (const Tuple & a, const Tuple & b)
- {
- String album = a.get_str (Tuple::Album);
- return (album && album == b.get_str (Tuple::Album));
- };
+ return (ref_pos > 0) ? ref_pos - 1 : -1;
+}
- // helper #2: determine whether an entry is among the shuffle choices
- auto is_choice = [&] (PlaylistEntry * prev, PlaylistEntry * entry)
- {
- return (! entry->shuffle_num) && (! by_album || ! prev ||
- prev->shuffle_num || ! same_album (prev->tuple, entry->tuple));
- };
+PlaylistData::PosChange PlaylistData::pos_after(int ref_pos, bool shuffle,
+ bool by_album) const
+{
+ if (m_queued.len())
+ return NO_POS; // let pos_new() handle queue entries
- if (m_position)
- {
- // step #1: check to see if the shuffle order is already established
- PlaylistEntry * next = nullptr;
+ if (shuffle)
+ return shuffle_pos_after(ref_pos, by_album);
- for (auto & entry : m_entries)
- {
- if (entry->shuffle_num > m_position->shuffle_num &&
- (! next || entry->shuffle_num < next->shuffle_num))
- next = entry.get ();
- }
+ if (ref_pos >= 0 && ref_pos + 1 < m_entries.len())
+ return {ref_pos + 1, true};
- if (next)
- {
- set_position (next, false);
- return true;
- }
+ return NO_POS;
+}
- // step #2: check to see if we should advance to the next entry
- if (by_album && m_position->number + 1 < m_entries.len ())
- {
- next = m_entries[m_position->number + 1].get ();
+PlaylistData::PosChange PlaylistData::pos_new(bool repeat, bool shuffle,
+ bool by_album, int hint_pos) const
+{
+ if (m_queued.len())
+ return {m_queued[0]->number, true};
- if (! next->shuffle_num && same_album (m_position->tuple, next->tuple))
- {
- set_position (next, true);
- return true;
- }
- }
- }
+ if (shuffle)
+ return shuffle_pos_random(repeat, by_album);
- // step #3: count the number of possible shuffle choices
- int choices = 0;
- PlaylistEntry * prev = nullptr;
+ if (hint_pos >= 0 && hint_pos < m_entries.len())
+ return {hint_pos, true};
- for (auto & entry : m_entries)
- {
- if (is_choice (prev, entry.get ()))
- choices ++;
+ return NO_POS;
+}
+
+PlaylistData::PosChange PlaylistData::pos_new_full(bool repeat, bool shuffle,
+ bool by_album, int hint_pos,
+ bool & repeated) const
+{
+ // first try to pick a new position *without* repeating
+ auto change = pos_new(false, shuffle, by_album, hint_pos);
+ repeated = false;
- prev = entry.get ();
+ if (change.new_pos < 0 && repeat)
+ {
+ change = pos_new(true, shuffle, by_album, 0);
+ repeated = (change.new_pos >= 0);
}
- if (! choices)
- return false;
+ return change;
+}
+
+void PlaylistData::change_position(PosChange change)
+{
+ m_position = entry_at(change.new_pos);
+ resume_time = 0;
- // step #4: pick one of those choices by random and find it again
- choices = rand () % choices;
- prev = nullptr;
+ /* move entry to top of shuffle list */
+ if (m_position && change.update_shuffle)
+ m_position->shuffle_num = ++m_last_shuffle_num;
- for (auto & entry : m_entries)
+ /* remove from queue if it's the first entry */
+ if (m_queued.len() && m_position == m_queued[0])
{
- if (is_choice (prev, entry.get ()))
- {
- if (! choices)
- {
- set_position (entry.get (), true);
- return true;
- }
+ m_queued.remove(0, 1);
+ m_position->queued = false;
+ queue_update(Playlist::Selection, m_position->number, 1, QueueChanged);
+ }
+}
- choices --;
- }
+bool PlaylistData::change_position_to_next(bool repeat, int hint_pos)
+{
+ bool shuffle = aud_get_bool("shuffle");
+ bool by_album = aud_get_bool("album_shuffle");
+ bool repeated = false;
+
+ auto change = pos_after(position(), shuffle, by_album);
+ if (change.new_pos < 0)
+ change = pos_new_full(repeat, shuffle, by_album, hint_pos, repeated);
+ if (change.new_pos < 0)
+ return false;
- prev = entry.get ();
- }
+ if (repeated)
+ shuffle_reset();
- return false; // never reached
+ change_position(change);
+ return true;
}
-void PlaylistData::shuffle_reset ()
+void PlaylistData::shuffle_reset()
{
m_last_shuffle_num = 0;
@@ -910,7 +965,7 @@ void PlaylistData::shuffle_reset ()
entry->shuffle_num = 0;
}
-Index<int> PlaylistData::shuffle_history () const
+Index<int> PlaylistData::shuffle_history() const
{
Index<int> history;
@@ -918,108 +973,152 @@ Index<int> PlaylistData::shuffle_history () const
for (auto & entry : m_entries)
{
if (entry->shuffle_num)
- history.append (entry->number);
+ history.append(entry->number);
}
// sort by shuffle order
- history.sort ([this] (int entry_a, int entry_b) {
- return m_entries[entry_a]->shuffle_num - m_entries[entry_b]->shuffle_num;
+ history.sort([this](int entry_a, int entry_b) {
+ return m_entries[entry_a]->shuffle_num -
+ m_entries[entry_b]->shuffle_num;
});
return history;
}
-void PlaylistData::shuffle_replay (const Index<int> & history)
+void PlaylistData::shuffle_replay(const Index<int> & history)
{
- shuffle_reset ();
+ shuffle_reset();
// replay the given history, entry by entry
for (int entry_num : history)
{
- auto entry = entry_at (entry_num);
+ auto entry = entry_at(entry_num);
if (entry)
- entry->shuffle_num = ++ m_last_shuffle_num;
+ entry->shuffle_num = ++m_last_shuffle_num;
}
}
-bool PlaylistData::prev_song ()
+void PlaylistData::set_position(int entry_num)
{
- if (aud_get_bool (nullptr, "shuffle"))
- {
- if (! shuffle_prev ())
- return false;
- }
- else
- {
- int pos = position ();
- if (pos < 1)
- return false;
+ change_position({entry_num, true});
+ queue_position_change();
+}
- set_position (m_entries[pos - 1].get (), true);
- }
+bool PlaylistData::prev_song()
+{
+ bool shuffle = aud_get_bool("shuffle");
+ int pos = pos_before(position(), shuffle);
+ if (pos < 0)
+ return false;
- queue_position_change ();
+ // update shuffle list if entry didn't come from it
+ change_position({pos, !shuffle});
+ queue_position_change();
return true;
}
-bool PlaylistData::next_song_with_hint (bool repeat, int hint)
+bool PlaylistData::next_song(bool repeat)
{
- int n_entries = m_entries.len ();
- if (! n_entries)
+ if (!change_position_to_next(repeat, -1))
return false;
- PlaylistEntry * entry;
- if ((entry = queue_pop ()))
- {
- set_position (entry, true);
- return true;
- }
+ queue_position_change();
+ return true;
+}
- if (aud_get_bool (nullptr, "shuffle"))
- {
- if (shuffle_next ())
- return true;
+bool PlaylistData::prev_album()
+{
+ bool shuffle = aud_get_bool("shuffle");
+ int pos = position();
- if (! repeat)
+ // find the start of the previous album
+ for (bool in_prev_album = false;;)
+ {
+ auto entry = entry_at(pos);
+ if (!entry)
return false;
- shuffle_reset ();
+ while (1)
+ {
+ auto prev_entry = entry_at(pos_before(pos, shuffle));
+ if (!prev_entry || !same_album(entry->tuple, prev_entry->tuple))
+ break;
- return shuffle_next ();
- }
+ pos = prev_entry->number;
+ }
- if (hint < 0 || hint >= n_entries)
- {
- if (! repeat)
- return false;
+ if (in_prev_album)
+ break; // we're at the start of the previous album
- hint = 0;
+ // we're at the start of the current album
+ // one more song back puts us in the previous album
+ pos = pos_before(pos, shuffle);
+ in_prev_album = true;
}
- set_position (m_entries[hint].get (), true);
+ // update shuffle list if entry didn't come from it
+ change_position({pos, !shuffle});
+ queue_position_change();
return true;
}
-bool PlaylistData::next_song (bool repeat)
+bool PlaylistData::next_album(bool repeat)
{
- if (! next_song_with_hint (repeat, position () + 1)) // -1 becomes 0
+ bool shuffle = aud_get_bool("shuffle");
+ PosChange change = {position(), false};
+ Index<PosChange> skipped;
+ bool repeated = false;
+
+ auto entry = entry_at(change.new_pos);
+ if (!entry)
return false;
- queue_position_change ();
+ // find the end of the album
+ while (1)
+ {
+ // album shuffle is always on for this function
+ change = pos_after(change.new_pos, shuffle, true);
+
+ auto next_entry = entry_at(change.new_pos);
+ if (!next_entry || !same_album(entry->tuple, next_entry->tuple))
+ break;
+
+ skipped.append(change);
+ }
+
+ // get one new position if there was nothing after the album
+ if (change.new_pos < 0)
+ {
+ change = pos_new_full(repeat, shuffle, true, -1, repeated);
+ if (change.new_pos < 0)
+ return false;
+ }
+
+ if (repeated)
+ shuffle_reset();
+ else
+ {
+ // add skipped songs to shuffle list
+ for (auto & skip : skipped)
+ change_position(skip);
+ }
+
+ change_position(change);
+ queue_position_change();
return true;
}
-int PlaylistData::next_unscanned_entry (int entry_num) const
+int PlaylistData::next_unscanned_entry(int entry_num) const
{
if (entry_num < 0)
return -1;
- for (; entry_num < m_entries.len (); entry_num ++)
+ for (; entry_num < m_entries.len(); entry_num++)
{
auto & entry = *m_entries[entry_num];
- if (entry.tuple.state () == Tuple::Initial &&
- strncmp (entry.filename, "stdin://", 8)) // blacklist stdin
+ if (entry.tuple.state() == Tuple::Initial &&
+ strncmp(entry.filename, "stdin://", 8)) // blacklist stdin
{
return entry_num;
}
@@ -1028,128 +1127,119 @@ int PlaylistData::next_unscanned_entry (int entry_num) const
return -1;
}
-ScanRequest * PlaylistData::create_scan_request (PlaylistEntry * entry,
- ScanRequest::Callback callback, int extra_flags)
+ScanRequest * PlaylistData::create_scan_request(PlaylistEntry * entry,
+ ScanRequest::Callback callback,
+ int extra_flags)
{
int flags = extra_flags;
- if (! entry->tuple.valid ())
+ if (!entry->tuple.valid())
flags |= SCAN_TUPLE;
/* scanner uses Tuple::AudioFile from existing tuple, if valid */
- return new ScanRequest (entry->filename, flags, callback, entry->decoder,
- (flags & SCAN_TUPLE) ? Tuple () : entry->tuple.ref ());
+ return new ScanRequest(entry->filename, flags, callback, entry->decoder,
+ (flags & SCAN_TUPLE) ? Tuple() : entry->tuple.ref());
}
-void PlaylistData::update_entry_from_scan (PlaylistEntry * entry, ScanRequest * request, int update_flags)
+void PlaylistData::update_entry_from_scan(PlaylistEntry * entry,
+ ScanRequest * request,
+ int update_flags)
{
- if (! entry->decoder)
+ if (!entry->decoder)
entry->decoder = request->decoder;
- if (! entry->tuple.valid () && request->tuple.valid ())
+ if (!entry->tuple.valid() && request->tuple.valid())
{
- set_entry_tuple (entry, std::move (request->tuple));
- queue_update (Playlist::Metadata, entry->number, 1, update_flags);
+ set_entry_tuple(entry, std::move(request->tuple));
+ queue_update(Playlist::Metadata, entry->number, 1, update_flags);
}
- if (! entry->decoder || ! entry->tuple.valid ())
+ if (!entry->decoder || !entry->tuple.valid())
entry->error = request->error;
- if (entry->tuple.state () == Tuple::Initial)
+ if (entry->tuple.state() == Tuple::Initial)
{
- entry->tuple.set_state (Tuple::Failed);
- queue_update (Playlist::Metadata, entry->number, 1, update_flags);
+ entry->tuple.set_state(Tuple::Failed);
+ queue_update(Playlist::Metadata, entry->number, 1, update_flags);
}
}
-void PlaylistData::update_playback_entry (Tuple && tuple)
+void PlaylistData::update_playback_entry(Tuple && tuple)
{
/* don't update cuesheet entries with stream metadata */
- if (m_position && ! m_position->tuple.is_set (Tuple::StartTime))
+ if (m_position && !m_position->tuple.is_set(Tuple::StartTime))
{
- set_entry_tuple (m_position, std::move (tuple));
- queue_update (Playlist::Metadata, m_position->number, 1);
+ set_entry_tuple(m_position, std::move(tuple));
+ queue_update(Playlist::Metadata, m_position->number, 1);
}
}
-bool PlaylistData::entry_needs_rescan (PlaylistEntry * entry, bool need_decoder, bool need_tuple)
+bool PlaylistData::entry_needs_rescan(PlaylistEntry * entry, bool need_decoder,
+ bool need_tuple)
{
- if (! strncmp (entry->filename, "stdin://", 8)) // blacklist stdin
+ if (!strncmp(entry->filename, "stdin://", 8)) // blacklist stdin
return false;
// check whether requested data (decoder and/or tuple) has been read
- return (need_decoder && ! entry->decoder) || (need_tuple && ! entry->tuple.valid ());
+ return (need_decoder && !entry->decoder) ||
+ (need_tuple && !entry->tuple.valid());
}
-void PlaylistData::reformat_titles ()
+void PlaylistData::reformat_titles()
{
for (auto & entry : m_entries)
- entry->format ();
+ entry->format();
- queue_update (Playlist::Metadata, 0, m_entries.len ());
+ queue_update(Playlist::Metadata, 0, m_entries.len());
}
-void PlaylistData::reset_tuples (bool selected_only)
+void PlaylistData::reset_tuples(bool selected_only)
{
for (auto & entry : m_entries)
{
- if (! selected_only || entry->selected)
- set_entry_tuple (entry.get (), Tuple ());
+ if (!selected_only || entry->selected)
+ set_entry_tuple(entry.get(), Tuple());
}
- queue_update (Playlist::Metadata, 0, m_entries.len ());
- pl_signal_rescan_needed (m_id);
+ queue_update(Playlist::Metadata, 0, m_entries.len());
+ pl_signal_rescan_needed(m_id);
}
-void PlaylistData::reset_tuple_of_file (const char * filename)
+void PlaylistData::reset_tuple_of_file(const char * filename)
{
bool found = false;
for (auto & entry : m_entries)
{
- if (! strcmp (entry->filename, filename))
+ if (!strcmp(entry->filename, filename))
{
- set_entry_tuple (entry.get (), Tuple ());
- queue_update (Playlist::Metadata, entry->number, 1);
+ set_entry_tuple(entry.get(), Tuple());
+ queue_update(Playlist::Metadata, entry->number, 1);
found = true;
}
}
if (found)
- pl_signal_rescan_needed (m_id);
+ pl_signal_rescan_needed(m_id);
}
-PlaylistEntry * PlaylistData::find_unselected_focus ()
+PlaylistEntry * PlaylistData::find_unselected_focus()
{
- if (! m_focus || ! m_focus->selected)
+ if (!m_focus || !m_focus->selected)
return m_focus;
- int n_entries = m_entries.len ();
+ int n_entries = m_entries.len();
- for (int search = m_focus->number + 1; search < n_entries; search ++)
+ for (int search = m_focus->number + 1; search < n_entries; search++)
{
- if (! m_entries[search]->selected)
- return m_entries[search].get ();
+ if (!m_entries[search]->selected)
+ return m_entries[search].get();
}
- for (int search = m_focus->number; search --;)
+ for (int search = m_focus->number; search--;)
{
- if (! m_entries[search]->selected)
- return m_entries[search].get ();
+ if (!m_entries[search]->selected)
+ return m_entries[search].get();
}
return nullptr;
}
-
-PlaylistEntry * PlaylistData::queue_pop ()
-{
- if (! m_queued.len ())
- return nullptr;
-
- auto entry = m_queued[0];
- m_queued.remove (0, 1);
- entry->queued = false;
-
- queue_update (Playlist::Selection, entry->number, 1, QueueChanged);
-
- return entry;
-}
diff --git a/src/libaudcore/playlist-data.h b/src/libaudcore/playlist-data.h
index 663c565..662261e 100644
--- a/src/libaudcore/playlist-data.h
+++ b/src/libaudcore/playlist-data.h
@@ -30,122 +30,147 @@ class PlaylistData
{
public:
/* update flags */
- enum {
- QueueChanged = (1 << 0),
+ enum
+ {
+ QueueChanged = (1 << 0),
DelayedUpdate = (1 << 1)
};
/* scan status */
- enum ScanStatus {
+ enum ScanStatus
+ {
NotScanning,
ScanActive,
ScanEnding
};
- struct CompareData {
+ struct CompareData
+ {
Playlist::StringCompareFunc filename_compare;
Playlist::TupleCompareFunc tuple_compare;
};
- PlaylistData (Playlist::ID * m_id, const char * title);
- ~PlaylistData ();
+ PlaylistData(Playlist::ID * m_id, const char * title);
+ ~PlaylistData();
- PlaylistEntry * entry_at (int i);
- const PlaylistEntry * entry_at (int i) const;
+ PlaylistEntry * entry_at(int i);
+ const PlaylistEntry * entry_at(int i) const;
- String entry_filename (int i) const;
- PluginHandle * entry_decoder (int i, String * error = nullptr) const;
- Tuple entry_tuple (int i, String * error = nullptr) const;
+ String entry_filename(int i) const;
+ PluginHandle * entry_decoder(int i, String * error = nullptr) const;
+ Tuple entry_tuple(int i, String * error = nullptr) const;
- void cancel_updates ();
- void swap_updates (bool & position_changed);
+ void cancel_updates();
+ void swap_updates(bool & position_changed);
- void insert_items (int at, Index<PlaylistAddItem> && items);
- void remove_entries (int at, int number);
+ void insert_items(int at, Index<PlaylistAddItem> && items);
+ void remove_entries(int at, int number);
- int position () const;
- int focus () const;
+ int position() const;
+ int focus() const;
- bool entry_selected (int entry_num) const;
- int n_selected (int at, int number) const;
+ bool entry_selected(int entry_num) const;
+ int n_selected(int at, int number) const;
- void set_focus (int entry_num);
+ void set_focus(int entry_num);
- void select_entry (int entry_num, bool selected);
- void select_all (bool selected);
- int shift_entries (int entry_num, int distance);
- void remove_selected ();
+ void select_entry(int entry_num, bool selected);
+ void select_all(bool selected);
+ int shift_entries(int entry_num, int distance);
+ void remove_selected();
- void sort (const CompareData & data);
- void sort_selected (const CompareData & data);
+ void sort(const CompareData & data);
+ void sort_selected(const CompareData & data);
- void reverse_order ();
- void randomize_order ();
- void reverse_selected ();
- void randomize_selected ();
+ void reverse_order();
+ void randomize_order();
+ void reverse_selected();
+ void randomize_selected();
- int queue_get_entry (int at) const;
- int queue_find_entry (int entry_num) const;
+ int queue_get_entry(int at) const;
+ int queue_find_entry(int entry_num) const;
- void queue_insert (int at, int entry_num);
- void queue_insert_selected (int pos);
- void queue_remove (int at, int number);
- void queue_remove_selected ();
+ void queue_insert(int at, int entry_num);
+ void queue_insert_selected(int pos);
+ void queue_remove(int at, int number);
+ void queue_remove_selected();
- void set_position (int entry_num);
+ Index<int> shuffle_history() const;
+ void shuffle_replay(const Index<int> & history);
- Index<int> shuffle_history () const;
- void shuffle_replay (const Index<int> & history);
+ void set_position(int entry_num);
- bool prev_song ();
- bool next_song (bool repeat);
+ bool prev_song();
+ bool next_song(bool repeat);
+ bool prev_album();
+ bool next_album(bool repeat);
- int next_unscanned_entry (int entry_num) const;
- bool entry_needs_rescan (PlaylistEntry * entry, bool need_decoder, bool need_tuple);
- ScanRequest * create_scan_request (PlaylistEntry * entry,
- ScanRequest::Callback callback, int extra_flags);
- void update_entry_from_scan (PlaylistEntry * entry, ScanRequest * request, int update_flags);
- void update_playback_entry (Tuple && tuple);
+ int next_unscanned_entry(int entry_num) const;
+ bool entry_needs_rescan(PlaylistEntry * entry, bool need_decoder,
+ bool need_tuple);
+ ScanRequest * create_scan_request(PlaylistEntry * entry,
+ ScanRequest::Callback callback,
+ int extra_flags);
+ void update_entry_from_scan(PlaylistEntry * entry, ScanRequest * request,
+ int update_flags);
+ void update_playback_entry(Tuple && tuple);
- void reformat_titles ();
- void reset_tuples (bool selected_only);
- void reset_tuple_of_file (const char * filename);
+ void reformat_titles();
+ void reset_tuples(bool selected_only);
+ void reset_tuple_of_file(const char * filename);
- Playlist::ID * id () const { return m_id; }
+ Playlist::ID * id() const { return m_id; }
- int n_entries () const { return m_entries.len (); }
- int n_queued () const { return m_queued.len (); }
+ int n_entries() const { return m_entries.len(); }
+ int n_queued() const { return m_queued.len(); }
- int64_t total_length () const { return m_total_length; }
- int64_t selected_length () const { return m_selected_length; }
+ int64_t total_length() const { return m_total_length; }
+ int64_t selected_length() const { return m_selected_length; }
- const Playlist::Update & last_update () const { return m_last_update; }
- bool update_pending () const { return m_next_update.level != Playlist::NoUpdate; }
+ const Playlist::Update & last_update() const { return m_last_update; }
+ bool update_pending() const
+ {
+ return m_next_update.level != Playlist::NoUpdate;
+ }
- static void update_formatter ();
- static void cleanup_formatter ();
+ static void update_formatter();
+ static void cleanup_formatter();
private:
- static void delete_entry (PlaylistEntry * entry);
+ struct PosChange
+ {
+ int new_pos;
+ bool update_shuffle;
+ };
+
+ static void delete_entry(PlaylistEntry * entry);
typedef SmartPtr<PlaylistEntry, delete_entry> EntryPtr;
- void number_entries (int at, int length);
- void set_entry_tuple (PlaylistEntry * entry, Tuple && tuple);
- void queue_update (Playlist::UpdateLevel level, int at, int count, int flags = 0);
- void queue_position_change ();
+ void number_entries(int at, int length);
+ void set_entry_tuple(PlaylistEntry * entry, Tuple && tuple);
+ void queue_update(Playlist::UpdateLevel level, int at, int count,
+ int flags = 0);
+ void queue_position_change();
- static void sort_entries (Index<EntryPtr> & entries, const CompareData & data);
+ static void sort_entries(Index<EntryPtr> & entries,
+ const CompareData & data);
- void set_position (PlaylistEntry * entry, bool update_shuffle);
+ int shuffle_pos_before(int ref_pos) const;
+ PosChange shuffle_pos_after(int ref_pos, bool by_album) const;
+ PosChange shuffle_pos_random(bool repeat, bool by_album) const;
- bool shuffle_prev ();
- bool shuffle_next ();
- void shuffle_reset ();
+ int pos_before(int ref_pos, bool shuffle) const;
+ PosChange pos_after(int ref_pos, bool shuffle, bool by_album) const;
+ PosChange pos_new(bool repeat, bool shuffle, bool by_album,
+ int hint_pos) const;
+ PosChange pos_new_full(bool repeat, bool shuffle, bool by_album,
+ int hint_pos, bool & repeated) const;
- bool next_song_with_hint (bool repeat, int hint);
+ void change_position(PosChange change);
+ bool change_position_to_next(bool repeat, int hint_pos);
+ void shuffle_reset();
- PlaylistEntry * find_unselected_focus ();
- PlaylistEntry * queue_pop ();
+ PlaylistEntry * find_unselected_focus();
public:
bool modified;
@@ -156,7 +181,7 @@ public:
private:
Playlist::ID * m_id;
Index<EntryPtr> m_entries;
- PlaylistEntry * m_position, * m_focus;
+ PlaylistEntry *m_position, *m_focus;
int m_selected_count;
int m_last_shuffle_num;
Index<PlaylistEntry *> m_queued;
@@ -166,10 +191,11 @@ private:
};
/* callbacks or "signals" (in the QObject sense) */
-void pl_signal_entry_deleted (PlaylistEntry * entry);
-void pl_signal_position_changed (Playlist::ID * id);
-void pl_signal_update_queued (Playlist::ID * id, Playlist::UpdateLevel level, int flags);
-void pl_signal_rescan_needed (Playlist::ID * id);
-void pl_signal_playlist_deleted (Playlist::ID * id);
+void pl_signal_entry_deleted(PlaylistEntry * entry);
+void pl_signal_position_changed(Playlist::ID * id);
+void pl_signal_update_queued(Playlist::ID * id, Playlist::UpdateLevel level,
+ int flags);
+void pl_signal_rescan_needed(Playlist::ID * id);
+void pl_signal_playlist_deleted(Playlist::ID * id);
#endif // PLAYLIST_DATA_H
diff --git a/src/libaudcore/playlist-files.cc b/src/libaudcore/playlist-files.cc
index a2914b1..c11c505 100644
--- a/src/libaudcore/playlist-files.cc
+++ b/src/libaudcore/playlist-files.cc
@@ -26,15 +26,16 @@
#include "plugins-internal.h"
#include "runtime.h"
-EXPORT bool Playlist::filename_is_playlist (const char * filename)
+EXPORT bool Playlist::filename_is_playlist(const char * filename)
{
- StringBuf ext = uri_get_extension (filename);
+ StringBuf ext = uri_get_extension(filename);
if (ext)
{
- for (PluginHandle * plugin : aud_plugin_list (PluginType::Playlist))
+ for (PluginHandle * plugin : aud_plugin_list(PluginType::Playlist))
{
- if (aud_plugin_get_enabled (plugin) && playlist_plugin_has_ext (plugin, ext))
+ if (aud_plugin_get_enabled(plugin) &&
+ playlist_plugin_has_ext(plugin, ext))
return true;
}
}
@@ -42,48 +43,52 @@ EXPORT bool Playlist::filename_is_playlist (const char * filename)
return false;
}
-bool playlist_load (const char * filename, String & title, Index<PlaylistAddItem> & items)
+bool playlist_load(const char * filename, String & title,
+ Index<PlaylistAddItem> & items)
{
- AUDINFO ("Loading playlist %s.\n", filename);
+ AUDINFO("Loading playlist %s.\n", filename);
- StringBuf ext = uri_get_extension (filename);
+ StringBuf ext = uri_get_extension(filename);
bool plugin_found = false;
if (ext)
{
- for (PluginHandle * plugin : aud_plugin_list (PluginType::Playlist))
+ for (PluginHandle * plugin : aud_plugin_list(PluginType::Playlist))
{
- if (! aud_plugin_get_enabled (plugin) || ! playlist_plugin_has_ext (plugin, ext))
+ if (!aud_plugin_get_enabled(plugin) ||
+ !playlist_plugin_has_ext(plugin, ext))
continue;
- AUDINFO ("Trying playlist plugin %s.\n", aud_plugin_get_name (plugin));
+ AUDINFO("Trying playlist plugin %s.\n",
+ aud_plugin_get_name(plugin));
plugin_found = true;
- auto pp = (PlaylistPlugin *) aud_plugin_get_header (plugin);
- if (! pp)
+ auto pp = (PlaylistPlugin *)aud_plugin_get_header(plugin);
+ if (!pp)
continue;
- VFSFile file (filename, "r");
- if (! file)
+ VFSFile file(filename, "r");
+ if (!file)
{
- aud_ui_show_error (str_printf (_("Error opening %s:\n%s"),
- filename, file.error ()));
+ aud_ui_show_error(str_printf(_("Error opening %s:\n%s"),
+ filename, file.error()));
return false;
}
- if (pp->load (filename, file, title, items))
+ if (pp->load(filename, file, title, items))
return true;
- title = String ();
- items.clear ();
+ title = String();
+ items.clear();
}
}
if (plugin_found)
- aud_ui_show_error (str_printf (_("Error loading %s."), filename));
+ aud_ui_show_error(str_printf(_("Error loading %s."), filename));
else
- aud_ui_show_error (str_printf (_("Cannot load %s: unsupported file "
- "name extension."), filename));
+ aud_ui_show_error(str_printf(_("Cannot load %s: unsupported file "
+ "name extension."),
+ filename));
return false;
}
@@ -93,87 +98,91 @@ bool playlist_load (const char * filename, String & title, Index<PlaylistAddItem
// All support for adding folders, cuesheets, subtunes, etc. is omitted here.
// Additionally, in order to avoid heavy I/O at startup, failed entries are not
// rescanned; they can be rescanned later by refreshing the playlist. */
-bool PlaylistEx::insert_flat_playlist (const char * filename) const
+bool PlaylistEx::insert_flat_playlist(const char * filename) const
{
String title;
Index<PlaylistAddItem> items;
- if (! playlist_load (filename, title, items))
+ if (!playlist_load(filename, title, items))
return false;
if (title)
- set_title (title);
+ set_title(title);
- insert_flat_items (0, std::move (items));
+ insert_flat_items(0, std::move(items));
return true;
}
-EXPORT bool Playlist::save_to_file (const char * filename, GetMode mode) const
+EXPORT bool Playlist::save_to_file(const char * filename, GetMode mode) const
{
- String title = get_title ();
+ String title = get_title();
Index<PlaylistAddItem> items;
- items.insert (0, n_entries ());
+ items.insert(0, n_entries());
int i = 0;
for (PlaylistAddItem & item : items)
{
- item.filename = entry_filename (i);
- item.tuple = entry_tuple (i, mode);
- item.tuple.delete_fallbacks ();
- i ++;
+ item.filename = entry_filename(i);
+ item.tuple = entry_tuple(i, mode);
+ item.tuple.delete_fallbacks();
+ i++;
}
- AUDINFO ("Saving playlist %s.\n", filename);
+ AUDINFO("Saving playlist %s.\n", filename);
- StringBuf ext = uri_get_extension (filename);
+ StringBuf ext = uri_get_extension(filename);
if (ext)
{
- for (PluginHandle * plugin : aud_plugin_list (PluginType::Playlist))
+ for (PluginHandle * plugin : aud_plugin_list(PluginType::Playlist))
{
- if (! aud_plugin_get_enabled (plugin) || ! playlist_plugin_has_ext (plugin, ext))
+ if (!aud_plugin_get_enabled(plugin) ||
+ !playlist_plugin_has_ext(plugin, ext))
continue;
- PlaylistPlugin * pp = (PlaylistPlugin *) aud_plugin_get_header (plugin);
- if (! pp || ! pp->can_save)
+ PlaylistPlugin * pp =
+ (PlaylistPlugin *)aud_plugin_get_header(plugin);
+ if (!pp || !pp->can_save)
continue;
- VFSFile file (filename, "w");
- if (! file)
+ VFSFile file(filename, "w");
+ if (!file)
{
- aud_ui_show_error (str_printf (_("Error opening %s:\n%s"),
- filename, file.error ()));
+ aud_ui_show_error(str_printf(_("Error opening %s:\n%s"),
+ filename, file.error()));
return false;
}
- if (pp->save (filename, file, title, items) && file.fflush () == 0)
+ if (pp->save(filename, file, title, items) && file.fflush() == 0)
return true;
- aud_ui_show_error (str_printf (_("Error saving %s."), filename));
+ aud_ui_show_error(str_printf(_("Error saving %s."), filename));
return false;
}
}
- aud_ui_show_error (str_printf (_("Cannot save %s: unsupported file name extension."), filename));
+ aud_ui_show_error(str_printf(
+ _("Cannot save %s: unsupported file name extension."), filename));
return false;
}
-EXPORT Index<Playlist::SaveFormat> Playlist::save_formats ()
+EXPORT Index<Playlist::SaveFormat> Playlist::save_formats()
{
Index<Playlist::SaveFormat> formats;
- for (auto plugin : aud_plugin_list (PluginType::Playlist))
+ for (auto plugin : aud_plugin_list(PluginType::Playlist))
{
- if (! aud_plugin_get_enabled (plugin) || ! playlist_plugin_can_save (plugin))
+ if (!aud_plugin_get_enabled(plugin) ||
+ !playlist_plugin_can_save(plugin))
continue;
- auto & format = formats.append ();
- format.name = String (aud_plugin_get_name (plugin));
+ auto & format = formats.append();
+ format.name = String(aud_plugin_get_name(plugin));
- for (auto & ext : playlist_plugin_get_exts (plugin))
- format.exts.append (ext);
+ for (auto & ext : playlist_plugin_get_exts(plugin))
+ format.exts.append(ext);
}
return formats;
diff --git a/src/libaudcore/playlist-internal.h b/src/libaudcore/playlist-internal.h
index bbccd6b..6333ecb 100644
--- a/src/libaudcore/playlist-internal.h
+++ b/src/libaudcore/playlist-internal.h
@@ -37,43 +37,42 @@ struct DecodeInfo
class PlaylistEx : public Playlist
{
public:
- PlaylistEx (Playlist::ID * id = nullptr) :
- Playlist (id) {}
- PlaylistEx (Playlist playlist) :
- Playlist (playlist) {}
+ PlaylistEx(Playlist::ID * id = nullptr) : Playlist(id) {}
+ PlaylistEx(Playlist playlist) : Playlist(playlist) {}
- int stamp () const;
+ int stamp() const;
- static Playlist insert_with_stamp (int at, int stamp);
+ static Playlist insert_with_stamp(int at, int stamp);
- bool get_modified () const;
- void set_modified (bool modified) const;
+ bool get_modified() const;
+ void set_modified(bool modified) const;
- bool insert_flat_playlist (const char * filename) const;
- void insert_flat_items (int at, Index<PlaylistAddItem> && items) const;
+ bool insert_flat_playlist(const char * filename) const;
+ void insert_flat_items(int at, Index<PlaylistAddItem> && items) const;
};
/* playlist.cc */
-void playlist_init ();
-void playlist_enable_scan (bool enable);
-void playlist_clear_updates ();
-void playlist_end ();
+void playlist_init();
+void playlist_enable_scan(bool enable);
+void playlist_clear_updates();
+void playlist_end();
-void playlist_load_state ();
-void playlist_save_state ();
+void playlist_load_state();
+void playlist_save_state();
-DecodeInfo playback_entry_read (int serial);
-void playback_entry_set_tuple (int serial, Tuple && tuple);
+DecodeInfo playback_entry_read(int serial);
+void playback_entry_set_tuple(int serial, Tuple && tuple);
/* playlist-cache.cc */
-void playlist_cache_load (Index<PlaylistAddItem> & items);
-void playlist_cache_clear (void * = nullptr);
+void playlist_cache_load(Index<PlaylistAddItem> & items);
+void playlist_cache_clear(void * = nullptr);
/* playlist-files.cc */
-bool playlist_load (const char * filename, String & title, Index<PlaylistAddItem> & items);
+bool playlist_load(const char * filename, String & title,
+ Index<PlaylistAddItem> & items);
/* playlist-utils.cc */
-void load_playlists ();
-void save_playlists (bool exiting);
+void load_playlists();
+void save_playlists(bool exiting);
#endif
diff --git a/src/libaudcore/playlist-utils.cc b/src/libaudcore/playlist-utils.cc
index 9492f29..ff78a2f 100644
--- a/src/libaudcore/playlist-utils.cc
+++ b/src/libaudcore/playlist-utils.cc
@@ -31,80 +31,115 @@
#include "tuple.h"
#include "vfs.h"
-static const char * get_basename (const char * filename)
+static const char * get_basename(const char * filename)
{
- const char * slash = strrchr (filename, '/');
+ const char * slash = strrchr(filename, '/');
return slash ? slash + 1 : filename;
}
-static int filename_compare_basename (const char * a, const char * b)
+static int filename_compare_path(const char * a, const char * b)
{
- return str_compare_encoded (get_basename (a), get_basename (b));
+ int dirlen_a = get_basename(a) - a;
+ int dirlen_b = get_basename(b) - b;
+
+ // if one folder is a subfolder of the other, sort it last
+ if (dirlen_a != dirlen_b && memcmp(a, b, aud::min(dirlen_a, dirlen_b)) == 0)
+ return dirlen_a - dirlen_b;
+
+ // in all other cases, compare the entire paths
+ return str_compare_encoded(a, b);
}
-static int tuple_compare_string (const Tuple & a, const Tuple & b, Tuple::Field field)
+static int filename_compare_basename(const char * a, const char * b)
{
- String string_a = a.get_str (field);
- String string_b = b.get_str (field);
+ return str_compare_encoded(get_basename(a), get_basename(b));
+}
- if (! string_a)
- return (! string_b) ? 0 : -1;
+static int tuple_compare_string(const Tuple & a, const Tuple & b,
+ Tuple::Field field)
+{
+ String string_a = a.get_str(field);
+ String string_b = b.get_str(field);
- return (! string_b) ? 1 : str_compare (string_a, string_b);
+ if (!string_a)
+ return (!string_b) ? 0 : -1;
+
+ return (!string_b) ? 1 : str_compare(string_a, string_b);
}
-static int tuple_compare_int (const Tuple & a, const Tuple & b, Tuple::Field field)
+static int tuple_compare_int(const Tuple & a, const Tuple & b,
+ Tuple::Field field)
{
- if (a.get_value_type (field) != Tuple::Int)
- return (b.get_value_type (field) != Tuple::Int) ? 0 : -1;
- if (b.get_value_type (field) != Tuple::Int)
+ if (a.get_value_type(field) != Tuple::Int)
+ return (b.get_value_type(field) != Tuple::Int) ? 0 : -1;
+ if (b.get_value_type(field) != Tuple::Int)
return 1;
- int int_a = a.get_int (field);
- int int_b = b.get_int (field);
+ int int_a = a.get_int(field);
+ int int_b = b.get_int(field);
return (int_a < int_b) ? -1 : (int_a > int_b);
}
-static int tuple_compare_title (const Tuple & a, const Tuple & b)
- { return tuple_compare_string (a, b, Tuple::Title); }
-static int tuple_compare_album (const Tuple & a, const Tuple & b)
- { return tuple_compare_string (a, b, Tuple::Album); }
-static int tuple_compare_artist (const Tuple & a, const Tuple & b)
- { return tuple_compare_string (a, b, Tuple::Artist); }
-static int tuple_compare_album_artist (const Tuple & a, const Tuple & b)
- { return tuple_compare_string (a, b, Tuple::AlbumArtist); }
-static int tuple_compare_date (const Tuple & a, const Tuple & b)
- { return tuple_compare_int (a, b, Tuple::Year); }
-static int tuple_compare_genre (const Tuple & a, const Tuple & b)
- { return tuple_compare_string (a, b, Tuple::Genre); }
-static int tuple_compare_track (const Tuple & a, const Tuple & b)
- { return tuple_compare_int (a, b, Tuple::Track); }
-static int tuple_compare_formatted_title (const Tuple & a, const Tuple & b)
- { return tuple_compare_string (a, b, Tuple::FormattedTitle); }
-static int tuple_compare_length (const Tuple & a, const Tuple & b)
- { return tuple_compare_int (a, b, Tuple::Length); }
-static int tuple_compare_comment (const Tuple & a, const Tuple & b)
- { return tuple_compare_string (a, b, Tuple::Comment); }
+static int tuple_compare_title(const Tuple & a, const Tuple & b)
+{
+ return tuple_compare_string(a, b, Tuple::Title);
+}
+static int tuple_compare_album(const Tuple & a, const Tuple & b)
+{
+ return tuple_compare_string(a, b, Tuple::Album);
+}
+static int tuple_compare_artist(const Tuple & a, const Tuple & b)
+{
+ return tuple_compare_string(a, b, Tuple::Artist);
+}
+static int tuple_compare_album_artist(const Tuple & a, const Tuple & b)
+{
+ return tuple_compare_string(a, b, Tuple::AlbumArtist);
+}
+static int tuple_compare_date(const Tuple & a, const Tuple & b)
+{
+ return tuple_compare_int(a, b, Tuple::Year);
+}
+static int tuple_compare_genre(const Tuple & a, const Tuple & b)
+{
+ return tuple_compare_string(a, b, Tuple::Genre);
+}
+static int tuple_compare_track(const Tuple & a, const Tuple & b)
+{
+ return tuple_compare_int(a, b, Tuple::Track);
+}
+static int tuple_compare_formatted_title(const Tuple & a, const Tuple & b)
+{
+ return tuple_compare_string(a, b, Tuple::FormattedTitle);
+}
+static int tuple_compare_length(const Tuple & a, const Tuple & b)
+{
+ return tuple_compare_int(a, b, Tuple::Length);
+}
+static int tuple_compare_comment(const Tuple & a, const Tuple & b)
+{
+ return tuple_compare_string(a, b, Tuple::Comment);
+}
static const Playlist::StringCompareFunc filename_comparisons[] = {
- str_compare_encoded, // path
- filename_compare_basename, // filename
- nullptr, // title
- nullptr, // album
- nullptr, // artist
- nullptr, // album artist
- nullptr, // date
- nullptr, // genre
- nullptr, // track
- nullptr, // formatted title
- nullptr, // length
- nullptr // comment
+ filename_compare_path, // path
+ filename_compare_basename, // filename
+ nullptr, // title
+ nullptr, // album
+ nullptr, // artist
+ nullptr, // album artist
+ nullptr, // date
+ nullptr, // genre
+ nullptr, // track
+ nullptr, // formatted title
+ nullptr, // length
+ nullptr // comment
};
static const Playlist::TupleCompareFunc tuple_comparisons[] = {
- nullptr, // path
- nullptr, // filename
+ nullptr, // path
+ nullptr, // filename
tuple_compare_title,
tuple_compare_album,
tuple_compare_artist,
@@ -114,51 +149,50 @@ static const Playlist::TupleCompareFunc tuple_comparisons[] = {
tuple_compare_track,
tuple_compare_formatted_title,
tuple_compare_length,
- tuple_compare_comment
-};
+ tuple_compare_comment};
-static_assert (aud::n_elems (filename_comparisons) == Playlist::n_sort_types &&
- aud::n_elems (tuple_comparisons) == Playlist::n_sort_types,
- "Update playlist comparison functions");
+static_assert(aud::n_elems(filename_comparisons) == Playlist::n_sort_types &&
+ aud::n_elems(tuple_comparisons) == Playlist::n_sort_types,
+ "Update playlist comparison functions");
-EXPORT void Playlist::sort_entries (SortType scheme) const
+EXPORT void Playlist::sort_entries(SortType scheme) const
{
if (filename_comparisons[scheme])
- sort_by_filename (filename_comparisons[scheme]);
+ sort_by_filename(filename_comparisons[scheme]);
else if (tuple_comparisons[scheme])
- sort_by_tuple (tuple_comparisons[scheme]);
+ sort_by_tuple(tuple_comparisons[scheme]);
}
-EXPORT void Playlist::sort_selected (SortType scheme) const
+EXPORT void Playlist::sort_selected(SortType scheme) const
{
if (filename_comparisons[scheme])
- sort_selected_by_filename (filename_comparisons[scheme]);
+ sort_selected_by_filename(filename_comparisons[scheme]);
else if (tuple_comparisons[scheme])
- sort_selected_by_tuple (tuple_comparisons[scheme]);
+ sort_selected_by_tuple(tuple_comparisons[scheme]);
}
/* FIXME: this considers empty fields as duplicates */
-EXPORT void Playlist::remove_duplicates (SortType scheme) const
+EXPORT void Playlist::remove_duplicates(SortType scheme) const
{
- int entries = n_entries ();
+ int entries = n_entries();
if (entries < 1)
return;
- select_all (false);
+ select_all(false);
if (filename_comparisons[scheme])
{
StringCompareFunc compare = filename_comparisons[scheme];
- sort_by_filename (compare);
- String last = entry_filename (0);
+ sort_by_filename(compare);
+ String last = entry_filename(0);
- for (int i = 1; i < entries; i ++)
+ for (int i = 1; i < entries; i++)
{
- String current = entry_filename (i);
+ String current = entry_filename(i);
- if (compare (last, current) == 0)
- select_entry (i, true);
+ if (compare(last, current) == 0)
+ select_entry(i, true);
last = current;
}
@@ -167,227 +201,232 @@ EXPORT void Playlist::remove_duplicates (SortType scheme) const
{
TupleCompareFunc compare = tuple_comparisons[scheme];
- sort_by_tuple (compare);
- Tuple last = entry_tuple (0);
+ sort_by_tuple(compare);
+ Tuple last = entry_tuple(0);
- for (int i = 1; i < entries; i ++)
+ for (int i = 1; i < entries; i++)
{
- Tuple current = entry_tuple (i);
+ Tuple current = entry_tuple(i);
- if (last.valid () && current.valid () && compare (last, current) == 0)
- select_entry (i, true);
+ if (last.valid() && current.valid() && compare(last, current) == 0)
+ select_entry(i, true);
- last = std::move (current);
+ last = std::move(current);
}
}
- remove_selected ();
+ remove_selected();
}
-EXPORT void Playlist::remove_unavailable () const
+EXPORT void Playlist::remove_unavailable() const
{
- int entries = n_entries ();
+ int entries = n_entries();
- select_all (false);
+ select_all(false);
- for (int i = 0; i < entries; i ++)
+ for (int i = 0; i < entries; i++)
{
- String filename = entry_filename (i);
+ String filename = entry_filename(i);
/* use VFS_NO_ACCESS since VFS_EXISTS doesn't distinguish between
* inaccessible files and URI schemes that don't support file_test() */
- if (VFSFile::test_file (filename, VFS_NO_ACCESS))
- select_entry (i, true);
+ if (VFSFile::test_file(filename, VFS_NO_ACCESS))
+ select_entry(i, true);
}
- remove_selected ();
+ remove_selected();
}
-EXPORT void Playlist::select_by_patterns (const Tuple & patterns) const
+EXPORT void Playlist::select_by_patterns(const Tuple & patterns) const
{
- int entries = n_entries ();
+ int entries = n_entries();
- select_all (true);
+ select_all(true);
- for (Tuple::Field field : {Tuple::Title, Tuple::Album, Tuple::Artist, Tuple::Basename})
+ for (Tuple::Field field :
+ {Tuple::Title, Tuple::Album, Tuple::Artist, Tuple::Basename})
{
- String pattern = patterns.get_str (field);
+ String pattern = patterns.get_str(field);
GRegex * regex;
- if (! pattern || ! pattern[0] || ! (regex = g_regex_new (pattern,
- G_REGEX_CASELESS, (GRegexMatchFlags) 0, nullptr)))
+ if (!pattern || !pattern[0] ||
+ !(regex = g_regex_new(pattern, G_REGEX_CASELESS,
+ (GRegexMatchFlags)0, nullptr)))
continue;
- for (int i = 0; i < entries; i ++)
+ for (int i = 0; i < entries; i++)
{
- if (! entry_selected (i))
+ if (!entry_selected(i))
continue;
- Tuple tuple = entry_tuple (i);
- String string = tuple.get_str (field);
+ Tuple tuple = entry_tuple(i);
+ String string = tuple.get_str(field);
- if (! string || ! g_regex_match (regex, string, (GRegexMatchFlags) 0, nullptr))
- select_entry (i, false);
+ if (!string ||
+ !g_regex_match(regex, string, (GRegexMatchFlags)0, nullptr))
+ select_entry(i, false);
}
- g_regex_unref (regex);
+ g_regex_unref(regex);
}
}
-static StringBuf make_playlist_path (int playlist)
+static StringBuf make_playlist_path(int playlist)
{
- if (! playlist)
- return filename_build ({aud_get_path (AudPath::UserDir), "playlist.xspf"});
+ if (!playlist)
+ return filename_build(
+ {aud_get_path(AudPath::UserDir), "playlist.xspf"});
- return filename_build ({aud_get_path (AudPath::UserDir),
- str_printf ("playlist_%02d.xspf", 1 + playlist)});
+ return filename_build({aud_get_path(AudPath::UserDir),
+ str_printf("playlist_%02d.xspf", 1 + playlist)});
}
-static void load_playlists_real ()
+static void load_playlists_real()
{
- const char * folder = aud_get_path (AudPath::PlaylistDir);
+ const char * folder = aud_get_path(AudPath::PlaylistDir);
/* old (v3.1 and earlier) naming scheme */
int count;
- for (count = 0; ; count ++)
+ for (count = 0;; count++)
{
- StringBuf path = make_playlist_path (count);
- if (! g_file_test (path, G_FILE_TEST_EXISTS))
+ StringBuf path = make_playlist_path(count);
+ if (!g_file_test(path, G_FILE_TEST_EXISTS))
break;
- PlaylistEx playlist = Playlist::insert_playlist (count);
- playlist.insert_flat_playlist (filename_to_uri (path));
- playlist.set_modified (true);
+ PlaylistEx playlist = Playlist::insert_playlist(count);
+ playlist.insert_flat_playlist(filename_to_uri(path));
+ playlist.set_modified(true);
}
/* unique ID-based naming scheme */
- StringBuf order_path = filename_build ({folder, "order"});
- auto order_string = VFSFile::read_file (order_path,
- VFSReadOptions (VFS_APPEND_NULL | VFS_IGNORE_MISSING));
- auto order = str_list_to_index (order_string.begin (), " ");
+ StringBuf order_path = filename_build({folder, "order"});
+ auto order_string = VFSFile::read_file(
+ order_path, VFSReadOptions(VFS_APPEND_NULL | VFS_IGNORE_MISSING));
+ auto order = str_list_to_index(order_string.begin(), " ");
- for (int i = 0; i < order.len (); i ++)
+ for (int i = 0; i < order.len(); i++)
{
const char * number = order[i];
- StringBuf path = filename_build ({folder, str_concat ({number, ".audpl"})});
- if (! g_file_test (path, G_FILE_TEST_EXISTS))
- path = filename_build ({folder, str_concat ({number, ".xspf"})});
+ StringBuf path =
+ filename_build({folder, str_concat({number, ".audpl"})});
+ if (!g_file_test(path, G_FILE_TEST_EXISTS))
+ path = filename_build({folder, str_concat({number, ".xspf"})});
- PlaylistEx playlist = PlaylistEx::insert_with_stamp (count + i, atoi (number));
- playlist.insert_flat_playlist (filename_to_uri (path));
- playlist.set_modified (g_str_has_suffix (path, ".xspf"));
+ PlaylistEx playlist =
+ PlaylistEx::insert_with_stamp(count + i, atoi(number));
+ playlist.insert_flat_playlist(filename_to_uri(path));
+ playlist.set_modified(g_str_has_suffix(path, ".xspf"));
}
- if (! Playlist::n_playlists ())
- Playlist::insert_playlist (0);
+ if (!Playlist::n_playlists())
+ Playlist::insert_playlist(0);
}
-static void save_playlists_real ()
+static void save_playlists_real()
{
- int lists = Playlist::n_playlists ();
- const char * folder = aud_get_path (AudPath::PlaylistDir);
+ int lists = Playlist::n_playlists();
+ const char * folder = aud_get_path(AudPath::PlaylistDir);
/* save playlists */
Index<String> order;
SimpleHash<String, bool> saved;
- for (int i = 0; i < lists; i ++)
+ for (int i = 0; i < lists; i++)
{
- PlaylistEx playlist = Playlist::by_index (i);
- StringBuf number = int_to_str (playlist.stamp ());
- StringBuf name = str_concat ({number, ".audpl"});
+ PlaylistEx playlist = Playlist::by_index(i);
+ StringBuf number = int_to_str(playlist.stamp());
+ StringBuf name = str_concat({number, ".audpl"});
- if (playlist.get_modified ())
+ if (playlist.get_modified())
{
- StringBuf path = filename_build ({folder, name});
- playlist.save_to_file (filename_to_uri (path), Playlist::NoWait);
- playlist.set_modified (false);
+ StringBuf path = filename_build({folder, name});
+ playlist.save_to_file(filename_to_uri(path), Playlist::NoWait);
+ playlist.set_modified(false);
}
- order.append (String (number));
- saved.add (String (name), true);
+ order.append(String(number));
+ saved.add(String(name), true);
}
- StringBuf order_string = index_to_str_list (order, " ");
- StringBuf order_path = filename_build ({folder, "order"});
- auto old_order_string = VFSFile::read_file (order_path,
- VFSReadOptions (VFS_APPEND_NULL | VFS_IGNORE_MISSING));
+ StringBuf order_string = index_to_str_list(order, " ");
+ StringBuf order_path = filename_build({folder, "order"});
+ auto old_order_string = VFSFile::read_file(
+ order_path, VFSReadOptions(VFS_APPEND_NULL | VFS_IGNORE_MISSING));
- if (strcmp (old_order_string.begin (), order_string))
- VFSFile::write_file (order_path, (const char *) order_string, order_string.len ());
+ if (strcmp(old_order_string.begin(), order_string))
+ VFSFile::write_file(order_path, (const char *)order_string,
+ order_string.len());
/* clean up deleted playlists and files from old naming scheme */
- g_unlink (make_playlist_path (0));
+ g_unlink(make_playlist_path(0));
- GDir * dir = g_dir_open (folder, 0, nullptr);
- if (! dir)
+ GDir * dir = g_dir_open(folder, 0, nullptr);
+ if (!dir)
return;
const char * name;
- while ((name = g_dir_read_name (dir)))
+ while ((name = g_dir_read_name(dir)))
{
- if (! g_str_has_suffix (name, ".audpl") && ! g_str_has_suffix (name, ".xspf"))
+ if (!g_str_has_suffix(name, ".audpl") &&
+ !g_str_has_suffix(name, ".xspf"))
continue;
- if (! saved.lookup (String (name)))
- g_unlink (filename_build ({folder, name}));
+ if (!saved.lookup(String(name)))
+ g_unlink(filename_build({folder, name}));
}
- g_dir_close (dir);
+ g_dir_close(dir);
}
static bool hooks_added, state_changed;
-static void update_cb (void * data, void *)
+static void update_cb(void * data, void *)
{
- auto level = aud::from_ptr<Playlist::UpdateLevel> (data);
+ auto level = aud::from_ptr<Playlist::UpdateLevel>(data);
if (level >= Playlist::Metadata)
state_changed = true;
}
-static void state_cb (void * data, void * user)
-{
- state_changed = true;
-}
+static void state_cb(void * data, void * user) { state_changed = true; }
-void load_playlists ()
+void load_playlists()
{
- load_playlists_real ();
- playlist_load_state ();
+ load_playlists_real();
+ playlist_load_state();
state_changed = false;
- if (! hooks_added)
+ if (!hooks_added)
{
- hook_associate ("playlist update", update_cb, nullptr);
- hook_associate ("playlist activate", state_cb, nullptr);
- hook_associate ("playlist position", state_cb, nullptr);
+ hook_associate("playlist update", update_cb, nullptr);
+ hook_associate("playlist activate", state_cb, nullptr);
+ hook_associate("playlist position", state_cb, nullptr);
hooks_added = true;
}
}
-void save_playlists (bool exiting)
+void save_playlists(bool exiting)
{
- save_playlists_real ();
+ save_playlists_real();
/* on exit, save resume states */
if (state_changed || exiting)
{
- playlist_save_state ();
+ playlist_save_state();
state_changed = false;
}
if (exiting && hooks_added)
{
- hook_dissociate ("playlist update", update_cb);
- hook_dissociate ("playlist activate", state_cb);
- hook_dissociate ("playlist position", state_cb);
+ hook_dissociate("playlist update", update_cb);
+ hook_dissociate("playlist activate", state_cb);
+ hook_dissociate("playlist position", state_cb);
hooks_added = false;
}
diff --git a/src/libaudcore/playlist.cc b/src/libaudcore/playlist.cc
index 6b64808..d7543c9 100644
--- a/src/libaudcore/playlist.cc
+++ b/src/libaudcore/playlist.cc
@@ -20,7 +20,6 @@
#include "playlist-internal.h"
#include <assert.h>
-#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -38,22 +37,26 @@
#include "parse.h"
#include "playlist-data.h"
#include "runtime.h"
+#include "threads.h"
-enum {
+enum
+{
ResumeStop,
ResumePlay,
ResumePause
};
/* update hooks */
-enum {
- SetActive = (1 << 0),
- SetPlaying = (1 << 1),
+enum
+{
+ SetActive = (1 << 0),
+ SetPlaying = (1 << 1),
PlaybackBegin = (1 << 2),
- PlaybackStop = (1 << 3)
+ PlaybackStop = (1 << 3)
};
-enum class UpdateState {
+enum class UpdateState
+{
None,
Delayed,
Queued
@@ -61,35 +64,25 @@ enum class UpdateState {
#define STATE_FILE "playlist-state"
-#define ENTER pthread_mutex_lock (& mutex)
-#define LEAVE pthread_mutex_unlock (& mutex)
-
-#define RETURN(...) do { \
- pthread_mutex_unlock (& mutex); \
- return __VA_ARGS__; \
-} while (0)
+#define ENTER_GET_PLAYLIST(...) \
+ auto mh = mutex.take(); \
+ PlaylistData * playlist = m_id ? m_id->data : nullptr; \
+ if (!playlist) \
+ return __VA_ARGS__
-#define ENTER_GET_PLAYLIST(...) \
- ENTER; \
- PlaylistData * playlist = m_id ? m_id->data : nullptr; \
- if (! playlist) \
- RETURN (__VA_ARGS__)
+#define SIMPLE_WRAPPER(type, failcode, func, ...) \
+ ENTER_GET_PLAYLIST(failcode); \
+ return playlist->func(__VA_ARGS__)
-#define SIMPLE_WRAPPER(type, failcode, func, ...) \
- ENTER_GET_PLAYLIST (failcode); \
- type retval = playlist->func (__VA_ARGS__); \
- RETURN (retval)
-
-#define SIMPLE_VOID_WRAPPER(func, ...) \
- ENTER_GET_PLAYLIST (); \
- playlist->func (__VA_ARGS__); \
- LEAVE
+#define SIMPLE_VOID_WRAPPER(func, ...) \
+ ENTER_GET_PLAYLIST(); \
+ playlist->func(__VA_ARGS__)
static const char * const default_title = N_("New Playlist");
static const char * const temp_title = N_("Now Playing");
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static aud::mutex mutex;
+static aud::condvar condvar;
/*
* Each playlist is associated with its own ID struct, which contains a unique
@@ -106,9 +99,9 @@ static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
*/
struct Playlist::ID
{
- int stamp; // integer stamp, determines filename
- int index; // display order
- PlaylistData * data; // pointer to actual playlist data
+ int stamp; // integer stamp, determines filename
+ int index; // display order
+ PlaylistData * data; // pointer to actual playlist data
};
static SimpleHash<IntHashKey, Playlist::ID> id_table;
@@ -127,13 +120,12 @@ static UpdateState update_state;
struct ScanItem : public ListNode
{
- ScanItem (PlaylistData * playlist, PlaylistEntry * entry,
- ScanRequest * request, bool for_playback) :
- playlist (playlist),
- entry (entry),
- request (request),
- for_playback (for_playback),
- handled_by_playback (false) {}
+ ScanItem(PlaylistData * playlist, PlaylistEntry * entry,
+ ScanRequest * request, bool for_playback)
+ : playlist(playlist), entry(entry), request(request),
+ for_playback(for_playback), handled_by_playback(false)
+ {
+ }
PlaylistData * playlist;
PlaylistEntry * entry;
@@ -146,39 +138,39 @@ static bool scan_enabled_nominal, scan_enabled;
static int scan_playlist, scan_row;
static List<ScanItem> scan_list;
-static void scan_finish (ScanRequest * request);
-static void scan_cancel (PlaylistEntry * entry);
-static void scan_restart ();
+static void scan_finish(ScanRequest * request);
+static void scan_cancel(PlaylistEntry * entry);
+static void scan_restart();
/* creates a new playlist with the requested stamp (if not already in use) */
-static Playlist::ID * create_playlist (int stamp)
+static Playlist::ID * create_playlist(int stamp)
{
Playlist::ID * id;
- if (stamp >= 0 && ! id_table.lookup (stamp))
- id = id_table.add (stamp, {stamp, -1, nullptr});
+ if (stamp >= 0 && !id_table.lookup(stamp))
+ id = id_table.add(stamp, {stamp, -1, nullptr});
else
{
- while (id_table.lookup (next_stamp))
- next_stamp ++;
+ while (id_table.lookup(next_stamp))
+ next_stamp++;
- id = id_table.add (next_stamp, {next_stamp, -1, nullptr});
+ id = id_table.add(next_stamp, {next_stamp, -1, nullptr});
}
- id->data = new PlaylistData (id, _(default_title));
+ id->data = new PlaylistData(id, _(default_title));
return id;
}
-static void number_playlists (int at, int length)
+static void number_playlists(int at, int length)
{
- for (int i = at; i < at + length; i ++)
- playlists[i]->id ()->index = i;
+ for (int i = at; i < at + length; i++)
+ playlists[i]->id()->index = i;
}
-static void update (void *)
+static void update(void *)
{
- ENTER;
+ auto mh = mutex.take();
int hooks = update_hooks;
auto level = update_level;
@@ -188,35 +180,35 @@ static void update (void *)
for (auto & p : playlists)
{
bool position_changed = false;
- p->swap_updates (position_changed);
+ p->swap_updates(position_changed);
if (position_changed)
- position_change_list.append (p->id ());
+ position_change_list.append(p->id());
}
update_hooks = 0;
update_level = Playlist::NoUpdate;
update_state = UpdateState::None;
- LEAVE;
+ mh.unlock();
if (level != Playlist::NoUpdate)
- hook_call ("playlist update", aud::to_ptr (level));
+ hook_call("playlist update", aud::to_ptr(level));
for (PlaylistEx playlist : position_change_list)
- hook_call ("playlist position", aud::to_ptr (playlist));
+ hook_call("playlist position", aud::to_ptr(playlist));
if ((hooks & SetActive))
- hook_call ("playlist activate", nullptr);
+ hook_call("playlist activate", nullptr);
if ((hooks & SetPlaying))
- hook_call ("playlist set playing", nullptr);
+ hook_call("playlist set playing", nullptr);
if ((hooks & PlaybackBegin))
- hook_call ("playback begin", nullptr);
+ hook_call("playback begin", nullptr);
if ((hooks & PlaybackStop))
- hook_call ("playback stop", nullptr);
+ hook_call("playback stop", nullptr);
}
-static void queue_update_hooks (int hooks)
+static void queue_update_hooks(int hooks)
{
if ((hooks & PlaybackBegin))
update_hooks &= ~PlaybackStop;
@@ -227,21 +219,21 @@ static void queue_update_hooks (int hooks)
if (update_state < UpdateState::Queued)
{
- queued_update.queue (update, nullptr);
+ queued_update.queue(update, nullptr);
update_state = UpdateState::Queued;
}
}
-static void queue_global_update (Playlist::UpdateLevel level, int flags = 0)
+static void queue_global_update(Playlist::UpdateLevel level, int flags = 0)
{
if (level == Playlist::Structure)
- scan_restart ();
+ scan_restart();
if ((flags & PlaylistData::DelayedUpdate))
{
if (update_state < UpdateState::Delayed)
{
- queued_update.queue (250, update, nullptr);
+ queued_update.queue(250, update, nullptr);
update_state = UpdateState::Delayed;
}
}
@@ -249,291 +241,286 @@ static void queue_global_update (Playlist::UpdateLevel level, int flags = 0)
{
if (update_state < UpdateState::Queued)
{
- queued_update.queue (update, nullptr);
+ queued_update.queue(update, nullptr);
update_state = UpdateState::Queued;
}
}
- update_level = aud::max (update_level, level);
+ update_level = aud::max(update_level, level);
}
-EXPORT bool Playlist::update_pending_any ()
+EXPORT bool Playlist::update_pending_any()
{
- ENTER;
- bool pending = (update_level != Playlist::NoUpdate);
- RETURN (pending);
+ auto mh = mutex.take();
+ return (update_level != Playlist::NoUpdate);
}
-EXPORT void Playlist::process_pending_update ()
-{
- update (nullptr);
-}
+EXPORT void Playlist::process_pending_update() { update(nullptr); }
-EXPORT bool Playlist::scan_in_progress () const
+EXPORT bool Playlist::scan_in_progress() const
{
- ENTER_GET_PLAYLIST (false);
- bool scanning = (playlist->scan_status != PlaylistData::NotScanning);
- RETURN (scanning);
+ ENTER_GET_PLAYLIST(false);
+ return (playlist->scan_status != PlaylistData::NotScanning);
}
-EXPORT bool Playlist::scan_in_progress_any ()
+EXPORT bool Playlist::scan_in_progress_any()
{
- ENTER;
+ auto mh = mutex.take();
- bool scanning = false;
for (auto & p : playlists)
{
if (p->scan_status != PlaylistData::NotScanning)
- scanning = true;
+ return true;
}
- RETURN (scanning);
+ return false;
}
-static ScanItem * scan_list_find_entry (PlaylistEntry * entry)
+static ScanItem * scan_list_find_entry(PlaylistEntry * entry)
{
- auto match = [entry] (const ScanItem & item)
- { return item.entry == entry; };
+ auto match = [entry](const ScanItem & item) { return item.entry == entry; };
- return scan_list.find (match);
+ return scan_list.find(match);
}
-static void scan_queue_entry (PlaylistData * playlist, PlaylistEntry * entry, bool for_playback = false)
+static void scan_queue_entry(PlaylistData * playlist, PlaylistEntry * entry,
+ bool for_playback = false)
{
int extra_flags = for_playback ? (SCAN_IMAGE | SCAN_FILE) : 0;
- auto request = playlist->create_scan_request (entry, scan_finish, extra_flags);
+ auto request =
+ playlist->create_scan_request(entry, scan_finish, extra_flags);
- scan_list.append (new ScanItem (playlist, entry, request, for_playback));
+ scan_list.append(new ScanItem(playlist, entry, request, for_playback));
/* playback entry will be scanned by the playback thread */
- if (! for_playback)
- scanner_request (request);
+ if (!for_playback)
+ scanner_request(request);
}
-static void scan_reset_playback ()
+static void scan_reset_playback()
{
- auto match = [] (const ScanItem & item)
- { return item.for_playback; };
+ auto match = [](const ScanItem & item) { return item.for_playback; };
- ScanItem * item = scan_list.find (match);
- if (! item)
+ ScanItem * item = scan_list.find(match);
+ if (!item)
return;
item->for_playback = false;
/* if playback was canceled before the entry was scanned, requeue it */
- if (! item->handled_by_playback)
- scanner_request (item->request);
+ if (!item->handled_by_playback)
+ scanner_request(item->request);
}
-static void scan_check_complete (PlaylistData * playlist)
+static void scan_check_complete(PlaylistData * playlist)
{
- auto match = [playlist] (const ScanItem & item)
- { return item.playlist == playlist; };
+ auto match = [playlist](const ScanItem & item) {
+ return item.playlist == playlist;
+ };
- if (playlist->scan_status != PlaylistData::ScanEnding || scan_list.find (match))
+ if (playlist->scan_status != PlaylistData::ScanEnding ||
+ scan_list.find(match))
return;
playlist->scan_status = PlaylistData::NotScanning;
if (update_state == UpdateState::Delayed)
{
- queued_update.queue (update, nullptr);
+ queued_update.queue(update, nullptr);
update_state = UpdateState::Queued;
}
- event_queue_cancel ("playlist scan complete");
- event_queue ("playlist scan complete", nullptr);
+ event_queue_cancel("playlist scan complete");
+ event_queue("playlist scan complete", nullptr);
}
-static bool scan_queue_next_entry ()
+static bool scan_queue_next_entry()
{
- if (! scan_enabled)
+ if (!scan_enabled)
return false;
- while (scan_playlist < playlists.len ())
+ while (scan_playlist < playlists.len())
{
- PlaylistData * playlist = playlists[scan_playlist].get ();
+ PlaylistData * playlist = playlists[scan_playlist].get();
if (playlist->scan_status == PlaylistData::ScanActive)
{
while (1)
{
- scan_row = playlist->next_unscanned_entry (scan_row);
+ scan_row = playlist->next_unscanned_entry(scan_row);
if (scan_row < 0)
break;
- auto entry = playlist->entry_at (scan_row);
- if (! scan_list_find_entry (entry))
+ auto entry = playlist->entry_at(scan_row);
+ if (!scan_list_find_entry(entry))
{
- scan_queue_entry (playlist, entry);
+ scan_queue_entry(playlist, entry);
return true;
}
- scan_row ++;
+ scan_row++;
}
playlist->scan_status = PlaylistData::ScanEnding;
- scan_check_complete (playlist);
+ scan_check_complete(playlist);
}
- scan_playlist ++;
+ scan_playlist++;
scan_row = 0;
}
return false;
}
-static void scan_schedule ()
+static void scan_schedule()
{
int scheduled = 0;
- for (ScanItem * item = scan_list.head (); item; item = scan_list.next (item))
+ for (ScanItem * item = scan_list.head(); item; item = scan_list.next(item))
{
- if (++ scheduled >= SCAN_THREADS)
+ if (++scheduled >= SCAN_THREADS)
return;
}
- while (scan_queue_next_entry ())
+ while (scan_queue_next_entry())
{
- if (++ scheduled >= SCAN_THREADS)
+ if (++scheduled >= SCAN_THREADS)
return;
}
}
-static void scan_finish (ScanRequest * request)
+static void scan_finish(ScanRequest * request)
{
- ENTER;
+ auto mh = mutex.take();
- auto match = [request] (const ScanItem & item)
- { return item.request == request; };
+ auto match = [request](const ScanItem & item) {
+ return item.request == request;
+ };
- ScanItem * item = scan_list.find (match);
- if (! item)
- RETURN ();
+ ScanItem * item = scan_list.find(match);
+ if (!item)
+ return;
PlaylistData * playlist = item->playlist;
PlaylistEntry * entry = item->entry;
- scan_list.remove (item);
+ scan_list.remove(item);
// only use delayed update if a scan is still in progress
int update_flags = 0;
if (scan_enabled && playlist->scan_status != PlaylistData::NotScanning)
update_flags = PlaylistData::DelayedUpdate;
- playlist->update_entry_from_scan (entry, request, update_flags);
+ playlist->update_entry_from_scan(entry, request, update_flags);
delete item;
- scan_check_complete (playlist);
- scan_schedule ();
+ scan_check_complete(playlist);
+ scan_schedule();
- pthread_cond_broadcast (& cond);
-
- LEAVE;
+ condvar.notify_all();
}
-static void scan_cancel (PlaylistEntry * entry)
+static void scan_cancel(PlaylistEntry * entry)
{
- ScanItem * item = scan_list_find_entry (entry);
- if (! item)
+ ScanItem * item = scan_list_find_entry(entry);
+ if (!item)
return;
- scan_list.remove (item);
+ scan_list.remove(item);
delete (item);
}
-static void scan_restart ()
+static void scan_restart()
{
scan_playlist = 0;
scan_row = 0;
- scan_schedule ();
+ scan_schedule();
}
/* mutex may be unlocked during the call */
-static void wait_for_entry (PlaylistData * playlist, int entry_num, bool need_decoder, bool need_tuple)
+static void wait_for_entry(aud::mutex::holder & mh, PlaylistData * playlist,
+ int entry_num, bool need_decoder, bool need_tuple)
{
bool scan_started = false;
while (1)
{
- PlaylistEntry * entry = playlist->entry_at (entry_num);
+ PlaylistEntry * entry = playlist->entry_at(entry_num);
// check whether entry is deleted or has already been scanned
- if (! entry || ! playlist->entry_needs_rescan (entry, need_decoder, need_tuple))
+ if (!entry ||
+ !playlist->entry_needs_rescan(entry, need_decoder, need_tuple))
return;
// start scan if not already running ...
- if (! scan_list_find_entry (entry))
+ if (!scan_list_find_entry(entry))
{
// ... but only once
if (scan_started)
return;
- scan_queue_entry (playlist, entry);
+ scan_queue_entry(playlist, entry);
}
// wait for scan to finish
scan_started = true;
- pthread_cond_wait (& cond, & mutex);
+ condvar.wait(mh);
}
}
-static void start_playback_locked (int seek_time, bool pause)
+static void start_playback_locked(int seek_time, bool pause)
{
- art_clear_current ();
- scan_reset_playback ();
+ art_clear_current();
+ scan_reset_playback();
- playback_play (seek_time, pause);
+ playback_play(seek_time, pause);
auto playlist = playing_id->data;
- auto entry = playlist->entry_at (playlist->position ());
+ auto entry = playlist->entry_at(playlist->position());
// playback always begins with a rescan of the current entry in order to
// open the file, ensure a valid tuple, and read album art
- scan_cancel (entry);
- scan_queue_entry (playlist, entry, true);
+ scan_cancel(entry);
+ scan_queue_entry(playlist, entry, true);
}
-static void stop_playback_locked ()
+static void stop_playback_locked()
{
- art_clear_current ();
- scan_reset_playback ();
+ art_clear_current();
+ scan_reset_playback();
- playback_stop ();
+ playback_stop();
}
-void pl_signal_entry_deleted (PlaylistEntry * entry)
-{
- scan_cancel (entry);
-}
+void pl_signal_entry_deleted(PlaylistEntry * entry) { scan_cancel(entry); }
-void pl_signal_position_changed (Playlist::ID * id)
+void pl_signal_position_changed(Playlist::ID * id)
{
if (update_state < UpdateState::Queued)
{
- queued_update.queue (update, nullptr);
+ queued_update.queue(update, nullptr);
update_state = UpdateState::Queued;
}
if (id == playing_id)
{
- if (id->data->position () >= 0)
+ if (id->data->position() >= 0)
{
- start_playback_locked (0, aud_drct_get_paused ());
- queue_update_hooks (PlaybackBegin);
+ start_playback_locked(0, aud_drct_get_paused());
+ queue_update_hooks(PlaybackBegin);
}
else
{
playing_id = nullptr;
- stop_playback_locked ();
- queue_update_hooks (SetPlaying | PlaybackStop);
+ stop_playback_locked();
+ queue_update_hooks(SetPlaying | PlaybackStop);
}
}
}
-void pl_signal_update_queued (Playlist::ID * id, Playlist::UpdateLevel level, int flags)
+void pl_signal_update_queued(Playlist::ID * id, Playlist::UpdateLevel level,
+ int flags)
{
auto playlist = id->data;
@@ -542,56 +529,53 @@ void pl_signal_update_queued (Playlist::ID * id, Playlist::UpdateLevel level, in
if (level >= Playlist::Metadata)
{
- int pos = playlist->position ();
+ int pos = playlist->position();
if (id == playing_id && pos >= 0)
- playback_set_info (pos, playlist->entry_tuple (pos));
+ playback_set_info(pos, playlist->entry_tuple(pos));
playlist->modified = true;
}
- queue_global_update (level, flags);
+ queue_global_update(level, flags);
}
-void pl_signal_rescan_needed (Playlist::ID * id)
+void pl_signal_rescan_needed(Playlist::ID * id)
{
id->data->scan_status = PlaylistData::ScanActive;
- scan_restart ();
+ scan_restart();
}
-void pl_signal_playlist_deleted (Playlist::ID * id)
+void pl_signal_playlist_deleted(Playlist::ID * id)
{
/* break weak pointer link */
id->data = nullptr;
id->index = -1;
}
-static void pl_hook_reformat_titles (void *, void *)
+static void pl_hook_reformat_titles(void *, void *)
{
- ENTER;
+ auto mh = mutex.take();
- PlaylistData::update_formatter ();
+ PlaylistData::update_formatter();
for (auto & playlist : playlists)
- playlist->reformat_titles ();
-
- LEAVE;
+ playlist->reformat_titles();
}
-static void pl_hook_trigger_scan (void *, void *)
+static void pl_hook_trigger_scan(void *, void *)
{
- ENTER;
- scan_enabled = scan_enabled_nominal && ! aud_get_bool (nullptr, "metadata_on_play");
- scan_restart ();
- LEAVE;
+ auto mh = mutex.take();
+ scan_enabled = scan_enabled_nominal && !aud_get_bool("metadata_on_play");
+ scan_restart();
}
-void playlist_init ()
+void playlist_init()
{
- srand (time (nullptr));
+ srand(time(nullptr));
- ENTER;
+ auto mh = mutex.take();
- PlaylistData::update_formatter ();
+ PlaylistData::update_formatter();
update_level = Playlist::NoUpdate;
update_hooks = 0;
@@ -599,644 +583,693 @@ void playlist_init ()
scan_enabled = scan_enabled_nominal = false;
scan_playlist = scan_row = 0;
- LEAVE;
+ mh.unlock();
- hook_associate ("set generic_title_format", pl_hook_reformat_titles, nullptr);
- hook_associate ("set leading_zero", pl_hook_reformat_titles, nullptr);
- hook_associate ("set metadata_fallbacks", pl_hook_reformat_titles, nullptr);
- hook_associate ("set show_hours", pl_hook_reformat_titles, nullptr);
- hook_associate ("set show_numbers_in_pl", pl_hook_reformat_titles, nullptr);
- hook_associate ("set metadata_on_play", pl_hook_trigger_scan, nullptr);
+ hook_associate("set generic_title_format", pl_hook_reformat_titles,
+ nullptr);
+ hook_associate("set leading_zero", pl_hook_reformat_titles, nullptr);
+ hook_associate("set metadata_fallbacks", pl_hook_reformat_titles, nullptr);
+ hook_associate("set show_hours", pl_hook_reformat_titles, nullptr);
+ hook_associate("set show_numbers_in_pl", pl_hook_reformat_titles, nullptr);
+ hook_associate("set metadata_on_play", pl_hook_trigger_scan, nullptr);
}
-void playlist_enable_scan (bool enable)
+void playlist_enable_scan(bool enable)
{
- ENTER;
+ auto mh = mutex.take();
scan_enabled_nominal = enable;
- scan_enabled = scan_enabled_nominal && ! aud_get_bool (nullptr, "metadata_on_play");
- scan_restart ();
-
- LEAVE;
+ scan_enabled = scan_enabled_nominal && !aud_get_bool("metadata_on_play");
+ scan_restart();
}
-void playlist_clear_updates ()
+void playlist_clear_updates()
{
- ENTER;
+ auto mh = mutex.take();
/* clear updates queued during init sequence */
for (auto & playlist : playlists)
- playlist->cancel_updates ();
+ playlist->cancel_updates();
- queued_update.stop ();
+ queued_update.stop();
update_level = Playlist::NoUpdate;
update_hooks = 0;
update_state = UpdateState::None;
-
- LEAVE;
}
-void playlist_end ()
+void playlist_end()
{
- hook_dissociate ("set generic_title_format", pl_hook_reformat_titles);
- hook_dissociate ("set leading_zero", pl_hook_reformat_titles);
- hook_dissociate ("set metadata_fallbacks", pl_hook_reformat_titles);
- hook_dissociate ("set show_hours", pl_hook_reformat_titles);
- hook_dissociate ("set show_numbers_in_pl", pl_hook_reformat_titles);
- hook_dissociate ("set metadata_on_play", pl_hook_trigger_scan);
+ hook_dissociate("set generic_title_format", pl_hook_reformat_titles);
+ hook_dissociate("set leading_zero", pl_hook_reformat_titles);
+ hook_dissociate("set metadata_fallbacks", pl_hook_reformat_titles);
+ hook_dissociate("set show_hours", pl_hook_reformat_titles);
+ hook_dissociate("set show_numbers_in_pl", pl_hook_reformat_titles);
+ hook_dissociate("set metadata_on_play", pl_hook_trigger_scan);
- playlist_cache_clear ();
+ playlist_cache_clear();
- ENTER;
+ auto mh = mutex.take();
/* playback should already be stopped */
- assert (! playing_id);
- assert (! scan_list.head ());
+ assert(!playing_id);
+ assert(!scan_list.head());
- queued_update.stop ();
+ queued_update.stop();
active_id = nullptr;
resume_playlist = -1;
resume_paused = false;
- playlists.clear ();
- id_table.clear ();
-
- PlaylistData::cleanup_formatter ();
-
- LEAVE;
-}
-
-EXPORT int Playlist::n_entries () const
- { SIMPLE_WRAPPER (int, 0, n_entries); }
-EXPORT void Playlist::remove_entries (int at, int number) const
- { SIMPLE_VOID_WRAPPER (remove_entries, at, number); }
-EXPORT String Playlist::entry_filename (int entry_num) const
- { SIMPLE_WRAPPER (String, String (), entry_filename, entry_num); }
-
-EXPORT int Playlist::get_position () const
- { SIMPLE_WRAPPER (int, -1, position); }
-EXPORT void Playlist::set_position (int entry_num) const
- { SIMPLE_VOID_WRAPPER (set_position, entry_num); }
-EXPORT bool Playlist::prev_song () const
- { SIMPLE_WRAPPER (bool, false, prev_song); }
-EXPORT bool Playlist::next_song (bool repeat) const
- { SIMPLE_WRAPPER (bool, false, next_song, repeat); }
-EXPORT int Playlist::get_focus () const
- { SIMPLE_WRAPPER (int, -1, focus); }
-EXPORT void Playlist::set_focus (int entry_num) const
- { SIMPLE_VOID_WRAPPER (set_focus, entry_num); }
-EXPORT bool Playlist::entry_selected (int entry_num) const
- { SIMPLE_WRAPPER (bool, false, entry_selected, entry_num); }
-EXPORT void Playlist::select_entry (int entry_num, bool selected) const
- { SIMPLE_VOID_WRAPPER (select_entry, entry_num, selected); }
-EXPORT int Playlist::n_selected (int at, int number) const
- { SIMPLE_WRAPPER (int, 0, n_selected, at, number); }
-EXPORT void Playlist::select_all (bool selected) const
- { SIMPLE_VOID_WRAPPER (select_all, selected); }
-EXPORT int Playlist::shift_entries (int entry_num, int distance) const
- { SIMPLE_WRAPPER (int, 0, shift_entries, entry_num, distance); }
-EXPORT void Playlist::remove_selected () const
- { SIMPLE_VOID_WRAPPER (remove_selected); }
-
-EXPORT void Playlist::sort_by_filename (StringCompareFunc compare) const
- { SIMPLE_VOID_WRAPPER (sort, {compare, nullptr}); }
-EXPORT void Playlist::sort_by_tuple (TupleCompareFunc compare) const
- { SIMPLE_VOID_WRAPPER (sort, {nullptr, compare}); }
-EXPORT void Playlist::sort_selected_by_filename (StringCompareFunc compare) const
- { SIMPLE_VOID_WRAPPER (sort_selected, {compare, nullptr}); }
-EXPORT void Playlist::sort_selected_by_tuple (TupleCompareFunc compare) const
- { SIMPLE_VOID_WRAPPER (sort_selected, {nullptr, compare}); }
-EXPORT void Playlist::reverse_order () const
- { SIMPLE_VOID_WRAPPER (reverse_order); }
-EXPORT void Playlist::reverse_selected () const
- { SIMPLE_VOID_WRAPPER (reverse_selected); }
-EXPORT void Playlist::randomize_order () const
- { SIMPLE_VOID_WRAPPER (randomize_order); }
-EXPORT void Playlist::randomize_selected () const
- { SIMPLE_VOID_WRAPPER (randomize_selected); }
-
-EXPORT void Playlist::rescan_all () const
- { SIMPLE_VOID_WRAPPER (reset_tuples, false); }
-EXPORT void Playlist::rescan_selected () const
- { SIMPLE_VOID_WRAPPER (reset_tuples, true); }
-
-EXPORT int64_t Playlist::total_length_ms () const
- { SIMPLE_WRAPPER (int64_t, 0, total_length); }
-EXPORT int64_t Playlist::selected_length_ms () const
- { SIMPLE_WRAPPER (int64_t, 0, selected_length); }
-
-EXPORT int Playlist::n_queued () const
- { SIMPLE_WRAPPER (int, 0, n_queued); }
-EXPORT void Playlist::queue_insert (int at, int entry_num) const
- { SIMPLE_VOID_WRAPPER (queue_insert, at, entry_num); }
-EXPORT void Playlist::queue_insert_selected (int at) const
- { SIMPLE_VOID_WRAPPER (queue_insert_selected, at); }
-EXPORT int Playlist::queue_get_entry (int at) const
- { SIMPLE_WRAPPER (int, -1, queue_get_entry, at); }
-EXPORT int Playlist::queue_find_entry (int entry_num) const
- { SIMPLE_WRAPPER (int, -1, queue_find_entry, entry_num); }
-EXPORT void Playlist::queue_remove (int at, int number) const
- { SIMPLE_VOID_WRAPPER (queue_remove, at, number); }
-EXPORT void Playlist::queue_remove_selected () const
- { SIMPLE_VOID_WRAPPER (queue_remove_selected); }
-
-EXPORT bool Playlist::update_pending () const
- { SIMPLE_WRAPPER (bool, false, update_pending); }
-EXPORT Playlist::Update Playlist::update_detail () const
- { SIMPLE_WRAPPER (Update, Update (), last_update); }
-
-void PlaylistEx::insert_flat_items (int at, Index<PlaylistAddItem> && items) const
- { SIMPLE_VOID_WRAPPER (insert_items, at, std::move (items)); }
-
-EXPORT int Playlist::index () const
-{
- ENTER_GET_PLAYLIST (-1);
- int at = m_id->index;
- RETURN (at);
+ playlists.clear();
+ id_table.clear();
+
+ PlaylistData::cleanup_formatter();
}
-EXPORT int PlaylistEx::stamp () const
+EXPORT int Playlist::n_entries() const { SIMPLE_WRAPPER(int, 0, n_entries); }
+EXPORT void Playlist::remove_entries(int at, int number) const
+{
+ SIMPLE_VOID_WRAPPER(remove_entries, at, number);
+}
+EXPORT String Playlist::entry_filename(int entry_num) const
{
- ENTER_GET_PLAYLIST (-1);
- int stamp = m_id->stamp;
- RETURN (stamp);
+ SIMPLE_WRAPPER(String, String(), entry_filename, entry_num);
}
-EXPORT int Playlist::n_playlists ()
+EXPORT int Playlist::get_position() const { SIMPLE_WRAPPER(int, -1, position); }
+EXPORT void Playlist::set_position(int entry_num) const
+{
+ SIMPLE_VOID_WRAPPER(set_position, entry_num);
+}
+EXPORT bool Playlist::prev_song() const
+{
+ SIMPLE_WRAPPER(bool, false, prev_song);
+}
+EXPORT bool Playlist::prev_album() const
+{
+ SIMPLE_WRAPPER(bool, false, prev_album);
+}
+EXPORT bool Playlist::next_song(bool repeat) const
{
- ENTER;
- int count = playlists.len ();
- RETURN (count);
+ SIMPLE_WRAPPER(bool, false, next_song, repeat);
+}
+EXPORT bool Playlist::next_album(bool repeat) const
+{
+ SIMPLE_WRAPPER(bool, false, next_album, repeat);
+}
+EXPORT int Playlist::get_focus() const { SIMPLE_WRAPPER(int, -1, focus); }
+EXPORT void Playlist::set_focus(int entry_num) const
+{
+ SIMPLE_VOID_WRAPPER(set_focus, entry_num);
+}
+EXPORT bool Playlist::entry_selected(int entry_num) const
+{
+ SIMPLE_WRAPPER(bool, false, entry_selected, entry_num);
+}
+EXPORT void Playlist::select_entry(int entry_num, bool selected) const
+{
+ SIMPLE_VOID_WRAPPER(select_entry, entry_num, selected);
+}
+EXPORT int Playlist::n_selected(int at, int number) const
+{
+ SIMPLE_WRAPPER(int, 0, n_selected, at, number);
+}
+EXPORT void Playlist::select_all(bool selected) const
+{
+ SIMPLE_VOID_WRAPPER(select_all, selected);
+}
+EXPORT int Playlist::shift_entries(int entry_num, int distance) const
+{
+ SIMPLE_WRAPPER(int, 0, shift_entries, entry_num, distance);
+}
+EXPORT void Playlist::remove_selected() const
+{
+ SIMPLE_VOID_WRAPPER(remove_selected);
}
-EXPORT Playlist Playlist::by_index (int at)
+EXPORT void Playlist::sort_by_filename(StringCompareFunc compare) const
+{
+ SIMPLE_VOID_WRAPPER(sort, {compare, nullptr});
+}
+EXPORT void Playlist::sort_by_tuple(TupleCompareFunc compare) const
{
- ENTER;
- Playlist::ID * id = (at >= 0 && at < playlists.len ()) ? playlists[at]->id () : nullptr;
- RETURN (Playlist (id));
+ SIMPLE_VOID_WRAPPER(sort, {nullptr, compare});
+}
+EXPORT void Playlist::sort_selected_by_filename(StringCompareFunc compare) const
+{
+ SIMPLE_VOID_WRAPPER(sort_selected, {compare, nullptr});
+}
+EXPORT void Playlist::sort_selected_by_tuple(TupleCompareFunc compare) const
+{
+ SIMPLE_VOID_WRAPPER(sort_selected, {nullptr, compare});
+}
+EXPORT void Playlist::reverse_order() const
+{
+ SIMPLE_VOID_WRAPPER(reverse_order);
+}
+EXPORT void Playlist::reverse_selected() const
+{
+ SIMPLE_VOID_WRAPPER(reverse_selected);
+}
+EXPORT void Playlist::randomize_order() const
+{
+ SIMPLE_VOID_WRAPPER(randomize_order);
+}
+EXPORT void Playlist::randomize_selected() const
+{
+ SIMPLE_VOID_WRAPPER(randomize_selected);
}
-static Playlist::ID * insert_playlist_locked (int at, int stamp = -1)
+EXPORT void Playlist::rescan_all() const
{
- if (at < 0 || at > playlists.len ())
- at = playlists.len ();
+ SIMPLE_VOID_WRAPPER(reset_tuples, false);
+}
+EXPORT void Playlist::rescan_selected() const
+{
+ SIMPLE_VOID_WRAPPER(reset_tuples, true);
+}
- auto id = create_playlist (stamp);
+EXPORT int64_t Playlist::total_length_ms() const
+{
+ SIMPLE_WRAPPER(int64_t, 0, total_length);
+}
+EXPORT int64_t Playlist::selected_length_ms() const
+{
+ SIMPLE_WRAPPER(int64_t, 0, selected_length);
+}
- playlists.insert (at, 1);
- playlists[at].capture (id->data);
+EXPORT int Playlist::n_queued() const { SIMPLE_WRAPPER(int, 0, n_queued); }
+EXPORT void Playlist::queue_insert(int at, int entry_num) const
+{
+ SIMPLE_VOID_WRAPPER(queue_insert, at, entry_num);
+}
+EXPORT void Playlist::queue_insert_selected(int at) const
+{
+ SIMPLE_VOID_WRAPPER(queue_insert_selected, at);
+}
+EXPORT int Playlist::queue_get_entry(int at) const
+{
+ SIMPLE_WRAPPER(int, -1, queue_get_entry, at);
+}
+EXPORT int Playlist::queue_find_entry(int entry_num) const
+{
+ SIMPLE_WRAPPER(int, -1, queue_find_entry, entry_num);
+}
+EXPORT void Playlist::queue_remove(int at, int number) const
+{
+ SIMPLE_VOID_WRAPPER(queue_remove, at, number);
+}
+EXPORT void Playlist::queue_remove_selected() const
+{
+ SIMPLE_VOID_WRAPPER(queue_remove_selected);
+}
- number_playlists (at, playlists.len () - at);
+EXPORT bool Playlist::update_pending() const
+{
+ SIMPLE_WRAPPER(bool, false, update_pending);
+}
+EXPORT Playlist::Update Playlist::update_detail() const
+{
+ SIMPLE_WRAPPER(Update, Update(), last_update);
+}
+
+void PlaylistEx::insert_flat_items(int at,
+ Index<PlaylistAddItem> && items) const
+{
+ SIMPLE_VOID_WRAPPER(insert_items, at, std::move(items));
+}
+
+EXPORT int Playlist::index() const
+{
+ ENTER_GET_PLAYLIST(-1);
+ return m_id->index;
+}
+
+EXPORT int PlaylistEx::stamp() const
+{
+ ENTER_GET_PLAYLIST(-1);
+ return m_id->stamp;
+}
+
+EXPORT int Playlist::n_playlists()
+{
+ auto mh = mutex.take();
+ return playlists.len();
+}
+
+EXPORT Playlist Playlist::by_index(int at)
+{
+ auto mh = mutex.take();
+ Playlist::ID * id =
+ (at >= 0 && at < playlists.len()) ? playlists[at]->id() : nullptr;
+ return Playlist(id);
+}
+
+static Playlist::ID * insert_playlist_locked(int at, int stamp = -1)
+{
+ if (at < 0 || at > playlists.len())
+ at = playlists.len();
+
+ auto id = create_playlist(stamp);
+
+ playlists.insert(at, 1);
+ playlists[at].capture(id->data);
+
+ number_playlists(at, playlists.len() - at);
/* this will only happen at startup */
- if (! active_id)
+ if (!active_id)
active_id = id;
- queue_global_update (Playlist::Structure);
+ queue_global_update(Playlist::Structure);
return id;
}
-static Playlist::ID * get_blank_locked ()
+static Playlist::ID * get_blank_locked()
{
- if (! strcmp (active_id->data->title, _(default_title)) && ! active_id->data->n_entries ())
+ if (!strcmp(active_id->data->title, _(default_title)) &&
+ !active_id->data->n_entries())
return active_id;
- return insert_playlist_locked (active_id->index + 1);
+ return insert_playlist_locked(active_id->index + 1);
}
-Playlist PlaylistEx::insert_with_stamp (int at, int stamp)
+Playlist PlaylistEx::insert_with_stamp(int at, int stamp)
{
- ENTER;
- auto id = insert_playlist_locked (at, stamp);
- RETURN (Playlist (id));
+ auto mh = mutex.take();
+ auto id = insert_playlist_locked(at, stamp);
+ return Playlist(id);
}
-EXPORT Playlist Playlist::insert_playlist (int at)
+EXPORT Playlist Playlist::insert_playlist(int at)
{
- ENTER;
- auto id = insert_playlist_locked (at);
- RETURN (Playlist (id));
+ auto mh = mutex.take();
+ auto id = insert_playlist_locked(at);
+ return Playlist(id);
}
-EXPORT void Playlist::reorder_playlists (int from, int to, int count)
+EXPORT void Playlist::reorder_playlists(int from, int to, int count)
{
- ENTER;
+ auto mh = mutex.take();
- if (from < 0 || from + count > playlists.len () || to < 0 || to +
- count > playlists.len () || count < 0)
- RETURN ();
+ if (from < 0 || from + count > playlists.len() || to < 0 ||
+ to + count > playlists.len() || count < 0)
+ return;
Index<SmartPtr<PlaylistData>> displaced;
if (to < from)
- displaced.move_from (playlists, to, -1, from - to, true, false);
+ displaced.move_from(playlists, to, -1, from - to, true, false);
else
- displaced.move_from (playlists, from + count, -1, to - from, true, false);
+ displaced.move_from(playlists, from + count, -1, to - from, true,
+ false);
- playlists.shift (from, to, count);
+ playlists.shift(from, to, count);
if (to < from)
{
- playlists.move_from (displaced, 0, to + count, from - to, false, true);
- number_playlists (to, from + count - to);
+ playlists.move_from(displaced, 0, to + count, from - to, false, true);
+ number_playlists(to, from + count - to);
}
else
{
- playlists.move_from (displaced, 0, from, to - from, false, true);
- number_playlists (from, to + count - from);
+ playlists.move_from(displaced, 0, from, to - from, false, true);
+ number_playlists(from, to + count - from);
}
- queue_global_update (Structure);
- LEAVE;
+ queue_global_update(Structure);
}
-EXPORT void Playlist::remove_playlist () const
+EXPORT void Playlist::remove_playlist() const
{
- ENTER_GET_PLAYLIST ();
+ ENTER_GET_PLAYLIST();
int at = m_id->index;
- playlists.remove (at, 1);
+ playlists.remove(at, 1);
- if (! playlists.len ())
- playlists.append (create_playlist (-1)->data);
+ if (!playlists.len())
+ playlists.append(create_playlist(-1)->data);
- number_playlists (at, playlists.len () - at);
+ number_playlists(at, playlists.len() - at);
if (m_id == active_id)
{
- int active_num = aud::min (at, playlists.len () - 1);
- active_id = playlists[active_num]->id ();
- queue_update_hooks (SetActive);
+ int active_num = aud::min(at, playlists.len() - 1);
+ active_id = playlists[active_num]->id();
+ queue_update_hooks(SetActive);
}
if (m_id == playing_id)
{
playing_id = nullptr;
- stop_playback_locked ();
- queue_update_hooks (SetPlaying | PlaybackStop);
+ stop_playback_locked();
+ queue_update_hooks(SetPlaying | PlaybackStop);
}
- queue_global_update (Structure);
- LEAVE;
+ queue_global_update(Structure);
}
-EXPORT void Playlist::set_filename (const char * filename) const
+EXPORT void Playlist::set_filename(const char * filename) const
{
- ENTER_GET_PLAYLIST ();
+ ENTER_GET_PLAYLIST();
- playlist->filename = String (filename);
+ playlist->filename = String(filename);
playlist->modified = true;
- queue_global_update (Metadata);
- LEAVE;
+ queue_global_update(Metadata);
}
-EXPORT String Playlist::get_filename () const
+EXPORT String Playlist::get_filename() const
{
- ENTER_GET_PLAYLIST (String ());
- String filename = playlist->filename;
- RETURN (filename);
+ ENTER_GET_PLAYLIST(String());
+ return playlist->filename;
}
-EXPORT void Playlist::set_title (const char * title) const
+EXPORT void Playlist::set_title(const char * title) const
{
- ENTER_GET_PLAYLIST ();
+ ENTER_GET_PLAYLIST();
- playlist->title = String (title);
+ playlist->title = String(title);
playlist->modified = true;
- queue_global_update (Metadata);
- LEAVE;
+ queue_global_update(Metadata);
}
-EXPORT String Playlist::get_title () const
+EXPORT String Playlist::get_title() const
{
- ENTER_GET_PLAYLIST (String ());
- String title = playlist->title;
- RETURN (title);
+ ENTER_GET_PLAYLIST(String());
+ return playlist->title;
}
-void PlaylistEx::set_modified (bool modified) const
+void PlaylistEx::set_modified(bool modified) const
{
- ENTER_GET_PLAYLIST ();
+ ENTER_GET_PLAYLIST();
playlist->modified = modified;
- LEAVE;
}
-bool PlaylistEx::get_modified () const
+bool PlaylistEx::get_modified() const
{
- ENTER_GET_PLAYLIST (false);
- bool modified = playlist->modified;
- RETURN (modified);
+ ENTER_GET_PLAYLIST(false);
+ return playlist->modified;
}
-EXPORT void Playlist::activate () const
+EXPORT void Playlist::activate() const
{
- ENTER_GET_PLAYLIST ();
+ ENTER_GET_PLAYLIST();
if (m_id != active_id)
{
active_id = m_id;
- queue_update_hooks (SetActive);
+ queue_update_hooks(SetActive);
}
-
- LEAVE;
}
-EXPORT Playlist Playlist::active_playlist ()
+EXPORT Playlist Playlist::active_playlist()
{
- ENTER;
- auto id = active_id;
- RETURN (Playlist (id));
+ auto mh = mutex.take();
+ return Playlist(active_id);
}
-EXPORT Playlist Playlist::new_playlist ()
+EXPORT Playlist Playlist::new_playlist()
{
- ENTER;
+ auto mh = mutex.take();
int at = active_id->index + 1;
- auto id = insert_playlist_locked (at);
+ auto id = insert_playlist_locked(at);
active_id = id;
- queue_update_hooks (SetActive);
+ queue_update_hooks(SetActive);
- RETURN (Playlist (id));
+ return Playlist(id);
}
-static void set_playing_locked (Playlist::ID * id, bool paused)
+static void set_playing_locked(Playlist::ID * id, bool paused)
{
if (id == playing_id)
{
/* already playing, just need to pause/unpause */
- if (aud_drct_get_paused () != paused)
- aud_drct_pause ();
+ if (aud_drct_get_paused() != paused)
+ aud_drct_pause();
return;
}
if (playing_id)
- playing_id->data->resume_time = aud_drct_get_time ();
+ playing_id->data->resume_time = aud_drct_get_time();
/* is there anything to play? */
- if (id && id->data->position () < 0 && ! id->data->next_song (true))
+ if (id && id->data->position() < 0 && !id->data->next_song(true))
id = nullptr;
playing_id = id;
if (id)
{
- start_playback_locked (id->data->resume_time, paused);
- queue_update_hooks (SetPlaying | PlaybackBegin);
+ start_playback_locked(id->data->resume_time, paused);
+ queue_update_hooks(SetPlaying | PlaybackBegin);
}
else
{
- stop_playback_locked ();
- queue_update_hooks (SetPlaying | PlaybackStop);
+ stop_playback_locked();
+ queue_update_hooks(SetPlaying | PlaybackStop);
}
}
-EXPORT void Playlist::start_playback (bool paused) const
+EXPORT void Playlist::start_playback(bool paused) const
{
- ENTER_GET_PLAYLIST ();
- set_playing_locked (m_id, paused);
- LEAVE;
+ ENTER_GET_PLAYLIST();
+ set_playing_locked(m_id, paused);
}
-EXPORT void aud_drct_stop ()
+EXPORT void aud_drct_stop()
{
- ENTER;
- set_playing_locked (nullptr, false);
- LEAVE;
+ auto mh = mutex.take();
+ set_playing_locked(nullptr, false);
}
-EXPORT Playlist Playlist::playing_playlist ()
+EXPORT Playlist Playlist::playing_playlist()
{
- ENTER;
- auto id = playing_id;
- RETURN (Playlist (id));
+ auto mh = mutex.take();
+ return Playlist(playing_id);
}
-EXPORT Playlist Playlist::blank_playlist ()
+EXPORT Playlist Playlist::blank_playlist()
{
- ENTER;
- auto id = get_blank_locked ();
- RETURN (Playlist (id));
+ auto mh = mutex.take();
+ auto id = get_blank_locked();
+ return Playlist(id);
}
-EXPORT Playlist Playlist::temporary_playlist ()
+EXPORT Playlist Playlist::temporary_playlist()
{
- ENTER;
+ auto mh = mutex.take();
const char * title = _(temp_title);
ID * id = nullptr;
for (auto & playlist : playlists)
{
- if (! strcmp (playlist->title, title))
+ if (!strcmp(playlist->title, title))
{
- id = playlist->id ();
+ id = playlist->id();
break;
}
}
- if (! id)
+ if (!id)
{
- id = get_blank_locked ();
- id->data->title = String (title);
+ id = get_blank_locked();
+ id->data->title = String(title);
}
- RETURN (Playlist (id));
+ return Playlist(id);
}
-EXPORT PluginHandle * Playlist::entry_decoder (int entry_num, GetMode mode, String * error) const
+EXPORT PluginHandle * Playlist::entry_decoder(int entry_num, GetMode mode,
+ String * error) const
{
- ENTER_GET_PLAYLIST (nullptr);
- wait_for_entry (playlist, entry_num, (mode == Wait), false);
- PluginHandle * decoder = playlist->entry_decoder (entry_num, error);
- RETURN (decoder);
+ ENTER_GET_PLAYLIST(nullptr);
+ wait_for_entry(mh, playlist, entry_num, (mode == Wait), false);
+ return playlist->entry_decoder(entry_num, error);
}
-EXPORT Tuple Playlist::entry_tuple (int entry_num, GetMode mode, String * error) const
+EXPORT Tuple Playlist::entry_tuple(int entry_num, GetMode mode,
+ String * error) const
{
- ENTER_GET_PLAYLIST (Tuple ());
- wait_for_entry (playlist, entry_num, false, (mode == Wait));
- Tuple tuple = playlist->entry_tuple (entry_num, error);
- RETURN (tuple);
+ ENTER_GET_PLAYLIST(Tuple());
+ wait_for_entry(mh, playlist, entry_num, false, (mode == Wait));
+ return playlist->entry_tuple(entry_num, error);
}
-EXPORT void Playlist::rescan_file (const char * filename)
+EXPORT void Playlist::rescan_file(const char * filename)
{
- ENTER;
+ auto mh = mutex.take();
for (auto & playlist : playlists)
- playlist->reset_tuple_of_file (filename);
-
- LEAVE;
+ playlist->reset_tuple_of_file(filename);
}
// called from playback thread
-DecodeInfo playback_entry_read (int serial)
+DecodeInfo playback_entry_read(int serial)
{
- ENTER;
+ auto mh = mutex.take();
DecodeInfo dec;
- if (playback_check_serial (serial))
+ if (playback_check_serial(serial))
{
auto playlist = playing_id->data;
- auto entry = playlist->entry_at (playlist->position ());
+ auto entry = playlist->entry_at(playlist->position());
- ScanItem * item = scan_list_find_entry (entry);
- assert (item && item->for_playback);
+ ScanItem * item = scan_list_find_entry(entry);
+ assert(item && item->for_playback);
ScanRequest * request = item->request;
item->handled_by_playback = true;
- LEAVE;
- request->run ();
- ENTER;
+ mh.unlock();
+ request->run();
+ mh.lock();
- if (playback_check_serial (serial))
+ if (playback_check_serial(serial))
{
- assert (playlist == playing_id->data);
+ assert(playlist == playing_id->data);
- int pos = playlist->position ();
- playback_set_info (pos, playlist->entry_tuple (pos));
+ int pos = playlist->position();
+ playback_set_info(pos, playlist->entry_tuple(pos));
- art_cache_current (request->filename,
- std::move (request->image_data), std::move (request->image_file));
+ art_cache_current(request->filename, std::move(request->image_data),
+ std::move(request->image_file));
dec.filename = request->filename;
dec.ip = request->ip;
- dec.file = std::move (request->file);
- dec.error = std::move (request->error);
+ dec.file = std::move(request->file);
+ dec.error = std::move(request->error);
}
delete request;
}
- RETURN (dec);
+ return dec;
}
// called from playback thread
-void playback_entry_set_tuple (int serial, Tuple && tuple)
+void playback_entry_set_tuple(int serial, Tuple && tuple)
{
- ENTER;
-
- if (playback_check_serial (serial))
- playing_id->data->update_playback_entry (std::move (tuple));
+ auto mh = mutex.take();
- LEAVE;
+ if (playback_check_serial(serial))
+ playing_id->data->update_playback_entry(std::move(tuple));
}
-void playlist_save_state ()
+void playlist_save_state()
{
/* get playback state before locking playlists */
- bool paused = aud_drct_get_paused ();
- int time = aud_drct_get_time ();
+ bool paused = aud_drct_get_paused();
+ int time = aud_drct_get_time();
- ENTER;
+ auto mh = mutex.take();
- const char * user_dir = aud_get_path (AudPath::UserDir);
- StringBuf path = filename_build ({user_dir, STATE_FILE});
+ const char * user_dir = aud_get_path(AudPath::UserDir);
+ StringBuf path = filename_build({user_dir, STATE_FILE});
- FILE * handle = g_fopen (path, "w");
- if (! handle)
- RETURN ();
+ FILE * handle = g_fopen(path, "w");
+ if (!handle)
+ return;
- fprintf (handle, "active %d\n", active_id ? active_id->index : -1);
- fprintf (handle, "playing %d\n", playing_id ? playing_id->index : -1);
+ fprintf(handle, "active %d\n", active_id ? active_id->index : -1);
+ fprintf(handle, "playing %d\n", playing_id ? playing_id->index : -1);
for (auto & playlist : playlists)
{
- fprintf (handle, "playlist %d\n", playlist->id ()->index);
+ fprintf(handle, "playlist %d\n", playlist->id()->index);
if (playlist->filename)
- fprintf (handle, "filename %s\n", (const char *) playlist->filename);
+ fprintf(handle, "filename %s\n", (const char *)playlist->filename);
- fprintf (handle, "position %d\n", playlist->position ());
+ fprintf(handle, "position %d\n", playlist->position());
/* save shuffle history */
- auto history = playlist->shuffle_history ();
+ auto history = playlist->shuffle_history();
- for (int i = 0; i < history.len (); i += 16)
+ for (int i = 0; i < history.len(); i += 16)
{
- int count = aud::min (16, history.len () - i);
- auto list = int_array_to_str (& history[i], count);
- fprintf (handle, "shuffle %s\n", (const char *) list);
+ int count = aud::min(16, history.len() - i);
+ auto list = int_array_to_str(&history[i], count);
+ fprintf(handle, "shuffle %s\n", (const char *)list);
}
/* resume state is stored per-playlist for historical reasons */
- bool is_playing = (playlist->id () == playing_id);
- fprintf (handle, "resume-state %d\n", (is_playing && paused) ? ResumePause : ResumePlay);
- fprintf (handle, "resume-time %d\n", is_playing ? time : playlist->resume_time);
+ bool is_playing = (playlist->id() == playing_id);
+ fprintf(handle, "resume-state %d\n",
+ (is_playing && paused) ? ResumePause : ResumePlay);
+ fprintf(handle, "resume-time %d\n",
+ is_playing ? time : playlist->resume_time);
}
- fclose (handle);
- LEAVE;
+ fclose(handle);
}
-void playlist_load_state ()
+void playlist_load_state()
{
- ENTER;
+ auto mh = mutex.take();
int playlist_num;
- const char * user_dir = aud_get_path (AudPath::UserDir);
- StringBuf path = filename_build ({user_dir, STATE_FILE});
+ const char * user_dir = aud_get_path(AudPath::UserDir);
+ StringBuf path = filename_build({user_dir, STATE_FILE});
- FILE * handle = g_fopen (path, "r");
- if (! handle)
- RETURN ();
+ FILE * handle = g_fopen(path, "r");
+ if (!handle)
+ return;
- TextParser parser (handle);
+ TextParser parser(handle);
- if (parser.get_int ("active", playlist_num))
+ if (parser.get_int("active", playlist_num))
{
- if (playlist_num >= 0 && playlist_num < playlists.len ())
- active_id = playlists[playlist_num]->id ();
+ if (playlist_num >= 0 && playlist_num < playlists.len())
+ active_id = playlists[playlist_num]->id();
- parser.next ();
+ parser.next();
}
- if (parser.get_int ("playing", resume_playlist))
- parser.next ();
+ if (parser.get_int("playing", resume_playlist))
+ parser.next();
- while (parser.get_int ("playlist", playlist_num) &&
- playlist_num >= 0 && playlist_num < playlists.len ())
+ while (parser.get_int("playlist", playlist_num) && playlist_num >= 0 &&
+ playlist_num < playlists.len())
{
- PlaylistData * playlist = playlists[playlist_num].get ();
+ PlaylistData * playlist = playlists[playlist_num].get();
- parser.next ();
+ parser.next();
- playlist->filename = parser.get_str ("filename");
+ playlist->filename = parser.get_str("filename");
if (playlist->filename)
- parser.next ();
+ parser.next();
int position = -1;
- if (parser.get_int ("position", position))
+ if (parser.get_int("position", position))
{
- playlist->set_position (position);
- parser.next ();
+ playlist->set_position(position);
+ parser.next();
}
/* restore shuffle history */
Index<int> history;
- for (String list; (list = parser.get_str ("shuffle")); parser.next ())
+ for (String list; (list = parser.get_str("shuffle")); parser.next())
{
- auto split = str_list_to_index (list, ", ");
+ auto split = str_list_to_index(list, ", ");
for (auto & str : split)
- history.append (str_to_int (str));
+ history.append(str_to_int(str));
}
- if (history.len ())
- playlist->shuffle_replay (history);
+ if (history.len())
+ playlist->shuffle_replay(history);
/* resume state is stored per-playlist for historical reasons */
int resume_state = ResumePlay;
- if (parser.get_int ("resume-state", resume_state))
- parser.next ();
+ if (parser.get_int("resume-state", resume_state))
+ parser.next();
if (playlist_num == resume_playlist)
{
@@ -1246,33 +1279,31 @@ void playlist_load_state ()
resume_paused = true;
}
- if (parser.get_int ("resume-time", playlist->resume_time))
- parser.next ();
+ if (parser.get_int("resume-time", playlist->resume_time))
+ parser.next();
}
- fclose (handle);
+ fclose(handle);
/* set initial focus and selection */
for (auto & playlist : playlists)
{
- int focus = playlist->position ();
- if (focus < 0 && playlist->n_entries ())
+ int focus = playlist->position();
+ if (focus < 0 && playlist->n_entries())
focus = 0;
if (focus >= 0)
{
- playlist->set_focus (focus);
- playlist->select_entry (focus, true);
+ playlist->set_focus(focus);
+ playlist->select_entry(focus, true);
}
}
-
- LEAVE;
}
-EXPORT void aud_resume ()
+EXPORT void aud_resume()
{
- if (aud_get_bool (nullptr, "always_resume_paused"))
+ if (aud_get_bool("always_resume_paused"))
resume_paused = true;
- Playlist::by_index (resume_playlist).start_playback (resume_paused);
+ Playlist::by_index(resume_playlist).start_playback(resume_paused);
}
diff --git a/src/libaudcore/playlist.h b/src/libaudcore/playlist.h
index e9270c1..e88ec30 100644
--- a/src/libaudcore/playlist.h
+++ b/src/libaudcore/playlist.h
@@ -40,33 +40,37 @@ public:
/* The values which can be passed to the "playlist update" hook. Selection
* means that entries have been selected or unselected, or that entries have
- * been added to or removed from the queue. Metadata means that new metadata
- * has been read for some entries, or that the title or filename of a playlist
- * has changed, and implies Selection. Structure covers any other change, and
- * implies both Selection and Metadata. */
- enum UpdateLevel {
+ * been added to or removed from the queue. Metadata means that new
+ * metadata has been read for some entries, or that the title or filename of
+ * a playlist has changed, and implies Selection. Structure covers any
+ * other change, and implies both Selection and Metadata. */
+ enum UpdateLevel
+ {
NoUpdate = 0,
Selection,
Metadata,
Structure
};
- struct Update {
- UpdateLevel level; // type of update
- int before; // number of unaffected entries at playlist start
- int after; // number of unaffected entries at playlist end
- bool queue_changed; // true if entries have been added to/removed from queue
+ struct Update
+ {
+ UpdateLevel level; // type of update
+ int before; // number of unaffected entries at playlist start
+ int after; // number of unaffected entries at playlist end
+ bool queue_changed; // true if entries have been added to/removed from
+ // queue
};
/* Preset sorting "schemes" */
- enum SortType {
- Path, // entry's entire URI
- Filename, // base name (no folder path)
+ enum SortType
+ {
+ Path, // entry's entire URI
+ Filename, // base name (no folder path)
Title,
Album,
Artist,
AlbumArtist,
- Date, // release date (not modification time)
+ Date, // release date (not modification time)
Genre,
Track,
FormattedTitle,
@@ -76,105 +80,108 @@ public:
};
/* Possible behaviors for entry_{decoder, tuple}. */
- enum GetMode {
- NoWait, // non-blocking call; returned tuple will be in Initial state if not yet scanned
- Wait // blocking call; returned tuple will be either Valid or Failed
+ enum GetMode
+ {
+ NoWait, // non-blocking call; returned tuple will be in Initial state if
+ // not yet scanned
+ Wait // blocking call; returned tuple will be either Valid or Failed
};
/* Format descriptor returned by save_formats() */
- struct SaveFormat {
- String name; // human-readable format name
- Index<String> exts; // supported filename extensions
+ struct SaveFormat
+ {
+ String name; // human-readable format name
+ Index<String> exts; // supported filename extensions
};
- typedef bool (* FilterFunc) (const char * filename, void * user);
- typedef int (* StringCompareFunc) (const char * a, const char * b);
- typedef int (* TupleCompareFunc) (const Tuple & a, const Tuple & b);
+ typedef bool (*FilterFunc)(const char * filename, void * user);
+ typedef int (*StringCompareFunc)(const char * a, const char * b);
+ typedef int (*TupleCompareFunc)(const Tuple & a, const Tuple & b);
/* --- CONSTRUCTOR ETC. --- */
/* Default constructor; indicates "no playlist" */
- constexpr Playlist () : m_id (nullptr) {}
+ constexpr Playlist() : m_id(nullptr) {}
- bool operator== (const Playlist & b) const { return m_id == b.m_id; }
- bool operator!= (const Playlist & b) const { return m_id != b.m_id; }
+ bool operator==(const Playlist & b) const { return m_id == b.m_id; }
+ bool operator!=(const Playlist & b) const { return m_id != b.m_id; }
/* The number of the playlist in display order, starting from 0.
* Returns -1 if the playlist no longer exists. */
- int index () const;
+ int index() const;
/* True if the playlist exists (i.e. has not been deleted). */
- bool exists () const { return index () >= 0; }
+ bool exists() const { return index() >= 0; }
/* --- CORE (STATIC) API --- */
/* Returns the number of playlists currently open (>= 1). */
- static int n_playlists ();
+ static int n_playlists();
/* Looks up a playlist by display order. */
- static Playlist by_index (int at);
+ static Playlist by_index(int at);
/* Adds a new playlist before the one numbered <at> (-1 = insert at end). */
- static Playlist insert_playlist (int at);
+ static Playlist insert_playlist(int at);
/* Moves a contiguous block of <count> playlists starting with the one
* numbered <from> such that that playlist ends up at the position <to>. */
- static void reorder_playlists (int from, int to, int count);
+ static void reorder_playlists(int from, int to, int count);
/* Returns the active (i.e. displayed) playlist. */
- static Playlist active_playlist ();
+ static Playlist active_playlist();
/* Convenience function which adds a new playlist after the active one and
* then sets the new one as active. Returns the new playlist. */
- static Playlist new_playlist ();
+ static Playlist new_playlist();
/* Returns the currently playing playlist. If no playlist is playing,
* returns Playlist(). */
- static Playlist playing_playlist ();
+ static Playlist playing_playlist();
/* Returns the number of a "blank" playlist. The active playlist is
* returned if it has the default title and has no entries; otherwise, a new
* playlist is added and returned. */
- static Playlist blank_playlist ();
+ static Playlist blank_playlist();
/* Returns the number of the "temporary" playlist (which is no different
* from any other playlist except in name). If the playlist does not exist,
* a "blank" playlist is renamed to become the temporary playlist. */
- static Playlist temporary_playlist ();
+ static Playlist temporary_playlist();
/* Discards the metadata stored for all the entries that refer to a
* particular song file, in whatever playlist they appear, and starts
* reading it afresh from that file in the background. */
- static void rescan_file (const char * filename);
+ static void rescan_file(const char * filename);
/* --- CORE (NON-STATIC) API --- */
/* Gets/sets the filename associated with this playlist.
* (Audacious currently makes no use of the filename.) */
- String get_filename () const;
- void set_filename (const char * filename) const;
+ String get_filename() const;
+ void set_filename(const char * filename) const;
/* Gets/sets the title of the playlist. */
- String get_title () const;
- void set_title (const char * title) const;
+ String get_title() const;
+ void set_title(const char * title) const;
/* Closes the playlist.
* The playlist is not saved, and no confirmation is presented to the user.
* When the last playlist is closed, a new one is added in its place.
* When the active playlist is closed, another is made active.
* When the playing playlist is closed, playback stops. */
- void remove_playlist () const;
+ void remove_playlist() const;
/* Makes this the active (i.e. displayed) playlist. */
- void activate () const;
+ void activate() const;
/* Starts playback of this playlist, unless it is empty.
* Resumes from the position last played if possible.
* If <paused> is true, starts playback in a paused state. */
- void start_playback (bool paused = false) const;
+ void start_playback(bool paused = false) const;
/* Returns the number of entries (numbered from 0). */
- int n_entries () const;
+ int n_entries() const;
/* Adds a single song file, playlist file, or folder before the entry <at>.
* If <at> is negative or equal to the number of entries, the item is added
@@ -183,210 +190,225 @@ public:
* Audacious will begin playback of the items once they have been added.
*
* This function is asynchronous (the items are added in the background). */
- void insert_entry (int at, const char * filename, Tuple && tuple, bool play) const;
+ void insert_entry(int at, const char * filename, Tuple && tuple,
+ bool play) const;
/* Adds multiple song files, playlist files, or folders to a playlist. */
- void insert_items (int at, Index<PlaylistAddItem> && items, bool play) const;
+ void insert_items(int at, Index<PlaylistAddItem> && items, bool play) const;
/* Similar to insert_items() but allows the caller to prevent some items
* from being added by returning false from the <filter> callback. Useful
* for searching a folder and adding only new files to the playlist. <user>
* is an opaque pointer passed to the callback. */
- void insert_filtered (int at, Index<PlaylistAddItem> && items,
- FilterFunc filter, void * user, bool play) const;
+ void insert_filtered(int at, Index<PlaylistAddItem> && items,
+ FilterFunc filter, void * user, bool play) const;
/* Removes entries from the playlist. The playback position may be moved,
* or playback may be stopped (according to user preference). */
- void remove_entries (int at, int number) const;
- void remove_entry (int at) const { remove_entries (at, 1); }
- void remove_all_entries () const { remove_entries (0, -1); }
+ void remove_entries(int at, int number) const;
+ void remove_entry(int at) const { remove_entries(at, 1); }
+ void remove_all_entries() const { remove_entries(0, -1); }
/* Returns an entry's filename. */
- String entry_filename (int entry) const;
+ String entry_filename(int entry) const;
/* Returns an entry's decoder plugin. On error, or if the entry has not yet
* been scanned, returns nullptr according to <mode>. An optional error
* message may be returned. */
- PluginHandle * entry_decoder (int entry, GetMode mode = Wait, String * error = nullptr) const;
+ PluginHandle * entry_decoder(int entry, GetMode mode = Wait,
+ String * error = nullptr) const;
/* Returns an entry's metadata. The state of the returned tuple may
* indicate that the entry has not yet been scanned, or an error occurred,
* according to <mode>. An optional error message may be returned. */
- Tuple entry_tuple (int entry, GetMode mode = Wait, String * error = nullptr) const;
+ Tuple entry_tuple(int entry, GetMode mode = Wait,
+ String * error = nullptr) const;
/* Gets/sets the playing or last-played entry (-1 = no entry).
* Affects playback only if this playlist is currently playing.
* set_position(get_position()) restarts playback from 0:00.
* set_position(-1) stops playback. */
- int get_position () const;
- void set_position (int position) const;
+ int get_position() const;
+ void set_position(int position) const;
/* Advances the playlist position to the next entry in playback order,
* taking current shuffle settings into account. At the end of the
* playlist, wraps around to the beginning if <repeat> is true. Returns
* true on success, false if playlist position was not changed. */
- bool next_song (bool repeat) const;
+ bool next_song(bool repeat) const;
+
+ /* Advances the playlist position to the first entry of the next album in
+ * playback order, taking current shuffle settings into account. At the
+ * end of the playlist, wraps around to the beginning if <repeat> is true.
+ * Returns true on success, false if playlist position was not changed. */
+ bool next_album(bool repeat) const;
/* Returns the playlist position to the previous entry in playback order.
* Does not support wrapping past the beginning of the playlist. Returns
* true on success, false if playlist position was not changed. */
- bool prev_song () const;
+ bool prev_song() const;
+
+ /* Returns the playlist position to the first entry in playback order where
+ * the album is not the current album. Does not support wrapping past the
+ * beginning of the playlist. Returns true on success, false if playlist
+ * position was not changed. */
+ bool prev_album() const;
/* Gets/sets the entry which has keyboard focus (-1 = no entry). */
- int get_focus () const;
- void set_focus (int entry) const;
+ int get_focus() const;
+ void set_focus(int entry) const;
/* Gets/sets whether an entry is selected. */
- bool entry_selected (int entry) const;
- void select_entry (int entry, bool selected) const;
+ bool entry_selected(int entry) const;
+ void select_entry(int entry, bool selected) const;
/* Returns the number of selected entries.
* An optional range of entries to examine may be specified. */
- int n_selected (int at = 0, int number = -1) const;
+ int n_selected(int at = 0, int number = -1) const;
/* Selects all (or none) of the entries in a playlist. */
- void select_all (bool selected) const;
+ void select_all(bool selected) const;
/* Moves a selected entry within a playlist by an offset of <distance>
* entries. Other selected entries are gathered around it. Returns the
* offset by which the entry was actually moved (which may be less than the
* requested offset. */
- int shift_entries (int position, int distance) const;
+ int shift_entries(int position, int distance) const;
/* Removes all selected entries. */
- void remove_selected () const;
+ void remove_selected() const;
/* Sorts the entries in a playlist based on filename. The callback function
* should return negative if the first filename comes before the second,
* positive if it comes after, or zero if the two are indistinguishable. */
- void sort_by_filename (StringCompareFunc compare) const;
+ void sort_by_filename(StringCompareFunc compare) const;
/* Sorts the entries in a playlist based on tuple. May fail if metadata
* scanning is still in progress (or has been disabled). */
- void sort_by_tuple (TupleCompareFunc compare) const;
+ void sort_by_tuple(TupleCompareFunc compare) const;
- /* Sorts the entries in a playlist based on formatted title string. May fail if
- * metadata scanning is still in progress (or has been disabled). */
- void sort_by_title (StringCompareFunc compare) const;
+ /* Sorts the entries in a playlist based on formatted title string. May
+ * fail if metadata scanning is still in progress (or has been disabled). */
+ void sort_by_title(StringCompareFunc compare) const;
/* Sorts only the selected entries in a playlist based on filename. */
- void sort_selected_by_filename (StringCompareFunc compare) const;
+ void sort_selected_by_filename(StringCompareFunc compare) const;
- /* Sorts only the selected entries in a playlist based on tuple. May fail if
- * metadata scanning is still in progress (or has been disabled). */
- void sort_selected_by_tuple (TupleCompareFunc compare) const;
+ /* Sorts only the selected entries in a playlist based on tuple. May fail
+ * if metadata scanning is still in progress (or has been disabled). */
+ void sort_selected_by_tuple(TupleCompareFunc compare) const;
/* Sorts only the selected entries in a playlist based on formatted title
* string. May fail if metadata scanning is still in progress (or has been
* disabled). */
- void sort_selected_by_title (StringCompareFunc compare) const;
+ void sort_selected_by_title(StringCompareFunc compare) const;
/* Reverses the order of the entries in a playlist. */
- void reverse_order () const;
+ void reverse_order() const;
/* Reorders the entries in a playlist randomly. */
- void randomize_order () const;
+ void randomize_order() const;
/* Reverses the order of the selected entries in a playlist. */
- void reverse_selected () const;
+ void reverse_selected() const;
/* Reorders the selected entries in a playlist randomly. */
- void randomize_selected () const;
+ void randomize_selected() const;
/* Discards the metadata stored for entries in a playlist and starts reading
* it fresh from the song files in the background. */
- void rescan_all () const;
- void rescan_selected () const;
+ void rescan_all() const;
+ void rescan_selected() const;
/* Calculates the length in milliseconds of entries in a playlist. Only
* takes into account entries for which metadata has already been read. */
- int64_t total_length_ms () const;
- int64_t selected_length_ms () const;
+ int64_t total_length_ms() const;
+ int64_t selected_length_ms() const;
/* Returns the number of entries in a playlist queue. */
- int n_queued () const;
+ int n_queued() const;
/* Adds an entry to the queue at <pos> (-1 = at end of queue).
* The same entry cannot be added to the queue more than once. */
- void queue_insert (int pos, int entry) const;
- void queue_insert_selected (int pos) const;
+ void queue_insert(int pos, int entry) const;
+ void queue_insert_selected(int pos) const;
/* Returns the entry at the given queue position. */
- int queue_get_entry (int pos) const;
+ int queue_get_entry(int pos) const;
/* Returns the queue position of the given entry (-1 if not queued). */
- int queue_find_entry (int entry) const;
+ int queue_find_entry(int entry) const;
/* Removes entries from the queue. */
- void queue_remove (int pos, int number = 1) const;
- void queue_remove_all () const { queue_remove (0, -1); }
+ void queue_remove(int pos, int number = 1) const;
+ void queue_remove_all() const { queue_remove(0, -1); }
- /* Removes the selected entries in a playlist from the queue, if they are in it. */
- void queue_remove_selected () const;
+ /* Removes the selected entries in a playlist from the queue, if they are in
+ * it. */
+ void queue_remove_selected() const;
/* Returns true if a "playlist update" hook call is pending.
* A running hook call is not considered pending. */
- bool update_pending () const;
- static bool update_pending_any ();
+ bool update_pending() const;
+ static bool update_pending_any();
/* Immediately calls any pending "playlist update" hook. Use cautiously. */
- static void process_pending_update ();
+ static void process_pending_update();
/* May be called within the "playlist update" hook to determine the update
* level and number of entries changed in a playlist. */
- Update update_detail () const;
+ Update update_detail() const;
/* Returns true if entries are being added in the background. */
- bool add_in_progress () const;
- static bool add_in_progress_any ();
+ bool add_in_progress() const;
+ static bool add_in_progress_any();
/* Returns true if entries are being scanned in the background. */
- bool scan_in_progress () const;
- static bool scan_in_progress_any ();
+ bool scan_in_progress() const;
+ static bool scan_in_progress_any();
/* --- UTILITY API --- */
/* Sorts entries according to a preset scheme. */
- void sort_entries (SortType scheme) const;
- void sort_selected (SortType scheme) const;
+ void sort_entries(SortType scheme) const;
+ void sort_selected(SortType scheme) const;
/* Removes duplicate entries according to a preset scheme.
* The current implementation also sorts the playlist. */
- void remove_duplicates (SortType scheme) const;
+ void remove_duplicates(SortType scheme) const;
/* Removes all entries referring to inaccessible files in a playlist. */
- void remove_unavailable () const;
+ void remove_unavailable() const;
/* Selects entries by matching regular expressions.
* Example: To select all titles starting with the letter "A",
* create a blank tuple and set its title field to "^A". */
- void select_by_patterns (const Tuple & patterns) const;
+ void select_by_patterns(const Tuple & patterns) const;
/* Saves metadata for the selected entries to an internal cache.
* This will speed up adding those entries to another playlist. */
- void cache_selected () const;
+ void cache_selected() const;
/* Saves the entries in a playlist to a playlist file.
* The format of the file is determined from the file extension.
* <mode> specifies whether to wait for metadata scanning to complete.
* Returns true on success. */
- bool save_to_file (const char * filename, GetMode mode) const;
+ bool save_to_file(const char * filename, GetMode mode) const;
/* Checks a filename for an extension matching a known playlist format. */
- static bool filename_is_playlist (const char * filename);
+ static bool filename_is_playlist(const char * filename);
/* Generates a list of the currently supported formats for saving playlists.
- * The list should not be cached since it may change as plugins are enabled or
- * disabled. */
- static Index<SaveFormat> save_formats ();
+ * The list should not be cached since it may change as plugins are enabled
+ * or disabled. */
+ static Index<SaveFormat> save_formats();
/* --- IMPLEMENTATION --- */
private:
ID * m_id;
- explicit constexpr Playlist (ID * id) :
- m_id (id) {}
+ explicit constexpr Playlist(ID * id) : m_id(id) {}
friend class PlaylistEx;
};
diff --git a/src/libaudcore/plugin-init.cc b/src/libaudcore/plugin-init.cc
index 0674a76..5d2ae39 100644
--- a/src/libaudcore/plugin-init.cc
+++ b/src/libaudcore/plugin-init.cc
@@ -29,38 +29,37 @@
#include "plugin.h"
#include "runtime.h"
-static bool general_plugin_start (PluginHandle * plugin)
+static bool general_plugin_start(PluginHandle * plugin)
{
- auto gp = (GeneralPlugin *) aud_plugin_get_header (plugin);
- return gp && gp->init ();
+ auto gp = (GeneralPlugin *)aud_plugin_get_header(plugin);
+ return gp && gp->init();
}
-void general_plugin_stop (PluginHandle * plugin)
+void general_plugin_stop(PluginHandle * plugin)
{
- GeneralPlugin * gp = (GeneralPlugin *) aud_plugin_get_header (plugin);
+ GeneralPlugin * gp = (GeneralPlugin *)aud_plugin_get_header(plugin);
if (gp)
- gp->cleanup ();
+ gp->cleanup();
}
struct MultiFuncs
{
- bool (* start) (PluginHandle * plugin);
- void (* stop) (PluginHandle * plugin);
+ bool (*start)(PluginHandle * plugin);
+ void (*stop)(PluginHandle * plugin);
};
struct SingleFuncs
{
- PluginHandle * (* get_current) ();
- bool (* set_current) (PluginHandle * plugin);
+ PluginHandle * (*get_current)();
+ bool (*set_current)(PluginHandle * plugin);
};
-union PluginFuncs
-{
+union PluginFuncs {
MultiFuncs m;
SingleFuncs s;
- constexpr PluginFuncs (MultiFuncs multi) : m (multi) {}
- constexpr PluginFuncs (SingleFuncs single) : s (single) {}
+ constexpr PluginFuncs(MultiFuncs multi) : m(multi) {}
+ constexpr PluginFuncs(SingleFuncs single) : s(single) {}
};
struct PluginParams
@@ -69,319 +68,334 @@ struct PluginParams
bool is_single;
PluginFuncs f;
- constexpr PluginParams (const char * name, MultiFuncs multi) :
- name (name), is_single (false), f (multi) {}
- constexpr PluginParams (const char * name, SingleFuncs single) :
- name (name), is_single (true), f (single) {}
+ constexpr PluginParams(const char * name, MultiFuncs multi)
+ : name(name), is_single(false), f(multi)
+ {
+ }
+ constexpr PluginParams(const char * name, SingleFuncs single)
+ : name(name), is_single(true), f(single)
+ {
+ }
};
static constexpr aud::array<PluginType, PluginParams> table = {
- PluginParams ("transport", MultiFuncs ({nullptr, nullptr})),
- PluginParams ("playlist", MultiFuncs ({nullptr, nullptr})),
- PluginParams ("input", MultiFuncs ({nullptr, nullptr})),
- PluginParams ("effect", MultiFuncs ({effect_plugin_start, effect_plugin_stop})),
- PluginParams ("output", SingleFuncs ({output_plugin_get_current, output_plugin_set_current})),
- PluginParams ("visualization", MultiFuncs ({vis_plugin_start, vis_plugin_stop})),
- PluginParams ("general", MultiFuncs ({general_plugin_start, general_plugin_stop})),
- PluginParams ("interface", SingleFuncs ({iface_plugin_get_current, iface_plugin_set_current}))
-};
-
-static bool start_plugin (PluginType type, PluginHandle * p, bool secondary = false)
+ PluginParams("transport", MultiFuncs({nullptr, nullptr})),
+ PluginParams("playlist", MultiFuncs({nullptr, nullptr})),
+ PluginParams("input", MultiFuncs({nullptr, nullptr})),
+ PluginParams("effect",
+ MultiFuncs({effect_plugin_start, effect_plugin_stop})),
+ PluginParams("output", SingleFuncs({output_plugin_get_current,
+ output_plugin_set_current})),
+ PluginParams("visualization",
+ MultiFuncs({vis_plugin_start, vis_plugin_stop})),
+ PluginParams("general",
+ MultiFuncs({general_plugin_start, general_plugin_stop})),
+ PluginParams("interface", SingleFuncs({iface_plugin_get_current,
+ iface_plugin_set_current}))};
+
+static bool start_plugin(PluginType type, PluginHandle * p,
+ bool secondary = false)
{
bool success;
if (secondary)
- success = output_plugin_set_secondary (p);
+ success = output_plugin_set_secondary(p);
else if (table[type].is_single)
- success = table[type].f.s.set_current (p);
+ success = table[type].f.s.set_current(p);
else
- success = table[type].f.m.start (p);
+ success = table[type].f.m.start(p);
- if (! success)
+ if (!success)
{
- AUDWARN ("%s failed to start.\n", aud_plugin_get_name (p));
- plugin_set_failed (p);
+ AUDWARN("%s failed to start.\n", aud_plugin_get_name(p));
+ plugin_set_failed(p);
}
return success;
}
-static PluginHandle * find_selected (PluginType type, PluginEnabled enabled)
+static PluginHandle * find_selected(PluginType type, PluginEnabled enabled)
{
- for (PluginHandle * p : aud_plugin_list (type))
+ for (PluginHandle * p : aud_plugin_list(type))
{
- if (plugin_get_enabled (p) == enabled)
+ if (plugin_get_enabled(p) == enabled)
return p;
}
return nullptr;
}
-static void start_required (PluginType type)
+static void start_required(PluginType type)
{
PluginHandle * sel;
- if ((sel = find_selected (type, PluginEnabled::Primary)))
+ if ((sel = find_selected(type, PluginEnabled::Primary)))
{
- AUDINFO ("Starting selected %s plugin %s.\n", table[type].name,
- aud_plugin_get_name (sel));
+ AUDINFO("Starting selected %s plugin %s.\n", table[type].name,
+ aud_plugin_get_name(sel));
- if (start_plugin (type, sel))
+ if (start_plugin(type, sel))
return;
}
- AUDINFO ("Probing for %s plugin.\n", table[type].name);
+ AUDINFO("Probing for %s plugin.\n", table[type].name);
- for (PluginHandle * p : aud_plugin_list (type))
+ for (PluginHandle * p : aud_plugin_list(type))
{
if (p == sel)
continue;
- AUDINFO ("Trying to start %s.\n", aud_plugin_get_name (p));
- plugin_set_enabled (p, PluginEnabled::Primary);
+ AUDINFO("Trying to start %s.\n", aud_plugin_get_name(p));
+ plugin_set_enabled(p, PluginEnabled::Primary);
- if (start_plugin (type, p))
+ if (start_plugin(type, p))
return;
}
- AUDERR ("No %s plugin found.\n"
- "(Did you forget to install audacious-plugins?)\n", table[type].name);
- abort ();
+ AUDERR("No %s plugin found.\n"
+ "(Did you forget to install audacious-plugins?)\n",
+ table[type].name);
+ abort();
}
-static void start_plugins (PluginType type)
+static void start_plugins(PluginType type)
{
/* no interface plugin in headless mode */
- if (type == PluginType::Iface && aud_get_headless_mode ())
+ if (type == PluginType::Iface && aud_get_headless_mode())
return;
if (table[type].is_single)
{
- start_required (type);
+ start_required(type);
if (type == PluginType::Output)
{
PluginHandle * sel;
- if ((sel = find_selected (type, PluginEnabled::Secondary)))
+ if ((sel = find_selected(type, PluginEnabled::Secondary)))
{
- AUDINFO ("Starting secondary output plugin %s.\n", aud_plugin_get_name (sel));
- start_plugin (type, sel, true);
+ AUDINFO("Starting secondary output plugin %s.\n",
+ aud_plugin_get_name(sel));
+ start_plugin(type, sel, true);
}
}
}
else if (table[type].f.m.start)
{
- for (PluginHandle * p : aud_plugin_list (type))
+ for (PluginHandle * p : aud_plugin_list(type))
{
- if (aud_plugin_get_enabled (p))
+ if (aud_plugin_get_enabled(p))
{
- AUDINFO ("Starting %s.\n", aud_plugin_get_name (p));
- start_plugin (type, p);
+ AUDINFO("Starting %s.\n", aud_plugin_get_name(p));
+ start_plugin(type, p);
}
}
}
}
-void start_plugins_one ()
+void start_plugins_one()
{
- plugin_system_init ();
+ plugin_system_init();
- start_plugins (PluginType::Transport);
- start_plugins (PluginType::Playlist);
- start_plugins (PluginType::Input);
- start_plugins (PluginType::Effect);
- start_plugins (PluginType::Output);
+ start_plugins(PluginType::Transport);
+ start_plugins(PluginType::Playlist);
+ start_plugins(PluginType::Input);
+ start_plugins(PluginType::Effect);
+ start_plugins(PluginType::Output);
}
-void start_plugins_two ()
+void start_plugins_two()
{
- start_plugins (PluginType::Vis);
- start_plugins (PluginType::General);
- start_plugins (PluginType::Iface);
+ start_plugins(PluginType::Vis);
+ start_plugins(PluginType::General);
+ start_plugins(PluginType::Iface);
}
-static void stop_plugins (PluginType type)
+static void stop_plugins(PluginType type)
{
if (table[type].is_single)
{
- PluginHandle * p = table[type].f.s.get_current ();
- AUDINFO ("Shutting down %s.\n", aud_plugin_get_name (p));
- table[type].f.s.set_current (nullptr);
+ PluginHandle * p = table[type].f.s.get_current();
+ AUDINFO("Shutting down %s.\n", aud_plugin_get_name(p));
+ table[type].f.s.set_current(nullptr);
- if (type == PluginType::Output && (p = output_plugin_get_secondary ()))
+ if (type == PluginType::Output && (p = output_plugin_get_secondary()))
{
- AUDINFO ("Shutting down %s.\n", aud_plugin_get_name (p));
- output_plugin_set_secondary (nullptr);
+ AUDINFO("Shutting down %s.\n", aud_plugin_get_name(p));
+ output_plugin_set_secondary(nullptr);
}
}
else if (table[type].f.m.stop)
{
- for (PluginHandle * p : aud_plugin_list (type))
+ for (PluginHandle * p : aud_plugin_list(type))
{
- if (aud_plugin_get_enabled (p))
+ if (aud_plugin_get_enabled(p))
{
- AUDINFO ("Shutting down %s.\n", aud_plugin_get_name (p));
- table[type].f.m.stop (p);
+ AUDINFO("Shutting down %s.\n", aud_plugin_get_name(p));
+ table[type].f.m.stop(p);
}
}
}
}
-void stop_plugins_two ()
+void stop_plugins_two()
{
/* interface plugin is already shut down */
- stop_plugins (PluginType::General);
- stop_plugins (PluginType::Vis);
+ stop_plugins(PluginType::General);
+ stop_plugins(PluginType::Vis);
}
-void stop_plugins_one ()
+void stop_plugins_one()
{
- stop_plugins (PluginType::Output);
- stop_plugins (PluginType::Effect);
- stop_plugins (PluginType::Input);
- stop_plugins (PluginType::Playlist);
- stop_plugins (PluginType::Transport);
+ stop_plugins(PluginType::Output);
+ stop_plugins(PluginType::Effect);
+ stop_plugins(PluginType::Input);
+ stop_plugins(PluginType::Playlist);
+ stop_plugins(PluginType::Transport);
- plugin_system_cleanup ();
+ plugin_system_cleanup();
}
-EXPORT PluginHandle * aud_plugin_get_current (PluginType type)
+EXPORT PluginHandle * aud_plugin_get_current(PluginType type)
{
- assert (table[type].is_single);
- return table[type].f.s.get_current ();
+ assert(table[type].is_single);
+ return table[type].f.s.get_current();
}
-static bool enable_single (PluginType type, PluginHandle * p)
+static bool enable_single(PluginType type, PluginHandle * p)
{
- PluginHandle * old = table[type].f.s.get_current ();
+ PluginHandle * old = table[type].f.s.get_current();
- AUDINFO ("Switching from %s to %s.\n", aud_plugin_get_name (old),
- aud_plugin_get_name (p));
+ AUDINFO("Switching from %s to %s.\n", aud_plugin_get_name(old),
+ aud_plugin_get_name(p));
- plugin_set_enabled (old, PluginEnabled::Disabled);
- plugin_set_enabled (p, PluginEnabled::Primary);
+ plugin_set_enabled(old, PluginEnabled::Disabled);
+ plugin_set_enabled(p, PluginEnabled::Primary);
- if (start_plugin (type, p))
+ if (start_plugin(type, p))
return true;
- AUDINFO ("Falling back to %s.\n", aud_plugin_get_name (old));
- plugin_set_enabled (old, PluginEnabled::Primary);
+ AUDINFO("Falling back to %s.\n", aud_plugin_get_name(old));
+ plugin_set_enabled(old, PluginEnabled::Primary);
- if (start_plugin (type, old))
+ if (start_plugin(type, old))
return false;
- abort ();
+ abort();
}
-static bool enable_multi (PluginType type, PluginHandle * p, bool enable)
+static bool enable_multi(PluginType type, PluginHandle * p, bool enable)
{
- AUDINFO ("%sabling %s.\n", enable ? "En" : "Dis", aud_plugin_get_name (p));
+ AUDINFO("%sabling %s.\n", enable ? "En" : "Dis", aud_plugin_get_name(p));
if (enable)
{
- plugin_set_enabled (p, PluginEnabled::Primary);
+ plugin_set_enabled(p, PluginEnabled::Primary);
- if (table[type].f.m.start && ! start_plugin (type, p))
+ if (table[type].f.m.start && !start_plugin(type, p))
return false;
if (type == PluginType::Vis || type == PluginType::General)
- hook_call ("dock plugin enabled", p);
+ hook_call("dock plugin enabled", p);
}
else
{
- plugin_set_enabled (p, PluginEnabled::Disabled);
+ plugin_set_enabled(p, PluginEnabled::Disabled);
if (type == PluginType::Vis || type == PluginType::General)
- hook_call ("dock plugin disabled", p);
+ hook_call("dock plugin disabled", p);
if (table[type].f.m.stop)
- table[type].f.m.stop (p);
+ table[type].f.m.stop(p);
}
return true;
}
-EXPORT bool aud_plugin_enable (PluginHandle * plugin, bool enable)
+EXPORT bool aud_plugin_enable(PluginHandle * plugin, bool enable)
{
- PluginEnabled enabled = plugin_get_enabled (plugin);
+ PluginEnabled enabled = plugin_get_enabled(plugin);
if (enabled == (enable ? PluginEnabled::Primary : PluginEnabled::Disabled))
return true;
- PluginType type = aud_plugin_get_type (plugin);
+ PluginType type = aud_plugin_get_type(plugin);
if (table[type].is_single)
{
- assert (enable);
- return enable_single (type, plugin);
+ assert(enable);
+ return enable_single(type, plugin);
}
- return enable_multi (type, plugin, enable);
+ return enable_multi(type, plugin, enable);
}
-bool plugin_enable_secondary (PluginHandle * plugin, bool enable)
+bool plugin_enable_secondary(PluginHandle * plugin, bool enable)
{
- assert (aud_plugin_get_type (plugin) == PluginType::Output);
+ assert(aud_plugin_get_type(plugin) == PluginType::Output);
- PluginEnabled enabled = plugin_get_enabled (plugin);
- assert (enabled != PluginEnabled::Primary);
+ PluginEnabled enabled = plugin_get_enabled(plugin);
+ assert(enabled != PluginEnabled::Primary);
- if (enabled == (enable ? PluginEnabled::Secondary : PluginEnabled::Disabled))
+ if (enabled ==
+ (enable ? PluginEnabled::Secondary : PluginEnabled::Disabled))
return true;
if (enable)
{
PluginHandle * old;
- if ((old = output_plugin_get_secondary ()))
- plugin_enable_secondary (old, false);
+ if ((old = output_plugin_get_secondary()))
+ plugin_enable_secondary(old, false);
- AUDINFO ("Enabling secondary output plugin %s.\n", aud_plugin_get_name (plugin));
- plugin_set_enabled (plugin, PluginEnabled::Secondary);
- return start_plugin (PluginType::Output, plugin, true);
+ AUDINFO("Enabling secondary output plugin %s.\n",
+ aud_plugin_get_name(plugin));
+ plugin_set_enabled(plugin, PluginEnabled::Secondary);
+ return start_plugin(PluginType::Output, plugin, true);
}
else
{
- AUDINFO ("Disabling secondary output plugin %s.\n", aud_plugin_get_name (plugin));
- plugin_set_enabled (plugin, PluginEnabled::Disabled);
- output_plugin_set_secondary (nullptr);
+ AUDINFO("Disabling secondary output plugin %s.\n",
+ aud_plugin_get_name(plugin));
+ plugin_set_enabled(plugin, PluginEnabled::Disabled);
+ output_plugin_set_secondary(nullptr);
return true;
}
}
/* Miscellaneous plugin-related functions ... */
-EXPORT int aud_plugin_send_message (PluginHandle * plugin, const char * code, const void * data, int size)
+EXPORT int aud_plugin_send_message(PluginHandle * plugin, const char * code,
+ const void * data, int size)
{
- if (! aud_plugin_get_enabled (plugin))
+ if (!aud_plugin_get_enabled(plugin))
return -1;
- Plugin * header = (Plugin *) aud_plugin_get_header (plugin);
- if (! header)
+ Plugin * header = (Plugin *)aud_plugin_get_header(plugin);
+ if (!header)
return -1;
- return header->take_message (code, data, size);
+ return header->take_message(code, data, size);
}
-EXPORT void * aud_plugin_get_gtk_widget (PluginHandle * plugin)
+EXPORT void * aud_plugin_get_gtk_widget(PluginHandle * plugin)
{
- if (! aud_plugin_get_enabled (plugin))
+ if (!aud_plugin_get_enabled(plugin))
return nullptr;
- PluginType type = aud_plugin_get_type (plugin);
+ PluginType type = aud_plugin_get_type(plugin);
if (type != PluginType::General && type != PluginType::Vis)
return nullptr;
- auto dp = (DockablePlugin *) aud_plugin_get_header (plugin);
- return dp ? dp->get_gtk_widget () : nullptr;
+ auto dp = (DockablePlugin *)aud_plugin_get_header(plugin);
+ return dp ? dp->get_gtk_widget() : nullptr;
}
-EXPORT void * aud_plugin_get_qt_widget (PluginHandle * plugin)
+EXPORT void * aud_plugin_get_qt_widget(PluginHandle * plugin)
{
- if (! aud_plugin_get_enabled (plugin))
+ if (!aud_plugin_get_enabled(plugin))
return nullptr;
- PluginType type = aud_plugin_get_type (plugin);
+ PluginType type = aud_plugin_get_type(plugin);
if (type != PluginType::General && type != PluginType::Vis)
return nullptr;
- auto dp = (DockablePlugin *) aud_plugin_get_header (plugin);
- return dp ? dp->get_qt_widget () : nullptr;
+ auto dp = (DockablePlugin *)aud_plugin_get_header(plugin);
+ return dp ? dp->get_qt_widget() : nullptr;
}
diff --git a/src/libaudcore/plugin-load.cc b/src/libaudcore/plugin-load.cc
index 5edb062..cf3953e 100644
--- a/src/libaudcore/plugin-load.cc
+++ b/src/libaudcore/plugin-load.cc
@@ -1,6 +1,6 @@
/*
* plugin-load.cc
- * Copyright 2007-2013 William Pitcock and John Lindgren
+ * Copyright 2007-2013 Ariadne Conill and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -21,7 +21,6 @@
#include <assert.h>
#include <errno.h>
-#include <pthread.h>
#include <string.h>
#include <sys/stat.h>
@@ -33,145 +32,146 @@
#include "plugin.h"
#include "runtime.h"
-static const char * plugin_dir_list[] = {
- "Transport",
- "Container",
- "Input",
- "Output",
- "Effect",
- "General",
- "Visualization"
-};
+static const char * plugin_dir_list[] = {"Transport", "Container", "Input",
+ "Output", "Effect", "General",
+ "Visualization"};
-struct LoadedModule {
+struct LoadedModule
+{
Plugin * header;
GModule * module;
};
static Index<LoadedModule> loaded_modules;
-bool plugin_check_flags (int flags)
+bool plugin_check_flags(int flags)
{
- switch (aud_get_mainloop_type ())
+ switch (aud_get_mainloop_type())
{
- case MainloopType::GLib: flags &= ~PluginGLibOnly; break;
- case MainloopType::Qt: flags &= ~PluginQtOnly; break;
+ case MainloopType::GLib:
+ flags &= ~PluginGLibOnly;
+ break;
+ case MainloopType::Qt:
+ flags &= ~PluginQtOnly;
+ break;
}
- return ! flags;
+ return !flags;
}
-Plugin * plugin_load (const char * filename)
+Plugin * plugin_load(const char * filename)
{
- AUDINFO ("Loading plugin: %s.\n", filename);
+ AUDINFO("Loading plugin: %s.\n", filename);
- GModule * module = g_module_open (filename, G_MODULE_BIND_LOCAL);
+ GModule * module = g_module_open(filename, G_MODULE_BIND_LOCAL);
- if (! module)
+ if (!module)
{
- AUDERR ("%s could not be loaded: %s\n", filename, g_module_error ());
+ AUDERR("%s could not be loaded: %s\n", filename, g_module_error());
return nullptr;
}
Plugin * header;
- if (! g_module_symbol (module, "aud_plugin_instance", (void * *) & header))
+ if (!g_module_symbol(module, "aud_plugin_instance", (void **)&header))
header = nullptr;
- if (! header || header->magic != _AUD_PLUGIN_MAGIC)
+ if (!header || header->magic != _AUD_PLUGIN_MAGIC)
{
- AUDERR ("%s is not a valid Audacious plugin.\n", filename);
- g_module_close (module);
+ AUDERR("%s is not a valid Audacious plugin.\n", filename);
+ g_module_close(module);
return nullptr;
}
if (header->version < _AUD_PLUGIN_VERSION_MIN ||
header->version > _AUD_PLUGIN_VERSION)
{
- AUDERR ("%s is not compatible with this version of Audacious.\n", filename);
- g_module_close (module);
+ AUDERR("%s is not compatible with this version of Audacious.\n",
+ filename);
+ g_module_close(module);
return nullptr;
}
- if (plugin_check_flags (header->info.flags) &&
+ if (plugin_check_flags(header->info.flags) &&
(header->type == PluginType::Transport ||
header->type == PluginType::Playlist ||
header->type == PluginType::Input ||
header->type == PluginType::Effect))
{
- if (! header->init ())
+ if (!header->init())
{
- AUDERR ("%s failed to initialize.\n", filename);
- g_module_close (module);
+ AUDERR("%s failed to initialize.\n", filename);
+ g_module_close(module);
return nullptr;
}
}
- loaded_modules.append (header, module);
+ loaded_modules.append(header, module);
return header;
}
-static void plugin_unload (LoadedModule & loaded)
+static void plugin_unload(LoadedModule & loaded)
{
- if (plugin_check_flags (loaded.header->info.flags) &&
+ if (plugin_check_flags(loaded.header->info.flags) &&
(loaded.header->type == PluginType::Transport ||
loaded.header->type == PluginType::Playlist ||
loaded.header->type == PluginType::Input ||
loaded.header->type == PluginType::Effect))
{
- loaded.header->cleanup ();
+ loaded.header->cleanup();
}
#ifndef VALGRIND_FRIENDLY
- g_module_close (loaded.module);
+ g_module_close(loaded.module);
#endif
}
/******************************************************************/
-static bool scan_plugin_func (const char * path, const char * basename, void * data)
+static bool scan_plugin_func(const char * path, const char * basename,
+ void * data)
{
- if (! str_has_suffix_nocase (basename, PLUGIN_SUFFIX))
+ if (!str_has_suffix_nocase(basename, PLUGIN_SUFFIX))
return false;
GStatBuf st;
- if (g_stat (path, & st) < 0)
+ if (g_stat(path, &st) < 0)
{
- AUDERR ("Unable to stat %s: %s\n", path, strerror (errno));
+ AUDERR("Unable to stat %s: %s\n", path, strerror(errno));
return false;
}
- if (S_ISREG (st.st_mode))
- plugin_register (path, st.st_mtime);
+ if (S_ISREG(st.st_mode))
+ plugin_register(path, st.st_mtime);
return false;
}
-static void scan_plugins (const char * path)
+static void scan_plugins(const char * path)
{
- dir_foreach (path, scan_plugin_func, nullptr);
+ dir_foreach(path, scan_plugin_func, nullptr);
}
-void plugin_system_init ()
+void plugin_system_init()
{
- assert (g_module_supported ());
+ assert(g_module_supported());
- plugin_registry_load ();
+ plugin_registry_load();
- const char * path = aud_get_path (AudPath::PluginDir);
+ const char * path = aud_get_path(AudPath::PluginDir);
for (const char * dir : plugin_dir_list)
- scan_plugins (filename_build ({path, dir}));
+ scan_plugins(filename_build({path, dir}));
- plugin_registry_prune ();
+ plugin_registry_prune();
}
-void plugin_system_cleanup ()
+void plugin_system_cleanup()
{
- plugin_registry_save ();
- plugin_registry_cleanup ();
+ plugin_registry_save();
+ plugin_registry_cleanup();
for (LoadedModule & loaded : loaded_modules)
- plugin_unload (loaded);
+ plugin_unload(loaded);
- loaded_modules.clear ();
+ loaded_modules.clear();
}
diff --git a/src/libaudcore/plugin-registry.cc b/src/libaudcore/plugin-registry.cc
index 3ca79f3..b5e8167 100644
--- a/src/libaudcore/plugin-registry.cc
+++ b/src/libaudcore/plugin-registry.cc
@@ -20,7 +20,6 @@
#include "plugins-internal.h"
#include <errno.h>
-#include <pthread.h>
#include <string.h>
#include <glib/gstdio.h>
@@ -31,17 +30,20 @@
#include "parse.h"
#include "plugin.h"
#include "runtime.h"
+#include "threads.h"
#define FILENAME "plugin-registry"
/* Increment this when the format of the plugin-registry file changes.
- * Add 10 if the format changes in a way that will break parse_plugins_fallback(). */
+ * Add 10 if the format changes in a way that will break
+ * parse_plugins_fallback(). */
#define FORMAT 11
/* Oldest file format supported by parse_plugins_fallback() */
-#define MIN_FORMAT 2 // "enabled" flag was added in Audacious 2.4
+#define MIN_FORMAT 2 // "enabled" flag was added in Audacious 2.4
-struct PluginWatch {
+struct PluginWatch
+{
PluginWatchFunc func;
void * data;
};
@@ -71,347 +73,333 @@ public:
aud::array<InputKey, Index<String>> keys;
int has_subtunes, writes_tag;
- PluginHandle (const char * basename, const char * path, bool loaded,
- int timestamp, int version, int flags, PluginType type, Plugin * header) :
- basename (basename),
- path (path),
- loaded (loaded),
- timestamp (timestamp),
- version (version),
- flags (flags),
- type (type),
- header (header),
- priority (0),
- has_about (false),
- has_configure (false),
- enabled ((type == PluginType::Transport ||
- type == PluginType::Playlist || type == PluginType::Input) ?
- PluginEnabled::Primary : PluginEnabled::Disabled),
- can_save (false),
- has_subtunes (false),
- writes_tag (false) {}
-
- ~PluginHandle ()
+ PluginHandle(const char * basename, const char * path, bool loaded,
+ int timestamp, int version, int flags, PluginType type,
+ Plugin * header)
+ : basename(basename), path(path), loaded(loaded), timestamp(timestamp),
+ version(version), flags(flags), type(type), header(header),
+ priority(0), has_about(false), has_configure(false),
+ enabled((type == PluginType::Transport ||
+ type == PluginType::Playlist || type == PluginType::Input)
+ ? PluginEnabled::Primary
+ : PluginEnabled::Disabled),
+ can_save(false), has_subtunes(false), writes_tag(false)
+ {
+ }
+
+ ~PluginHandle()
{
- if (watches.len ())
- AUDWARN ("Plugin watch count not zero at exit!\n");
+ if (watches.len())
+ AUDWARN("Plugin watch count not zero at exit!\n");
}
};
static constexpr aud::array<PluginType, const char *> plugin_type_names = {
- "transport",
- "playlist",
- "input",
- "effect",
- "output",
- "vis",
- "general",
- "iface"
-};
+ "transport", "playlist", "input", "effect",
+ "output", "vis", "general", "iface"};
static constexpr aud::array<InputKey, const char *> input_key_names = {
- "scheme",
- "ext",
- "mime"
-};
+ "scheme", "ext", "mime"};
static aud::array<PluginType, Index<PluginHandle *>> plugins;
static aud::array<PluginType, Index<PluginHandle *>> compatible;
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static aud::mutex mutex;
static bool modified = false;
-static StringBuf get_basename (const char * path)
+static StringBuf get_basename(const char * path)
{
- const char * slash = strrchr (path, G_DIR_SEPARATOR);
- const char * dot = slash ? strrchr (slash + 1, '.') : nullptr;
+ const char * slash = strrchr(path, G_DIR_SEPARATOR);
+ const char * dot = slash ? strrchr(slash + 1, '.') : nullptr;
- return dot ? str_copy (slash + 1, dot - (slash + 1)) : StringBuf ();
+ return dot ? str_copy(slash + 1, dot - (slash + 1)) : StringBuf();
}
-static FILE * open_registry_file (const char * mode)
+static FILE * open_registry_file(const char * mode)
{
- StringBuf path = filename_build ({aud_get_path (AudPath::UserDir), FILENAME});
- FILE * handle = g_fopen (path, mode);
+ StringBuf path = filename_build({aud_get_path(AudPath::UserDir), FILENAME});
+ FILE * handle = g_fopen(path, mode);
- if (! handle && errno != ENOENT)
- AUDWARN ("%s: %s\n", (const char *) path, strerror (errno));
+ if (!handle && errno != ENOENT)
+ AUDWARN("%s: %s\n", (const char *)path, strerror(errno));
return handle;
}
-static void transport_plugin_save (PluginHandle * plugin, FILE * handle)
+static void transport_plugin_save(PluginHandle * plugin, FILE * handle)
{
for (const String & scheme : plugin->schemes)
- fprintf (handle, "scheme %s\n", (const char *) scheme);
+ fprintf(handle, "scheme %s\n", (const char *)scheme);
}
-static void playlist_plugin_save (PluginHandle * plugin, FILE * handle)
+static void playlist_plugin_save(PluginHandle * plugin, FILE * handle)
{
for (const String & ext : plugin->exts)
- fprintf (handle, "ext %s\n", (const char *) ext);
+ fprintf(handle, "ext %s\n", (const char *)ext);
- fprintf (handle, "saves %d\n", plugin->can_save);
+ fprintf(handle, "saves %d\n", plugin->can_save);
}
-static void input_plugin_save (PluginHandle * plugin, FILE * handle)
+static void input_plugin_save(PluginHandle * plugin, FILE * handle)
{
- for (auto k : aud::range<InputKey> ())
+ for (auto k : aud::range<InputKey>())
{
for (const String & key : plugin->keys[k])
- fprintf (handle, "%s %s\n", input_key_names[k], (const char *) key);
+ fprintf(handle, "%s %s\n", input_key_names[k], (const char *)key);
}
- fprintf (handle, "subtunes %d\n", plugin->has_subtunes);
- fprintf (handle, "writes %d\n", plugin->writes_tag);
+ fprintf(handle, "subtunes %d\n", plugin->has_subtunes);
+ fprintf(handle, "writes %d\n", plugin->writes_tag);
}
-static void plugin_save (PluginHandle * plugin, FILE * handle)
+static void plugin_save(PluginHandle * plugin, FILE * handle)
{
- fprintf (handle, "%s %s\n", plugin_type_names[plugin->type], (const char *) plugin->path);
- fprintf (handle, "stamp %d\n", plugin->timestamp);
- fprintf (handle, "version %d\n", plugin->version);
- fprintf (handle, "flags %d\n", plugin->flags);
- fprintf (handle, "name %s\n", (const char *) plugin->name);
+ fprintf(handle, "%s %s\n", plugin_type_names[plugin->type],
+ (const char *)plugin->path);
+ fprintf(handle, "stamp %d\n", plugin->timestamp);
+ fprintf(handle, "version %d\n", plugin->version);
+ fprintf(handle, "flags %d\n", plugin->flags);
+ fprintf(handle, "name %s\n", (const char *)plugin->name);
if (plugin->domain)
- fprintf (handle, "domain %s\n", (const char *) plugin->domain);
+ fprintf(handle, "domain %s\n", (const char *)plugin->domain);
- fprintf (handle, "priority %d\n", plugin->priority);
- fprintf (handle, "about %d\n", plugin->has_about);
- fprintf (handle, "config %d\n", plugin->has_configure);
- fprintf (handle, "enabled %d\n", (int) plugin->enabled);
+ fprintf(handle, "priority %d\n", plugin->priority);
+ fprintf(handle, "about %d\n", plugin->has_about);
+ fprintf(handle, "config %d\n", plugin->has_configure);
+ fprintf(handle, "enabled %d\n", (int)plugin->enabled);
if (plugin->type == PluginType::Transport)
- transport_plugin_save (plugin, handle);
+ transport_plugin_save(plugin, handle);
else if (plugin->type == PluginType::Playlist)
- playlist_plugin_save (plugin, handle);
+ playlist_plugin_save(plugin, handle);
else if (plugin->type == PluginType::Input)
- input_plugin_save (plugin, handle);
+ input_plugin_save(plugin, handle);
}
-void plugin_registry_save ()
+void plugin_registry_save()
{
- if (! modified)
+ if (!modified)
return;
- FILE * handle = open_registry_file ("w");
- if (! handle)
+ FILE * handle = open_registry_file("w");
+ if (!handle)
return;
- fprintf (handle, "format %d\n", FORMAT);
+ fprintf(handle, "format %d\n", FORMAT);
for (auto & list : plugins)
{
for (PluginHandle * plugin : list)
- plugin_save (plugin, handle);
+ plugin_save(plugin, handle);
}
- fclose (handle);
+ fclose(handle);
modified = false;
}
-void plugin_registry_cleanup ()
+void plugin_registry_cleanup()
{
for (auto & list : plugins)
{
for (PluginHandle * plugin : list)
delete plugin;
- list.clear ();
+ list.clear();
}
for (auto & list : compatible)
- list.clear ();
+ list.clear();
}
-static void transport_plugin_parse (PluginHandle * plugin, TextParser & parser)
+static void transport_plugin_parse(PluginHandle * plugin, TextParser & parser)
{
while (1)
{
- String value = parser.get_str ("scheme");
- if (! value)
+ String value = parser.get_str("scheme");
+ if (!value)
break;
- plugin->schemes.append (std::move (value));
- parser.next ();
+ plugin->schemes.append(std::move(value));
+ parser.next();
}
}
-static void playlist_plugin_parse (PluginHandle * plugin, TextParser & parser)
+static void playlist_plugin_parse(PluginHandle * plugin, TextParser & parser)
{
while (1)
{
- String value = parser.get_str ("ext");
- if (! value)
+ String value = parser.get_str("ext");
+ if (!value)
break;
- plugin->exts.append (std::move (value));
- parser.next ();
+ plugin->exts.append(std::move(value));
+ parser.next();
}
- if (parser.get_int ("saves", plugin->can_save))
- parser.next ();
+ if (parser.get_int("saves", plugin->can_save))
+ parser.next();
}
-static void input_plugin_parse (PluginHandle * plugin, TextParser & parser)
+static void input_plugin_parse(PluginHandle * plugin, TextParser & parser)
{
- for (auto key : aud::range<InputKey> ())
+ for (auto key : aud::range<InputKey>())
{
while (1)
{
- String value = parser.get_str (input_key_names[key]);
- if (! value)
+ String value = parser.get_str(input_key_names[key]);
+ if (!value)
break;
- plugin->keys[key].append (std::move (value));
- parser.next ();
+ plugin->keys[key].append(std::move(value));
+ parser.next();
}
}
- if (parser.get_int ("subtunes", plugin->has_subtunes))
- parser.next ();
- if (parser.get_int ("writes", plugin->writes_tag))
- parser.next ();
+ if (parser.get_int("subtunes", plugin->has_subtunes))
+ parser.next();
+ if (parser.get_int("writes", plugin->writes_tag))
+ parser.next();
}
-static bool plugin_parse (TextParser & parser)
+static bool plugin_parse(TextParser & parser)
{
PluginType type;
String path;
- for (auto type2 : aud::range<PluginType> ())
+ for (auto type2 : aud::range<PluginType>())
{
type = type2;
- if ((path = parser.get_str (plugin_type_names[type2])))
+ if ((path = parser.get_str(plugin_type_names[type2])))
break;
}
- if (! path)
+ if (!path)
return false;
- StringBuf basename = get_basename (path);
- if (! basename)
+ StringBuf basename = get_basename(path);
+ if (!basename)
return false;
- parser.next ();
+ parser.next();
int timestamp;
- if (! parser.get_int ("stamp", timestamp))
+ if (!parser.get_int("stamp", timestamp))
return false;
- parser.next ();
+ parser.next();
int version = 0, flags = 0;
- if (parser.get_int ("version", version))
- parser.next ();
- if (parser.get_int ("flags", flags))
- parser.next ();
+ if (parser.get_int("version", version))
+ parser.next();
+ if (parser.get_int("flags", flags))
+ parser.next();
- auto plugin = new PluginHandle (basename, String (), false, timestamp,
- version, flags, type, nullptr);
+ auto plugin = new PluginHandle(basename, String(), false, timestamp,
+ version, flags, type, nullptr);
- plugins[type].append (plugin);
+ plugins[type].append(plugin);
- plugin->name = parser.get_str ("name");
+ plugin->name = parser.get_str("name");
if (plugin->name)
- parser.next ();
+ parser.next();
- plugin->domain = parser.get_str ("domain");
+ plugin->domain = parser.get_str("domain");
if (plugin->domain)
- parser.next ();
+ parser.next();
- if (parser.get_int ("priority", plugin->priority))
- parser.next ();
- if (parser.get_int ("about", plugin->has_about))
- parser.next ();
- if (parser.get_int ("config", plugin->has_configure))
- parser.next ();
+ if (parser.get_int("priority", plugin->priority))
+ parser.next();
+ if (parser.get_int("about", plugin->has_about))
+ parser.next();
+ if (parser.get_int("config", plugin->has_configure))
+ parser.next();
int enabled;
- if (parser.get_int ("enabled", enabled))
+ if (parser.get_int("enabled", enabled))
{
- plugin->enabled = (PluginEnabled) enabled;
- parser.next ();
+ plugin->enabled = (PluginEnabled)enabled;
+ parser.next();
}
if (type == PluginType::Transport)
- transport_plugin_parse (plugin, parser);
+ transport_plugin_parse(plugin, parser);
else if (type == PluginType::Playlist)
- playlist_plugin_parse (plugin, parser);
+ playlist_plugin_parse(plugin, parser);
else if (type == PluginType::Input)
- input_plugin_parse (plugin, parser);
+ input_plugin_parse(plugin, parser);
return true;
}
/* try to migrate enabled status from another version */
-static void parse_plugins_fallback (TextParser & parser)
+static void parse_plugins_fallback(TextParser & parser)
{
- for (; ! parser.eof (); parser.next ())
+ for (; !parser.eof(); parser.next())
{
PluginType type;
String path;
int enabled;
- for (auto type2 : aud::range<PluginType> ())
+ for (auto type2 : aud::range<PluginType>())
{
type = type2;
- if ((path = parser.get_str (plugin_type_names[type2])))
+ if ((path = parser.get_str(plugin_type_names[type2])))
break;
}
- if (! path)
+ if (!path)
continue;
- StringBuf basename = get_basename (path);
- if (! basename)
+ StringBuf basename = get_basename(path);
+ if (!basename)
continue;
- parser.next ();
+ parser.next();
- for (; ! parser.eof (); parser.next ())
+ for (; !parser.eof(); parser.next())
{
- if (parser.get_int ("enabled", enabled))
+ if (parser.get_int("enabled", enabled))
break;
}
- if (parser.eof ())
+ if (parser.eof())
return;
// setting timestamp to zero forces a rescan
- auto plugin = new PluginHandle (basename, String (), false, 0, 0, 0, type, nullptr);
- plugins[type].append (plugin);
- plugin->enabled = (PluginEnabled) enabled;
+ auto plugin =
+ new PluginHandle(basename, String(), false, 0, 0, 0, type, nullptr);
+ plugins[type].append(plugin);
+ plugin->enabled = (PluginEnabled)enabled;
}
}
-void plugin_registry_load ()
+void plugin_registry_load()
{
- FILE * handle = open_registry_file ("r");
- if (! handle)
+ FILE * handle = open_registry_file("r");
+ if (!handle)
return;
- TextParser parser (handle);
+ TextParser parser(handle);
int format;
- if (! parser.get_int ("format", format))
+ if (!parser.get_int("format", format))
goto ERR;
- parser.next ();
+ parser.next();
if (format == FORMAT)
{
- while (plugin_parse (parser))
+ while (plugin_parse(parser))
continue;
}
else if (format >= MIN_FORMAT && format < FORMAT + 10)
- parse_plugins_fallback (parser);
+ parse_plugins_fallback(parser);
ERR:
- fclose (handle);
+ fclose(handle);
}
-static int plugin_compare (PluginHandle * const & a, PluginHandle * const & b)
+static int plugin_compare(PluginHandle * const & a, PluginHandle * const & b)
{
if (a->type < b->type)
return -1;
@@ -423,51 +411,52 @@ static int plugin_compare (PluginHandle * const & a, PluginHandle * const & b)
return 1;
int diff;
- if ((diff = str_compare (dgettext (a->domain, a->name), dgettext (b->domain, b->name))))
+ if ((diff = str_compare(dgettext(a->domain, a->name),
+ dgettext(b->domain, b->name))))
return diff;
- return str_compare (a->path, b->path);
+ return str_compare(a->path, b->path);
}
-void plugin_registry_prune ()
+void plugin_registry_prune()
{
- auto check_not_found = [] (PluginHandle * plugin)
- {
+ auto check_not_found = [](PluginHandle * plugin) {
if (plugin->path)
return false;
- AUDINFO ("Plugin not found: %s\n", (const char *) plugin->basename);
+ AUDINFO("Plugin not found: %s\n", (const char *)plugin->basename);
delete plugin;
return true;
};
- auto check_incompatible = [] (PluginHandle * plugin)
- {
- if (plugin_check_flags (plugin->flags))
+ auto check_incompatible = [](PluginHandle * plugin) {
+ if (plugin_check_flags(plugin->flags))
return false;
- AUDINFO ("Incompatible plugin flags: %s\n", (const char *) plugin->basename);
+ AUDINFO("Incompatible plugin flags: %s\n",
+ (const char *)plugin->basename);
return true;
};
- for (auto type : aud::range<PluginType> ())
+ for (auto type : aud::range<PluginType>())
{
- plugins[type].remove_if (check_not_found);
- plugins[type].sort (plugin_compare);
- compatible[type].insert (plugins[type].begin (), 0, plugins[type].len ());
- compatible[type].remove_if (check_incompatible);
+ plugins[type].remove_if(check_not_found);
+ plugins[type].sort(plugin_compare);
+ compatible[type].insert(plugins[type].begin(), 0, plugins[type].len());
+ compatible[type].remove_if(check_incompatible);
}
}
/* Note: If there are multiple plugins with the same basename, this returns only
* one of them. Different plugins should be given different basenames. */
-static PluginHandle * plugin_lookup_basename (const char * basename, bool compat_only)
+static PluginHandle * plugin_lookup_basename(const char * basename,
+ bool compat_only)
{
for (auto & list : (compat_only ? compatible : plugins))
{
for (PluginHandle * plugin : list)
{
- if (! strcmp (plugin->basename, basename))
+ if (!strcmp(plugin->basename, basename))
return plugin;
}
}
@@ -475,145 +464,147 @@ static PluginHandle * plugin_lookup_basename (const char * basename, bool compat
return nullptr;
}
-EXPORT PluginHandle * aud_plugin_lookup_basename (const char * basename)
+EXPORT PluginHandle * aud_plugin_lookup_basename(const char * basename)
{
- return plugin_lookup_basename (basename, true);
+ return plugin_lookup_basename(basename, true);
}
-static void plugin_get_info (PluginHandle * plugin, bool is_new)
+static void plugin_get_info(PluginHandle * plugin, bool is_new)
{
Plugin * header = plugin->header;
plugin->version = header->version;
plugin->flags = header->info.flags;
- plugin->name = String (header->info.name);
- plugin->domain = String (header->info.domain);
- plugin->has_about = (bool) header->info.about;
- plugin->has_configure = (bool) header->info.prefs;
+ plugin->name = String(header->info.name);
+ plugin->domain = String(header->info.domain);
+ plugin->has_about = (bool)header->info.about;
+ plugin->has_configure = (bool)header->info.prefs;
if (header->type == PluginType::Transport)
{
- TransportPlugin * tp = (TransportPlugin *) header;
+ TransportPlugin * tp = (TransportPlugin *)header;
- plugin->schemes.clear ();
+ plugin->schemes.clear();
for (const char * scheme : tp->schemes)
- plugin->schemes.append (String (scheme));
+ plugin->schemes.append(String(scheme));
}
else if (header->type == PluginType::Playlist)
{
- PlaylistPlugin * pp = (PlaylistPlugin *) header;
+ PlaylistPlugin * pp = (PlaylistPlugin *)header;
- plugin->exts.clear ();
+ plugin->exts.clear();
for (const char * ext : pp->extensions)
- plugin->exts.append (String (ext));
+ plugin->exts.append(String(ext));
plugin->can_save = pp->can_save;
}
else if (header->type == PluginType::Input)
{
- InputPlugin * ip = (InputPlugin *) header;
+ InputPlugin * ip = (InputPlugin *)header;
plugin->priority = ip->input_info.priority;
- for (auto k : aud::range<InputKey> ())
+ for (auto k : aud::range<InputKey>())
{
- plugin->keys[k].clear ();
- for (auto key = ip->input_info.keys[k]; key && * key; key ++)
- plugin->keys[k].append (String (* key));
+ plugin->keys[k].clear();
+ for (auto key = ip->input_info.keys[k]; key && *key; key++)
+ plugin->keys[k].append(String(*key));
}
- plugin->has_subtunes = (ip->input_info.flags & InputPlugin::FlagSubtunes);
- plugin->writes_tag = (ip->input_info.flags & InputPlugin::FlagWritesTag);
+ plugin->has_subtunes =
+ (ip->input_info.flags & InputPlugin::FlagSubtunes);
+ plugin->writes_tag =
+ (ip->input_info.flags & InputPlugin::FlagWritesTag);
}
else if (header->type == PluginType::Output)
{
- OutputPlugin * op = (OutputPlugin *) header;
+ OutputPlugin * op = (OutputPlugin *)header;
plugin->priority = 10 - op->priority;
}
else if (header->type == PluginType::Effect)
{
- EffectPlugin * ep = (EffectPlugin *) header;
+ EffectPlugin * ep = (EffectPlugin *)header;
plugin->priority = ep->order;
}
else if (header->type == PluginType::General)
{
- GeneralPlugin * gp = (GeneralPlugin *) header;
+ GeneralPlugin * gp = (GeneralPlugin *)header;
if (is_new && gp->enabled_by_default)
plugin->enabled = PluginEnabled::Primary;
}
}
-void plugin_register (const char * path, int timestamp)
+void plugin_register(const char * path, int timestamp)
{
- StringBuf basename = get_basename (path);
- if (! basename)
+ StringBuf basename = get_basename(path);
+ if (!basename)
return;
- PluginHandle * plugin = plugin_lookup_basename (basename, false);
+ PluginHandle * plugin = plugin_lookup_basename(basename, false);
if (plugin)
{
- AUDINFO ("Register plugin: %s\n", path);
- plugin->path = String (path);
+ AUDINFO("Register plugin: %s\n", path);
+ plugin->path = String(path);
if (plugin->timestamp != timestamp)
{
- AUDINFO ("Rescan plugin: %s\n", path);
- Plugin * header = plugin_load (path);
- if (! header || header->type != plugin->type)
+ AUDINFO("Rescan plugin: %s\n", path);
+ Plugin * header = plugin_load(path);
+ if (!header || header->type != plugin->type)
return;
plugin->loaded = true;
plugin->header = header;
plugin->timestamp = timestamp;
- plugin_get_info (plugin, false);
+ plugin_get_info(plugin, false);
modified = true;
}
}
else
{
- AUDINFO ("New plugin: %s\n", path);
- Plugin * header = plugin_load (path);
- if (! header)
+ AUDINFO("New plugin: %s\n", path);
+ Plugin * header = plugin_load(path);
+ if (!header)
return;
- plugin = new PluginHandle (basename, path, true, timestamp,
- header->version, header->info.flags, header->type, header);
- plugins[plugin->type].append (plugin);
+ plugin =
+ new PluginHandle(basename, path, true, timestamp, header->version,
+ header->info.flags, header->type, header);
+ plugins[plugin->type].append(plugin);
- plugin_get_info (plugin, true);
+ plugin_get_info(plugin, true);
modified = true;
}
}
-EXPORT PluginType aud_plugin_get_type (PluginHandle * plugin)
+EXPORT PluginType aud_plugin_get_type(PluginHandle * plugin)
{
return plugin->type;
}
-EXPORT const char * aud_plugin_get_basename (PluginHandle * plugin)
+EXPORT const char * aud_plugin_get_basename(PluginHandle * plugin)
{
return plugin->basename;
}
-EXPORT const void * aud_plugin_get_header (PluginHandle * plugin)
+EXPORT const void * aud_plugin_get_header(PluginHandle * plugin)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- if (! plugin->loaded)
+ if (!plugin->loaded)
{
- Plugin * header = plugin_load (plugin->path);
+ Plugin * header = plugin_load(plugin->path);
if (header && header->type == plugin->type)
plugin->header = header;
plugin->loaded = true;
}
- pthread_mutex_unlock (& mutex);
return plugin->header;
}
-EXPORT PluginHandle * aud_plugin_by_header (const void * header)
+EXPORT PluginHandle * aud_plugin_by_header(const void * header)
{
for (auto & list : compatible)
{
@@ -627,119 +618,159 @@ EXPORT PluginHandle * aud_plugin_by_header (const void * header)
return nullptr;
}
-EXPORT const Index<PluginHandle *> & aud_plugin_list (PluginType type)
+EXPORT const Index<PluginHandle *> & aud_plugin_list(PluginType type)
{
return compatible[type];
}
-EXPORT const char * aud_plugin_get_name (PluginHandle * plugin)
+EXPORT const char * aud_plugin_get_name(PluginHandle * plugin)
{
- return dgettext (plugin->domain, plugin->name);
+ return dgettext(plugin->domain, plugin->name);
}
-EXPORT bool aud_plugin_has_about (PluginHandle * plugin)
+EXPORT bool aud_plugin_has_about(PluginHandle * plugin)
{
return plugin->has_about;
}
-EXPORT bool aud_plugin_has_configure (PluginHandle * plugin)
+EXPORT bool aud_plugin_has_configure(PluginHandle * plugin)
{
return plugin->has_configure;
}
-EXPORT bool aud_plugin_get_enabled (PluginHandle * plugin)
+EXPORT bool aud_plugin_get_enabled(PluginHandle * plugin)
{
return plugin->enabled != PluginEnabled::Disabled;
}
-static void plugin_call_watches (PluginHandle * plugin)
+static void plugin_call_watches(PluginHandle * plugin)
{
- auto call_and_check_remove = [=] (const PluginWatch & watch)
- { return ! watch.func (plugin, watch.data); };
+ auto call_and_check_remove = [=](const PluginWatch & watch) {
+ return !watch.func(plugin, watch.data);
+ };
- plugin->watches.remove_if (call_and_check_remove);
+ plugin->watches.remove_if(call_and_check_remove);
}
-PluginEnabled plugin_get_enabled (PluginHandle * plugin)
+PluginEnabled plugin_get_enabled(PluginHandle * plugin)
{
return plugin->enabled;
}
-void plugin_set_enabled (PluginHandle * plugin, PluginEnabled enabled)
+void plugin_set_enabled(PluginHandle * plugin, PluginEnabled enabled)
{
plugin->enabled = enabled;
- plugin_call_watches (plugin);
+ plugin_call_watches(plugin);
modified = true;
}
-void plugin_set_failed (PluginHandle * plugin)
+void plugin_set_failed(PluginHandle * plugin)
{
plugin->header = nullptr;
- plugin_set_enabled (plugin, PluginEnabled::Disabled);
+ plugin_set_enabled(plugin, PluginEnabled::Disabled);
}
-EXPORT void aud_plugin_add_watch (PluginHandle * plugin, PluginWatchFunc func, void * data)
+EXPORT void aud_plugin_add_watch(PluginHandle * plugin, PluginWatchFunc func,
+ void * data)
{
- plugin->watches.append (func, data);
+ plugin->watches.append(func, data);
}
-EXPORT void aud_plugin_remove_watch (PluginHandle * plugin, PluginWatchFunc func, void * data)
+EXPORT void aud_plugin_remove_watch(PluginHandle * plugin, PluginWatchFunc func,
+ void * data)
{
- auto is_match = [=] (const PluginWatch & watch)
- { return watch.func == func && watch.data == data; };
+ auto is_match = [=](const PluginWatch & watch) {
+ return watch.func == func && watch.data == data;
+ };
- plugin->watches.remove_if (is_match);
+ plugin->watches.remove_if(is_match);
}
-bool transport_plugin_has_scheme (PluginHandle * plugin, const char * scheme)
+const Index<String> & transport_plugin_get_schemes(PluginHandle * plugin)
+{
+ return plugin->schemes;
+}
+
+bool transport_plugin_has_scheme(PluginHandle * plugin, const char * scheme)
{
for (String & s : plugin->schemes)
{
- if (! strcmp (s, scheme))
+ if (!strcmp(s, scheme))
return true;
}
return false;
}
-bool playlist_plugin_can_save (PluginHandle * plugin)
+bool playlist_plugin_can_save(PluginHandle * plugin)
{
return plugin->can_save;
}
-const Index<String> & playlist_plugin_get_exts (PluginHandle * plugin)
+const Index<String> & playlist_plugin_get_exts(PluginHandle * plugin)
{
return plugin->exts;
}
-bool playlist_plugin_has_ext (PluginHandle * plugin, const char * ext)
+bool playlist_plugin_has_ext(PluginHandle * plugin, const char * ext)
{
for (String & e : plugin->exts)
{
- if (! strcmp_nocase (e, ext))
+ if (!strcmp_nocase(e, ext))
return true;
}
return false;
}
-bool input_plugin_has_key (PluginHandle * plugin, InputKey key, const char * value)
+bool input_plugin_has_key(PluginHandle * plugin, InputKey key,
+ const char * value)
{
for (String & s : plugin->keys[key])
{
- if (! strcmp_nocase (s, value))
+ if (!strcmp_nocase(s, value))
return true;
}
return false;
}
-bool input_plugin_has_subtunes (PluginHandle * plugin)
+bool input_plugin_has_subtunes(PluginHandle * plugin)
{
return plugin->has_subtunes;
}
-bool input_plugin_can_write_tuple (PluginHandle * plugin)
+bool input_plugin_can_write_tuple(PluginHandle * plugin)
{
return plugin->writes_tag;
}
+
+EXPORT Index<const char *> aud_plugin_get_supported_mime_types()
+{
+ Index<const char *> mimes;
+
+ for (PluginHandle * p : aud_plugin_list(PluginType::Input))
+ {
+ if (!aud_plugin_get_enabled(p))
+ continue;
+
+ for (auto k : p->keys[InputKey::MIME])
+ mimes.append((const char *)k);
+ }
+
+ /* sort and remove duplicates */
+ /* lambda needed to avoid -Wnoexcept-type with GCC */
+ mimes.sort([](const char * a, const char * b) { return strcmp(a, b); });
+
+ int len = mimes.len();
+ for (int i = 0; i + 1 < len; i++)
+ {
+ if (!strcmp(mimes[i], mimes[i + 1]))
+ mimes[i] = nullptr;
+ }
+
+ mimes.remove_if([](const char * m) { return m == nullptr; });
+ mimes.append(nullptr);
+
+ return mimes;
+}
diff --git a/src/libaudcore/plugin.h b/src/libaudcore/plugin.h
index 65d0428..bd45fea 100644
--- a/src/libaudcore/plugin.h
+++ b/src/libaudcore/plugin.h
@@ -1,6 +1,6 @@
/*
* plugin.h
- * Copyright 2005-2013 William Pitcock, Yoshiki Yazawa, Eugene Zagidullin, and
+ * Copyright 2005-2013 Ariadne Conill, Yoshiki Yazawa, Eugene Zagidullin, and
* John Lindgren
*
* Redistribution and use in source and binary forms, with or without
@@ -25,14 +25,14 @@
#include <libaudcore/export.h>
#include <libaudcore/plugins.h>
#include <libaudcore/tuple.h>
-#include <libaudcore/visualizer.h>
#include <libaudcore/vfs.h>
+#include <libaudcore/visualizer.h>
enum class AudMenuID;
struct PluginPreferences;
/* "Magic" bytes identifying an Audacious plugin header. */
-#define _AUD_PLUGIN_MAGIC ((int) 0x8EAC8DE2)
+#define _AUD_PLUGIN_MAGIC ((int)0x8EAC8DE2)
/* API version. Plugins are marked with this number at compile time.
*
@@ -48,7 +48,10 @@ struct PluginPreferences;
* _AUD_PLUGIN_VERSION_MIN to the same value. */
#define _AUD_PLUGIN_VERSION_MIN 48 /* 3.8-devel */
-#define _AUD_PLUGIN_VERSION 48 /* 3.8-devel */
+#define _AUD_PLUGIN_VERSION 48 /* 3.8-devel */
+
+/* Default priority. */
+#define _AUD_PLUGIN_DEFAULT_PRIO 5
/* A NOTE ON THREADS
*
@@ -80,7 +83,8 @@ struct PluginPreferences;
* Since 3.2, Audacious implements a basic messaging system between plugins.
* Messages are sent using aud_plugin_send_message() and received through the
* take_message() method specified in the header of the receiving plugin.
- * Plugins that do not need to receive messages can set take_message() to nullptr.
+ * Plugins that do not need to receive messages can set take_message() to
+ * nullptr.
*
* Each message includes a code indicating the type of message, a pointer to
* some data, and a value indicating the size of that data. What the message
@@ -97,9 +101,10 @@ struct PluginPreferences;
* program's main thread. */
/* plugin flags */
-enum {
+enum
+{
PluginGLibOnly = 0x1, // plugin requires GLib main loop
- PluginQtOnly = 0x2 // plugin requires Qt main loop
+ PluginQtOnly = 0x2 // plugin requires Qt main loop
};
struct PluginInfo
@@ -114,9 +119,9 @@ struct PluginInfo
class LIBAUDCORE_PUBLIC Plugin
{
public:
- constexpr Plugin (PluginType type, PluginInfo info) :
- type (type),
- info (info) {}
+ constexpr Plugin(PluginType type, PluginInfo info) : type(type), info(info)
+ {
+ }
const int magic = _AUD_PLUGIN_MAGIC;
const int version = _AUD_PLUGIN_VERSION;
@@ -124,40 +129,52 @@ public:
const PluginType type;
const PluginInfo info;
- virtual bool init () { return true; }
- virtual void cleanup () {}
+ virtual bool init() { return true; }
+ virtual void cleanup() {}
- virtual int take_message (const char * code, const void * data, int size) { return -1; }
+ virtual int take_message(const char * code, const void * data, int size)
+ {
+ return -1;
+ }
};
class LIBAUDCORE_PUBLIC TransportPlugin : public Plugin
{
public:
- constexpr TransportPlugin (const PluginInfo info,
- const ArrayRef<const char *> schemes) :
- Plugin (PluginType::Transport, info),
- schemes (schemes) {}
+ constexpr TransportPlugin(const PluginInfo info,
+ const ArrayRef<const char *> schemes)
+ : Plugin(PluginType::Transport, info), schemes(schemes)
+ {
+ }
/* supported URI schemes (without "://") */
const ArrayRef<const char *> schemes;
- virtual VFSImpl * fopen (const char * filename, const char * mode, String & error) = 0;
+ virtual VFSImpl * fopen(const char * filename, const char * mode,
+ String & error) = 0;
- virtual VFSFileTest test_file (const char * filename, VFSFileTest test, String & error)
- { return VFSFileTest (0); }
+ virtual VFSFileTest test_file(const char * filename, VFSFileTest test,
+ String & error)
+ {
+ return VFSFileTest(0);
+ }
- virtual Index<String> read_folder (const char * filename, String & error)
- { return Index<String> (); }
+ virtual Index<String> read_folder(const char * filename, String & error)
+ {
+ return Index<String>();
+ }
};
class LIBAUDCORE_PUBLIC PlaylistPlugin : public Plugin
{
public:
- constexpr PlaylistPlugin (const PluginInfo info,
- const ArrayRef<const char *> extensions, bool can_save) :
- Plugin (PluginType::Playlist, info),
- extensions (extensions),
- can_save (can_save) {}
+ constexpr PlaylistPlugin(const PluginInfo info,
+ const ArrayRef<const char *> extensions,
+ bool can_save)
+ : Plugin(PluginType::Playlist, info), extensions(extensions),
+ can_save(can_save)
+ {
+ }
/* supported file extensions (without periods) */
const ArrayRef<const char *> extensions;
@@ -169,26 +186,32 @@ public:
* file: VFS handle of playlist file (in, read-only file, not seekable)
* title: title of playlist (out)
* items: playlist entries (out) */
- virtual bool load (const char * path, VFSFile & file, String & title,
- Index<PlaylistAddItem> & items) = 0;
+ virtual bool load(const char * path, VFSFile & file, String & title,
+ Index<PlaylistAddItem> & items) = 0;
/* path: URI of playlist file (in)
* file: VFS handle of playlist file (in, write-only file, not seekable)
* title: title of playlist (in)
* items: playlist entries (in) */
- virtual bool save (const char * path, VFSFile & file, const char * title,
- const Index<PlaylistAddItem> & items) { return false; }
+ virtual bool save(const char * path, VFSFile & file, const char * title,
+ const Index<PlaylistAddItem> & items)
+ {
+ return false;
+ }
};
class LIBAUDCORE_PUBLIC OutputPlugin : public Plugin
{
public:
- constexpr OutputPlugin (const PluginInfo info, int priority, bool force_reopen = false) :
- Plugin (PluginType::Output, info),
- priority (priority),
- force_reopen (force_reopen) {}
+ constexpr OutputPlugin(const PluginInfo info, int priority,
+ bool force_reopen = false)
+ : Plugin(PluginType::Output, info), priority(priority),
+ force_reopen(force_reopen)
+ {
+ }
- /* During probing, plugins with higher priority (10 to 0) are tried first. */
+ /* During probing, plugins with higher priority (10 to 0) are tried first.
+ */
const int priority;
/* Whether close_audio() and open_audio() must always be called between
@@ -197,56 +220,59 @@ public:
const bool force_reopen;
/* Returns current volume for left and right channels (0 to 100). */
- virtual StereoVolume get_volume () = 0;
+ virtual StereoVolume get_volume() = 0;
/* Changes volume for left and right channels (0 to 100). */
- virtual void set_volume (StereoVolume volume) = 0;
+ virtual void set_volume(StereoVolume volume) = 0;
/* Sets information about the song being played. This function will be
* called before open_audio(). */
- virtual void set_info (const char * filename, const Tuple & tuple) {}
+ virtual void set_info(const char * filename, const Tuple & tuple) {}
/* Begins playback of a PCM stream. <format> is one of the FMT_*
* enumeration values defined in libaudcore/audio.h. Returns true on
* success. */
- virtual bool open_audio (int format, int rate, int chans, String & error) = 0;
+ virtual bool open_audio(int format, int rate, int chans,
+ String & error) = 0;
/* Ends playback. Any buffered audio data is discarded. */
- virtual void close_audio () = 0;
+ virtual void close_audio() = 0;
/* Waits until write_audio() will return a size greater than zero.
* get_delay(), pause(), and flush() may be called meanwhile; if flush()
* is called, period_wait() should return immediately. */
- virtual void period_wait () = 0;
+ virtual void period_wait() = 0;
/* Writes up to <size> bytes of data, in the format given to open_audio().
* If there is not enough buffer space for all <size> bytes, writes only as
* many bytes as can be written immediately without blocking. Returns the
* number of bytes actually written. */
- virtual int write_audio (const void * data, int size) = 0;
+ virtual int write_audio(const void * data, int size) = 0;
/* Waits until all buffered data has been heard by the user. */
- virtual void drain () = 0;
+ virtual void drain() = 0;
/* Returns an estimate of how many milliseconds will pass before all the
* data passed to write_audio() has been heard by the user. */
- virtual int get_delay () = 0;
+ virtual int get_delay() = 0;
/* Pauses the stream if <p> is nonzero; otherwise unpauses it.
* write_audio() will not be called while the stream is paused. */
- virtual void pause (bool pause) = 0;
+ virtual void pause(bool pause) = 0;
/* Discards any buffered audio data. */
- virtual void flush () = 0;
+ virtual void flush() = 0;
};
class LIBAUDCORE_PUBLIC EffectPlugin : public Plugin
{
public:
- constexpr EffectPlugin (const PluginInfo info, int order, bool preserves_format) :
- Plugin (PluginType::Effect, info),
- order (order),
- preserves_format (preserves_format) {}
+ constexpr EffectPlugin(const PluginInfo info, int order,
+ bool preserves_format)
+ : Plugin(PluginType::Effect, info), order(order),
+ preserves_format(preserves_format)
+ {
+ }
/* Effects with lowest order (0 to 9) are applied first. */
const int order;
@@ -258,27 +284,29 @@ public:
/* All processing is done in floating point. If the effect plugin wants to
* change the channel count or sample rate, it can change the parameters
* passed to start(). They cannot be changed in the middle of a song. */
- virtual void start (int & channels, int & rate) = 0;
+ virtual void start(int & channels, int & rate) = 0;
/* Performs effect processing. process() may modify the audio samples in
* place and return a reference to the same buffer, or it may return a
* reference to an internal working buffer. The number of output samples
* need not be the same as the number of input samples. */
- virtual Index<float> & process (Index<float> & data) = 0;
+ virtual Index<float> & process(Index<float> & data) = 0;
/* Optional. A seek is taking place; any buffers should be discarded.
* Unless the "force" flag is set, the plugin may choose to override the
* normal flush behavior and handle the flush itself (for example, to
* perform crossfading). The flush() function should return false in this
- * case to prevent flush() from being called in downstream effect plugins. */
- virtual bool flush (bool force)
- { return true; }
+ * case to prevent flush() from being called in downstream effect plugins.
+ */
+ virtual bool flush(bool force) { return true; }
/* Exactly like process() except that any buffers should be drained (i.e.
* the data processed and returned). finish() will be called a second time
* at the end of the last song in the playlist. */
- virtual Index<float> & finish (Index<float> & data, bool end_of_playlist)
- { return process (data); }
+ virtual Index<float> & finish(Index<float> & data, bool end_of_playlist)
+ {
+ return process(data);
+ }
/* Required only for plugins that change the time domain (e.g. a time
* stretch) or use read-ahead buffering. translate_delay() must do two
@@ -286,11 +314,11 @@ public:
* output time domain back to the input time domain; second, increase
* <delay> by the size of the read-ahead buffer. It should return the
* adjusted delay. */
- virtual int adjust_delay (int delay)
- { return delay; }
+ virtual int adjust_delay(int delay) { return delay; }
};
-enum class InputKey {
+enum class InputKey
+{
Ext,
MIME,
Scheme,
@@ -300,7 +328,8 @@ enum class InputKey {
class LIBAUDCORE_PUBLIC InputPlugin : public Plugin
{
public:
- enum {
+ enum
+ {
/* Indicates that the plugin can write file tags */
FlagWritesTag = (1 << 0),
@@ -330,67 +359,86 @@ public:
int flags, priority;
aud::array<InputKey, List> keys;
- constexpr InputInfo (int flags = 0) :
- flags (flags), priority (0), keys {} {}
+ constexpr InputInfo(int flags = 0)
+ : flags(flags), priority(_AUD_PLUGIN_DEFAULT_PRIO), keys{}
+ {
+ }
/* Associates file extensions with the plugin. */
- constexpr InputInfo with_exts (List exts) const
- { return InputInfo (flags, priority,
- exts, keys[InputKey::MIME], keys[InputKey::Scheme]); }
+ constexpr InputInfo with_exts(List exts) const
+ {
+ return InputInfo(flags, priority, exts, keys[InputKey::MIME],
+ keys[InputKey::Scheme]);
+ }
/* Associates MIME types with the plugin. */
- constexpr InputInfo with_mimes (List mimes) const
- { return InputInfo (flags, priority,
- keys[InputKey::Ext], mimes, keys[InputKey::Scheme]); }
+ constexpr InputInfo with_mimes(List mimes) const
+ {
+ return InputInfo(flags, priority, keys[InputKey::Ext], mimes,
+ keys[InputKey::Scheme]);
+ }
/* Associates custom URI schemes with the plugin. Plugins using custom
* URI schemes are expected to handle their own I/O. Hence, any VFSFile
* passed to play(), read_tuple(), etc. will be null. */
- constexpr InputInfo with_schemes (List schemes) const
- { return InputInfo (flags, priority,
- keys[InputKey::Ext], keys[InputKey::MIME], schemes); }
+ constexpr InputInfo with_schemes(List schemes) const
+ {
+ return InputInfo(flags, priority, keys[InputKey::Ext],
+ keys[InputKey::MIME], schemes);
+ }
/* Sets how quickly the plugin should be tried in searching for a plugin
* to handle a file which could not be identified from its extension.
* Plugins with priority 0 are tried first, 10 last. */
- constexpr InputInfo with_priority (int priority) const
- { return InputInfo (flags, priority,
- keys[InputKey::Ext], keys[InputKey::MIME], keys[InputKey::Scheme]); }
+ constexpr InputInfo with_priority(int priority) const
+ {
+ return InputInfo(flags, priority, keys[InputKey::Ext],
+ keys[InputKey::MIME], keys[InputKey::Scheme]);
+ }
private:
- constexpr InputInfo (int flags, int priority, List exts, List mimes, List schemes) :
- flags (flags), priority (priority), keys {exts, mimes, schemes} {}
+ constexpr InputInfo(int flags, int priority, List exts, List mimes,
+ List schemes)
+ : flags(flags), priority(priority), keys{exts, mimes, schemes}
+ {
+ }
};
- constexpr InputPlugin (PluginInfo info, InputInfo input_info) :
- Plugin (PluginType::Input, info),
- input_info (input_info) {}
+ constexpr InputPlugin(PluginInfo info, InputInfo input_info)
+ : Plugin(PluginType::Input, info), input_info(input_info)
+ {
+ }
const InputInfo input_info;
/* Returns true if the plugin can handle the file. */
- virtual bool is_our_file (const char * filename, VFSFile & file) = 0;
+ virtual bool is_our_file(const char * filename, VFSFile & file) = 0;
/* Reads metadata and album art (if requested and available) from the file.
* The filename fields of the tuple are already set before the function is
* called. If album art is not needed, <image> will be nullptr. The return
* value should be true if <tuple> was successfully read, regardless of
* whether album art was read. */
- virtual bool read_tag (const char * filename, VFSFile & file, Tuple & tuple,
- Index<char> * image) = 0;
+ virtual bool read_tag(const char * filename, VFSFile & file, Tuple & tuple,
+ Index<char> * image) = 0;
/* Plays the file. Returns false on error. Also see input-api.h. */
- virtual bool play (const char * filename, VFSFile & file) = 0;
+ virtual bool play(const char * filename, VFSFile & file) = 0;
/* Optional. Writes metadata to the file, returning false on error. */
- virtual bool write_tuple (const char * filename, VFSFile & file, const Tuple & tuple)
- { return false; }
+ virtual bool write_tuple(const char * filename, VFSFile & file,
+ const Tuple & tuple)
+ {
+ return false;
+ }
/* Optional. Displays a window showing info about the file. In general,
* this function should be avoided since Audacious already provides a file
* info window. */
- virtual bool file_info_box (const char * filename, VFSFile & file)
- { return false; }
+ virtual bool file_info_box(const char * filename, VFSFile & file)
+ {
+ return false;
+ }
protected:
/* Prepares the output system for playback in the specified format. Also
@@ -399,57 +447,62 @@ protected:
* calling open_audio. There is no return value. If the requested audio
* format is not supported, write_audio() will do nothing and check_stop()
* will immediately return true. */
- static void open_audio (int format, int rate, int channels);
+ static void open_audio(int format, int rate, int channels);
/* Informs the output system of replay gain values for the current song so
* that volume levels can be adjusted accordingly, if the user so desires.
- * This may be called at any time during playback should the values change. */
- static void set_replay_gain (const ReplayGainInfo & gain);
+ * This may be called at any time during playback should the values change.
+ */
+ static void set_replay_gain(const ReplayGainInfo & gain);
/* Passes audio data to the output system for playback. The data must be in
* the format passed to open_audio(), and the length (in bytes) must be an
* integral number of frames. This function blocks until all the data has
* been written (though it may not yet be heard by the user). */
- static void write_audio (const void * data, int length);
+ static void write_audio(const void * data, int length);
/* Returns the current tuple for the stream. */
- static Tuple get_playback_tuple ();
+ static Tuple get_playback_tuple();
/* Updates the tuple for the stream. */
- static void set_playback_tuple (Tuple && tuple);
+ static void set_playback_tuple(Tuple && tuple);
/* Updates the displayed bitrate, in bits per second. */
- static void set_stream_bitrate (int bitrate);
+ static void set_stream_bitrate(int bitrate);
/* Checks whether playback is to be stopped. The play() function should
* poll check_stop() periodically and return as soon as check_stop() returns
* true. */
- static bool check_stop ();
+ static bool check_stop();
/* Checks whether a seek has been requested. If so, returns the position to
* seek to, in milliseconds. Otherwise, returns -1. */
- static int check_seek ();
+ static int check_seek();
};
class LIBAUDCORE_PUBLIC DockablePlugin : public Plugin
{
public:
- constexpr DockablePlugin (PluginType type, PluginInfo info) :
- Plugin (type, info) {}
+ constexpr DockablePlugin(PluginType type, PluginInfo info)
+ : Plugin(type, info)
+ {
+ }
/* GtkWidget * get_gtk_widget () */
- virtual void * get_gtk_widget () { return nullptr; }
+ virtual void * get_gtk_widget() { return nullptr; }
/* QWidget * get_qt_widget () */
- virtual void * get_qt_widget () { return nullptr; }
+ virtual void * get_qt_widget() { return nullptr; }
};
class LIBAUDCORE_PUBLIC GeneralPlugin : public DockablePlugin
{
public:
- constexpr GeneralPlugin (PluginInfo info, bool enabled_by_default) :
- DockablePlugin (PluginType::General, info),
- enabled_by_default (enabled_by_default) {}
+ constexpr GeneralPlugin(PluginInfo info, bool enabled_by_default)
+ : DockablePlugin(PluginType::General, info),
+ enabled_by_default(enabled_by_default)
+ {
+ }
const bool enabled_by_default;
};
@@ -457,33 +510,34 @@ public:
class LIBAUDCORE_PUBLIC VisPlugin : public DockablePlugin, public Visualizer
{
public:
- constexpr VisPlugin (PluginInfo info, int type_mask) :
- DockablePlugin (PluginType::Vis, info),
- Visualizer (type_mask) {}
+ constexpr VisPlugin(PluginInfo info, int type_mask)
+ : DockablePlugin(PluginType::Vis, info), Visualizer(type_mask)
+ {
+ }
};
class LIBAUDCORE_PUBLIC IfacePlugin : public Plugin
{
public:
- constexpr IfacePlugin (PluginInfo info) :
- Plugin (PluginType::Iface, info) {}
-
- virtual void show (bool show) = 0;
- virtual void run () = 0;
- virtual void quit () = 0;
-
- virtual void show_about_window () = 0;
- virtual void hide_about_window () = 0;
- virtual void show_filebrowser (bool open) = 0;
- virtual void hide_filebrowser () = 0;
- virtual void show_jump_to_song () = 0;
- virtual void hide_jump_to_song () = 0;
- virtual void show_prefs_window () = 0;
- virtual void hide_prefs_window () = 0;
- virtual void plugin_menu_add (AudMenuID id, void func (), const char * name, const char * icon) = 0;
- virtual void plugin_menu_remove (AudMenuID id, void func ()) = 0;
-
- virtual void startup_notify (const char * id) {}
+ constexpr IfacePlugin(PluginInfo info) : Plugin(PluginType::Iface, info) {}
+
+ virtual void show(bool show) = 0;
+ virtual void run() = 0;
+ virtual void quit() = 0;
+
+ virtual void show_about_window() = 0;
+ virtual void hide_about_window() = 0;
+ virtual void show_filebrowser(bool open) = 0;
+ virtual void hide_filebrowser() = 0;
+ virtual void show_jump_to_song() = 0;
+ virtual void hide_jump_to_song() = 0;
+ virtual void show_prefs_window() = 0;
+ virtual void hide_prefs_window() = 0;
+ virtual void plugin_menu_add(AudMenuID id, void func(), const char * name,
+ const char * icon) = 0;
+ virtual void plugin_menu_remove(AudMenuID id, void func()) = 0;
+
+ virtual void startup_notify(const char * id) {}
};
#endif
diff --git a/src/libaudcore/plugins-internal.h b/src/libaudcore/plugins-internal.h
index d521c5c..23ae67b 100644
--- a/src/libaudcore/plugins-internal.h
+++ b/src/libaudcore/plugins-internal.h
@@ -20,49 +20,52 @@
#ifndef LIBAUDCORE_PLUGINS_INTERNAL_H
#define LIBAUDCORE_PLUGINS_INTERNAL_H
-#include "plugins.h"
#include "objects.h"
+#include "plugins.h"
enum class InputKey;
class Plugin;
-enum class PluginEnabled {
+enum class PluginEnabled
+{
Disabled = 0,
Primary = 1,
Secondary = 2
};
/* plugin-init.c */
-void start_plugins_one ();
-void start_plugins_two ();
-void stop_plugins_two ();
-void stop_plugins_one ();
+void start_plugins_one();
+void start_plugins_two();
+void stop_plugins_two();
+void stop_plugins_one();
-bool plugin_enable_secondary (PluginHandle * plugin, bool enable);
+bool plugin_enable_secondary(PluginHandle * plugin, bool enable);
/* plugin-load.c */
-void plugin_system_init ();
-void plugin_system_cleanup ();
-bool plugin_check_flags (int flags);
-Plugin * plugin_load (const char * path);
+void plugin_system_init();
+void plugin_system_cleanup();
+bool plugin_check_flags(int flags);
+Plugin * plugin_load(const char * path);
/* plugin-registry.c */
-void plugin_registry_load ();
-void plugin_registry_prune ();
-void plugin_registry_save ();
-void plugin_registry_cleanup ();
+void plugin_registry_load();
+void plugin_registry_prune();
+void plugin_registry_save();
+void plugin_registry_cleanup();
-void plugin_register (const char * path, int timestamp);
-PluginEnabled plugin_get_enabled (PluginHandle * plugin);
-void plugin_set_enabled (PluginHandle * plugin, PluginEnabled enabled);
-void plugin_set_failed (PluginHandle * plugin);
+void plugin_register(const char * path, int timestamp);
+PluginEnabled plugin_get_enabled(PluginHandle * plugin);
+void plugin_set_enabled(PluginHandle * plugin, PluginEnabled enabled);
+void plugin_set_failed(PluginHandle * plugin);
-bool transport_plugin_has_scheme (PluginHandle * plugin, const char * scheme);
-bool playlist_plugin_can_save (PluginHandle * plugin);
-const Index<String> & playlist_plugin_get_exts (PluginHandle * plugin);
-bool playlist_plugin_has_ext (PluginHandle * plugin, const char * ext);
-bool input_plugin_has_key (PluginHandle * plugin, InputKey key, const char * value);
-bool input_plugin_has_subtunes (PluginHandle * plugin);
-bool input_plugin_can_write_tuple (PluginHandle * plugin);
+const Index<String> & transport_plugin_get_schemes(PluginHandle * plugin);
+bool transport_plugin_has_scheme(PluginHandle * plugin, const char * scheme);
+bool playlist_plugin_can_save(PluginHandle * plugin);
+const Index<String> & playlist_plugin_get_exts(PluginHandle * plugin);
+bool playlist_plugin_has_ext(PluginHandle * plugin, const char * ext);
+bool input_plugin_has_key(PluginHandle * plugin, InputKey key,
+ const char * value);
+bool input_plugin_has_subtunes(PluginHandle * plugin);
+bool input_plugin_can_write_tuple(PluginHandle * plugin);
#endif
diff --git a/src/libaudcore/plugins.h b/src/libaudcore/plugins.h
index 7223560..bf156f6 100644
--- a/src/libaudcore/plugins.h
+++ b/src/libaudcore/plugins.h
@@ -22,7 +22,8 @@
#include <libaudcore/index.h>
-enum class PluginType {
+enum class PluginType
+{
Transport,
Playlist,
Input,
@@ -38,31 +39,37 @@ class PluginHandle;
/* CAUTION: These functions are not thread safe. */
-PluginHandle * aud_plugin_get_current (PluginType type);
-bool aud_plugin_get_enabled (PluginHandle * plugin);
-bool aud_plugin_enable (PluginHandle * plugin, bool enable);
+PluginHandle * aud_plugin_get_current(PluginType type);
+bool aud_plugin_get_enabled(PluginHandle * plugin);
+bool aud_plugin_enable(PluginHandle * plugin, bool enable);
-int aud_plugin_send_message (PluginHandle * plugin, const char * code, const void * data, int size);
-void * aud_plugin_get_gtk_widget (PluginHandle * plugin); // returns (GtkWidget *)
-void * aud_plugin_get_qt_widget (PluginHandle * plugin); // return (QWidget *)
+int aud_plugin_send_message(PluginHandle * plugin, const char * code,
+ const void * data, int size);
+void *
+aud_plugin_get_gtk_widget(PluginHandle * plugin); // returns (GtkWidget *)
+void * aud_plugin_get_qt_widget(PluginHandle * plugin); // return (QWidget *)
-PluginType aud_plugin_get_type (PluginHandle * plugin);
-const char * aud_plugin_get_basename (PluginHandle * plugin);
-PluginHandle * aud_plugin_lookup_basename (const char * basename);
+PluginType aud_plugin_get_type(PluginHandle * plugin);
+const char * aud_plugin_get_basename(PluginHandle * plugin);
+PluginHandle * aud_plugin_lookup_basename(const char * basename);
-const void * aud_plugin_get_header (PluginHandle * plugin);
-PluginHandle * aud_plugin_by_header (const void * header);
+const void * aud_plugin_get_header(PluginHandle * plugin);
+PluginHandle * aud_plugin_by_header(const void * header);
-const Index<PluginHandle *> & aud_plugin_list (PluginType type);
+const Index<PluginHandle *> & aud_plugin_list(PluginType type);
-const char * aud_plugin_get_name (PluginHandle * plugin);
-bool aud_plugin_has_about (PluginHandle * plugin);
-bool aud_plugin_has_configure (PluginHandle * plugin);
+const char * aud_plugin_get_name(PluginHandle * plugin);
+bool aud_plugin_has_about(PluginHandle * plugin);
+bool aud_plugin_has_configure(PluginHandle * plugin);
/* returns true to continue watching, false to stop */
-typedef bool (* PluginWatchFunc) (PluginHandle * plugin, void * data);
+typedef bool (*PluginWatchFunc)(PluginHandle * plugin, void * data);
-void aud_plugin_add_watch (PluginHandle * plugin, PluginWatchFunc func, void * data);
-void aud_plugin_remove_watch (PluginHandle * plugin, PluginWatchFunc func, void * data);
+void aud_plugin_add_watch(PluginHandle * plugin, PluginWatchFunc func,
+ void * data);
+void aud_plugin_remove_watch(PluginHandle * plugin, PluginWatchFunc func,
+ void * data);
+
+Index<const char *> aud_plugin_get_supported_mime_types();
#endif
diff --git a/src/libaudcore/preferences.cc b/src/libaudcore/preferences.cc
index 4f14e39..3d6d8a2 100644
--- a/src/libaudcore/preferences.cc
+++ b/src/libaudcore/preferences.cc
@@ -22,102 +22,102 @@
#include <assert.h>
-EXPORT bool WidgetConfig::get_bool () const
+EXPORT bool WidgetConfig::get_bool() const
{
- assert (type == Bool);
+ assert(type == Bool);
if (value)
- return * (bool *) value;
+ return *(bool *)value;
else if (name)
- return aud_get_bool (section, name);
+ return aud_get_bool(section, name);
else
return false;
}
-EXPORT void WidgetConfig::set_bool (bool val) const
+EXPORT void WidgetConfig::set_bool(bool val) const
{
- assert (type == Bool);
+ assert(type == Bool);
if (value)
- * (bool *) value = val;
+ *(bool *)value = val;
else if (name)
- aud_set_bool (section, name, val);
+ aud_set_bool(section, name, val);
if (callback)
- callback ();
+ callback();
}
-EXPORT int WidgetConfig::get_int () const
+EXPORT int WidgetConfig::get_int() const
{
- assert (type == Int);
+ assert(type == Int);
if (value)
- return * (int *) value;
+ return *(int *)value;
else if (name)
- return aud_get_int (section, name);
+ return aud_get_int(section, name);
else
return 0;
}
-EXPORT void WidgetConfig::set_int (int val) const
+EXPORT void WidgetConfig::set_int(int val) const
{
- assert (type == Int);
+ assert(type == Int);
if (value)
- * (int *) value = val;
+ *(int *)value = val;
else if (name)
- aud_set_int (section, name, val);
+ aud_set_int(section, name, val);
if (callback)
- callback ();
+ callback();
}
-EXPORT double WidgetConfig::get_float () const
+EXPORT double WidgetConfig::get_float() const
{
- assert (type == Float);
+ assert(type == Float);
if (value)
- return * (double *) value;
+ return *(double *)value;
else if (name)
- return aud_get_double (section, name);
+ return aud_get_double(section, name);
else
return 0;
}
-EXPORT void WidgetConfig::set_float (double val) const
+EXPORT void WidgetConfig::set_float(double val) const
{
- assert (type == Float);
+ assert(type == Float);
if (value)
- * (double *) value = val;
+ *(double *)value = val;
else if (name)
- aud_set_double (section, name, val);
+ aud_set_double(section, name, val);
if (callback)
- callback ();
+ callback();
}
-EXPORT String WidgetConfig::get_string () const
+EXPORT String WidgetConfig::get_string() const
{
- assert (type == String);
+ assert(type == String);
if (value)
- return * (::String *) value;
+ return *(::String *)value;
else if (name)
- return aud_get_str (section, name);
+ return aud_get_str(section, name);
else
- return ::String ();
+ return ::String();
}
-EXPORT void WidgetConfig::set_string (const char * val) const
+EXPORT void WidgetConfig::set_string(const char * val) const
{
- assert (type == String);
+ assert(type == String);
if (value)
- * (::String *) value = ::String (val);
+ *(::String *)value = ::String(val);
else if (name)
- aud_set_str (section, name, val);
+ aud_set_str(section, name, val);
if (callback)
- callback ();
+ callback();
}
diff --git a/src/libaudcore/preferences.h b/src/libaudcore/preferences.h
index 8946b01..957c928 100644
--- a/src/libaudcore/preferences.h
+++ b/src/libaudcore/preferences.h
@@ -1,6 +1,6 @@
/*
* preferences.h
- * Copyright 2007-2014 Tomasz Moń, William Pitcock, and John Lindgren
+ * Copyright 2007-2014 Tomasz Moń, Ariadne Conill, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -24,83 +24,98 @@
struct PreferencesWidget;
-enum class FileSelectMode {
+enum class FileSelectMode
+{
File,
Folder
};
-struct ComboItem {
+struct ComboItem
+{
const char * label;
const char * str;
int num;
- constexpr ComboItem (const char * label, const char * str) :
- label (label),
- str (str),
- num (-1) {}
+ constexpr ComboItem(const char * label, const char * str)
+ : label(label), str(str), num(-1)
+ {
+ }
- constexpr ComboItem (const char * label, int num) :
- label (label),
- str (nullptr),
- num (num) {}
+ constexpr ComboItem(const char * label, int num)
+ : label(label), str(nullptr), num(num)
+ {
+ }
};
-struct WidgetVButton {
- void (* callback) ();
+struct WidgetVButton
+{
+ void (*callback)();
const char * icon;
};
-struct WidgetVRadio {
+struct WidgetVRadio
+{
int value;
};
-struct WidgetVSpin {
+struct WidgetVSpin
+{
double min, max, step;
const char * right_label; /* text right to widget */
};
-struct WidgetVTable {
+struct WidgetVTable
+{
ArrayRef<PreferencesWidget> widgets;
};
-struct WidgetVFonts {
+struct WidgetVFonts
+{
const char * title;
};
-struct WidgetVEntry {
+struct WidgetVEntry
+{
bool password;
};
-struct WidgetVFileEntry {
+struct WidgetVFileEntry
+{
FileSelectMode mode;
};
-struct WidgetVCombo {
+struct WidgetVCombo
+{
/* static init */
ArrayRef<ComboItem> elems;
/* runtime init */
- ArrayRef<ComboItem> (* fill) ();
+ ArrayRef<ComboItem> (*fill)();
};
-struct WidgetVBox {
+struct WidgetVBox
+{
ArrayRef<PreferencesWidget> widgets;
- bool horizontal; /* false gives vertical, true gives horizontal alignment of child widgets */
- bool frame; /* whether to draw frame around box */
+ bool horizontal; /* false gives vertical, true gives horizontal alignment of
+ child widgets */
+ bool frame; /* whether to draw frame around box */
};
-struct NotebookTab {
+struct NotebookTab
+{
const char * name;
ArrayRef<PreferencesWidget> widgets;
};
-struct WidgetVNotebook {
+struct WidgetVNotebook
+{
ArrayRef<NotebookTab> tabs;
};
-struct WidgetVSeparator {
- bool horizontal; /* false gives vertical, true gives horizontal separator */
+struct WidgetVSeparator
+{
+ bool horizontal; /* false gives vertical, true gives horizontal separator */
};
union WidgetVariant {
@@ -119,27 +134,33 @@ union WidgetVariant {
/* for custom GTK or Qt widgets */
/* GtkWidget * (* populate) (); */
/* QWidget * (* populate) (); */
- void * (* populate) ();
-
- constexpr WidgetVariant (WidgetVButton button) : button (button) {}
- constexpr WidgetVariant (WidgetVRadio radio) : radio_btn (radio) {}
- constexpr WidgetVariant (WidgetVSpin spin) : spin_btn (spin) {}
- constexpr WidgetVariant (WidgetVTable table) : table (table) {}
- constexpr WidgetVariant (WidgetVFonts fonts) : font_btn (fonts) {}
- constexpr WidgetVariant (WidgetVEntry entry) : entry (entry) {}
- constexpr WidgetVariant (WidgetVFileEntry file_entry) : file_entry (file_entry) {}
- constexpr WidgetVariant (WidgetVCombo combo) : combo (combo) {}
- constexpr WidgetVariant (WidgetVBox box) : box (box) {}
- constexpr WidgetVariant (WidgetVNotebook notebook) : notebook (notebook) {}
- constexpr WidgetVariant (WidgetVSeparator separator) : separator (separator) {}
+ void * (*populate)();
+
+ constexpr WidgetVariant(WidgetVButton button) : button(button) {}
+ constexpr WidgetVariant(WidgetVRadio radio) : radio_btn(radio) {}
+ constexpr WidgetVariant(WidgetVSpin spin) : spin_btn(spin) {}
+ constexpr WidgetVariant(WidgetVTable table) : table(table) {}
+ constexpr WidgetVariant(WidgetVFonts fonts) : font_btn(fonts) {}
+ constexpr WidgetVariant(WidgetVEntry entry) : entry(entry) {}
+ constexpr WidgetVariant(WidgetVFileEntry file_entry)
+ : file_entry(file_entry)
+ {
+ }
+ constexpr WidgetVariant(WidgetVCombo combo) : combo(combo) {}
+ constexpr WidgetVariant(WidgetVBox box) : box(box) {}
+ constexpr WidgetVariant(WidgetVNotebook notebook) : notebook(notebook) {}
+ constexpr WidgetVariant(WidgetVSeparator separator) : separator(separator)
+ {
+ }
/* also serves as default constructor */
- constexpr WidgetVariant (void * (* populate) () = 0) : populate (populate) {}
+ constexpr WidgetVariant(void * (*populate)() = 0) : populate(populate) {}
};
struct WidgetConfig
{
- enum Type {
+ enum Type
+ {
None,
Bool,
Int,
@@ -152,68 +173,91 @@ struct WidgetConfig
/* pointer to immediate value */
void * value;
/* identifier for configuration value */
- const char * section, * name;
+ const char *section, *name;
/* called when value is changed */
- void (* callback) ();
+ void (*callback)();
/* widget updates when this hook is called */
const char * hook;
- constexpr WidgetConfig () :
- type (None),
- value (nullptr),
- section (nullptr),
- name (nullptr),
- callback (nullptr),
- hook (nullptr) {}
-
- constexpr WidgetConfig (Type type, void * value, const char * section,
- const char * name, void (* callback) (), const char * hook) :
- type (type),
- value (value),
- section (section),
- name (name),
- callback (callback),
- hook (hook) {}
-
- bool get_bool () const;
- void set_bool (bool val) const;
- int get_int () const;
- void set_int (int val) const;
- double get_float () const;
- void set_float (double val) const;
- ::String get_string () const;
- void set_string (const char * val) const;
+ constexpr WidgetConfig()
+ : type(None), value(nullptr), section(nullptr), name(nullptr),
+ callback(nullptr), hook(nullptr)
+ {
+ }
+
+ constexpr WidgetConfig(Type type, void * value, const char * section,
+ const char * name, void (*callback)(),
+ const char * hook)
+ : type(type), value(value), section(section), name(name),
+ callback(callback), hook(hook)
+ {
+ }
+
+ bool get_bool() const;
+ void set_bool(bool val) const;
+ int get_int() const;
+ void set_int(int val) const;
+ double get_float() const;
+ void set_float(double val) const;
+ ::String get_string() const;
+ void set_string(const char * val) const;
};
-constexpr WidgetConfig WidgetBool (bool & value,
- void (* callback) () = nullptr, const char * hook = nullptr)
- { return WidgetConfig (WidgetConfig::Bool, (void *) & value, 0, 0, callback, hook); }
-constexpr WidgetConfig WidgetInt (int & value,
- void (* callback) () = nullptr, const char * hook = nullptr)
- { return WidgetConfig (WidgetConfig::Int, (void *) & value, 0, 0, callback, hook); }
-constexpr WidgetConfig WidgetFloat (double & value,
- void (* callback) () = nullptr, const char * hook = nullptr)
- { return WidgetConfig (WidgetConfig::Float, (void *) & value, 0, 0, callback, hook); }
-constexpr WidgetConfig WidgetString (String & value,
- void (* callback) () = nullptr, const char * hook = nullptr)
- { return WidgetConfig (WidgetConfig::String, (void *) & value, 0, 0, callback, hook); }
-
-constexpr WidgetConfig WidgetBool (const char * section, const char * name,
- void (* callback) () = nullptr, const char * hook = nullptr)
- { return WidgetConfig (WidgetConfig::Bool, 0, section, name, callback, hook); }
-constexpr WidgetConfig WidgetInt (const char * section, const char * name,
- void (* callback) () = nullptr, const char * hook = nullptr)
- { return WidgetConfig (WidgetConfig::Int, 0, section, name, callback, hook); }
-constexpr WidgetConfig WidgetFloat (const char * section, const char * name,
- void (* callback) () = nullptr, const char * hook = nullptr)
- { return WidgetConfig (WidgetConfig::Float, 0, section, name, callback, hook); }
-constexpr WidgetConfig WidgetString (const char * section, const char * name,
- void (* callback) () = nullptr, const char * hook = nullptr)
- { return WidgetConfig (WidgetConfig::String, 0, section, name, callback, hook); }
+constexpr WidgetConfig WidgetBool(bool & value, void (*callback)() = nullptr,
+ const char * hook = nullptr)
+{
+ return WidgetConfig(WidgetConfig::Bool, (void *)&value, 0, 0, callback,
+ hook);
+}
+constexpr WidgetConfig WidgetInt(int & value, void (*callback)() = nullptr,
+ const char * hook = nullptr)
+{
+ return WidgetConfig(WidgetConfig::Int, (void *)&value, 0, 0, callback,
+ hook);
+}
+constexpr WidgetConfig WidgetFloat(double & value, void (*callback)() = nullptr,
+ const char * hook = nullptr)
+{
+ return WidgetConfig(WidgetConfig::Float, (void *)&value, 0, 0, callback,
+ hook);
+}
+constexpr WidgetConfig WidgetString(String & value,
+ void (*callback)() = nullptr,
+ const char * hook = nullptr)
+{
+ return WidgetConfig(WidgetConfig::String, (void *)&value, 0, 0, callback,
+ hook);
+}
+
+constexpr WidgetConfig WidgetBool(const char * section, const char * name,
+ void (*callback)() = nullptr,
+ const char * hook = nullptr)
+{
+ return WidgetConfig(WidgetConfig::Bool, 0, section, name, callback, hook);
+}
+constexpr WidgetConfig WidgetInt(const char * section, const char * name,
+ void (*callback)() = nullptr,
+ const char * hook = nullptr)
+{
+ return WidgetConfig(WidgetConfig::Int, 0, section, name, callback, hook);
+}
+constexpr WidgetConfig WidgetFloat(const char * section, const char * name,
+ void (*callback)() = nullptr,
+ const char * hook = nullptr)
+{
+ return WidgetConfig(WidgetConfig::Float, 0, section, name, callback, hook);
+}
+constexpr WidgetConfig WidgetString(const char * section, const char * name,
+ void (*callback)() = nullptr,
+ const char * hook = nullptr)
+{
+ return WidgetConfig(WidgetConfig::String, 0, section, name, callback, hook);
+}
struct PreferencesWidget
{
- enum Type {
+ enum Type
+ {
Label,
Button,
CheckButton,
@@ -232,90 +276,134 @@ struct PreferencesWidget
};
Type type;
- const char * label; /* widget title (for SPIN_BTN it's text left to widget) */
+ const char *
+ label; /* widget title (for SPIN_BTN it's text left to widget) */
bool child;
WidgetConfig cfg;
WidgetVariant data;
};
-enum WidgetIsChild {
+enum WidgetIsChild
+{
WIDGET_NOT_CHILD,
WIDGET_CHILD
};
-constexpr PreferencesWidget WidgetLabel (const char * label,
- WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::Label, label, (child == WIDGET_CHILD)}; }
-
-constexpr PreferencesWidget WidgetButton (const char * label,
- WidgetVButton button, WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::Button, label, (child == WIDGET_CHILD), {}, button}; }
-
-constexpr PreferencesWidget WidgetCheck (const char * label,
- WidgetConfig cfg, WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::CheckButton, label,
- (child == WIDGET_CHILD), cfg}; }
-
-constexpr PreferencesWidget WidgetRadio (const char * label,
- WidgetConfig cfg, WidgetVRadio radio, WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::RadioButton, label,
- (child == WIDGET_CHILD), cfg, radio}; }
-
-constexpr PreferencesWidget WidgetSpin (const char * label,
- WidgetConfig cfg, WidgetVSpin spin, WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::SpinButton, label,
- (child == WIDGET_CHILD), cfg, spin}; }
-
-constexpr PreferencesWidget WidgetEntry (const char * label,
- WidgetConfig cfg, WidgetVEntry entry = WidgetVEntry(),
- WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::Entry, label,
- (child == WIDGET_CHILD), cfg, entry}; }
-
-constexpr PreferencesWidget WidgetFileEntry (const char * label,
- WidgetConfig cfg, WidgetVFileEntry file_entry = WidgetVFileEntry(),
- WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::FileEntry, label,
- (child == WIDGET_CHILD), cfg, file_entry}; }
-
-constexpr PreferencesWidget WidgetCombo (const char * label,
- WidgetConfig cfg, WidgetVCombo combo, WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::ComboBox, label,
- (child == WIDGET_CHILD), cfg, combo}; }
-
-constexpr PreferencesWidget WidgetFonts (const char * label,
- WidgetConfig cfg, WidgetVFonts fonts, WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::FontButton, label,
- (child == WIDGET_CHILD), cfg, fonts}; }
-
-constexpr PreferencesWidget WidgetBox (WidgetVBox box, WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::Box, 0, (child == WIDGET_CHILD), {}, box}; }
-
-constexpr PreferencesWidget WidgetTable (WidgetVTable table,
- WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::Table, 0, (child == WIDGET_CHILD), {}, table}; }
-
-constexpr PreferencesWidget WidgetNotebook (WidgetVNotebook notebook)
- { return {PreferencesWidget::Notebook, 0, 0, {}, notebook}; }
-
-constexpr PreferencesWidget WidgetSeparator (WidgetVSeparator separator = WidgetVSeparator ())
- { return {PreferencesWidget::Separator, 0, 0, {}, separator}; }
-
-constexpr PreferencesWidget WidgetCustomGTK (void * (* populate) (),
- WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::CustomGTK, 0, (child == WIDGET_CHILD), {}, populate}; }
-
-constexpr PreferencesWidget WidgetCustomQt (void * (* populate) (),
- WidgetIsChild child = WIDGET_NOT_CHILD)
- { return {PreferencesWidget::CustomQt, 0, (child == WIDGET_CHILD), {}, populate}; }
-
-struct PluginPreferences {
+constexpr PreferencesWidget WidgetLabel(const char * label,
+ WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {PreferencesWidget::Label, label, (child == WIDGET_CHILD)};
+}
+
+constexpr PreferencesWidget WidgetButton(const char * label,
+ WidgetVButton button,
+ WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {
+ PreferencesWidget::Button, label, (child == WIDGET_CHILD), {}, button};
+}
+
+constexpr PreferencesWidget WidgetCheck(const char * label, WidgetConfig cfg,
+ WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {PreferencesWidget::CheckButton, label, (child == WIDGET_CHILD),
+ cfg};
+}
+
+constexpr PreferencesWidget WidgetRadio(const char * label, WidgetConfig cfg,
+ WidgetVRadio radio,
+ WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {PreferencesWidget::RadioButton, label, (child == WIDGET_CHILD), cfg,
+ radio};
+}
+
+constexpr PreferencesWidget WidgetSpin(const char * label, WidgetConfig cfg,
+ WidgetVSpin spin,
+ WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {PreferencesWidget::SpinButton, label, (child == WIDGET_CHILD), cfg,
+ spin};
+}
+
+constexpr PreferencesWidget WidgetEntry(const char * label, WidgetConfig cfg,
+ WidgetVEntry entry = WidgetVEntry(),
+ WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {PreferencesWidget::Entry, label, (child == WIDGET_CHILD), cfg,
+ entry};
+}
+
+constexpr PreferencesWidget
+WidgetFileEntry(const char * label, WidgetConfig cfg,
+ WidgetVFileEntry file_entry = WidgetVFileEntry(),
+ WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {PreferencesWidget::FileEntry, label, (child == WIDGET_CHILD), cfg,
+ file_entry};
+}
+
+constexpr PreferencesWidget WidgetCombo(const char * label, WidgetConfig cfg,
+ WidgetVCombo combo,
+ WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {PreferencesWidget::ComboBox, label, (child == WIDGET_CHILD), cfg,
+ combo};
+}
+
+constexpr PreferencesWidget WidgetFonts(const char * label, WidgetConfig cfg,
+ WidgetVFonts fonts,
+ WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {PreferencesWidget::FontButton, label, (child == WIDGET_CHILD), cfg,
+ fonts};
+}
+
+constexpr PreferencesWidget WidgetBox(WidgetVBox box,
+ WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {PreferencesWidget::Box, 0, (child == WIDGET_CHILD), {}, box};
+}
+
+constexpr PreferencesWidget WidgetTable(WidgetVTable table,
+ WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {PreferencesWidget::Table, 0, (child == WIDGET_CHILD), {}, table};
+}
+
+constexpr PreferencesWidget WidgetNotebook(WidgetVNotebook notebook)
+{
+ return {PreferencesWidget::Notebook, 0, 0, {}, notebook};
+}
+
+constexpr PreferencesWidget
+WidgetSeparator(WidgetVSeparator separator = WidgetVSeparator())
+{
+ return {PreferencesWidget::Separator, 0, 0, {}, separator};
+}
+
+constexpr PreferencesWidget
+WidgetCustomGTK(void * (*populate)(), WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {
+ PreferencesWidget::CustomGTK, 0, (child == WIDGET_CHILD), {}, populate};
+}
+
+constexpr PreferencesWidget
+WidgetCustomQt(void * (*populate)(), WidgetIsChild child = WIDGET_NOT_CHILD)
+{
+ return {
+ PreferencesWidget::CustomQt, 0, (child == WIDGET_CHILD), {}, populate};
+}
+
+struct PluginPreferences
+{
ArrayRef<PreferencesWidget> widgets;
- void (* init) ();
- void (* apply) ();
- void (* cleanup) ();
+ void (*init)();
+ void (*apply)();
+ void (*cleanup)();
};
#endif /* LIBAUDCORE_PREFERENCES_H */
diff --git a/src/libaudcore/probe-buffer.cc b/src/libaudcore/probe-buffer.cc
index e23992c..f5ce248 100644
--- a/src/libaudcore/probe-buffer.cc
+++ b/src/libaudcore/probe-buffer.cc
@@ -24,41 +24,37 @@
static constexpr int MAXBUF = 256 * 1024;
-ProbeBuffer::ProbeBuffer (const char * filename, VFSImpl * file) :
- m_filename (filename),
- m_file (file)
+ProbeBuffer::ProbeBuffer(const char * filename, VFSImpl * file)
+ : m_filename(filename), m_file(file)
{
- AUDINFO ("<%p> buffering enabled for %s\n", this, (const char *) m_filename);
+ AUDINFO("<%p> buffering enabled for %s\n", this, (const char *)m_filename);
}
-ProbeBuffer::~ProbeBuffer ()
-{
- delete[] m_buffer;
-}
+ProbeBuffer::~ProbeBuffer() { delete[] m_buffer; }
-void ProbeBuffer::increase_buffer (int64_t size)
+void ProbeBuffer::increase_buffer(int64_t size)
{
- size = aud::min ((size + 0xFF) & ~0xFF, (int64_t) MAXBUF);
+ size = aud::min((size + 0xFF) & ~0xFF, (int64_t)MAXBUF);
if (m_filled < size)
{
- if (! m_buffer)
+ if (!m_buffer)
m_buffer = new char[MAXBUF];
- m_filled += m_file->fread (m_buffer + m_filled, 1, size - m_filled);
+ m_filled += m_file->fread(m_buffer + m_filled, 1, size - m_filled);
}
}
-void ProbeBuffer::release_buffer ()
+void ProbeBuffer::release_buffer()
{
- AUDINFO ("<%p> buffering disabled for %s\n", this, (const char *) m_filename);
+ AUDINFO("<%p> buffering disabled for %s\n", this, (const char *)m_filename);
delete[] m_buffer;
m_buffer = nullptr;
m_filled = 0;
m_at = -1;
}
-int64_t ProbeBuffer::fread (void * buffer, int64_t size, int64_t count)
+int64_t ProbeBuffer::fread(void * buffer, int64_t size, int64_t count)
{
int64_t total = 0;
int64_t remain = size * count;
@@ -66,37 +62,37 @@ int64_t ProbeBuffer::fread (void * buffer, int64_t size, int64_t count)
/* read from buffer if possible */
if (remain && m_at >= 0 && m_at < MAXBUF)
{
- increase_buffer (m_at + remain);
+ increase_buffer(m_at + remain);
- int copy = aud::min (remain, (int64_t) (m_filled - m_at));
- memcpy (buffer, m_buffer + m_at, copy);
+ int copy = aud::min(remain, (int64_t)(m_filled - m_at));
+ memcpy(buffer, m_buffer + m_at, copy);
m_at += copy;
- buffer = (char *) buffer + copy;
+ buffer = (char *)buffer + copy;
total += copy;
remain -= copy;
}
/* then read from real file if allowed */
- if (remain && ! m_limited)
+ if (remain && !m_limited)
{
/* release buffer if leaving bufferable area */
if (m_at == MAXBUF)
- release_buffer ();
+ release_buffer();
if (m_at < 0)
- total += m_file->fread (buffer, 1, remain);
+ total += m_file->fread(buffer, 1, remain);
}
return (size > 0) ? total / size : 0;
}
-int64_t ProbeBuffer::fwrite (const void * data, int64_t size, int64_t count)
+int64_t ProbeBuffer::fwrite(const void * data, int64_t size, int64_t count)
{
return 0; /* not allowed */
}
-int ProbeBuffer::fseek (int64_t offset, VFSSeekType whence)
+int ProbeBuffer::fseek(int64_t offset, VFSSeekType whence)
{
/* seek within the buffer if possible */
if (m_at >= 0 && whence != VFS_SEEK_END)
@@ -113,7 +109,7 @@ int ProbeBuffer::fseek (int64_t offset, VFSSeekType whence)
if (offset <= MAXBUF)
{
- increase_buffer (offset);
+ increase_buffer(offset);
if (offset > m_filled)
return -1; /* seek past end of file */
@@ -124,56 +120,48 @@ int ProbeBuffer::fseek (int64_t offset, VFSSeekType whence)
}
/* seek within real file if allowed */
- if (m_limited || m_file->fseek (offset, whence) < 0)
+ if (m_limited || m_file->fseek(offset, whence) < 0)
return -1;
/* release buffer only if real seek succeeded
* (prevents change of file position if seek failed) */
if (m_at >= 0)
- release_buffer ();
+ release_buffer();
/* activate buffering again when seeking to beginning of file */
if (whence == VFS_SEEK_SET && offset == 0)
{
- AUDINFO ("<%p> buffering enabled for %s\n", this, (const char *) m_filename);
+ AUDINFO("<%p> buffering enabled for %s\n", this,
+ (const char *)m_filename);
m_at = 0;
}
return 0;
}
-int64_t ProbeBuffer::ftell ()
+int64_t ProbeBuffer::ftell()
{
if (m_at >= 0)
return m_at;
- return m_file->ftell ();
+ return m_file->ftell();
}
-bool ProbeBuffer::feof ()
+bool ProbeBuffer::feof()
{
if (m_at >= 0 && m_at < m_filled)
return false;
- return m_file->feof ();
+ return m_file->feof();
}
-int ProbeBuffer::ftruncate (int64_t size)
-{
- return -1; /* not allowed */
-}
+int ProbeBuffer::ftruncate(int64_t size) { return -1; /* not allowed */ }
-int ProbeBuffer::fflush ()
-{
- return 0; /* no-op */
-}
+int ProbeBuffer::fflush() { return 0; /* no-op */ }
-int64_t ProbeBuffer::fsize ()
-{
- return m_file->fsize ();
-}
+int64_t ProbeBuffer::fsize() { return m_file->fsize(); }
-String ProbeBuffer::get_metadata (const char * field)
+String ProbeBuffer::get_metadata(const char * field)
{
- return m_file->get_metadata (field);
+ return m_file->get_metadata(field);
}
diff --git a/src/libaudcore/probe-buffer.h b/src/libaudcore/probe-buffer.h
index 5cdfc29..1f85b69 100644
--- a/src/libaudcore/probe-buffer.h
+++ b/src/libaudcore/probe-buffer.h
@@ -39,28 +39,27 @@
class ProbeBuffer : public VFSImpl
{
public:
- ProbeBuffer (const char * filename, VFSImpl * file);
- ~ProbeBuffer ();
+ ProbeBuffer(const char * filename, VFSImpl * file);
+ ~ProbeBuffer();
- int64_t fread (void * ptr, int64_t size, int64_t nmemb);
- int fseek (int64_t offset, VFSSeekType whence);
+ int64_t fread(void * ptr, int64_t size, int64_t nmemb);
+ int fseek(int64_t offset, VFSSeekType whence);
- int64_t ftell ();
- int64_t fsize ();
- bool feof ();
+ int64_t ftell();
+ int64_t fsize();
+ bool feof();
- int64_t fwrite (const void * ptr, int64_t size, int64_t nmemb);
- int ftruncate (int64_t length);
- int fflush ();
+ int64_t fwrite(const void * ptr, int64_t size, int64_t nmemb);
+ int ftruncate(int64_t length);
+ int fflush();
- String get_metadata (const char * field);
+ String get_metadata(const char * field);
- void set_limit_to_buffer (bool limit)
- { m_limited = limit; }
+ void set_limit_to_buffer(bool limit) { m_limited = limit; }
private:
- void increase_buffer (int64_t size);
- void release_buffer ();
+ void increase_buffer(int64_t size);
+ void release_buffer();
String m_filename;
SmartPtr<VFSImpl> m_file;
diff --git a/src/libaudcore/probe.cc b/src/libaudcore/probe.cc
index 38cf73d..5868167 100644
--- a/src/libaudcore/probe.cc
+++ b/src/libaudcore/probe.cc
@@ -17,8 +17,8 @@
* the use of this software.
*/
-#include "internal.h"
#include "probe.h"
+#include "internal.h"
#include <string.h>
@@ -29,52 +29,53 @@
#include "plugins-internal.h"
#include "runtime.h"
-bool open_input_file (const char * filename, const char * mode,
- InputPlugin * ip, VFSFile & file, String * error)
+bool open_input_file(const char * filename, const char * mode, InputPlugin * ip,
+ VFSFile & file, String * error)
{
/* no need to open a handle for custom URI schemes */
if (ip && ip->input_info.keys[InputKey::Scheme])
return true;
/* already open? */
- if (file && file.fseek (0, VFS_SEEK_SET) == 0)
+ if (file && file.fseek(0, VFS_SEEK_SET) == 0)
return true;
- file = VFSFile (filename, mode);
- if (! file && error)
- * error = String (file.error ());
+ file = VFSFile(filename, mode);
+ if (!file && error)
+ *error = String(file.error());
- return (bool) file;
+ return (bool)file;
}
-InputPlugin * load_input_plugin (PluginHandle * decoder, String * error)
+InputPlugin * load_input_plugin(PluginHandle * decoder, String * error)
{
- auto ip = (InputPlugin *) aud_plugin_get_header (decoder);
- if (! ip && error)
- * error = String (_("Error loading plugin"));
+ auto ip = (InputPlugin *)aud_plugin_get_header(decoder);
+ if (!ip && error)
+ *error = String(_("Error loading plugin"));
return ip;
}
/* figure out some basic info without opening the file */
-int probe_by_filename (const char * filename)
+int probe_by_filename(const char * filename)
{
int flags = 0;
- auto & list = aud_plugin_list (PluginType::Input);
+ auto & list = aud_plugin_list(PluginType::Input);
- StringBuf scheme = uri_get_scheme (filename);
- StringBuf ext = uri_get_extension (filename);
+ StringBuf scheme = uri_get_scheme(filename);
+ StringBuf ext = uri_get_extension(filename);
for (PluginHandle * plugin : list)
{
- if (! aud_plugin_get_enabled (plugin))
+ if (!aud_plugin_get_enabled(plugin))
continue;
- if ((scheme && input_plugin_has_key (plugin, InputKey::Scheme, scheme)) ||
- (ext && input_plugin_has_key (plugin, InputKey::Ext, ext)))
+ if ((scheme &&
+ input_plugin_has_key(plugin, InputKey::Scheme, scheme)) ||
+ (ext && input_plugin_has_key(plugin, InputKey::Ext, ext)))
{
flags |= PROBE_FLAG_HAS_DECODER;
- if (input_plugin_has_subtunes (plugin))
+ if (input_plugin_has_subtunes(plugin))
flags |= PROBE_FLAG_MIGHT_HAVE_SUBTUNES;
}
}
@@ -82,164 +83,167 @@ int probe_by_filename (const char * filename)
return flags;
}
-EXPORT PluginHandle * aud_file_find_decoder (const char * filename, bool fast,
- VFSFile & file, String * error)
+EXPORT PluginHandle * aud_file_find_decoder(const char * filename, bool fast,
+ VFSFile & file, String * error)
{
- AUDINFO ("%s %s.\n", fast ? "Fast-probing" : "Probing", filename);
+ AUDINFO("%s %s.\n", fast ? "Fast-probing" : "Probing", filename);
- auto & list = aud_plugin_list (PluginType::Input);
+ auto & list = aud_plugin_list(PluginType::Input);
- StringBuf scheme = uri_get_scheme (filename);
- StringBuf ext = uri_get_extension (filename);
+ StringBuf scheme = uri_get_scheme(filename);
+ StringBuf ext = uri_get_extension(filename);
Index<PluginHandle *> ext_matches;
for (PluginHandle * plugin : list)
{
- if (! aud_plugin_get_enabled (plugin))
+ if (!aud_plugin_get_enabled(plugin))
continue;
- if (scheme && input_plugin_has_key (plugin, InputKey::Scheme, scheme))
+ if (scheme && input_plugin_has_key(plugin, InputKey::Scheme, scheme))
{
- AUDINFO ("Matched %s by URI scheme.\n", aud_plugin_get_name (plugin));
+ AUDINFO("Matched %s by URI scheme.\n", aud_plugin_get_name(plugin));
return plugin;
}
- if (ext && input_plugin_has_key (plugin, InputKey::Ext, ext))
- ext_matches.append (plugin);
+ if (ext && input_plugin_has_key(plugin, InputKey::Ext, ext))
+ ext_matches.append(plugin);
}
- if (ext_matches.len () == 1)
+ if (ext_matches.len() == 1)
{
- AUDINFO ("Matched %s by extension.\n", aud_plugin_get_name (ext_matches[0]));
+ AUDINFO("Matched %s by extension.\n",
+ aud_plugin_get_name(ext_matches[0]));
return ext_matches[0];
}
- AUDDBG ("Matched %d plugins by extension.\n", ext_matches.len ());
+ AUDDBG("Matched %d plugins by extension.\n", ext_matches.len());
- if (fast && ! ext_matches.len ())
+ if (fast && !ext_matches.len())
return nullptr;
- AUDDBG ("Opening %s.\n", filename);
+ AUDDBG("Opening %s.\n", filename);
- if (! open_input_file (filename, "r", nullptr, file, error))
+ if (!open_input_file(filename, "r", nullptr, file, error))
{
- AUDINFO ("Open failed.\n");
+ AUDINFO("Open failed.\n");
return nullptr;
}
- String mime = file.get_metadata ("content-type");
+ String mime = file.get_metadata("content-type");
if (mime)
{
- for (PluginHandle * plugin : (ext_matches.len () ? ext_matches : list))
+ for (PluginHandle * plugin : (ext_matches.len() ? ext_matches : list))
{
- if (! aud_plugin_get_enabled (plugin))
+ if (!aud_plugin_get_enabled(plugin))
continue;
- if (input_plugin_has_key (plugin, InputKey::MIME, mime))
+ if (input_plugin_has_key(plugin, InputKey::MIME, mime))
{
- AUDINFO ("Matched %s by MIME type %s.\n",
- aud_plugin_get_name (plugin), (const char *) mime);
+ AUDINFO("Matched %s by MIME type %s.\n",
+ aud_plugin_get_name(plugin), (const char *)mime);
return plugin;
}
}
}
- file.set_limit_to_buffer (true);
+ file.set_limit_to_buffer(true);
- for (PluginHandle * plugin : (ext_matches.len () ? ext_matches : list))
+ for (PluginHandle * plugin : (ext_matches.len() ? ext_matches : list))
{
- if (! aud_plugin_get_enabled (plugin))
+ if (!aud_plugin_get_enabled(plugin))
continue;
- AUDINFO ("Trying %s.\n", aud_plugin_get_name (plugin));
+ AUDINFO("Trying %s.\n", aud_plugin_get_name(plugin));
- auto ip = (InputPlugin *) aud_plugin_get_header (plugin);
- if (! ip)
+ auto ip = (InputPlugin *)aud_plugin_get_header(plugin);
+ if (!ip)
continue;
- if (ip->is_our_file (filename, file))
+ if (ip->is_our_file(filename, file))
{
- AUDINFO ("Matched %s by content.\n", aud_plugin_get_name (plugin));
- file.set_limit_to_buffer (false);
+ AUDINFO("Matched %s by content.\n", aud_plugin_get_name(plugin));
+ file.set_limit_to_buffer(false);
return plugin;
}
- if (file.fseek (0, VFS_SEEK_SET) != 0)
+ if (file.fseek(0, VFS_SEEK_SET) != 0)
{
if (error)
- * error = String (_("Seek error"));
+ *error = String(_("Seek error"));
- AUDINFO ("Seek failed.\n");
+ AUDINFO("Seek failed.\n");
return nullptr;
}
}
if (error)
- * error = String (_("File format not recognized"));
+ *error = String(_("File format not recognized"));
- AUDINFO ("No plugins matched.\n");
+ AUDINFO("No plugins matched.\n");
return nullptr;
}
-EXPORT bool aud_file_read_tag (const char * filename, PluginHandle * decoder,
- VFSFile & file, Tuple & tuple, Index<char> * image, String * error)
+EXPORT bool aud_file_read_tag(const char * filename, PluginHandle * decoder,
+ VFSFile & file, Tuple & tuple,
+ Index<char> * image, String * error)
{
- auto ip = load_input_plugin (decoder, error);
- if (! ip)
+ auto ip = load_input_plugin(decoder, error);
+ if (!ip)
return false;
- if (! open_input_file (filename, "r", ip, file, error))
+ if (!open_input_file(filename, "r", ip, file, error))
return false;
Tuple new_tuple;
- new_tuple.set_filename (filename);
+ new_tuple.set_filename(filename);
- if (ip->read_tag (filename, file, new_tuple, image))
+ if (ip->read_tag(filename, file, new_tuple, image))
{
// cleanly replace existing tuple
- new_tuple.set_state (Tuple::Valid);
- tuple = std::move (new_tuple);
+ new_tuple.set_state(Tuple::Valid);
+ tuple = std::move(new_tuple);
return true;
}
if (error)
- * error = String (_("Error reading metadata"));
+ *error = String(_("Error reading metadata"));
return false;
}
-EXPORT bool aud_file_can_write_tuple (const char * filename, PluginHandle * decoder)
+EXPORT bool aud_file_can_write_tuple(const char * filename,
+ PluginHandle * decoder)
{
- return input_plugin_can_write_tuple (decoder);
+ return input_plugin_can_write_tuple(decoder);
}
-EXPORT bool aud_file_write_tuple (const char * filename,
- PluginHandle * decoder, const Tuple & tuple)
+EXPORT bool aud_file_write_tuple(const char * filename, PluginHandle * decoder,
+ const Tuple & tuple)
{
- auto ip = (InputPlugin *) aud_plugin_get_header (decoder);
- if (! ip)
+ auto ip = (InputPlugin *)aud_plugin_get_header(decoder);
+ if (!ip)
return false;
VFSFile file;
- if (! open_input_file (filename, "r+", ip, file))
+ if (!open_input_file(filename, "r+", ip, file))
return false;
- bool success = ip->write_tuple (filename, file, tuple);
+ bool success = ip->write_tuple(filename, file, tuple);
- if (success && file && file.fflush () != 0)
+ if (success && file && file.fflush() != 0)
success = false;
if (success)
- Playlist::rescan_file (filename);
+ Playlist::rescan_file(filename);
return success;
}
-EXPORT bool aud_custom_infowin (const char * filename, PluginHandle * decoder)
+EXPORT bool aud_custom_infowin(const char * filename, PluginHandle * decoder)
{
// blacklist stdin
- if (! strncmp (filename, "stdin://", 8))
+ if (!strncmp(filename, "stdin://", 8))
return false;
// In hindsight, a flag should have been added indicating whether a
@@ -247,17 +251,17 @@ EXPORT bool aud_custom_infowin (const char * filename, PluginHandle * decoder)
// plugins do so. Since custom info windows are deprecated anyway,
// check for those two plugins explicitly and in all other cases,
// don't open the input file to prevent freezing the UI.
- const char * base = aud_plugin_get_basename (decoder);
- if (strcmp (base, "amidi-plug") && strcmp (base, "vtx"))
+ const char * base = aud_plugin_get_basename(decoder);
+ if (strcmp(base, "amidi-plug") && strcmp(base, "vtx"))
return false;
- auto ip = (InputPlugin *) aud_plugin_get_header (decoder);
- if (! ip)
+ auto ip = (InputPlugin *)aud_plugin_get_header(decoder);
+ if (!ip)
return false;
VFSFile file;
- if (! open_input_file (filename, "r", ip, file))
+ if (!open_input_file(filename, "r", ip, file))
return false;
- return ip->file_info_box (filename, file);
+ return ip->file_info_box(filename, file);
}
diff --git a/src/libaudcore/probe.h b/src/libaudcore/probe.h
index c206f6c..c2be567 100644
--- a/src/libaudcore/probe.h
+++ b/src/libaudcore/probe.h
@@ -30,30 +30,32 @@ class VFSFile;
/* ====== ALBUM ART API ====== */
/* request format */
-enum {
- AUD_ART_DATA = (1 << 0), /* image data in memory */
- AUD_ART_FILE = (1 << 1) /* filename of image data on disk */
+enum
+{
+ AUD_ART_DATA = (1 << 0), /* image data in memory */
+ AUD_ART_FILE = (1 << 1) /* filename of image data on disk */
};
/* opaque type storing art data */
struct AudArtItem;
/* don't use these directly, use AudArtPtr */
-const Index<char> * aud_art_data (const AudArtItem * item);
-const char * aud_art_file (const AudArtItem * item);
-void aud_art_unref (AudArtItem * item);
+const Index<char> * aud_art_data(const AudArtItem * item);
+const char * aud_art_file(const AudArtItem * item);
+void aud_art_unref(AudArtItem * item);
/* handle for accessing/tracking album art data */
class AudArtPtr : public SmartPtr<AudArtItem, aud_art_unref>
{
public:
- AudArtPtr () : SmartPtr () {}
- explicit AudArtPtr (AudArtItem * ptr) : SmartPtr (ptr) {}
+ AudArtPtr() : SmartPtr() {}
+ explicit AudArtPtr(AudArtItem * ptr) : SmartPtr(ptr) {}
- const Index<char> * data () const
- { return get () ? aud_art_data (get ()) : nullptr; }
- const char * file () const
- { return get () ? aud_art_file (get ()) : nullptr; }
+ const Index<char> * data() const
+ {
+ return get() ? aud_art_data(get()) : nullptr;
+ }
+ const char * file() const { return get() ? aud_art_file(get()) : nullptr; }
};
/*
@@ -71,22 +73,25 @@ public:
*
* On error, a null pointer is returned and *queued is set to false.
*/
-AudArtPtr aud_art_request (const char * file, int format, bool * queued = nullptr);
+AudArtPtr aud_art_request(const char * file, int format,
+ bool * queued = nullptr);
/* ====== GENERAL PROBING API ====== */
/* The following two functions take an additional VFSFile parameter to allow
* opening a file, probing for a decoder, and then reading the song metadata
* without opening the file a second time. If you don't already have a file
- * handle open, then just pass in a null VFSFile and it will be opened for you. */
-PluginHandle * aud_file_find_decoder (const char * filename, bool fast,
- VFSFile & file, String * error = nullptr);
-bool aud_file_read_tag (const char * filename, PluginHandle * decoder,
- VFSFile & file, Tuple & tuple, Index<char> * image = nullptr,
- String * error = nullptr);
+ * handle open, then just pass in a null VFSFile and it will be opened for you.
+ */
+PluginHandle * aud_file_find_decoder(const char * filename, bool fast,
+ VFSFile & file, String * error = nullptr);
+bool aud_file_read_tag(const char * filename, PluginHandle * decoder,
+ VFSFile & file, Tuple & tuple,
+ Index<char> * image = nullptr, String * error = nullptr);
-bool aud_file_can_write_tuple (const char * filename, PluginHandle * decoder);
-bool aud_file_write_tuple (const char * filename, PluginHandle * decoder, const Tuple & tuple);
-bool aud_custom_infowin (const char * filename, PluginHandle * decoder);
+bool aud_file_can_write_tuple(const char * filename, PluginHandle * decoder);
+bool aud_file_write_tuple(const char * filename, PluginHandle * decoder,
+ const Tuple & tuple);
+bool aud_custom_infowin(const char * filename, PluginHandle * decoder);
#endif
diff --git a/src/libaudcore/ringbuf.cc b/src/libaudcore/ringbuf.cc
index 07fbc59..0c5fef1 100644
--- a/src/libaudcore/ringbuf.cc
+++ b/src/libaudcore/ringbuf.cc
@@ -24,40 +24,40 @@
#include <stdlib.h>
#include <string.h>
-void RingBufBase::get_areas (int pos, int len, Areas & areas)
+void RingBufBase::get_areas(int pos, int len, Areas & areas)
{
- assert (pos >= 0 && len >= 0 && pos + len <= m_len);
+ assert(pos >= 0 && len >= 0 && pos + len <= m_len);
int start = (m_offset + pos) % m_size;
- int part = aud::min (len, m_size - start);
+ int part = aud::min(len, m_size - start);
- areas.area1 = (char *) m_data + start;
+ areas.area1 = (char *)m_data + start;
areas.area2 = m_data;
areas.len1 = part;
areas.len2 = len - part;
}
-void RingBufBase::do_realloc (int size)
+void RingBufBase::do_realloc(int size)
{
- void * mem = realloc (m_data, size);
- if (size && ! mem)
- throw std::bad_alloc (); /* nothing changed yet */
+ void * mem = realloc(m_data, size);
+ if (size && !mem)
+ throw std::bad_alloc(); /* nothing changed yet */
m_data = mem;
}
-EXPORT void RingBufBase::alloc (int size)
+EXPORT void RingBufBase::alloc(int size)
{
- assert (size >= m_len);
+ assert(size >= m_len);
if (size == m_size)
return;
/* reallocate first when growing */
if (size > m_size)
- do_realloc (size);
+ do_realloc(size);
- __sync_add_and_fetch (& misc_bytes_allocated, size - m_size);
+ __sync_add_and_fetch(&misc_bytes_allocated, size - m_size);
int old_size = m_size;
int to_end = m_size - m_offset;
@@ -67,38 +67,38 @@ EXPORT void RingBufBase::alloc (int size)
if (to_end < m_len)
{
int new_offset = size - to_end;
- memmove ((char *) m_data + new_offset, (char *) m_data + m_offset, to_end);
+ memmove((char *)m_data + new_offset, (char *)m_data + m_offset, to_end);
m_offset = new_offset;
}
/* reallocate last when shrinking */
if (size < old_size)
- do_realloc (size);
+ do_realloc(size);
}
-EXPORT void RingBufBase::destroy (aud::EraseFunc erase_func)
+EXPORT void RingBufBase::destroy(aud::EraseFunc erase_func)
{
- if (! m_data)
+ if (!m_data)
return;
- __sync_sub_and_fetch (& misc_bytes_allocated, m_size);
+ __sync_sub_and_fetch(&misc_bytes_allocated, m_size);
- discard (-1, erase_func);
+ discard(-1, erase_func);
- free (m_data);
+ free(m_data);
m_data = nullptr;
m_size = 0;
}
-EXPORT void RingBufBase::add (int len)
+EXPORT void RingBufBase::add(int len)
{
- assert (len >= 0 && m_len + len <= m_size);
+ assert(len >= 0 && m_len + len <= m_size);
m_len += len;
}
-EXPORT void RingBufBase::remove (int len)
+EXPORT void RingBufBase::remove(int len)
{
- assert (len >= 0 && len <= m_len);
+ assert(len >= 0 && len <= m_len);
if (len == m_len)
m_offset = m_len = 0;
@@ -109,54 +109,55 @@ EXPORT void RingBufBase::remove (int len)
}
}
-EXPORT void RingBufBase::copy_in (const void * from, int len, aud::CopyFunc copy_func)
+EXPORT void RingBufBase::copy_in(const void * from, int len,
+ aud::CopyFunc copy_func)
{
Areas areas;
- add (len);
- get_areas (m_len - len, len, areas);
+ add(len);
+ get_areas(m_len - len, len, areas);
if (copy_func)
{
- copy_func (from, areas.area1, areas.len1);
- copy_func ((const char *) from + areas.len1, areas.area2, areas.len2);
+ copy_func(from, areas.area1, areas.len1);
+ copy_func((const char *)from + areas.len1, areas.area2, areas.len2);
}
else
{
- memcpy (areas.area1, from, areas.len1);
- memcpy (areas.area2, (const char *) from + areas.len1, areas.len2);
+ memcpy(areas.area1, from, areas.len1);
+ memcpy(areas.area2, (const char *)from + areas.len1, areas.len2);
}
}
-EXPORT void RingBufBase::move_in (void * from, int len, aud::FillFunc fill_func)
+EXPORT void RingBufBase::move_in(void * from, int len, aud::FillFunc fill_func)
{
Areas areas;
- add (len);
- get_areas (m_len - len, len, areas);
+ add(len);
+ get_areas(m_len - len, len, areas);
- memcpy (areas.area1, from, areas.len1);
- memcpy (areas.area2, (const char *) from + areas.len1, areas.len2);
+ memcpy(areas.area1, from, areas.len1);
+ memcpy(areas.area2, (const char *)from + areas.len1, areas.len2);
if (fill_func)
- fill_func (from, len);
+ fill_func(from, len);
}
-EXPORT void RingBufBase::move_out (void * to, int len, aud::EraseFunc erase_func)
+EXPORT void RingBufBase::move_out(void * to, int len, aud::EraseFunc erase_func)
{
Areas areas;
- get_areas (0, len, areas);
+ get_areas(0, len, areas);
if (erase_func)
- erase_func (to, len);
+ erase_func(to, len);
- memcpy (to, areas.area1, areas.len1);
- memcpy ((char *) to + areas.len1, areas.area2, areas.len2);
+ memcpy(to, areas.area1, areas.len1);
+ memcpy((char *)to + areas.len1, areas.area2, areas.len2);
- remove (len);
+ remove(len);
}
-EXPORT void RingBufBase::discard (int len, aud::EraseFunc erase_func)
+EXPORT void RingBufBase::discard(int len, aud::EraseFunc erase_func)
{
- if (! m_data)
+ if (!m_data)
return;
if (len < 0)
@@ -165,33 +166,33 @@ EXPORT void RingBufBase::discard (int len, aud::EraseFunc erase_func)
if (erase_func)
{
Areas areas;
- get_areas (0, len, areas);
- erase_func (areas.area1, areas.len1);
- erase_func (areas.area2, areas.len2);
+ get_areas(0, len, areas);
+ erase_func(areas.area1, areas.len1);
+ erase_func(areas.area2, areas.len2);
}
- remove (len);
+ remove(len);
}
-EXPORT void RingBufBase::move_in (IndexBase & index, int from, int len)
+EXPORT void RingBufBase::move_in(IndexBase & index, int from, int len)
{
- assert (from >= 0 && from <= index.len ());
- assert (len <= index.len () - from);
+ assert(from >= 0 && from <= index.len());
+ assert(len <= index.len() - from);
if (len < 0)
- len = index.len () - from;
+ len = index.len() - from;
- move_in ((char *) index.begin () + from, len, nullptr);
- index.remove (from, len, nullptr);
+ move_in((char *)index.begin() + from, len, nullptr);
+ index.remove(from, len, nullptr);
}
-EXPORT void RingBufBase::move_out (IndexBase & index, int to, int len)
+EXPORT void RingBufBase::move_out(IndexBase & index, int to, int len)
{
- assert (len <= m_len);
+ assert(len <= m_len);
if (len < 0)
len = m_len;
- void * ptr = index.insert (to, len);
- move_out (ptr, len, nullptr);
+ void * ptr = index.insert(to, len);
+ move_out(ptr, len, nullptr);
}
diff --git a/src/libaudcore/ringbuf.h b/src/libaudcore/ringbuf.h
index 5206588..2dd72bd 100644
--- a/src/libaudcore/ringbuf.h
+++ b/src/libaudcore/ringbuf.h
@@ -38,17 +38,13 @@
class RingBufBase
{
public:
- constexpr RingBufBase () :
- m_data (nullptr),
- m_size (0),
- m_offset (0),
- m_len (0) {}
-
- RingBufBase (RingBufBase && b) :
- m_data (b.m_data),
- m_size (b.m_size),
- m_offset (b.m_offset),
- m_len (b.m_len)
+ constexpr RingBufBase() : m_data(nullptr), m_size(0), m_offset(0), m_len(0)
+ {
+ }
+
+ RingBufBase(RingBufBase && b)
+ : m_data(b.m_data), m_size(b.m_size), m_offset(b.m_offset),
+ m_len(b.m_len)
{
b.m_data = nullptr;
b.m_size = 0;
@@ -57,42 +53,42 @@ public:
}
// allocated size of the buffer
- int size () const
- { return m_size; }
+ int size() const { return m_size; }
// number of bytes currently used
- int len () const
- { return m_len; }
+ int len() const { return m_len; }
// number of bytes that can be read linearly
- int linear () const
- { return aud::min (m_len, m_size - m_offset); }
+ int linear() const { return aud::min(m_len, m_size - m_offset); }
- void * at (int pos) const
- { return (char *) m_data + (m_offset + pos) % m_size; }
+ void * at(int pos) const
+ {
+ return (char *)m_data + (m_offset + pos) % m_size;
+ }
- void alloc (int size);
- void destroy (aud::EraseFunc erase_func);
+ void alloc(int size);
+ void destroy(aud::EraseFunc erase_func);
- void add (int len); // no fill
- void remove (int len); // no erase
+ void add(int len); // no fill
+ void remove(int len); // no erase
- void copy_in (const void * from, int len, aud::CopyFunc copy_func);
- void move_in (void * from, int len, aud::FillFunc fill_func);
- void move_out (void * to, int len, aud::EraseFunc erase_func);
- void discard (int len, aud::EraseFunc erase_func);
+ void copy_in(const void * from, int len, aud::CopyFunc copy_func);
+ void move_in(void * from, int len, aud::FillFunc fill_func);
+ void move_out(void * to, int len, aud::EraseFunc erase_func);
+ void discard(int len, aud::EraseFunc erase_func);
- void move_in (IndexBase & index, int from, int len);
- void move_out (IndexBase & index, int to, int len);
+ void move_in(IndexBase & index, int from, int len);
+ void move_out(IndexBase & index, int to, int len);
private:
- struct Areas {
- void * area1, * area2;
+ struct Areas
+ {
+ void *area1, *area2;
int len1, len2;
};
- void get_areas (int pos, int len, Areas & areas);
- void do_realloc (int size);
+ void get_areas(int pos, int len, Areas & areas);
+ void do_realloc(int size);
void * m_data;
int m_size, m_offset, m_len;
@@ -102,71 +98,75 @@ template<class T>
class RingBuf : private RingBufBase
{
public:
- constexpr RingBuf () :
- RingBufBase () {}
-
- ~RingBuf ()
- { destroy (); }
-
- RingBuf (RingBuf && b) :
- RingBufBase (std::move (b)) {}
- RingBuf & operator= (RingBuf && b)
- { return aud::move_assign (* this, std::move (b)); }
-
- int size () const
- { return cooked (RingBufBase::size ()); }
- int len () const
- { return cooked (RingBufBase::len ()); }
- int linear () const
- { return cooked (RingBufBase::linear ()); }
- int space () const
- { return size () - len (); }
-
- T & operator[] (int i)
- { return * (T *) RingBufBase::at (raw (i)); }
- const T & operator[] (int i) const
- { return * (const T *) RingBufBase::at (raw (i)); }
-
- void alloc (int size)
- { RingBufBase::alloc (raw (size)); }
- void destroy ()
- { RingBufBase::destroy (aud::erase_func<T> ()); }
-
- void copy_in (const T * from, int len)
- { RingBufBase::copy_in (from, raw (len), aud::copy_func<T> ()); }
- void move_in (T * from, int len)
- { RingBufBase::move_in (from, raw (len), aud::fill_func<T> ()); }
- void move_out (T * to, int len)
- { RingBufBase::move_out (to, raw (len), aud::erase_func<T> ()); }
- void discard (int len = -1)
- { RingBufBase::discard (raw (len), aud::erase_func<T> ()); }
-
- void move_in (Index<T> & index, int from, int len)
- { RingBufBase::move_in (index.base (), raw (from), raw (len)); }
- void move_out (Index<T> & index, int to, int len)
- { RingBufBase::move_out (index.base (), raw (to), raw (len)); }
-
- template<class ... Args>
- T & push (Args && ... args)
+ constexpr RingBuf() : RingBufBase() {}
+
+ ~RingBuf() { destroy(); }
+
+ RingBuf(RingBuf && b) : RingBufBase(std::move(b)) {}
+ RingBuf & operator=(RingBuf && b)
+ {
+ return aud::move_assign(*this, std::move(b));
+ }
+
+ int size() const { return cooked(RingBufBase::size()); }
+ int len() const { return cooked(RingBufBase::len()); }
+ int linear() const { return cooked(RingBufBase::linear()); }
+ int space() const { return size() - len(); }
+
+ T & operator[](int i) { return *(T *)RingBufBase::at(raw(i)); }
+ const T & operator[](int i) const
+ {
+ return *(const T *)RingBufBase::at(raw(i));
+ }
+
+ void alloc(int size) { RingBufBase::alloc(raw(size)); }
+ void destroy() { RingBufBase::destroy(aud::erase_func<T>()); }
+
+ void copy_in(const T * from, int len)
+ {
+ RingBufBase::copy_in(from, raw(len), aud::copy_func<T>());
+ }
+ void move_in(T * from, int len)
+ {
+ RingBufBase::move_in(from, raw(len), aud::fill_func<T>());
+ }
+ void move_out(T * to, int len)
+ {
+ RingBufBase::move_out(to, raw(len), aud::erase_func<T>());
+ }
+ void discard(int len = -1)
+ {
+ RingBufBase::discard(raw(len), aud::erase_func<T>());
+ }
+
+ void move_in(Index<T> & index, int from, int len)
+ {
+ RingBufBase::move_in(index.base(), raw(from), raw(len));
+ }
+ void move_out(Index<T> & index, int to, int len)
+ {
+ RingBufBase::move_out(index.base(), raw(to), raw(len));
+ }
+
+ template<class... Args>
+ T & push(Args &&... args)
{
- add (raw (1));
- return * aud::construct<T>::make (at (raw (len () - 1)), std::forward<Args> (args) ...);
+ add(raw(1));
+ return *aud::construct<T>::make(at(raw(len() - 1)),
+ std::forward<Args>(args)...);
}
- T & head ()
- { return * (T *) at (raw (0)); }
+ T & head() { return *(T *)at(raw(0)); }
- void pop ()
+ void pop()
{
- head ().~T ();
- remove (raw (1));
+ head().~T();
+ remove(raw(1));
}
private:
- static constexpr int raw (int len)
- { return len * sizeof (T); }
- static constexpr int cooked (int len)
- { return len / sizeof (T); }
+ static constexpr int raw(int len) { return len * sizeof(T); }
+ static constexpr int cooked(int len) { return len / sizeof(T); }
};
#endif // LIBAUDCORE_RINGBUF_H
diff --git a/src/libaudcore/runtime.cc b/src/libaudcore/runtime.cc
index 382e773..062cc59 100644
--- a/src/libaudcore/runtime.cc
+++ b/src/libaudcore/runtime.cc
@@ -67,301 +67,299 @@ size_t misc_bytes_allocated;
static bool headless_mode;
static int instance_number = 1;
-#if defined(USE_QT) && ! defined(USE_GTK)
-static MainloopType mainloop_type = MainloopType::Qt;
-#else
+#if defined(USE_GTK) && !defined(USE_QT)
static MainloopType mainloop_type = MainloopType::GLib;
+#else
+static MainloopType mainloop_type = MainloopType::Qt;
#endif
static aud::array<AudPath, String> aud_paths;
-EXPORT void aud_set_headless_mode (bool headless)
- { headless_mode = headless; }
-EXPORT bool aud_get_headless_mode ()
- { return headless_mode; }
+EXPORT void aud_set_headless_mode(bool headless) { headless_mode = headless; }
+EXPORT bool aud_get_headless_mode() { return headless_mode; }
-EXPORT void aud_set_instance (int instance)
- { instance_number = instance; }
-EXPORT int aud_get_instance ()
- { return instance_number; }
+EXPORT void aud_set_instance(int instance) { instance_number = instance; }
+EXPORT int aud_get_instance() { return instance_number; }
-EXPORT void aud_set_mainloop_type (MainloopType type)
- { mainloop_type = type; }
-EXPORT MainloopType aud_get_mainloop_type ()
- { return mainloop_type; }
+EXPORT void aud_set_mainloop_type(MainloopType type) { mainloop_type = type; }
+EXPORT MainloopType aud_get_mainloop_type() { return mainloop_type; }
-static StringBuf get_path_to_self ()
+static StringBuf get_path_to_self()
{
#ifdef __linux__
- StringBuf buf (-1);
- int len = readlink ("/proc/self/exe", buf, buf.len ());
+ StringBuf buf(-1);
+ int len = readlink("/proc/self/exe", buf, buf.len());
if (len < 0)
{
- AUDERR ("Failed to read /proc/self/exe: %s\n", strerror (errno));
- return StringBuf ();
+ AUDERR("Failed to read /proc/self/exe: %s\n", strerror(errno));
+ return StringBuf();
}
- if (len == buf.len ())
- throw std::bad_alloc ();
+ if (len == buf.len())
+ throw std::bad_alloc();
- buf.resize (len);
+ buf.resize(len);
return buf;
#elif defined _WIN32
- StringBuf buf (-1);
- wchar_t * bufw = (wchar_t *) (char *) buf;
- int sizew = buf.len () / sizeof (wchar_t);
- int lenw = GetModuleFileNameW (nullptr, bufw, sizew);
+ StringBuf buf(-1);
+ wchar_t * bufw = (wchar_t *)(char *)buf;
+ int sizew = buf.len() / sizeof(wchar_t);
+ int lenw = GetModuleFileNameW(nullptr, bufw, sizew);
- if (! lenw)
+ if (!lenw)
{
- AUDERR ("GetModuleFileName failed.\n");
- return StringBuf ();
+ AUDERR("GetModuleFileName failed.\n");
+ return StringBuf();
}
if (lenw == sizew)
- throw std::bad_alloc ();
+ throw std::bad_alloc();
- buf.resize (lenw * sizeof (wchar_t));
- buf = str_convert (buf, buf.len (), UTF16_NATIVE, "UTF-8");
- return buf.settle ();
+ buf.resize(lenw * sizeof(wchar_t));
+ buf = str_convert(buf, buf.len(), UTF16_NATIVE, "UTF-8");
+ return buf.settle();
#elif defined __APPLE__
- StringBuf buf (-1);
- uint32_t size = buf.len ();
+ StringBuf buf(-1);
+ uint32_t size = buf.len();
- if (_NSGetExecutablePath (buf, & size) < 0)
- throw std::bad_alloc ();
+ if (_NSGetExecutablePath(buf, &size) < 0)
+ throw std::bad_alloc();
- buf.resize (strlen (buf));
+ buf.resize(strlen(buf));
return buf;
#else
- return StringBuf ();
+ return StringBuf();
#endif
}
-static String relocate_path (const char * path, const char * from, const char * to)
+static String relocate_path(const char * path, const char * from,
+ const char * to)
{
- int oldlen = strlen (from);
- int newlen = strlen (to);
+ int oldlen = strlen(from);
+ int newlen = strlen(to);
if (oldlen && from[oldlen - 1] == G_DIR_SEPARATOR)
- oldlen --;
+ oldlen--;
if (newlen && to[newlen - 1] == G_DIR_SEPARATOR)
- newlen --;
+ newlen--;
#ifdef _WIN32
- if (strcmp_nocase (path, from, oldlen) || (path[oldlen] && path[oldlen] != G_DIR_SEPARATOR))
+ if (strcmp_nocase(path, from, oldlen) ||
+ (path[oldlen] && path[oldlen] != G_DIR_SEPARATOR))
#else
- if (strncmp (path, from, oldlen) || (path[oldlen] && path[oldlen] != G_DIR_SEPARATOR))
+ if (strncmp(path, from, oldlen) ||
+ (path[oldlen] && path[oldlen] != G_DIR_SEPARATOR))
#endif
- return String (path);
+ return String(path);
- return String (str_printf ("%.*s%s", newlen, to, path + oldlen));
+ return String(str_printf("%.*s%s", newlen, to, path + oldlen));
}
-static void set_default_paths ()
+static void set_default_paths()
{
- aud_paths[AudPath::BinDir] = String (INSTALL_BINDIR);
- aud_paths[AudPath::DataDir] = String (INSTALL_DATADIR);
- aud_paths[AudPath::PluginDir] = String (INSTALL_PLUGINDIR);
- aud_paths[AudPath::LocaleDir] = String (INSTALL_LOCALEDIR);
- aud_paths[AudPath::DesktopFile] = String (INSTALL_DESKTOPFILE);
- aud_paths[AudPath::IconFile] = String (INSTALL_ICONFILE);
+ aud_paths[AudPath::BinDir] = String(INSTALL_BINDIR);
+ aud_paths[AudPath::DataDir] = String(INSTALL_DATADIR);
+ aud_paths[AudPath::PluginDir] = String(INSTALL_PLUGINDIR);
+ aud_paths[AudPath::LocaleDir] = String(INSTALL_LOCALEDIR);
+ aud_paths[AudPath::DesktopFile] = String(INSTALL_DESKTOPFILE);
+ aud_paths[AudPath::IconFile] = String(INSTALL_ICONFILE);
}
-static void set_install_paths ()
+static void set_install_paths()
{
- StringBuf bindir = filename_normalize (str_copy (INSTALL_BINDIR));
- StringBuf datadir = filename_normalize (str_copy (INSTALL_DATADIR));
- StringBuf plugindir = filename_normalize (str_copy (INSTALL_PLUGINDIR));
- StringBuf localedir = filename_normalize (str_copy (INSTALL_LOCALEDIR));
- StringBuf desktopfile = filename_normalize (str_copy (INSTALL_DESKTOPFILE));
- StringBuf iconfile = filename_normalize (str_copy (INSTALL_ICONFILE));
+ StringBuf bindir = filename_normalize(str_copy(INSTALL_BINDIR));
+ StringBuf datadir = filename_normalize(str_copy(INSTALL_DATADIR));
+ StringBuf plugindir = filename_normalize(str_copy(INSTALL_PLUGINDIR));
+ StringBuf localedir = filename_normalize(str_copy(INSTALL_LOCALEDIR));
+ StringBuf desktopfile = filename_normalize(str_copy(INSTALL_DESKTOPFILE));
+ StringBuf iconfile = filename_normalize(str_copy(INSTALL_ICONFILE));
- StringBuf from = str_copy (bindir);
+ StringBuf from = str_copy(bindir);
/* get path to current executable */
- StringBuf to = get_path_to_self ();
+ StringBuf to = get_path_to_self();
- if (! to)
+ if (!to)
{
- set_default_paths ();
+ set_default_paths();
return;
}
- to = filename_normalize (std::move (to));
+ to = filename_normalize(std::move(to));
- const char * base = last_path_element (to);
+ const char * base = last_path_element(to);
- if (! base)
+ if (!base)
{
- set_default_paths ();
+ set_default_paths();
return;
}
- cut_path_element (to, base - to);
+ cut_path_element(to, base - to);
/* trim trailing path elements common to old and new paths */
/* at the end, the old and new installation prefixes are left */
- const char * a, * b;
- while ((a = last_path_element (from)) &&
- (b = last_path_element (to)) &&
+ const char *a, *b;
+ while ((a = last_path_element(from)) && (b = last_path_element(to)) &&
#ifdef _WIN32
- ! strcmp_nocase (a, b))
+ !strcmp_nocase(a, b))
#else
- ! strcmp (a, b))
+ !strcmp(a, b))
#endif
{
- cut_path_element (from, a - from);
- cut_path_element (to, b - to);
+ cut_path_element(from, a - from);
+ cut_path_element(to, b - to);
}
/* replace old prefix with new one in each path */
- aud_paths[AudPath::BinDir] = relocate_path (bindir, from, to);
- aud_paths[AudPath::DataDir] = relocate_path (datadir, from, to);
- aud_paths[AudPath::PluginDir] = relocate_path (plugindir, from, to);
- aud_paths[AudPath::LocaleDir] = relocate_path (localedir, from, to);
- aud_paths[AudPath::DesktopFile] = relocate_path (desktopfile, from, to);
- aud_paths[AudPath::IconFile] = relocate_path (iconfile, from, to);
+ aud_paths[AudPath::BinDir] = relocate_path(bindir, from, to);
+ aud_paths[AudPath::DataDir] = relocate_path(datadir, from, to);
+ aud_paths[AudPath::PluginDir] = relocate_path(plugindir, from, to);
+ aud_paths[AudPath::LocaleDir] = relocate_path(localedir, from, to);
+ aud_paths[AudPath::DesktopFile] = relocate_path(desktopfile, from, to);
+ aud_paths[AudPath::IconFile] = relocate_path(iconfile, from, to);
}
-static void set_config_paths ()
+static void set_config_paths()
{
- const char * xdg_config_home = g_get_user_config_dir ();
- StringBuf name = (instance_number == 1) ? str_copy ("audacious") :
- str_printf ("audacious-%d", instance_number);
+ const char * xdg_config_home = g_get_user_config_dir();
+ StringBuf name = (instance_number == 1)
+ ? str_copy("audacious")
+ : str_printf("audacious-%d", instance_number);
- aud_paths[AudPath::UserDir] = String (filename_build ({xdg_config_home, name}));
- aud_paths[AudPath::PlaylistDir] = String (filename_build
- ({aud_paths[AudPath::UserDir], "playlists"}));
+ aud_paths[AudPath::UserDir] =
+ String(filename_build({xdg_config_home, name}));
+ aud_paths[AudPath::PlaylistDir] =
+ String(filename_build({aud_paths[AudPath::UserDir], "playlists"}));
- if (g_mkdir_with_parents (aud_paths[AudPath::PlaylistDir], DIRMODE) < 0)
- AUDERR ("Failed to create %s: %s\n",
- (const char *) aud_paths[AudPath::PlaylistDir], strerror (errno));
+ if (g_mkdir_with_parents(aud_paths[AudPath::PlaylistDir], DIRMODE) < 0)
+ AUDERR("Failed to create %s: %s\n",
+ (const char *)aud_paths[AudPath::PlaylistDir], strerror(errno));
#ifdef _WIN32
/* set some UNIX-style environment variables */
- g_setenv ("HOME", g_get_home_dir (), true);
- g_setenv ("XDG_CONFIG_HOME", xdg_config_home, true);
- g_setenv ("XDG_DATA_HOME", g_get_user_data_dir (), true);
- g_setenv ("XDG_CACHE_HOME", g_get_user_cache_dir (), true);
+ g_setenv("HOME", g_get_home_dir(), true);
+ g_setenv("XDG_CONFIG_HOME", xdg_config_home, true);
+ g_setenv("XDG_DATA_HOME", g_get_user_data_dir(), true);
+ g_setenv("XDG_CACHE_HOME", g_get_user_cache_dir(), true);
#endif
}
-EXPORT const char * aud_get_path (AudPath id)
+EXPORT const char * aud_get_path(AudPath id)
{
- if (! aud_paths[id])
+ if (!aud_paths[id])
{
if (id <= AudPath::IconFile)
- set_install_paths ();
+ set_install_paths();
else
- set_config_paths ();
+ set_config_paths();
}
return aud_paths[id];
}
-EXPORT void aud_init_i18n ()
+EXPORT void aud_init_i18n()
{
- const char * localedir = aud_get_path (AudPath::LocaleDir);
-
- setlocale (LC_ALL, "");
- bindtextdomain (PACKAGE, localedir);
- bind_textdomain_codeset (PACKAGE, "UTF-8");
- bindtextdomain (PACKAGE "-plugins", localedir);
- bind_textdomain_codeset (PACKAGE "-plugins", "UTF-8");
- textdomain (PACKAGE);
+ const char * localedir = aud_get_path(AudPath::LocaleDir);
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, localedir);
+ bind_textdomain_codeset(PACKAGE, "UTF-8");
+ bindtextdomain(PACKAGE "-plugins", localedir);
+ bind_textdomain_codeset(PACKAGE "-plugins", "UTF-8");
+ textdomain(PACKAGE);
}
-EXPORT void aud_init ()
+EXPORT void aud_init()
{
- g_thread_pool_set_max_idle_time (100);
+ g_thread_pool_set_max_idle_time(100);
- config_load ();
+ config_load();
- chardet_init ();
- eq_init ();
- output_init ();
- playlist_init ();
+ chardet_init();
+ eq_init();
+ output_init();
+ playlist_init();
- start_plugins_one ();
+ start_plugins_one();
- record_init ();
- scanner_init ();
- load_playlists ();
+ record_init();
+ scanner_init();
+ load_playlists();
}
-static void do_autosave (void *)
+static void do_autosave(void *)
{
- hook_call ("config save", nullptr);
- save_playlists (false);
- plugin_registry_save ();
- config_save ();
+ hook_call("config save", nullptr);
+ save_playlists(false);
+ plugin_registry_save();
+ config_save();
}
-EXPORT void aud_run ()
+EXPORT void aud_run()
{
/* playlist_enable_scan() should be after aud_resume(); the intent is to
* avoid scanning until the currently playing entry is known, at which time
* it can be scanned more efficiently (album art read in the same pass). */
- playlist_enable_scan (true);
- playlist_clear_updates ();
- start_plugins_two ();
+ playlist_enable_scan(true);
+ playlist_clear_updates();
+ start_plugins_two();
static QueuedFunc autosave;
- autosave.start (AUTOSAVE_INTERVAL, do_autosave, nullptr);
+ autosave.start(AUTOSAVE_INTERVAL, do_autosave, nullptr);
/* calls "config save" before returning */
- interface_run ();
+ interface_run();
- autosave.stop ();
+ autosave.stop();
- stop_plugins_two ();
- playlist_enable_scan (false);
+ stop_plugins_two();
+ playlist_enable_scan(false);
}
-EXPORT void aud_cleanup ()
+EXPORT void aud_cleanup()
{
- save_playlists (true);
+ save_playlists(true);
- aud_drct_stop ();
- playback_stop (true);
+ aud_drct_stop();
+ playback_stop(true);
- adder_cleanup ();
- scanner_cleanup ();
- record_cleanup ();
+ adder_cleanup();
+ scanner_cleanup();
+ record_cleanup();
- stop_plugins_one ();
+ stop_plugins_one();
- art_cleanup ();
- chardet_cleanup ();
- eq_cleanup ();
- output_cleanup ();
- playlist_end ();
+ art_cleanup();
+ chardet_cleanup();
+ eq_cleanup();
+ output_cleanup();
+ playlist_end();
- event_queue_cancel_all ();
- hook_cleanup ();
- timer_cleanup ();
+ event_queue_cancel_all();
+ hook_cleanup();
+ timer_cleanup();
- config_save ();
- config_cleanup ();
+ config_save();
+ config_cleanup();
}
-EXPORT void aud_leak_check ()
+EXPORT void aud_leak_check()
{
for (String & path : aud_paths)
- path = String ();
+ path = String();
- string_leak_check ();
+ string_leak_check();
if (misc_bytes_allocated)
- AUDWARN ("Bytes allocated at exit: %ld\n", (long) misc_bytes_allocated);
+ AUDWARN("Bytes allocated at exit: %ld\n", (long)misc_bytes_allocated);
}
diff --git a/src/libaudcore/runtime.h b/src/libaudcore/runtime.h
index 1a1a352..244eacd 100644
--- a/src/libaudcore/runtime.h
+++ b/src/libaudcore/runtime.h
@@ -22,7 +22,8 @@
#include <libaudcore/objects.h>
-enum class AudPath {
+enum class AudPath
+{
BinDir,
DataDir,
PluginDir,
@@ -34,25 +35,29 @@ enum class AudPath {
count
};
-enum class MainloopType {
+enum class MainloopType
+{
GLib,
Qt
};
-enum class OutputReset {
+enum class OutputReset
+{
EffectsOnly,
ReopenStream,
ResetPlugin
};
-enum class OutputStream {
+enum class OutputStream
+{
AsDecoded,
AfterReplayGain,
AfterEffects,
AfterEqualizer
};
-enum class ReplayGainMode {
+enum class ReplayGainMode
+{
Track,
Album,
Automatic
@@ -60,76 +65,138 @@ enum class ReplayGainMode {
namespace audlog
{
- enum Level {
- Debug,
- Info,
- Warning,
- Error
- };
+enum Level
+{
+ Debug,
+ Info,
+ Warning,
+ Error
+};
- typedef void (* Handler) (Level level, const char * file, int line,
- const char * func, const char * message);
+typedef void (*Handler)(Level level, const char * file, int line,
+ const char * func, const char * message);
- void set_stderr_level (Level level);
- void subscribe (Handler handler, Level level);
- void unsubscribe (Handler handler);
+void set_stderr_level(Level level);
+void subscribe(Handler handler, Level level);
+void unsubscribe(Handler handler);
#ifdef _WIN32
- void log (Level level, const char * file, int line, const char * func,
- const char * format, ...) __attribute__ ((__format__ (gnu_printf, 5, 6)));
+void log(Level level, const char * file, int line, const char * func,
+ const char * format, ...)
+ __attribute__((__format__(gnu_printf, 5, 6)));
#else
- void log (Level level, const char * file, int line, const char * func,
- const char * format, ...) __attribute__ ((__format__ (__printf__, 5, 6)));
+void log(Level level, const char * file, int line, const char * func,
+ const char * format, ...)
+ __attribute__((__format__(__printf__, 5, 6)));
#endif
- const char * get_level_name (Level level);
-}
-
-#define AUDERR(...) do { audlog::log (audlog::Error, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); } while (0)
-#define AUDWARN(...) do { audlog::log (audlog::Warning, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); } while (0)
-#define AUDINFO(...) do { audlog::log (audlog::Info, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); } while (0)
-#define AUDDBG(...) do { audlog::log (audlog::Debug, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); } while (0)
-
-const char * aud_get_path (AudPath id);
-
-void aud_set_headless_mode (bool headless);
-bool aud_get_headless_mode ();
+const char * get_level_name(Level level);
+} // namespace audlog
+
+#define AUDERR(...) \
+ do \
+ { \
+ audlog::log(audlog::Error, __FILE__, __LINE__, __FUNCTION__, \
+ __VA_ARGS__); \
+ } while (0)
+#define AUDWARN(...) \
+ do \
+ { \
+ audlog::log(audlog::Warning, __FILE__, __LINE__, __FUNCTION__, \
+ __VA_ARGS__); \
+ } while (0)
+#define AUDINFO(...) \
+ do \
+ { \
+ audlog::log(audlog::Info, __FILE__, __LINE__, __FUNCTION__, \
+ __VA_ARGS__); \
+ } while (0)
+#define AUDDBG(...) \
+ do \
+ { \
+ audlog::log(audlog::Debug, __FILE__, __LINE__, __FUNCTION__, \
+ __VA_ARGS__); \
+ } while (0)
+
+const char * aud_get_path(AudPath id);
+
+void aud_set_headless_mode(bool headless);
+bool aud_get_headless_mode();
// Note that the UserDir and PlaylistDir paths vary depending on the instance
// number. Therefore, calling aud_set_instance() after these paths have been
// referenced, or after aud_init(), is an error.
-void aud_set_instance (int instance);
-int aud_get_instance ();
+void aud_set_instance(int instance);
+int aud_get_instance();
+
+void aud_set_mainloop_type(MainloopType type);
+MainloopType aud_get_mainloop_type();
-void aud_set_mainloop_type (MainloopType type);
-MainloopType aud_get_mainloop_type ();
+void aud_init_i18n();
-void aud_init_i18n ();
+void aud_config_set_defaults(const char * section,
+ const char * const * entries);
-void aud_config_set_defaults (const char * section, const char * const * entries);
+void aud_set_str(const char * section, const char * name, const char * value);
+String aud_get_str(const char * section, const char * name);
+void aud_set_bool(const char * section, const char * name, bool value);
+bool aud_get_bool(const char * section, const char * name);
+void aud_toggle_bool(const char * section, const char * name);
+void aud_set_int(const char * section, const char * name, int value);
+int aud_get_int(const char * section, const char * name);
+void aud_set_double(const char * section, const char * name, double value);
+double aud_get_double(const char * section, const char * name);
-void aud_set_str (const char * section, const char * name, const char * value);
-String aud_get_str (const char * section, const char * name);
-void aud_set_bool (const char * section, const char * name, bool value);
-bool aud_get_bool (const char * section, const char * name);
-void aud_toggle_bool (const char * section, const char * name);
-void aud_set_int (const char * section, const char * name, int value);
-int aud_get_int (const char * section, const char * name);
-void aud_set_double (const char * section, const char * name, double value);
-double aud_get_double (const char * section, const char * name);
+/* overloads for main ("audacious") config section */
+static inline void aud_set_str(const char * name, const char * value)
+{
+ aud_set_str(nullptr, name, value);
+}
+static inline String aud_get_str(const char * name)
+{
+ return aud_get_str(nullptr, name);
+}
+static inline void aud_set_bool(const char * name, bool value)
+{
+ aud_set_bool(nullptr, name, value);
+}
+static inline bool aud_get_bool(const char * name)
+{
+ return aud_get_bool(nullptr, name);
+}
+static inline void aud_toggle_bool(const char * name)
+{
+ aud_toggle_bool(nullptr, name);
+}
+static inline void aud_set_int(const char * name, int value)
+{
+ aud_set_int(nullptr, name, value);
+}
+static inline int aud_get_int(const char * name)
+{
+ return aud_get_int(nullptr, name);
+}
+static inline void aud_set_double(const char * name, double value)
+{
+ aud_set_double(nullptr, name, value);
+}
+static inline double aud_get_double(const char * name)
+{
+ return aud_get_double(nullptr, name);
+}
-void aud_init ();
-void aud_resume ();
-void aud_run ();
-void aud_quit ();
-void aud_cleanup ();
+void aud_init();
+void aud_resume();
+void aud_run();
+void aud_quit();
+void aud_cleanup();
-void aud_leak_check ();
+void aud_leak_check();
-String aud_history_get (int entry);
-void aud_history_add (const char * path);
-void aud_history_clear ();
+String aud_history_get(int entry);
+void aud_history_add(const char * path);
+void aud_history_clear();
-void aud_output_reset (OutputReset type);
+void aud_output_reset(OutputReset type);
#endif
diff --git a/src/libaudcore/scanner.cc b/src/libaudcore/scanner.cc
index 75cb04a..2ad2ebc 100644
--- a/src/libaudcore/scanner.cc
+++ b/src/libaudcore/scanner.cc
@@ -19,7 +19,7 @@
#include "scanner.h"
-#include <glib.h> /* for GThreadPool */
+#include <glib.h> /* for GThreadPool */
#include "audstrings.h"
#include "cue-cache.h"
@@ -32,99 +32,97 @@
static GThreadPool * pool;
-ScanRequest::ScanRequest (const String & filename, int flags, Callback callback,
- PluginHandle * decoder, Tuple && tuple) :
- filename (filename),
- flags (flags),
- callback (callback),
- decoder (decoder),
- tuple (std::move (tuple)),
- ip (nullptr)
+ScanRequest::ScanRequest(const String & filename, int flags, Callback callback,
+ PluginHandle * decoder, Tuple && tuple)
+ : filename(filename), flags(flags), callback(callback), decoder(decoder),
+ tuple(std::move(tuple)), ip(nullptr)
{
/* If this is a cuesheet entry (and it has not already been loaded), capture
* a reference to the cache immediately. During a playlist scan, requests
* have overlapping lifecycles--each new ScanRequest is created by the
* callback of the previous request--so the cached cuesheet persists as long
* as consecutive playlist entries reference it. */
- if (! this->tuple.valid () && is_cuesheet_entry (filename))
- cue_cache.capture (new CueCacheRef (strip_subtune (filename)));
+ if (!this->tuple.valid() && is_cuesheet_entry(filename))
+ cue_cache.capture(new CueCacheRef(strip_subtune(filename)));
}
-void ScanRequest::read_cuesheet_entry ()
+void ScanRequest::read_cuesheet_entry()
{
- for (auto & item : cue_cache->load ())
+ for (auto & item : cue_cache->load())
{
if (item.filename == filename)
{
decoder = item.decoder;
- tuple = item.tuple.ref ();
+ tuple = item.tuple.ref();
break;
}
}
}
-void ScanRequest::run ()
+void ScanRequest::run()
{
/* load cuesheet entry (possibly cached) */
if (cue_cache)
- read_cuesheet_entry ();
+ read_cuesheet_entry();
/* for a cuesheet entry, determine the source filename */
- String audio_file = tuple.get_str (Tuple::AudioFile);
- if (! audio_file)
+ String audio_file = tuple.get_str(Tuple::AudioFile);
+ if (!audio_file)
audio_file = filename;
- bool need_tuple = (flags & SCAN_TUPLE) && ! tuple.valid ();
+ bool need_tuple = (flags & SCAN_TUPLE) && !tuple.valid();
bool need_image = (flags & SCAN_IMAGE);
- if (! decoder)
- decoder = aud_file_find_decoder (audio_file, false, file, & error);
- if (! decoder)
+ if (!decoder)
+ decoder = aud_file_find_decoder(audio_file, false, file, &error);
+ if (!decoder)
goto err;
if (need_tuple || need_image)
{
- if (! (ip = load_input_plugin (decoder, & error)))
+ if (!(ip = load_input_plugin(decoder, &error)))
goto err;
- Index<char> * pimage = need_image ? & image_data : nullptr;
- if (! aud_file_read_tag (audio_file, decoder, file, tuple, pimage, & error))
+ Tuple dummy_tuple;
+ /* don't overwrite tuple if already valid (e.g. from a cuesheet) */
+ Tuple & rtuple = need_tuple ? tuple : dummy_tuple;
+ Index<char> * pimage = need_image ? &image_data : nullptr;
+ if (!aud_file_read_tag(audio_file, decoder, file, rtuple, pimage,
+ &error))
goto err;
- if ((flags & SCAN_IMAGE) && ! image_data.len ())
- image_file = art_search (audio_file);
+ if (need_image && !image_data.len())
+ image_file = art_search(audio_file);
}
/* rewind/reopen the input file */
if ((flags & SCAN_FILE))
- open_input_file (audio_file, "r", ip, file, & error);
+ open_input_file(audio_file, "r", ip, file, &error);
else
{
err:
/* close file if not needed or if an error occurred */
- file = VFSFile ();
+ file = VFSFile();
}
- callback (this);
+ callback(this);
}
-static void scan_worker (void * data, void *)
+static void scan_worker(void * data, void *)
{
- ((ScanRequest *) data)->run ();
- delete (ScanRequest *) data;
+ ((ScanRequest *)data)->run();
+ delete (ScanRequest *)data;
}
-void scanner_init ()
+void scanner_init()
{
- pool = g_thread_pool_new (scan_worker, nullptr, SCAN_THREADS, false, nullptr);
+ pool =
+ g_thread_pool_new(scan_worker, nullptr, SCAN_THREADS, false, nullptr);
}
-void scanner_request (ScanRequest * request)
+void scanner_request(ScanRequest * request)
{
- g_thread_pool_push (pool, request, nullptr);
+ g_thread_pool_push(pool, request, nullptr);
}
-void scanner_cleanup ()
-{
- g_thread_pool_free (pool, false, true);
-}
+void scanner_cleanup() { g_thread_pool_free(pool, false, true); }
diff --git a/src/libaudcore/scanner.h b/src/libaudcore/scanner.h
index 667afb3..0b6ad30 100644
--- a/src/libaudcore/scanner.h
+++ b/src/libaudcore/scanner.h
@@ -31,13 +31,13 @@ class PluginHandle;
#define SCAN_TUPLE (1 << 0)
#define SCAN_IMAGE (1 << 1)
-#define SCAN_FILE (1 << 2)
+#define SCAN_FILE (1 << 2)
#define SCAN_THREADS 2
struct ScanRequest
{
- typedef void (* Callback) (ScanRequest * request);
+ typedef void (*Callback)(ScanRequest * request);
const String filename;
const int flags;
@@ -53,19 +53,19 @@ struct ScanRequest
String image_file;
String error;
- ScanRequest (const String & filename, int flags, Callback callback,
- PluginHandle * decoder = nullptr, Tuple && tuple = Tuple ());
+ ScanRequest(const String & filename, int flags, Callback callback,
+ PluginHandle * decoder = nullptr, Tuple && tuple = Tuple());
- void run ();
+ void run();
private:
SmartPtr<CueCacheRef> cue_cache;
- void read_cuesheet_entry ();
+ void read_cuesheet_entry();
};
-void scanner_init ();
-void scanner_request (ScanRequest * request);
-void scanner_cleanup ();
+void scanner_init();
+void scanner_request(ScanRequest * request);
+void scanner_cleanup();
#endif
diff --git a/src/libaudcore/stringbuf.cc b/src/libaudcore/stringbuf.cc
index dd923ca..0b50ea2 100644
--- a/src/libaudcore/stringbuf.cc
+++ b/src/libaudcore/stringbuf.cc
@@ -18,13 +18,14 @@
*/
#include <pthread.h>
-#include <stdlib.h>
#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
#include <new>
#include "objects.h"
+#include "threads.h"
#ifdef _WIN32
#include <windows.h>
@@ -37,109 +38,114 @@
struct StringHeader
{
- StringHeader * next, * prev;
+ StringHeader *next, *prev;
int len;
};
struct StringStack
{
- static constexpr int Size = 1048576; // 1 MB
+ static constexpr int Size = 1048576; // 1 MB
StringHeader * top;
char buf[Size - sizeof top];
};
-static constexpr intptr_t align (intptr_t ptr, intptr_t size)
+static constexpr intptr_t align(intptr_t ptr, intptr_t size)
{
return (ptr + (size - 1)) / size * size;
}
-static StringHeader * align_after (StringStack * stack, StringHeader * prev_header)
+static StringHeader * align_after(StringStack * stack,
+ StringHeader * prev_header)
{
char * base;
if (prev_header)
- base = (char *) prev_header + sizeof (StringHeader) + prev_header->len + 1;
+ base =
+ (char *)prev_header + sizeof(StringHeader) + prev_header->len + 1;
else
base = stack->buf;
- return (StringHeader *) align ((intptr_t) base, alignof (StringHeader));
+ return (StringHeader *)align((intptr_t)base, alignof(StringHeader));
}
static pthread_key_t key;
-static pthread_once_t once = PTHREAD_ONCE_INIT;
+static std::once_flag once;
#ifdef _WIN32
static HANDLE mapping;
#endif
-static void free_stack (void * stack)
+static void free_stack(void * stack)
{
if (stack)
#ifdef _WIN32
- UnmapViewOfFile (stack);
+ UnmapViewOfFile(stack);
#else
- munmap (stack, sizeof (StringStack));
+ munmap(stack, sizeof(StringStack));
#endif
}
-static void make_key ()
+static void make_key()
{
- pthread_key_create (& key, free_stack);
+ pthread_key_create(&key, free_stack);
#ifdef _WIN32
- mapping = CreateFileMappingW (INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE,
- 0, sizeof (StringStack), nullptr);
+ mapping = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE,
+ 0, sizeof(StringStack), nullptr);
- if (! mapping)
- throw std::bad_alloc ();
+ if (!mapping)
+ throw std::bad_alloc();
#endif
}
-static StringStack * get_stack ()
+static StringStack * get_stack()
{
- pthread_once (& once, make_key);
+ std::call_once(once, make_key);
- StringStack * stack = (StringStack *) pthread_getspecific (key);
+ StringStack * stack = (StringStack *)pthread_getspecific(key);
- if (! stack)
+ if (!stack)
{
#ifdef _WIN32
- stack = (StringStack *) MapViewOfFile (mapping, FILE_MAP_COPY, 0, 0, sizeof (StringStack));
+ stack = (StringStack *)MapViewOfFile(mapping, FILE_MAP_COPY, 0, 0,
+ sizeof(StringStack));
- if (! stack)
- throw std::bad_alloc ();
+ if (!stack)
+ throw std::bad_alloc();
#else
- stack = (StringStack *) mmap (nullptr, sizeof (StringStack),
- PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ stack = (StringStack *)mmap(nullptr, sizeof(StringStack),
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (stack == MAP_FAILED)
- throw std::bad_alloc ();
+ throw std::bad_alloc();
#endif
stack->top = nullptr;
- pthread_setspecific (key, stack);
+ pthread_setspecific(key, stack);
}
return stack;
}
-EXPORT void StringBuf::resize (int len)
+EXPORT void StringBuf::resize(int len)
{
- if (! stack)
- stack = get_stack ();
+ if (!stack)
+ stack = get_stack();
StringHeader * header = nullptr;
bool need_alloc = true;
if (m_data)
{
- header = (StringHeader *) (m_data - sizeof (StringHeader));
+ header = (StringHeader *)(m_data - sizeof(StringHeader));
/* check if there is enough space in the current location */
- char * limit = header->next ? (char *) header->next : (char *) stack + sizeof (StringStack);
+ char * limit = header->next ? (char *)header->next
+ : (char *)stack + sizeof(StringStack);
int max_len = limit - 1 - m_data;
- if ((len < 0 && ! header->next) || (len >= 0 && len < max_len))
+ if ((len < 0 && !header->next) || (len >= 0 && len < max_len))
{
m_len = header->len = (len < 0) ? max_len : len;
need_alloc = false;
@@ -149,13 +155,13 @@ EXPORT void StringBuf::resize (int len)
if (need_alloc)
{
/* allocate a new string at the top of the stack */
- StringHeader * new_header = align_after (stack, stack->top);
- char * new_data = (char *) new_header + sizeof (StringHeader);
- char * limit = (char *) stack + sizeof (StringStack);
+ StringHeader * new_header = align_after(stack, stack->top);
+ char * new_data = (char *)new_header + sizeof(StringHeader);
+ char * limit = (char *)stack + sizeof(StringStack);
int max_len = limit - 1 - new_data;
- if (max_len < aud::max (len, 0))
- throw std::bad_alloc ();
+ if (max_len < aud::max(len, 0))
+ throw std::bad_alloc();
int new_len = (len < 0) ? max_len : len;
@@ -171,8 +177,8 @@ EXPORT void StringBuf::resize (int len)
/* move the old data, if any */
if (m_data)
{
- int bytes_to_copy = aud::min (m_len, new_len);
- memcpy (new_data, m_data, bytes_to_copy);
+ int bytes_to_copy = aud::min(m_len, new_len);
+ memcpy(new_data, m_data, bytes_to_copy);
if (header->prev)
header->prev->next = header->next;
@@ -192,11 +198,11 @@ EXPORT void StringBuf::resize (int len)
m_data[len] = 0;
}
-EXPORT StringBuf::~StringBuf ()
+EXPORT StringBuf::~StringBuf()
{
if (m_data)
{
- auto header = (StringHeader *) (m_data - sizeof (StringHeader));
+ auto header = (StringHeader *)(m_data - sizeof(StringHeader));
if (header->prev)
header->prev->next = header->next;
@@ -208,18 +214,18 @@ EXPORT StringBuf::~StringBuf ()
}
}
-EXPORT void StringBuf::steal (StringBuf && other)
+EXPORT void StringBuf::steal(StringBuf && other)
{
- (* this = std::move (other)).settle ();
+ (*this = std::move(other)).settle();
}
-EXPORT StringBuf && StringBuf::settle ()
+EXPORT StringBuf && StringBuf::settle()
{
if (m_data)
{
/* collapse any space preceding this string */
- auto header = (StringHeader *) (m_data - sizeof (StringHeader));
- StringHeader * new_header = align_after (stack, header->prev);
+ auto header = (StringHeader *)(m_data - sizeof(StringHeader));
+ StringHeader * new_header = align_after(stack, header->prev);
if (new_header != header)
{
@@ -231,45 +237,45 @@ EXPORT StringBuf && StringBuf::settle ()
else
header->next->prev = new_header;
- memmove (new_header, header, sizeof (StringHeader) + m_len + 1);
- m_data = (char *) new_header + sizeof (StringHeader);
+ memmove(new_header, header, sizeof(StringHeader) + m_len + 1);
+ m_data = (char *)new_header + sizeof(StringHeader);
}
}
- return std::move (* this);
+ return std::move(*this);
}
-EXPORT void StringBuf::combine (StringBuf && other)
+EXPORT void StringBuf::combine(StringBuf && other)
{
- if (! other.m_data)
+ if (!other.m_data)
return;
- insert (m_len, other.m_data, other.m_len);
- other = StringBuf ();
- settle ();
+ insert(m_len, other.m_data, other.m_len);
+ other = StringBuf();
+ settle();
}
-EXPORT char * StringBuf::insert (int pos, const char * s, int len)
+EXPORT char * StringBuf::insert(int pos, const char * s, int len)
{
int len0 = m_len;
if (pos < 0)
pos = len0;
if (len < 0)
- len = strlen (s);
+ len = strlen(s);
- resize (len0 + len);
- memmove (m_data + pos + len, m_data + pos, len0 - pos);
+ resize(len0 + len);
+ memmove(m_data + pos + len, m_data + pos, len0 - pos);
if (s)
- memcpy (m_data + pos, s, len);
+ memcpy(m_data + pos, s, len);
return m_data + pos;
}
-EXPORT void StringBuf::remove (int pos, int len)
+EXPORT void StringBuf::remove(int pos, int len)
{
int after = m_len - pos - len;
- memmove (m_data + pos, m_data + pos + len, after);
- resize (pos + after);
+ memmove(m_data + pos, m_data + pos + len, after);
+ resize(pos + after);
}
diff --git a/src/libaudcore/strpool.cc b/src/libaudcore/strpool.cc
index c9308d7..96edb99 100644
--- a/src/libaudcore/strpool.cc
+++ b/src/libaudcore/strpool.cc
@@ -30,48 +30,53 @@
#include <glib.h>
-EXPORT char * String::raw_get (const char * str)
- { return g_strdup (str); }
-EXPORT char * String::raw_ref (const char * str)
- { return g_strdup (str); }
-EXPORT void String::raw_unref (char * str)
- { g_free (str); }
+EXPORT char * String::raw_get(const char * str) { return g_strdup(str); }
+EXPORT char * String::raw_ref(const char * str) { return g_strdup(str); }
+EXPORT void String::raw_unref(char * str) { g_free(str); }
-void string_leak_check () {}
+void string_leak_check() {}
-EXPORT unsigned String::raw_hash (const char * str)
- { return str_calc_hash (str); }
-EXPORT bool String::raw_equal (const char * str1, const char * str2)
- { return ! strcmp_safe (str1, str2); }
+EXPORT unsigned String::raw_hash(const char * str)
+{
+ return str_calc_hash(str);
+}
+EXPORT bool String::raw_equal(const char * str1, const char * str2)
+{
+ return !strcmp_safe(str1, str2);
+}
#else // ! VALGRIND_FRIENDLY
struct StrNode : public MultiHash::Node
{
/* the characters of the string immediately follow the StrNode struct */
- const char * str () const
- { return reinterpret_cast<const char *> (this + 1); }
- char * str ()
- { return reinterpret_cast<char *> (this + 1); }
+ const char * str() const
+ {
+ return reinterpret_cast<const char *>(this + 1);
+ }
+ char * str() { return reinterpret_cast<char *>(this + 1); }
- static const StrNode * of (const char * s)
- { return reinterpret_cast<const StrNode *> (s) - 1; }
- static StrNode * of (char * s)
- { return reinterpret_cast<StrNode *> (s) - 1; }
+ static const StrNode * of(const char * s)
+ {
+ return reinterpret_cast<const StrNode *>(s) - 1;
+ }
+ static StrNode * of(char * s) { return reinterpret_cast<StrNode *>(s) - 1; }
- static StrNode * create (const char * s)
+ static StrNode * create(const char * s)
{
- auto size = sizeof (StrNode) + strlen (s) + 1;
- auto node = static_cast<StrNode *> (malloc (size));
- if (! node)
- throw std::bad_alloc ();
+ auto size = sizeof(StrNode) + strlen(s) + 1;
+ auto node = static_cast<StrNode *>(malloc(size));
+ if (!node)
+ throw std::bad_alloc();
- strcpy (node->str (), s);
+ strcpy(node->str(), s);
return node;
}
- bool match (const char * data) const
- { return data == str () || ! strcmp (data, str ()); }
+ bool match(const char * data) const
+ {
+ return data == str() || !strcmp(data, str());
+ }
};
static MultiHash_T<StrNode, char> strpool_table;
@@ -80,32 +85,31 @@ struct Getter
{
StrNode * node;
- StrNode * add (const char * data)
+ StrNode * add(const char * data)
{
- node = StrNode::create (data);
+ node = StrNode::create(data);
node->refs = 1;
return node;
}
- bool found (StrNode * node_)
+ bool found(StrNode * node_)
{
node = node_;
- __sync_fetch_and_add (& node->refs, 1);
+ __sync_fetch_and_add(&node->refs, 1);
return false;
}
};
struct Remover
{
- StrNode * add (const char *)
- { return nullptr; }
+ StrNode * add(const char *) { return nullptr; }
- bool found (StrNode * node)
+ bool found(StrNode * node)
{
- if (! __sync_bool_compare_and_swap (& node->refs, 1, 0))
+ if (!__sync_bool_compare_and_swap(&node->refs, 1, 0))
return false;
- free (node);
+ free(node);
return true;
}
};
@@ -115,28 +119,28 @@ struct Remover
* In either case, returns the copy. Because this copy may be shared by other
* parts of the code, it should not be modified. If <str> is null, simply
* returns null with no side effects. */
-EXPORT char * String::raw_get (const char * str)
+EXPORT char * String::raw_get(const char * str)
{
- if (! str)
+ if (!str)
return nullptr;
Getter op;
- strpool_table.lookup (str, str_calc_hash (str), op);
- return op.node->str ();
+ strpool_table.lookup(str, str_calc_hash(str), op);
+ return op.node->str();
}
/* Increments the reference count of <str>, where <str> is the address of a
* string already in the pool. Faster than calling raw_get() a second time.
* Returns <str> for convenience. If <str> is null, simply returns null with no
* side effects. */
-EXPORT char * String::raw_ref (const char * str_)
+EXPORT char * String::raw_ref(const char * str_)
{
- auto str = const_cast<char *> (str_);
- if (! str)
+ auto str = const_cast<char *>(str_);
+ if (!str)
return nullptr;
- auto node = StrNode::of (str);
- __sync_fetch_and_add (& node->refs, 1);
+ auto node = StrNode::of(str);
+ __sync_fetch_and_add(&node->refs, 1);
return str;
}
@@ -144,51 +148,52 @@ EXPORT char * String::raw_ref (const char * str_)
* string in the pool. If the reference count drops to zero, releases the
* memory used by <str>. If <str> is null, simply returns null with no side
* effects. */
-EXPORT void String::raw_unref (char * str)
+EXPORT void String::raw_unref(char * str)
{
- if (! str)
+ if (!str)
return;
- auto node = StrNode::of (str);
+ auto node = StrNode::of(str);
while (1)
{
- unsigned refs = __sync_fetch_and_add (& node->refs, 0);
+ unsigned refs = __sync_fetch_and_add(&node->refs, 0);
if (refs > 1)
{
- if (__sync_bool_compare_and_swap (& node->refs, refs, refs - 1))
+ if (__sync_bool_compare_and_swap(&node->refs, refs, refs - 1))
break;
}
else
{
Remover op;
- int status = strpool_table.lookup (str, node->hash, op);
- if (! (status & MultiHash::Found))
- throw std::bad_alloc ();
+ int status = strpool_table.lookup(str, node->hash, op);
+ if (!(status & MultiHash::Found))
+ throw std::bad_alloc();
if (status & MultiHash::Removed)
break;
}
}
}
-void string_leak_check ()
+void string_leak_check()
{
- strpool_table.iterate ([] (const StrNode * node) {
- AUDWARN ("String leaked: %s\n", node->str ());
+ strpool_table.iterate([](const StrNode * node) {
+ AUDWARN("String leaked: %s\n", node->str());
return false;
});
}
/* Returns the cached hash value of a pooled string (or 0 for null). */
-EXPORT unsigned String::raw_hash (const char * str)
+EXPORT unsigned String::raw_hash(const char * str)
{
- return str ? StrNode::of (str)->hash : 0;
+ return str ? StrNode::of(str)->hash : 0;
}
/* Checks whether two pooled strings are equal. Since the pool never contains
* duplicate strings, this is a simple pointer comparison and thus much faster
- * than strcmp(). null is considered equal to null but not equal to any string. */
-EXPORT bool String::raw_equal (const char * str1, const char * str2)
+ * than strcmp(). null is considered equal to null but not equal to any string.
+ */
+EXPORT bool String::raw_equal(const char * str1, const char * str2)
{
return str1 == str2;
}
diff --git a/src/libaudcore/templates.h b/src/libaudcore/templates.h
index cc1d533..e5f03ec 100644
--- a/src/libaudcore/templates.h
+++ b/src/libaudcore/templates.h
@@ -1,6 +1,6 @@
/*
* templates.h
- * Copyright 2014 John Lindgren
+ * Copyright 2014-2019 John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,72 +29,100 @@
#undef min
#undef max
-namespace aud {
+namespace aud
+{
// Utility functions
// =================
// minimum of two numbers
template<class T>
-constexpr T min (T a, T b)
- { return a < b ? a : b; }
+constexpr T min(T a, T b)
+{
+ return a < b ? a : b;
+}
// maximum of two numbers
template<class T>
-constexpr T max (T a, T b)
- { return a > b ? a : b; }
+constexpr T max(T a, T b)
+{
+ return a > b ? a : b;
+}
// make sure a number is within the given range
template<class T>
-constexpr T clamp (T x, T low, T high)
- { return min (max (x, low), high); }
+constexpr T clamp(T x, T low, T high)
+{
+ return min(max(x, low), high);
+}
// absolute value
template<class T>
-constexpr T abs (T x)
- { return x < 0 ? -x : x; }
+constexpr T abs(T x)
+{
+ return x < 0 ? -x : x;
+}
// change the sign of x to the sign of s
template<class T>
-constexpr T chsign (T x, T s)
- { return (x < 0) ^ (s < 0) ? -x : x; }
+constexpr T chsign(T x, T s)
+{
+ return (x < 0) ^ (s < 0) ? -x : x;
+}
// integer division with rounding
template<class T>
-constexpr T rdiv (T x, T y)
- { return (x + chsign (y / 2, x)) / y; }
+constexpr T rdiv(T x, T y)
+{
+ return (x + chsign(y / 2, x)) / y;
+}
// convert integer from one scale to another, with rounding
template<class T>
-constexpr T rescale (T x, T old_scale, T new_scale)
- { return rdiv (x * new_scale, old_scale); }
+constexpr T rescale(T x, T old_scale, T new_scale)
+{
+ return rdiv(x * new_scale, old_scale);
+}
// number of characters needed to represent an integer (including minus sign)
template<class T>
-constexpr T n_digits (T x)
- { return x < 0 ? 1 + n_digits (-x) : x < 10 ? 1 : 1 + n_digits (x / 10); }
+constexpr T n_digits(T x)
+{
+ return x < 0 ? 1 + n_digits(-x) : x < 10 ? 1 : 1 + n_digits(x / 10);
+}
// number of elements in an array
template<class T, int N>
-constexpr int n_elems (const T (&) [N])
- { return N; }
+constexpr int n_elems(const T (&)[N])
+{
+ return N;
+}
// Casts for storing various data in a void pointer
// ================================================
template<class T>
-inline void * to_ptr (T t)
+inline void * to_ptr(T t)
{
- union { void * v; T t; } u = {nullptr};
- static_assert (sizeof u == sizeof (void *), "Type cannot be stored in a pointer");
- u.t = t; return u.v;
+ union {
+ void * v;
+ T t;
+ } u = {nullptr};
+ static_assert(sizeof u == sizeof(void *),
+ "Type cannot be stored in a pointer");
+ u.t = t;
+ return u.v;
}
template<class T>
-inline T from_ptr (void * v)
+inline T from_ptr(void * v)
{
- union { void * v; T t; } u = {v};
- static_assert (sizeof u == sizeof (void *), "Type cannot be stored in a pointer");
+ union {
+ void * v;
+ T t;
+ } u = {v};
+ static_assert(sizeof u == sizeof(void *),
+ "Type cannot be stored in a pointer");
return u.t;
}
@@ -102,12 +130,12 @@ inline T from_ptr (void * v)
// ================================================
template<class T>
-T & move_assign (T & a, T && b)
+T & move_assign(T & a, T && b)
{
- if (& a != & b)
+ if (&a != &b)
{
- a.~T ();
- new (& a) T (std::move (b));
+ a.~T();
+ new (&a) T(std::move(b));
}
return a;
}
@@ -116,23 +144,61 @@ T & move_assign (T & a, T && b)
// ================================================================
template<class T>
-void delete_obj (void * obj)
- { (void) sizeof (T); delete (T *) obj; }
+void delete_obj(void * obj)
+{
+ (void)sizeof(T);
+ delete (T *)obj;
+}
template<class T>
-void delete_typed (T * obj)
- { (void) sizeof (T); delete obj; }
+void delete_typed(T * obj)
+{
+ (void)sizeof(T);
+ delete obj;
+}
+
+template<class T, void (*func)(void *)>
+void typed_func(T * obj)
+{
+ func(obj);
+}
+
+template<class T, void (T::*func)()>
+static void obj_member(void * obj)
+{
+ (((T *)obj)->*func)();
+}
+template<class T, void (T::*func)() const>
+static void obj_member(void * obj)
+{
+ (((T *)obj)->*func)();
+}
-template<class T, void (* func) (void *)>
-void typed_func (T * obj)
- { func (obj); }
+// Class which provides scope-based "ownership" of an object
+// (similar to std::unique_lock, but more flexible)
+// =========================================================
-template<class T, void (T::* func) ()>
-static void obj_member (void * obj)
- { (((T *) obj)->* func) (); }
-template<class T, void (T::* func) () const>
-static void obj_member (void * obj)
- { (((T *) obj)->* func) (); }
+template<class T, void (T::*acquire)(), void (T::*release)()>
+class owner
+{
+public:
+ explicit owner(T * obj = nullptr) : m_obj(obj)
+ {
+ if (m_obj)
+ (m_obj->*acquire)();
+ }
+ ~owner()
+ {
+ if (m_obj)
+ (m_obj->*release)();
+ }
+
+ owner(owner && b) : m_obj(b.m_obj) { b.m_obj = nullptr; }
+ owner & operator=(owner && b) { return move_assign(*this, std::move(b)); }
+
+private:
+ T * m_obj;
+};
// Wrapper class allowing enumerations to be used as array indexes;
// the enumeration must begin with zero and have a "count" constant
@@ -142,54 +208,44 @@ template<class T, class V>
struct array
{
// cannot use std::forward here; it is not constexpr until C++14
- template<class ... Args>
- constexpr array (Args && ... args) :
- vals { static_cast<Args &&> (args) ...} {}
+ template<class... Args>
+ constexpr array(Args &&... args) : vals{static_cast<Args &&>(args)...}
+ {
+ }
// Due to GCC bug #63707, the forwarding constructor given above cannot be
// used to initialize the array when V is a class with no copy constructor.
// As a very limited workaround, provide a second constructor which can be
// used to initialize the array to default values in this case.
- constexpr array () :
- vals () {}
-
- constexpr const V & operator[] (T t) const
- { return vals[(int) t]; }
- constexpr const V * begin () const
- { return vals; }
- constexpr const V * end () const
- { return vals + (int) T::count; }
- V & operator[] (T t)
- { return vals[(int) t]; }
- V * begin ()
- { return vals; }
- V * end ()
- { return vals + (int) T::count; }
+ constexpr array() : vals() {}
+
+ constexpr const V & operator[](T t) const { return vals[(int)t]; }
+ constexpr const V * begin() const { return vals; }
+ constexpr const V * end() const { return vals + (int)T::count; }
+ V & operator[](T t) { return vals[(int)t]; }
+ V * begin() { return vals; }
+ V * end() { return vals + (int)T::count; }
private:
- V vals[(int) T::count];
+ V vals[(int)T::count];
};
// Wrapper class allowing enumerations to be used in range-based for loops
// =======================================================================
-template<class T, T first = (T) 0, T last = (T) ((int) T::count - 1)>
+template<class T, T first = (T)0, T last = (T)((int)T::count - 1)>
struct range
{
- struct iter {
+ struct iter
+ {
T v;
- constexpr T operator* () const
- { return v; }
- constexpr bool operator!= (iter other) const
- { return v != other.v; }
- void operator++ ()
- { v = (T) ((int) v + 1); }
+ constexpr T operator*() const { return v; }
+ constexpr bool operator!=(iter other) const { return v != other.v; }
+ void operator++() { v = (T)((int)v + 1); }
};
- static constexpr iter begin ()
- { return {first}; }
- static constexpr iter end ()
- { return {(T) ((int) last + 1)}; }
+ static constexpr iter begin() { return {first}; }
+ static constexpr iter end() { return {(T)((int)last + 1)}; }
};
// Replacement for std::allocator::construct, which also supports aggregate
@@ -199,28 +255,36 @@ struct range
// class constructor proxy
template<class T, bool aggregate>
-struct construct_base {
- template<class ... Args>
- static T * make (void * loc, Args && ... args)
- { return new (loc) T (std::forward<Args> (args) ...); }
+struct construct_base
+{
+ template<class... Args>
+ static T * make(void * loc, Args &&... args)
+ {
+ return new (loc) T(std::forward<Args>(args)...);
+ }
};
// aggregate constructor proxy
template<class T>
-struct construct_base<T, true> {
- template<class ... Args>
- static T * make (void * loc, Args && ... args)
- { return new (loc) T {std::forward<Args> (args) ...}; }
+struct construct_base<T, true>
+{
+ template<class... Args>
+ static T * make(void * loc, Args &&... args)
+ {
+ return new (loc) T{std::forward<Args>(args)...};
+ }
};
// generic constructor proxy
template<class T>
-struct construct {
- template<class ... Args>
- static T * make (void * loc, Args && ... args)
+struct construct
+{
+ template<class... Args>
+ static T * make(void * loc, Args &&... args)
{
- constexpr bool aggregate = ! std::is_constructible<T, Args && ...>::value;
- return construct_base<T, aggregate>::make (loc, std::forward<Args> (args) ...);
+ constexpr bool aggregate = !std::is_constructible<T, Args &&...>::value;
+ return construct_base<T, aggregate>::make(loc,
+ std::forward<Args>(args)...);
}
};
@@ -230,25 +294,31 @@ struct construct {
// "metaprogramming" string type: each different string is a unique type
template<char... args>
-struct metastring {
- char data[sizeof... (args) + 1] = {args..., '\0'};
+struct metastring
+{
+ char data[sizeof...(args) + 1] = {args..., '\0'};
};
// recursive number-printing template, general case (three or more digits)
template<int size, int x, char... args>
-struct numeric_builder {
- typedef typename numeric_builder<size - 1, x / 10, '0' + abs (x) % 10, args...>::type type;
+struct numeric_builder
+{
+ typedef typename numeric_builder<size - 1, x / 10, '0' + abs(x) % 10,
+ args...>::type type;
};
// special case for two digits; minus sign is handled here
template<int x, char... args>
-struct numeric_builder<2, x, args...> {
- typedef metastring<x < 0 ? '-' : '0' + x / 10, '0' + abs (x) % 10, args...> type;
+struct numeric_builder<2, x, args...>
+{
+ typedef metastring <
+ x<0 ? '-' : '0' + x / 10, '0' + abs(x) % 10, args...> type;
};
// special case for one digit (positive numbers only)
template<int x, char... args>
-struct numeric_builder<1, x, args...> {
+struct numeric_builder<1, x, args...>
+{
typedef metastring<'0' + x, args...> type;
};
@@ -258,10 +328,10 @@ class numeric_string
{
private:
// generate a unique string type representing this number
- typedef typename numeric_builder<n_digits (x), x>::type type;
+ typedef typename numeric_builder<n_digits(x), x>::type type;
// declare a static string of that type (instantiated later at file scope)
- static constexpr type value {};
+ static constexpr type value{};
public:
// pointer to the instantiated string
@@ -276,45 +346,46 @@ constexpr typename numeric_string<x>::type numeric_string<x>::value;
// these will be nullptr for basic types (use memset/memcpy instead)
// =================================================================
-typedef void (* FillFunc) (void * data, int len);
-typedef void (* CopyFunc) (const void * from, void * to, int len);
-typedef void (* EraseFunc) (void * data, int len);
+typedef void (*FillFunc)(void * data, int len);
+typedef void (*CopyFunc)(const void * from, void * to, int len);
+typedef void (*EraseFunc)(void * data, int len);
template<class T>
-static constexpr FillFunc fill_func ()
-{
- return std::is_trivial<T>::value ? (FillFunc) nullptr :
- [] (void * data, int len) {
- T * iter = (T *) data;
- T * end = (T *) ((char *) data + len);
- while (iter < end)
- new (iter ++) T ();
- };
+static constexpr FillFunc fill_func()
+{
+ return std::is_trivial<T>::value ? (FillFunc) nullptr
+ : [](void * data, int len) {
+ T * iter = (T *)data;
+ T * end = (T *)((char *)data + len);
+ while (iter < end)
+ new (iter++) T();
+ };
}
template<class T>
-static constexpr CopyFunc copy_func ()
-{
- return std::is_trivial<T>::value ? (CopyFunc) nullptr :
- [] (const void * from, void * to, int len) {
- const T * src = (const T *) from;
- T * dest = (T *) to;
- T * end = (T *) ((char *) to + len);
- while (dest < end)
- new (dest ++) T (* src ++);
- };
+static constexpr CopyFunc copy_func()
+{
+ return std::is_trivial<T>::value
+ ? (CopyFunc) nullptr
+ : [](const void * from, void * to, int len) {
+ const T * src = (const T *)from;
+ T * dest = (T *)to;
+ T * end = (T *)((char *)to + len);
+ while (dest < end)
+ new (dest++) T(*src++);
+ };
}
template<class T>
-static constexpr EraseFunc erase_func ()
-{
- return std::is_trivial<T>::value ? (EraseFunc) nullptr :
- [] (void * data, int len) {
- T * iter = (T *) data;
- T * end = (T *) ((char *) data + len);
- while (iter < end)
- (* iter ++).~T ();
- };
+static constexpr EraseFunc erase_func()
+{
+ return std::is_trivial<T>::value ? (EraseFunc) nullptr
+ : [](void * data, int len) {
+ T * iter = (T *)data;
+ T * end = (T *)((char *)data + len);
+ while (iter < end)
+ (*iter++).~T();
+ };
}
} // namespace aud
diff --git a/src/libaudcore/tests/test-mainloop.cc b/src/libaudcore/tests/test-mainloop.cc
index 384c533..418c7dc 100644
--- a/src/libaudcore/tests/test-mainloop.cc
+++ b/src/libaudcore/tests/test-mainloop.cc
@@ -19,9 +19,9 @@
#include "mainloop.h"
#include "runtime.h"
+#include "threads.h"
#include <assert.h>
-#include <pthread.h>
#include <stdio.h>
#include <string.h>
@@ -36,7 +36,7 @@ static QueuedFunc counters[70];
static QueuedFunc timer, delayed;
static int count;
-static pthread_t main_thread;
+static std::thread::id main_thread;
static void never_called (void * data)
{
@@ -46,7 +46,7 @@ static void never_called (void * data)
static void count_up (void * data)
{
- assert (pthread_self () == main_thread);
+ assert (std::this_thread::get_id () == main_thread);
// check that idle calls are run in the same order they were queued
assert (count == (int) (size_t) data);
@@ -61,7 +61,7 @@ static void count_up (void * data)
static void count_down (void * data)
{
- assert (pthread_self () == main_thread);
+ assert (std::this_thread::get_id () == main_thread);
assert (data == & count);
// check that the timer reports being started
@@ -84,7 +84,7 @@ static void count_down (void * data)
static void check_count (void * data)
{
- assert (pthread_self () == main_thread);
+ assert (std::this_thread::get_id () == main_thread);
// check relative timing of 10 Hz timer and 250 ms delayed call
assert (count == (int) (size_t) data);
@@ -92,7 +92,7 @@ static void check_count (void * data)
printf ("CHECK: %d\n", count);
}
-static void * worker (void * data)
+static void worker ()
{
// queue some more idle calls from a secondary thread
for (int i = 50; i < 70; i ++)
@@ -100,8 +100,6 @@ static void * worker (void * data)
// queue up a delayed call that should only be called once
delayed.queue (250, check_count, (void *) (size_t) 40);
-
- return nullptr;
}
int main (int argc, const char * * argv)
@@ -109,7 +107,7 @@ int main (int argc, const char * * argv)
if (argc >= 2 && ! strcmp (argv[1], "--qt"))
use_qt = true;
- main_thread = pthread_self ();
+ main_thread = std::this_thread::get_id ();
// queue up a bunch of idle calls
for (int i = 0; i < 50; i ++)
@@ -129,12 +127,11 @@ int main (int argc, const char * * argv)
// queue up a call and then immediately delete the QueuedFunc
QueuedFunc ().queue (never_called, nullptr);
- pthread_t thread;
- pthread_create (& thread, nullptr, worker, nullptr);
+ auto thread = std::thread (worker);
mainloop_run ();
- pthread_join (thread, nullptr);
+ thread.join ();
// check that the timer reports being stopped
assert (! timer.running ());
diff --git a/src/libaudcore/threads.h b/src/libaudcore/threads.h
new file mode 100644
index 0000000..2f13b0c
--- /dev/null
+++ b/src/libaudcore/threads.h
@@ -0,0 +1,100 @@
+/*
+ * threads.h
+ * Copyright 2019 John Lindgren
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions, and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions, and the following disclaimer in the documentation
+ * provided with the distribution.
+ *
+ * This software is provided "as is" and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising from
+ * the use of this software.
+ */
+
+#ifndef LIBAUDCORE_THREADS_H
+#define LIBAUDCORE_THREADS_H
+
+#include <libaudcore/templates.h>
+#include <libaudcore/tinylock.h>
+
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+
+namespace aud
+{
+
+/* A wrapper class around TinyLock, encouraging correct usage */
+class spinlock
+{
+public:
+ spinlock() = default;
+
+ /* Not copyable or movable */
+ spinlock(const spinlock &) = delete;
+ spinlock & operator=(const spinlock &) = delete;
+
+ /* Explicit lock/unlock */
+ void lock() { tiny_lock(&m_lock); }
+ void unlock() { tiny_unlock(&m_lock); }
+
+ /* Scope-based lock ownership */
+ typedef owner<spinlock, &spinlock::lock, &spinlock::unlock> holder;
+ /* Convenience method for taking ownership of the lock */
+ holder take() __attribute__((warn_unused_result)) { return holder(this); }
+
+private:
+ TinyLock m_lock = 0;
+};
+
+/* A wrapper class around TinyRWLock, encouraging correct usage */
+class spinlock_rw
+{
+public:
+ spinlock_rw() = default;
+
+ /* Not copyable or movable */
+ spinlock_rw(const spinlock_rw &) = delete;
+ spinlock_rw & operator=(const spinlock_rw &) = delete;
+
+ /* Explicit lock/unlock */
+ void lock_r() { tiny_lock_read(&m_lock); }
+ void unlock_r() { tiny_unlock_read(&m_lock); }
+ void lock_w() { tiny_lock_write(&m_lock); }
+ void unlock_w() { tiny_unlock_write(&m_lock); }
+
+ /* Scope-based lock ownership */
+ typedef owner<spinlock_rw, &spinlock_rw::lock_r, &spinlock_rw::unlock_r>
+ reader;
+ typedef owner<spinlock_rw, &spinlock_rw::lock_w, &spinlock_rw::unlock_w>
+ writer;
+ /* Convenience methods for taking ownership of the lock */
+ reader read() __attribute__((warn_unused_result)) { return reader(this); }
+ writer write() __attribute__((warn_unused_result)) { return writer(this); }
+
+private:
+ TinyRWLock m_lock = 0;
+};
+
+/* An alias for std::mutex */
+class mutex : public std::mutex
+{
+public:
+ /* Scope-based lock ownership */
+ typedef std::unique_lock<std::mutex> holder;
+ /* Convenience method for taking ownership of the lock */
+ holder take() __attribute__((warn_unused_result)) { return holder(*this); }
+};
+
+/* An alias for std::condition_variable */
+typedef std::condition_variable condvar;
+
+} // namespace aud
+
+#endif // LIBAUDCORE_THREADS_H
diff --git a/src/libaudcore/timer.cc b/src/libaudcore/timer.cc
index 4de6abf..2443f04 100644
--- a/src/libaudcore/timer.cc
+++ b/src/libaudcore/timer.cc
@@ -18,17 +18,16 @@
*/
#include "hook.h"
-
-#include <pthread.h>
-
#include "index.h"
#include "internal.h"
#include "mainloop.h"
#include "runtime.h"
+#include "threads.h"
static const aud::array<TimerRate, int> rate_to_ms = {1000, 250, 100, 33};
-struct TimerItem {
+struct TimerItem
+{
TimerFunc func;
void * data;
};
@@ -39,7 +38,7 @@ struct TimerList
Index<TimerItem> items;
int use_count = 0;
- bool contains (TimerFunc func, void * data) const
+ bool contains(TimerFunc func, void * data) const
{
for (auto & item : items)
{
@@ -50,93 +49,84 @@ struct TimerList
return false;
}
- void check_stop ()
+ void check_stop()
{
- if (! use_count)
+ if (!use_count)
{
- auto is_empty = [] (const TimerItem & item)
- { return ! item.func; };
+ auto is_empty = [](const TimerItem & item) { return !item.func; };
- items.remove_if (is_empty, true);
+ items.remove_if(is_empty, true);
- if (! items.len () && source.running ())
- source.stop ();
+ if (!items.len() && source.running())
+ source.stop();
}
}
};
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static aud::mutex mutex;
static aud::array<TimerRate, TimerList> lists;
-static void timer_run (void * list_)
+static void timer_run(void * list_)
{
- auto & list = * (TimerList *) list_;
- pthread_mutex_lock (& mutex);
+ auto & list = *(TimerList *)list_;
+ auto mh = mutex.take();
- list.use_count ++;
+ list.use_count++;
/* note: the list may grow (but not shrink) during the call */
- for (int i = 0; i < list.items.len (); i ++)
+ for (int i = 0; i < list.items.len(); i++)
{
/* copy locally to prevent race condition */
TimerItem item = list.items[i];
if (item.func)
{
- pthread_mutex_unlock (& mutex);
- item.func (item.data);
- pthread_mutex_lock (& mutex);
+ mh.unlock();
+ item.func(item.data);
+ mh.lock();
}
}
- list.use_count --;
- list.check_stop ();
-
- pthread_mutex_unlock (& mutex);
+ list.use_count--;
+ list.check_stop();
}
-EXPORT void timer_add (TimerRate rate, TimerFunc func, void * data)
+EXPORT void timer_add(TimerRate rate, TimerFunc func, void * data)
{
auto & list = lists[rate];
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- if (! list.contains (func, data))
+ if (!list.contains(func, data))
{
- list.items.append (func, data);
+ list.items.append(func, data);
- if (! list.source.running ())
- list.source.start (rate_to_ms[rate], timer_run, & list);
+ if (!list.source.running())
+ list.source.start(rate_to_ms[rate], timer_run, &list);
}
-
- pthread_mutex_unlock (& mutex);
}
-EXPORT void timer_remove (TimerRate rate, TimerFunc func, void * data)
+EXPORT void timer_remove(TimerRate rate, TimerFunc func, void * data)
{
auto & list = lists[rate];
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
for (TimerItem & item : list.items)
{
- if (item.func == func && (! data || item.data == data))
+ if (item.func == func && (!data || item.data == data))
item.func = nullptr;
}
- list.check_stop ();
-
- pthread_mutex_unlock (& mutex);
+ list.check_stop();
}
-void timer_cleanup ()
+void timer_cleanup()
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
int timers_running = 0;
for (TimerList & list : lists)
- timers_running += list.items.len ();
+ timers_running += list.items.len();
if (timers_running)
- AUDWARN ("%d timers still registered at exit\n", timers_running);
-
- pthread_mutex_unlock (& mutex);
+ AUDWARN("%d timers still registered at exit\n", timers_running);
}
diff --git a/src/libaudcore/tinylock.cc b/src/libaudcore/tinylock.cc
index 873aff1..0424e8b 100644
--- a/src/libaudcore/tinylock.cc
+++ b/src/libaudcore/tinylock.cc
@@ -19,47 +19,41 @@
#include "tinylock.h"
-#ifndef VALGRIND_FRIENDLY
-
#include <limits.h>
#include <sched.h>
#define WRITE_BIT (SHRT_MAX + 1)
-EXPORT void tiny_lock (TinyLock * lock)
+EXPORT void tiny_lock(TinyLock * lock)
{
- while (__builtin_expect (__sync_lock_test_and_set (lock, 1), 0))
- sched_yield ();
+ while (__builtin_expect(__sync_lock_test_and_set(lock, 1), 0))
+ sched_yield();
}
-EXPORT void tiny_unlock (TinyLock * lock)
-{
- __sync_lock_release (lock);
-}
+EXPORT void tiny_unlock(TinyLock * lock) { __sync_lock_release(lock); }
-EXPORT void tiny_lock_read (TinyRWLock * lock)
+EXPORT void tiny_lock_read(TinyRWLock * lock)
{
- while (__builtin_expect (__sync_fetch_and_add (lock, 1) & WRITE_BIT, 0))
+ while (__builtin_expect(__sync_fetch_and_add(lock, 1) & WRITE_BIT, 0))
{
- __sync_fetch_and_sub (lock, 1);
- sched_yield ();
+ __sync_fetch_and_sub(lock, 1);
+ sched_yield();
}
}
-EXPORT void tiny_unlock_read (TinyRWLock * lock)
+EXPORT void tiny_unlock_read(TinyRWLock * lock)
{
- __sync_fetch_and_sub (lock, 1);
+ __sync_fetch_and_sub(lock, 1);
}
-EXPORT void tiny_lock_write (TinyRWLock * lock)
+EXPORT void tiny_lock_write(TinyRWLock * lock)
{
- while (! __builtin_expect (__sync_bool_compare_and_swap (lock, 0, WRITE_BIT), 1))
- sched_yield ();
+ while (
+ !__builtin_expect(__sync_bool_compare_and_swap(lock, 0, WRITE_BIT), 1))
+ sched_yield();
}
-EXPORT void tiny_unlock_write (TinyRWLock * lock)
+EXPORT void tiny_unlock_write(TinyRWLock * lock)
{
- __sync_fetch_and_sub (lock, WRITE_BIT);
+ __sync_fetch_and_sub(lock, WRITE_BIT);
}
-
-#endif /* ! VALGRIND_FRIENDLY */
diff --git a/src/libaudcore/tinylock.h.in b/src/libaudcore/tinylock.h
index 873af1b..1b16a06 100644
--- a/src/libaudcore/tinylock.h.in
+++ b/src/libaudcore/tinylock.h
@@ -20,37 +20,24 @@
#ifndef LIBAUDCORE_TINYLOCK_H
#define LIBAUDCORE_TINYLOCK_H
-#if @VALGRIND_FRIENDLY@ /* VALGRIND_FRIENDLY */
-
-#include <pthread.h>
-
-typedef pthread_mutex_t TinyLock;
-typedef pthread_rwlock_t TinyRWLock;
-
-#define tiny_lock pthread_mutex_lock
-#define tiny_unlock pthread_mutex_unlock
-#define tiny_lock_read pthread_rwlock_rdlock
-#define tiny_unlock_read pthread_rwlock_unlock
-#define tiny_lock_write pthread_rwlock_wrlock
-#define tiny_unlock_write pthread_rwlock_unlock
-
-#else /* ! VALGRIND_FRIENDLY */
-
-/* TinyLock is an extremely low-overhead lock object (in terms of speed and
- * memory usage). It makes no guarantees of fair scheduling, however. */
+/*
+ * TinyLock is an extremely low-overhead lock object (in terms of speed and
+ * memory usage). It makes no guarantees of fair scheduling, however.
+ *
+ * Consider using the aud::spinlock wrapper class from threads.h rather than
+ * using this API directly.
+ */
typedef char TinyLock;
-void tiny_lock (TinyLock * lock);
-void tiny_unlock (TinyLock * lock);
+void tiny_lock(TinyLock * lock);
+void tiny_unlock(TinyLock * lock);
typedef unsigned short TinyRWLock;
-void tiny_lock_read (TinyRWLock * lock);
-void tiny_unlock_read (TinyRWLock * lock);
-void tiny_lock_write (TinyRWLock * lock);
-void tiny_unlock_write (TinyRWLock * lock);
-
-#endif /* ! VALGRIND_FRIENDLY */
+void tiny_lock_read(TinyRWLock * lock);
+void tiny_unlock_read(TinyRWLock * lock);
+void tiny_lock_write(TinyRWLock * lock);
+void tiny_unlock_write(TinyRWLock * lock);
#endif /* LIBAUDCORE_TINYLOCK_H */
diff --git a/src/libaudcore/tuple-compiler.cc b/src/libaudcore/tuple-compiler.cc
index b8d50cd..97198b5 100644
--- a/src/libaudcore/tuple-compiler.cc
+++ b/src/libaudcore/tuple-compiler.cc
@@ -21,8 +21,8 @@
#include <stdlib.h>
#include <string.h>
-#include <new>
#include <glib.h>
+#include <new>
#include "audstrings.h"
#include "runtime.h"
@@ -30,7 +30,8 @@
struct Variable
{
- enum {
+ enum
+ {
Invalid = 0,
Text,
Integer,
@@ -41,12 +42,13 @@ struct Variable
int integer;
Tuple::Field field;
- bool set (const char * name, bool literal);
- bool exists (const Tuple & tuple) const;
- Tuple::ValueType get (const Tuple & tuple, String & tmps, int & tmpi) const;
+ bool set(const char * name, bool literal);
+ bool exists(const Tuple & tuple) const;
+ Tuple::ValueType get(const Tuple & tuple, String & tmps, int & tmpi) const;
};
-enum class Op {
+enum class Op
+{
Invalid = 0,
Var,
Exists,
@@ -59,7 +61,8 @@ enum class Op {
Empty
};
-struct TupleCompiler::Node {
+struct TupleCompiler::Node
+{
Op op;
Variable var1, var2;
Index<Node> children;
@@ -67,26 +70,26 @@ struct TupleCompiler::Node {
typedef TupleCompiler::Node Node;
-bool Variable::set (const char * name, bool literal)
+bool Variable::set(const char * name, bool literal)
{
- if (g_ascii_isdigit (name[0]))
+ if (g_ascii_isdigit(name[0]))
{
type = Integer;
- integer = atoi (name);
+ integer = atoi(name);
}
else if (literal)
{
type = Text;
- text = String (name);
+ text = String(name);
}
else
{
type = Field;
- field = Tuple::field_by_name (name);
+ field = Tuple::field_by_name(name);
if (field < 0)
{
- AUDWARN ("Invalid variable '%s'.\n", name);
+ AUDWARN("Invalid variable '%s'.\n", name);
return false;
}
}
@@ -94,13 +97,14 @@ bool Variable::set (const char * name, bool literal)
return true;
}
-bool Variable::exists (const Tuple & tuple) const
+bool Variable::exists(const Tuple & tuple) const
{
- g_return_val_if_fail (type == Field, false);
- return tuple.get_value_type (field) != Tuple::Empty;
+ g_return_val_if_fail(type == Field, false);
+ return tuple.get_value_type(field) != Tuple::Empty;
}
-Tuple::ValueType Variable::get (const Tuple & tuple, String & tmps, int & tmpi) const
+Tuple::ValueType Variable::get(const Tuple & tuple, String & tmps,
+ int & tmpi) const
{
switch (type)
{
@@ -113,14 +117,14 @@ Tuple::ValueType Variable::get (const Tuple & tuple, String & tmps, int & tmpi)
return Tuple::Int;
case Field:
- switch (tuple.get_value_type (field))
+ switch (tuple.get_value_type(field))
{
case Tuple::String:
- tmps = tuple.get_str (field);
+ tmps = tuple.get_str(field);
return Tuple::String;
case Tuple::Int:
- tmpi = tuple.get_int (field);
+ tmpi = tuple.get_int(field);
return Tuple::Int;
default:
@@ -128,139 +132,139 @@ Tuple::ValueType Variable::get (const Tuple & tuple, String & tmps, int & tmpi)
}
default:
- g_return_val_if_reached (Tuple::Empty);
+ g_return_val_if_reached(Tuple::Empty);
}
}
-TupleCompiler::TupleCompiler () {}
-TupleCompiler::~TupleCompiler () {}
+TupleCompiler::TupleCompiler() {}
+TupleCompiler::~TupleCompiler() {}
-static StringBuf get_item (const char * & str, char endch, bool & literal)
+static StringBuf get_item(const char *& str, char endch, bool & literal)
{
const char * s = str;
- StringBuf buf (-1);
+ StringBuf buf(-1);
char * set = buf;
- char * stop = buf + buf.len ();
+ char * stop = buf + buf.len();
- if (* s == '"')
+ if (*s == '"')
{
- if (! literal)
+ if (!literal)
{
- buf = StringBuf (); // release space before AUDWARN
- AUDWARN ("Unexpected string literal at '%s'.\n", s);
- return StringBuf ();
+ buf = StringBuf(); // release space before AUDWARN
+ AUDWARN("Unexpected string literal at '%s'.\n", s);
+ return StringBuf();
}
- s ++;
+ s++;
}
else
literal = false;
if (literal)
{
- while (* s != '"')
+ while (*s != '"')
{
- if (* s == '\\')
- s ++;
+ if (*s == '\\')
+ s++;
- if (! * s)
+ if (!*s)
{
- buf = StringBuf (); // release space before AUDWARN
- AUDWARN ("Unterminated string literal.\n");
- return StringBuf ();
+ buf = StringBuf(); // release space before AUDWARN
+ AUDWARN("Unterminated string literal.\n");
+ return StringBuf();
}
if (set == stop)
- throw std::bad_alloc ();
+ throw std::bad_alloc();
- * set ++ = * s ++;
+ *set++ = *s++;
}
- s ++;
+ s++;
}
else
{
- while (g_ascii_isalnum (* s) || * s == '-')
+ while (g_ascii_isalnum(*s) || *s == '-')
{
if (set == stop)
- throw std::bad_alloc ();
+ throw std::bad_alloc();
- * set ++ = * s ++;
+ *set++ = *s++;
}
}
- if (* s != endch)
+ if (*s != endch)
{
- buf = StringBuf (); // release space before AUDWARN
- AUDWARN ("Expected '%c' at '%s'.\n", endch, s);
- return StringBuf ();
+ buf = StringBuf(); // release space before AUDWARN
+ AUDWARN("Expected '%c' at '%s'.\n", endch, s);
+ return StringBuf();
}
str = s + 1;
- buf.resize (set - buf);
+ buf.resize(set - buf);
return buf;
}
-static bool compile_expression (Index<Node> & nodes, const char * & expression);
+static bool compile_expression(Index<Node> & nodes, const char *& expression);
-static bool parse_construct (Node & node, const char * & c)
+static bool parse_construct(Node & node, const char *& c)
{
bool literal1 = true, literal2 = true;
- StringBuf tmps1 = get_item (c, ',', literal1);
- if (! tmps1)
+ StringBuf tmps1 = get_item(c, ',', literal1);
+ if (!tmps1)
return false;
- StringBuf tmps2 = get_item (c, ':', literal2);
- if (! tmps2)
+ StringBuf tmps2 = get_item(c, ':', literal2);
+ if (!tmps2)
return false;
- if (! node.var1.set (tmps1, literal1))
+ if (!node.var1.set(tmps1, literal1))
return false;
- if (! node.var2.set (tmps2, literal2))
+ if (!node.var2.set(tmps2, literal2))
return false;
- return compile_expression (node.children, c);
+ return compile_expression(node.children, c);
}
/* Compile format expression into Node tree. */
-static bool compile_expression (Index<Node> & nodes, const char * & expression)
+static bool compile_expression(Index<Node> & nodes, const char *& expression)
{
const char * c = expression;
- while (* c && * c != '}')
+ while (*c && *c != '}')
{
- Node & node = nodes.append ();
+ Node & node = nodes.append();
- if (* c == '$')
+ if (*c == '$')
{
/* Expression? */
if (c[1] != '{')
{
- AUDWARN ("Expected '${' at '%s'.\n", c);
+ AUDWARN("Expected '${' at '%s'.\n", c);
return false;
}
c += 2;
- switch (* c)
+ switch (*c)
{
case '?':
case '(':
- {
- if (* c == '?')
+ {
+ if (*c == '?')
{
node.op = Op::Exists;
- c ++;
+ c++;
}
else
{
- if (strncmp (c, "(empty)?", 8))
+ if (strncmp(c, "(empty)?", 8))
{
- AUDWARN ("Expected '(empty)?' at '%s'.\n", c);
+ AUDWARN("Expected '(empty)?' at '%s'.\n", c);
return false;
}
@@ -269,32 +273,32 @@ static bool compile_expression (Index<Node> & nodes, const char * & expression)
}
bool literal = false;
- StringBuf tmps = get_item (c, ':', literal);
- if (! tmps)
+ StringBuf tmps = get_item(c, ':', literal);
+ if (!tmps)
return false;
- if (! node.var1.set (tmps, false))
+ if (!node.var1.set(tmps, false))
return false;
- if (! compile_expression (node.children, c))
+ if (!compile_expression(node.children, c))
return false;
break;
- }
+ }
case '=':
case '!':
- node.op = (* c == '=') ? Op::Equal : Op::Unequal;
+ node.op = (*c == '=') ? Op::Equal : Op::Unequal;
if (c[1] != '=')
{
- AUDWARN ("Expected '%c=' at '%s'.\n", c[0], c);
+ AUDWARN("Expected '%c=' at '%s'.\n", c[0], c);
return false;
}
c += 2;
- if (! parse_construct (node, c))
+ if (!parse_construct(node, c))
return false;
break;
@@ -303,81 +307,81 @@ static bool compile_expression (Index<Node> & nodes, const char * & expression)
case '>':
if (c[1] == '=')
{
- node.op = (* c == '<') ? Op::LessEqual : Op::GreaterEqual;
+ node.op = (*c == '<') ? Op::LessEqual : Op::GreaterEqual;
c += 2;
}
else
{
- node.op = (* c == '<') ? Op::Less : Op::Greater;
- c ++;
+ node.op = (*c == '<') ? Op::Less : Op::Greater;
+ c++;
}
- if (! parse_construct (node, c))
+ if (!parse_construct(node, c))
return false;
break;
default:
- {
+ {
bool literal = false;
- StringBuf tmps = get_item (c, '}', literal);
- if (! tmps)
+ StringBuf tmps = get_item(c, '}', literal);
+ if (!tmps)
return false;
- c --;
+ c--;
node.op = Op::Var;
- if (! node.var1.set (tmps, false))
+ if (!node.var1.set(tmps, false))
return false;
- }
+ }
}
- if (* c != '}')
+ if (*c != '}')
{
- AUDWARN ("Expected '}' at '%s'.\n", c);
+ AUDWARN("Expected '}' at '%s'.\n", c);
return false;
}
- c ++;
+ c++;
}
- else if (* c == '{')
+ else if (*c == '{')
{
- AUDWARN ("Unexpected '%c' at '%s'.\n", * c, c);
+ AUDWARN("Unexpected '%c' at '%s'.\n", *c, c);
return false;
}
else
{
/* Parse raw/literal text */
- StringBuf buf (-1);
+ StringBuf buf(-1);
char * set = buf;
- char * stop = buf + buf.len ();
+ char * stop = buf + buf.len();
- while (* c && * c != '$' && * c != '{' && * c != '}')
+ while (*c && *c != '$' && *c != '{' && *c != '}')
{
- if (* c == '\\')
+ if (*c == '\\')
{
- c ++;
+ c++;
- if (! * c)
+ if (!*c)
{
- buf = StringBuf (); // release space before AUDWARN
- AUDWARN ("Incomplete escaped character.\n");
+ buf = StringBuf(); // release space before AUDWARN
+ AUDWARN("Incomplete escaped character.\n");
return false;
}
}
if (set == stop)
- throw std::bad_alloc ();
+ throw std::bad_alloc();
- * set ++ = * c ++;
+ *set++ = *c++;
}
- buf.resize (set - buf);
+ buf.resize(set - buf);
node.op = Op::Var;
node.var1.type = Variable::Text;
- node.var1.text = String (buf);
+ node.var1.text = String(buf);
}
}
@@ -385,50 +389,48 @@ static bool compile_expression (Index<Node> & nodes, const char * & expression)
return true;
}
-bool TupleCompiler::compile (const char * expr)
+bool TupleCompiler::compile(const char * expr)
{
const char * c = expr;
Index<Node> nodes;
- if (! compile_expression (nodes, c))
+ if (!compile_expression(nodes, c))
return false;
- if (* c)
+ if (*c)
{
- AUDWARN ("Unexpected '%c' at '%s'.\n", * c, c);
+ AUDWARN("Unexpected '%c' at '%s'.\n", *c, c);
return false;
}
- root_nodes = std::move (nodes);
+ root_nodes = std::move(nodes);
return true;
}
-void TupleCompiler::reset ()
-{
- root_nodes.clear ();
-}
+void TupleCompiler::reset() { root_nodes.clear(); }
/* Evaluate tuple in given TupleEval expression in given
* context and return resulting string. */
-static void eval_expression (const Index<Node> & nodes, const Tuple & tuple, StringBuf & out)
+static void eval_expression(const Index<Node> & nodes, const Tuple & tuple,
+ StringBuf & out)
{
for (const Node & node : nodes)
{
switch (node.op)
{
case Op::Var:
- {
+ {
String tmps;
int tmpi;
- switch (node.var1.get (tuple, tmps, tmpi))
+ switch (node.var1.get(tuple, tmps, tmpi))
{
case Tuple::String:
- out.insert (-1, tmps);
+ out.insert(-1, tmps);
break;
case Tuple::Int:
- str_insert_int (out, -1, tmpi);
+ str_insert_int(out, -1, tmpi);
break;
default:
@@ -436,7 +438,7 @@ static void eval_expression (const Index<Node> & nodes, const Tuple & tuple, Str
}
break;
- }
+ }
case Op::Equal:
case Op::Unequal:
@@ -444,13 +446,13 @@ static void eval_expression (const Index<Node> & nodes, const Tuple & tuple, Str
case Op::LessEqual:
case Op::Greater:
case Op::GreaterEqual:
- {
+ {
bool result = false;
String tmps1, tmps2;
int tmpi1 = 0, tmpi2 = 0;
- Tuple::ValueType type1 = node.var1.get (tuple, tmps1, tmpi1);
- Tuple::ValueType type2 = node.var2.get (tuple, tmps2, tmpi2);
+ Tuple::ValueType type1 = node.var1.get(tuple, tmps1, tmpi1);
+ Tuple::ValueType type2 = node.var2.get(tuple, tmps2, tmpi2);
if (type1 != Tuple::Empty && type2 != Tuple::Empty)
{
@@ -459,16 +461,16 @@ static void eval_expression (const Index<Node> & nodes, const Tuple & tuple, Str
if (type1 == type2)
{
if (type1 == Tuple::String)
- resulti = strcmp (tmps1, tmps2);
+ resulti = strcmp(tmps1, tmps2);
else
resulti = tmpi1 - tmpi2;
}
else
{
if (type1 == Tuple::Int)
- resulti = tmpi1 - atoi (tmps2);
+ resulti = tmpi1 - atoi(tmps2);
else
- resulti = atoi (tmps1) - tmpi2;
+ resulti = atoi(tmps1) - tmpi2;
}
switch (node.op)
@@ -498,57 +500,57 @@ static void eval_expression (const Index<Node> & nodes, const Tuple & tuple, Str
break;
default:
- g_warn_if_reached ();
+ g_warn_if_reached();
}
}
if (result)
- eval_expression (node.children, tuple, out);
+ eval_expression(node.children, tuple, out);
break;
- }
+ }
case Op::Exists:
- if (node.var1.exists (tuple))
- eval_expression (node.children, tuple, out);
+ if (node.var1.exists(tuple))
+ eval_expression(node.children, tuple, out);
break;
case Op::Empty:
- if (! node.var1.exists (tuple))
- eval_expression (node.children, tuple, out);
+ if (!node.var1.exists(tuple))
+ eval_expression(node.children, tuple, out);
break;
default:
- g_warn_if_reached ();
+ g_warn_if_reached();
}
}
}
-void TupleCompiler::format (Tuple & tuple) const
+void TupleCompiler::format(Tuple & tuple) const
{
- tuple.unset (Tuple::FormattedTitle); // prevent recursion
+ tuple.unset(Tuple::FormattedTitle); // prevent recursion
- StringBuf buf (0);
- eval_expression (root_nodes, tuple, buf);
+ StringBuf buf(0);
+ eval_expression(root_nodes, tuple, buf);
if (buf[0])
{
- tuple.set_str (Tuple::FormattedTitle, buf);
+ tuple.set_str(Tuple::FormattedTitle, buf);
return;
}
/* formatting failed, try fallbacks */
for (Tuple::Field fallback : {Tuple::Title, Tuple::Basename})
{
- String title = tuple.get_str (fallback);
+ String title = tuple.get_str(fallback);
if (title)
{
- tuple.set_str (Tuple::FormattedTitle, title);
+ tuple.set_str(Tuple::FormattedTitle, title);
return;
}
}
- tuple.set_str (Tuple::FormattedTitle, "");
+ tuple.set_str(Tuple::FormattedTitle, "");
}
diff --git a/src/libaudcore/tuple-compiler.h b/src/libaudcore/tuple-compiler.h
index 88cc21f..3e25faf 100644
--- a/src/libaudcore/tuple-compiler.h
+++ b/src/libaudcore/tuple-compiler.h
@@ -48,13 +48,13 @@ class TupleCompiler
public:
struct Node;
- TupleCompiler ();
- ~TupleCompiler ();
+ TupleCompiler();
+ ~TupleCompiler();
- bool compile (const char * expr);
- void reset ();
+ bool compile(const char * expr);
+ void reset();
- void format (Tuple & tuple) const;
+ void format(Tuple & tuple) const;
private:
Index<Node> root_nodes;
diff --git a/src/libaudcore/tuple.cc b/src/libaudcore/tuple.cc
index 603a475..02dde50 100644
--- a/src/libaudcore/tuple.cc
+++ b/src/libaudcore/tuple.cc
@@ -1,6 +1,6 @@
/*
* tuple.c
- * Copyright 2007-2013 William Pitcock, Christian Birchinger, Matti Hämäläinen,
+ * Copyright 2007-2013 Ariadne Conill, Christian Birchinger, Matti Hämäläinen,
* Giacomo Lozito, Eugene Zagidullin, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,7 @@
#include <stdlib.h>
#include <string.h>
-#include <glib.h> /* for g_utf8_validate */
+#include <glib.h> /* for g_utf8_validate */
#include "audio.h"
#include "audstrings.h"
@@ -32,7 +32,8 @@
#include "tuple.h"
#include "vfs.h"
-enum {
+enum
+{
FallbackTitle = Tuple::n_fields,
FallbackArtist,
FallbackAlbum,
@@ -40,17 +41,16 @@ enum {
n_private_fields
};
-static_assert (n_private_fields <= 64,
- "The current tuple implementation is limited to 64 fields");
+static_assert(n_private_fields <= 64,
+ "The current tuple implementation is limited to 64 fields");
-union TupleVal
-{
+union TupleVal {
String str;
int x;
// dummy constructor and destructor
- TupleVal () {}
- ~TupleVal () {}
+ TupleVal() {}
+ ~TupleVal() {}
};
/**
@@ -59,48 +59,47 @@ union TupleVal
*/
struct TupleData
{
- uint64_t setmask; // which fields are present
- Index<TupleVal> vals; // ordered list of field values
+ uint64_t setmask; // which fields are present
+ Index<TupleVal> vals; // ordered list of field values
- short * subtunes; /**< Array of int containing subtune index numbers.
- Can be nullptr if indexing is linear or if
- there are no subtunes. */
- short nsubtunes; /**< Number of subtunes, if any. Values greater than 0
- mean that there are subtunes and #subtunes array
- may be set. */
+ short * subtunes; /**< Array of int containing subtune index numbers.
+ Can be nullptr if indexing is linear or if
+ there are no subtunes. */
+ short nsubtunes; /**< Number of subtunes, if any. Values greater than 0
+ mean that there are subtunes and #subtunes array
+ may be set. */
short state;
int refcount;
- TupleData ();
- ~TupleData ();
+ TupleData();
+ ~TupleData();
- TupleData (const TupleData & other);
- void operator= (const TupleData & other) = delete;
+ TupleData(const TupleData & other);
+ void operator=(const TupleData & other) = delete;
- bool is_set (int field) const
- { return (setmask & bitmask (field)); }
+ bool is_set(int field) const { return (setmask & bitmask(field)); }
- bool is_same (const TupleData & other);
+ bool is_same(const TupleData & other);
- TupleVal * lookup (int field, bool add, bool remove);
- void set_int (int field, int x);
- void set_str (int field, const char * str);
- void set_subtunes (short nsubs, const short * subs);
+ TupleVal * lookup(int field, bool add, bool remove);
+ void set_int(int field, int x);
+ void set_str(int field, const char * str);
+ void set_subtunes(short nsubs, const short * subs);
- static TupleData * ref (TupleData * tuple);
- static void unref (TupleData * tuple);
+ static TupleData * ref(TupleData * tuple);
+ static void unref(TupleData * tuple);
- static TupleData * copy_on_write (TupleData * tuple);
+ static TupleData * copy_on_write(TupleData * tuple);
private:
- static constexpr uint64_t bitmask (int n)
- { return (uint64_t) 1 << n; }
+ static constexpr uint64_t bitmask(int n) { return (uint64_t)1 << n; }
};
/** Ordered table of basic #Tuple field names and their #ValueType.
*/
-static const struct {
+static const struct
+{
const char * name;
Tuple::ValueType type;
int fallback;
@@ -146,15 +145,20 @@ static const struct {
{"formatted-title", Tuple::String, -1},
+ {"description", Tuple::String, -1},
+ {"musicbrainz-id", Tuple::String, -1},
+
/* fallbacks */
{nullptr, Tuple::String, -1},
{nullptr, Tuple::String, -1},
{nullptr, Tuple::String, -1},
};
-static_assert (aud::n_elems (field_info) == n_private_fields, "Update field_data");
+static_assert(aud::n_elems(field_info) == n_private_fields,
+ "Update field_data");
-struct FieldDictEntry {
+struct FieldDictEntry
+{
const char * name;
Tuple::Field field;
};
@@ -171,6 +175,7 @@ static const FieldDictEntry field_dict[] = {
{"composer", Tuple::Composer},
{"copyright", Tuple::Copyright},
{"date", Tuple::Date},
+ {"description", Tuple::Description},
{"file-ext", Tuple::Suffix},
{"file-name", Tuple::Basename},
{"file-path", Tuple::Path},
@@ -183,6 +188,7 @@ static const FieldDictEntry field_dict[] = {
{"gain-track-peak", Tuple::TrackPeak},
{"genre", Tuple::Genre},
{"length", Tuple::Length},
+ {"musicbrainz-id", Tuple::MusicBrainzID},
{"performer", Tuple::Performer},
{"quality", Tuple::Quality},
{"segment-end", Tuple::EndTime},
@@ -191,15 +197,16 @@ static const FieldDictEntry field_dict[] = {
{"subsong-num", Tuple::NumSubtunes},
{"title", Tuple::Title},
{"track-number", Tuple::Track},
- {"year", Tuple::Year}
-};
+ {"year", Tuple::Year}};
-static_assert (aud::n_elems (field_dict) == Tuple::n_fields, "Update field_dict");
+static_assert(aud::n_elems(field_dict) == Tuple::n_fields, "Update field_dict");
-static constexpr bool is_valid_field (int field)
- { return field > Tuple::Invalid && field < Tuple::n_fields; }
+static constexpr bool is_valid_field(int field)
+{
+ return field > Tuple::Invalid && field < Tuple::n_fields;
+}
-static int bitcount (uint64_t x)
+static int bitcount(uint64_t x)
{
/* algorithm from http://en.wikipedia.org/wiki/Hamming_weight */
x -= (x >> 1) & 0x5555555555555555;
@@ -208,77 +215,78 @@ static int bitcount (uint64_t x)
return (x * 0x0101010101010101) >> 56;
}
-static int field_dict_compare (const void * a, const void * b)
+static int field_dict_compare(const void * a, const void * b)
{
- return strcmp (((FieldDictEntry *) a)->name, ((FieldDictEntry *) b)->name);
+ return strcmp(((FieldDictEntry *)a)->name, ((FieldDictEntry *)b)->name);
}
-EXPORT Tuple::Field Tuple::field_by_name (const char * name)
+EXPORT Tuple::Field Tuple::field_by_name(const char * name)
{
FieldDictEntry find = {name, Invalid};
- FieldDictEntry * found = (FieldDictEntry *) bsearch (& find, field_dict,
- n_fields, sizeof (FieldDictEntry), field_dict_compare);
+ FieldDictEntry * found =
+ (FieldDictEntry *)bsearch(&find, field_dict, n_fields,
+ sizeof(FieldDictEntry), field_dict_compare);
return found ? found->field : Invalid;
}
-EXPORT const char * Tuple::field_get_name (Field field)
+EXPORT const char * Tuple::field_get_name(Field field)
{
- assert (is_valid_field (field));
+ assert(is_valid_field(field));
return field_info[field].name;
}
-EXPORT Tuple::ValueType Tuple::field_get_type (Field field)
+EXPORT Tuple::ValueType Tuple::field_get_type(Field field)
{
- assert (is_valid_field (field));
+ assert(is_valid_field(field));
return field_info[field].type;
}
-TupleVal * TupleData::lookup (int field, bool add, bool remove)
+TupleVal * TupleData::lookup(int field, bool add, bool remove)
{
/* calculate number of preceding fields */
- const uint64_t mask = bitmask (field);
- const int pos = bitcount (setmask & (mask - 1));
+ const uint64_t mask = bitmask(field);
+ const int pos = bitcount(setmask & (mask - 1));
if ((setmask & mask))
{
if ((add || remove) && field_info[field].type == Tuple::String)
- vals[pos].str.~String ();
+ vals[pos].str.~String();
if (remove)
{
setmask &= ~mask;
- vals.remove (pos, 1);
+ vals.remove(pos, 1);
return nullptr;
}
- return & vals[pos];
+ return &vals[pos];
}
- if (! (add || remove) && field_info[field].fallback >= 0)
- return lookup (field_info[field].fallback, false, false);
+ if (!(add || remove) && field_info[field].fallback >= 0)
+ return lookup(field_info[field].fallback, false, false);
- if (! add)
+ if (!add)
return nullptr;
setmask |= mask;
- vals.insert (pos, 1);
- return & vals[pos];
+ vals.insert(pos, 1);
+ return &vals[pos];
}
-void TupleData::set_int (int field, int x)
+void TupleData::set_int(int field, int x)
{
- TupleVal * val = lookup (field, true, false);
+ TupleVal * val = lookup(field, true, false);
val->x = x;
}
-void TupleData::set_str (int field, const char * str)
+void TupleData::set_str(int field, const char * str)
{
- TupleVal * val = lookup (field, true, false);
- new (& val->str) String (str);
+ TupleVal * val = lookup(field, true, false);
+ new (&val->str) String(str);
}
-void TupleData::set_subtunes (short nsubs, const short * subs)
+void TupleData::set_subtunes(short nsubs, const short * subs)
{
nsubtunes = nsubs;
@@ -288,76 +296,72 @@ void TupleData::set_subtunes (short nsubs, const short * subs)
if (nsubs && subs)
{
subtunes = new short[nsubs];
- memcpy (subtunes, subs, sizeof subtunes[0] * nsubs);
+ memcpy(subtunes, subs, sizeof subtunes[0] * nsubs);
}
}
-TupleData::TupleData () :
- setmask (0),
- subtunes (nullptr),
- nsubtunes (0),
- state (Tuple::Initial),
- refcount (1) {}
+TupleData::TupleData()
+ : setmask(0), subtunes(nullptr), nsubtunes(0), state(Tuple::Initial),
+ refcount(1)
+{
+}
-TupleData::TupleData (const TupleData & other) :
- setmask (other.setmask),
- subtunes (nullptr),
- nsubtunes (0),
- state (other.state),
- refcount (1)
+TupleData::TupleData(const TupleData & other)
+ : setmask(other.setmask), subtunes(nullptr), nsubtunes(0),
+ state(other.state), refcount(1)
{
- vals.insert (0, other.vals.len ());
+ vals.insert(0, other.vals.len());
- auto get = other.vals.begin ();
- auto set = vals.begin ();
+ auto get = other.vals.begin();
+ auto set = vals.begin();
- for (int f = 0; f < n_private_fields; f ++)
+ for (int f = 0; f < n_private_fields; f++)
{
- if (other.setmask & bitmask (f))
+ if (other.setmask & bitmask(f))
{
if (field_info[f].type == Tuple::String)
- new (& set->str) String (get->str);
+ new (&set->str) String(get->str);
else
set->x = get->x;
- get ++;
- set ++;
+ get++;
+ set++;
}
}
- set_subtunes (other.nsubtunes, other.subtunes);
+ set_subtunes(other.nsubtunes, other.subtunes);
}
-TupleData::~TupleData ()
+TupleData::~TupleData()
{
- auto iter = vals.begin ();
+ auto iter = vals.begin();
- for (int f = 0; f < n_private_fields; f ++)
+ for (int f = 0; f < n_private_fields; f++)
{
- if (setmask & bitmask (f))
+ if (setmask & bitmask(f))
{
if (field_info[f].type == Tuple::String)
- iter->str.~String ();
+ iter->str.~String();
- iter ++;
+ iter++;
}
}
delete[] subtunes;
}
-bool TupleData::is_same (const TupleData & other)
+bool TupleData::is_same(const TupleData & other)
{
if (state != other.state || setmask != other.setmask ||
- nsubtunes != other.nsubtunes || (! subtunes) != (! other.subtunes))
+ nsubtunes != other.nsubtunes || (!subtunes) != (!other.subtunes))
return false;
- auto a = vals.begin ();
- auto b = other.vals.begin ();
+ auto a = vals.begin();
+ auto b = other.vals.begin();
- for (int f = 0; f < n_private_fields; f ++)
+ for (int f = 0; f < n_private_fields; f++)
{
- if (setmask & bitmask (f))
+ if (setmask & bitmask(f))
{
bool same;
@@ -366,211 +370,216 @@ bool TupleData::is_same (const TupleData & other)
else
same = (a->x = b->x);
- if (! same)
+ if (!same)
return false;
- a ++;
- b ++;
+ a++;
+ b++;
}
}
- if (subtunes && memcmp (subtunes, other.subtunes, sizeof subtunes[0] * nsubtunes))
+ if (subtunes &&
+ memcmp(subtunes, other.subtunes, sizeof subtunes[0] * nsubtunes))
return false;
return true;
}
-TupleData * TupleData::ref (TupleData * tuple)
+TupleData * TupleData::ref(TupleData * tuple)
{
if (tuple)
- __sync_fetch_and_add (& tuple->refcount, 1);
+ __sync_fetch_and_add(&tuple->refcount, 1);
return tuple;
}
-void TupleData::unref (TupleData * tuple)
+void TupleData::unref(TupleData * tuple)
{
- if (tuple && ! __sync_sub_and_fetch (& tuple->refcount, 1))
+ if (tuple && !__sync_sub_and_fetch(&tuple->refcount, 1))
delete tuple;
}
-TupleData * TupleData::copy_on_write (TupleData * tuple)
+TupleData * TupleData::copy_on_write(TupleData * tuple)
{
- if (! tuple)
+ if (!tuple)
return new TupleData;
- if (__sync_fetch_and_add (& tuple->refcount, 0) == 1)
+ if (__sync_fetch_and_add(&tuple->refcount, 0) == 1)
return tuple;
- TupleData * copy = new TupleData (* tuple);
- unref (tuple);
+ TupleData * copy = new TupleData(*tuple);
+ unref(tuple);
return copy;
}
-EXPORT Tuple::~Tuple ()
-{
- TupleData::unref (data);
-}
+EXPORT Tuple::~Tuple() { TupleData::unref(data); }
-EXPORT bool Tuple::operator== (const Tuple & b) const
+EXPORT bool Tuple::operator==(const Tuple & b) const
{
if (data == b.data)
return true;
- if (! data || ! b.data)
+ if (!data || !b.data)
return false;
- return data->is_same (* b.data);
+ return data->is_same(*b.data);
}
-EXPORT Tuple Tuple::ref () const
+EXPORT Tuple Tuple::ref() const
{
Tuple tuple;
- tuple.data = TupleData::ref (data);
+ tuple.data = TupleData::ref(data);
return tuple;
}
-EXPORT Tuple::State Tuple::state () const
+EXPORT Tuple::State Tuple::state() const
{
- return data ? (Tuple::State) data->state : Initial;
+ return data ? (Tuple::State)data->state : Initial;
}
-EXPORT void Tuple::set_state (State st)
+EXPORT void Tuple::set_state(State st)
{
- data = TupleData::copy_on_write (data);
+ data = TupleData::copy_on_write(data);
data->state = st;
}
-EXPORT Tuple::ValueType Tuple::get_value_type (Field field) const
+EXPORT Tuple::ValueType Tuple::get_value_type(Field field) const
{
- assert (is_valid_field (field));
+ assert(is_valid_field(field));
const auto & info = field_info[field];
- if (data && (data->is_set (field) || (info.fallback >= 0 && data->is_set (info.fallback))))
+ if (data && (data->is_set(field) ||
+ (info.fallback >= 0 && data->is_set(info.fallback))))
return info.type;
return Empty;
}
-EXPORT int Tuple::get_int (Field field) const
+EXPORT int Tuple::get_int(Field field) const
{
- assert (is_valid_field (field) && field_info[field].type == Int);
+ assert(is_valid_field(field) && field_info[field].type == Int);
- TupleVal * val = data ? data->lookup (field, false, false) : nullptr;
+ TupleVal * val = data ? data->lookup(field, false, false) : nullptr;
return val ? val->x : -1;
}
-EXPORT String Tuple::get_str (Field field) const
+EXPORT String Tuple::get_str(Field field) const
{
- assert (is_valid_field (field) && field_info[field].type == String);
+ assert(is_valid_field(field) && field_info[field].type == String);
- TupleVal * val = data ? data->lookup (field, false, false) : nullptr;
- return val ? val->str : ::String ();
+ TupleVal * val = data ? data->lookup(field, false, false) : nullptr;
+ return val ? val->str : ::String();
}
-EXPORT void Tuple::set_int (Field field, int x)
+EXPORT void Tuple::set_int(Field field, int x)
{
- assert (is_valid_field (field) && field_info[field].type == Int);
+ assert(is_valid_field(field) && field_info[field].type == Int);
- data = TupleData::copy_on_write (data);
- data->set_int (field, x);
+ data = TupleData::copy_on_write(data);
+ data->set_int(field, x);
}
-EXPORT void Tuple::set_str (Field field, const char * str)
+EXPORT void Tuple::set_str(Field field, const char * str)
{
- assert (is_valid_field (field) && field_info[field].type == String);
+ assert(is_valid_field(field) && field_info[field].type == String);
- if (! str)
+ if (!str)
{
- unset (field);
+ unset(field);
return;
}
- data = TupleData::copy_on_write (data);
+ data = TupleData::copy_on_write(data);
- if (g_utf8_validate (str, -1, nullptr))
- data->set_str (field, str);
+ if (g_utf8_validate(str, -1, nullptr))
+ data->set_str(field, str);
else
{
- StringBuf utf8 = str_to_utf8 (str, -1);
- data->set_str (field, utf8 ? (const char *) utf8 : _("(character encoding error)"));
+ StringBuf utf8 = str_to_utf8(str, -1);
+ data->set_str(field, utf8 ? (const char *)utf8
+ : _("(character encoding error)"));
}
}
-EXPORT void Tuple::unset (Field field)
+EXPORT void Tuple::unset(Field field)
{
- assert (is_valid_field (field));
+ assert(is_valid_field(field));
- if (! data)
+ if (!data)
return;
- data = TupleData::copy_on_write (data);
- data->lookup (field, false, true);
+ data = TupleData::copy_on_write(data);
+ data->lookup(field, false, true);
}
-EXPORT void Tuple::set_filename (const char * filename)
+EXPORT void Tuple::set_filename(const char * filename)
{
- assert (filename);
+ assert(filename);
- data = TupleData::copy_on_write (data);
+ data = TupleData::copy_on_write(data);
// stdin is handled as a special case
- if (! strncmp (filename, "stdin://", 8))
+ if (!strncmp(filename, "stdin://", 8))
{
- data->set_str (Basename, _("Standard input"));
+ data->set_str(Basename, _("Standard input"));
return;
}
- const char * base, * ext, * sub;
+ const char *base, *ext, *sub;
int isub;
- uri_parse (filename, & base, & ext, & sub, & isub);
+ uri_parse(filename, &base, &ext, &sub, &isub);
if (base > filename)
- data->set_str (Path, uri_to_display (str_copy (filename, base - filename)));
+ data->set_str(Path,
+ uri_to_display(str_copy(filename, base - filename)));
if (ext > base)
- data->set_str (Basename, str_to_utf8 (str_decode_percent (base, ext - base)));
+ data->set_str(Basename,
+ str_to_utf8(str_decode_percent(base, ext - base)));
if (sub > ext + 1)
- data->set_str (Suffix, str_to_utf8 (str_decode_percent (ext + 1, sub - ext - 1)));
+ data->set_str(Suffix,
+ str_to_utf8(str_decode_percent(ext + 1, sub - ext - 1)));
if (sub[0])
- data->set_int (Subtune, isub);
+ data->set_int(Subtune, isub);
}
-EXPORT void Tuple::set_format (const char * format, int chans, int rate, int brate)
+EXPORT void Tuple::set_format(const char * format, int chans, int rate,
+ int brate)
{
if (format)
- set_str (Codec, format);
+ set_str(Codec, format);
StringBuf buf;
if (chans > 0)
{
if (chans == 1)
- buf = str_copy (_("Mono"));
+ buf = str_copy(_("Mono"));
else if (chans == 2)
- buf = str_copy (_("Stereo"));
+ buf = str_copy(_("Stereo"));
else
- buf = str_printf (dngettext (PACKAGE, "%d channel", "%d channels", chans), chans);
+ buf = str_printf(
+ dngettext(PACKAGE, "%d channel", "%d channels", chans), chans);
if (rate > 0)
- buf.insert (-1, ", ");
+ buf.insert(-1, ", ");
}
if (rate > 0)
- str_append_printf (buf, "%d kHz", rate / 1000);
+ str_append_printf(buf, "%d kHz", rate / 1000);
if (buf[0])
- set_str (Quality, buf);
+ set_str(Quality, buf);
if (brate > 0)
- set_int (Bitrate, brate);
+ set_int(Bitrate, brate);
}
-EXPORT void Tuple::set_subtunes (short n_subtunes, const short * subtunes)
+EXPORT void Tuple::set_subtunes(short n_subtunes, const short * subtunes)
{
- data = TupleData::copy_on_write (data);
- data->set_subtunes (n_subtunes, subtunes);
+ data = TupleData::copy_on_write(data);
+ data->set_subtunes(n_subtunes, subtunes);
}
EXPORT short Tuple::get_n_subtunes() const
@@ -578,102 +587,102 @@ EXPORT short Tuple::get_n_subtunes() const
return data ? data->nsubtunes : 0;
}
-EXPORT short Tuple::get_nth_subtune (short n) const
+EXPORT short Tuple::get_nth_subtune(short n) const
{
- if (! data || n < 0 || n >= data->nsubtunes)
+ if (!data || n < 0 || n >= data->nsubtunes)
return -1;
return data->subtunes ? data->subtunes[n] : 1 + n;
}
-EXPORT void Tuple::set_gain (Field field, Field unit_field, const char * str)
+EXPORT void Tuple::set_gain(Field field, Field unit_field, const char * str)
{
- set_int (field, lround (str_to_double (str) * 1000000));
- set_int (unit_field, 1000000);
+ set_int(field, lround(str_to_double(str) * 1000000));
+ set_int(unit_field, 1000000);
}
/* combining this with get_replay_gain() would be cleaner but would
* require adding a validity flag to ReplayGainInfo, breaking ABI */
-EXPORT bool Tuple::has_replay_gain () const
+EXPORT bool Tuple::has_replay_gain() const
{
- return get_int (GainDivisor) > 0 &&
- (data->is_set (AlbumGain) || data->is_set (TrackGain));
+ return get_int(GainDivisor) > 0 &&
+ (data->is_set(AlbumGain) || data->is_set(TrackGain));
}
-EXPORT ReplayGainInfo Tuple::get_replay_gain () const
+EXPORT ReplayGainInfo Tuple::get_replay_gain() const
{
- ReplayGainInfo gain {};
+ ReplayGainInfo gain{};
- if (! data)
+ if (!data)
return gain;
- int gain_unit = get_int (GainDivisor);
- int peak_unit = get_int (PeakDivisor);
+ int gain_unit = get_int(GainDivisor);
+ int peak_unit = get_int(PeakDivisor);
if (gain_unit > 0)
{
- bool have_album = data->is_set (AlbumGain);
- bool have_track = data->is_set (TrackGain);
+ bool have_album = data->is_set(AlbumGain);
+ bool have_track = data->is_set(TrackGain);
if (have_album)
- gain.album_gain = get_int (AlbumGain) / (float) gain_unit;
+ gain.album_gain = get_int(AlbumGain) / (float)gain_unit;
if (have_track)
- gain.track_gain = get_int (TrackGain) / (float) gain_unit;
+ gain.track_gain = get_int(TrackGain) / (float)gain_unit;
/* fill in missing information if we can */
- if (! have_album && have_track)
+ if (!have_album && have_track)
gain.album_gain = gain.track_gain;
- if (have_album && ! have_track)
+ if (have_album && !have_track)
gain.track_gain = gain.album_gain;
}
if (peak_unit > 0)
{
- bool have_album = data->is_set (AlbumPeak);
- bool have_track = data->is_set (TrackPeak);
+ bool have_album = data->is_set(AlbumPeak);
+ bool have_track = data->is_set(TrackPeak);
if (have_album)
- gain.album_peak = get_int (AlbumPeak) / (float) peak_unit;
+ gain.album_peak = get_int(AlbumPeak) / (float)peak_unit;
if (have_track)
- gain.track_peak = get_int (TrackPeak) / (float) peak_unit;
+ gain.track_peak = get_int(TrackPeak) / (float)peak_unit;
/* fill in missing information if we can */
- if (! have_album && have_track)
+ if (!have_album && have_track)
gain.album_peak = gain.track_peak;
- if (have_album && ! have_track)
+ if (have_album && !have_track)
gain.track_peak = gain.album_peak;
}
return gain;
}
-EXPORT bool Tuple::fetch_stream_info (VFSFile & stream)
+EXPORT bool Tuple::fetch_stream_info(VFSFile & stream)
{
bool updated = false;
int value;
- ::String val = stream.get_metadata ("track-name");
+ ::String val = stream.get_metadata("track-name");
- if (val && val != get_str (Title))
+ if (val && val != get_str(Title))
{
- set_str (Title, val);
+ set_str(Title, val);
updated = true;
}
- val = stream.get_metadata ("stream-name");
+ val = stream.get_metadata("stream-name");
- if (val && val != get_str (Artist))
+ if (val && val != get_str(Artist))
{
- set_str (Artist, val);
+ set_str(Artist, val);
updated = true;
}
- val = stream.get_metadata ("content-bitrate");
- value = val ? atoi (val) / 1000 : 0;
+ val = stream.get_metadata("content-bitrate");
+ value = val ? atoi(val) / 1000 : 0;
- if (value && value != get_int (Bitrate))
+ if (value && value != get_int(Bitrate))
{
- set_int (Bitrate, value);
+ set_int(Bitrate, value);
updated = true;
}
@@ -684,12 +693,12 @@ EXPORT bool Tuple::fetch_stream_info (VFSFile & stream)
* be modified, and the string returned will use the same memory. May return
* nullptr. */
-static char * split_folder (char * path, char sep)
+static char * split_folder(char * path, char sep)
{
char * c;
- while ((c = strrchr (path, sep)))
+ while ((c = strrchr(path, sep)))
{
- * c = 0;
+ *c = 0;
if (c[1])
return c + 1;
}
@@ -701,86 +710,86 @@ static char * split_folder (char * path, char sep)
* "http://some.domain.org/folder/file.mp3" -> "some.domain.org"
* "http://some.stream.fm:8000" -> "some.stream.fm" */
-static const char * find_domain (const char * name)
+static const char * find_domain(const char * name)
{
- if (! strncmp (name, "http://", 7))
+ if (!strncmp(name, "http://", 7))
return name + 7;
- if (! strncmp (name, "https://", 8))
+ if (!strncmp(name, "https://", 8))
return name + 8;
- if (! strncmp (name, "mms://", 6))
+ if (!strncmp(name, "mms://", 6))
return name + 6;
return nullptr;
}
-static StringBuf extract_domain (const char * start)
+static StringBuf extract_domain(const char * start)
{
- StringBuf name = str_copy (start);
+ StringBuf name = str_copy(start);
char * c;
- if ((c = strchr (name, '/')))
- name.resize (c - name);
- if ((c = strchr (name, ':')))
- name.resize (c - name);
- if ((c = strchr (name, '?')))
- name.resize (c - name);
+ if ((c = strchr(name, '/')))
+ name.resize(c - name);
+ if ((c = strchr(name, ':')))
+ name.resize(c - name);
+ if ((c = strchr(name, '?')))
+ name.resize(c - name);
return name;
}
-EXPORT void Tuple::generate_fallbacks ()
+EXPORT void Tuple::generate_fallbacks()
{
- if (! data)
+ if (!data)
return;
- generate_title ();
+ generate_title();
- auto artist = get_str (Artist);
- auto album = get_str (Album);
+ auto artist = get_str(Artist);
+ auto album = get_str(Album);
if (artist && album)
return;
- data = TupleData::copy_on_write (data);
+ data = TupleData::copy_on_write(data);
// use album artist, if present
- if (! artist && (artist = get_str (AlbumArtist)))
+ if (!artist && (artist = get_str(AlbumArtist)))
{
- data->set_str (FallbackArtist, artist);
+ data->set_str(FallbackArtist, artist);
if (album)
return; // nothing left to do
}
- auto filepath = get_str (Path);
- if (! filepath)
+ auto filepath = get_str(Path);
+ if (!filepath)
return;
const char * s;
char sep;
- if (! strcmp (filepath, "cdda://"))
+ if (!strcmp(filepath, "cdda://"))
{
// audio CD:
// use "Audio CD" as the album
- if (! album)
- data->set_str (FallbackAlbum, _("Audio CD"));
+ if (!album)
+ data->set_str(FallbackAlbum, _("Audio CD"));
}
- else if ((s = find_domain (filepath)))
+ else if ((s = find_domain(filepath)))
{
// internet URL:
// use the domain name as the album
- if (! album)
- data->set_str (FallbackAlbum, extract_domain (s));
+ if (!album)
+ data->set_str(FallbackAlbum, extract_domain(s));
}
else
{
// any other URI:
// use the top two path elements as the artist and album
- if ((s = strstr (filepath, "://")))
+ if ((s = strstr(filepath, "://")))
{
s += 3;
sep = '/';
@@ -788,7 +797,7 @@ EXPORT void Tuple::generate_fallbacks ()
else
{
#ifdef _WIN32
- if (g_ascii_isalpha (filepath[0]) && filepath[1] == ':')
+ if (g_ascii_isalpha(filepath[0]) && filepath[1] == ':')
s = filepath + 2;
else
#endif
@@ -797,72 +806,75 @@ EXPORT void Tuple::generate_fallbacks ()
sep = G_DIR_SEPARATOR;
}
- StringBuf buf = str_copy (s);
+ StringBuf buf = str_copy(s);
- char * first = split_folder (buf, sep);
- char * second = (first && first > buf) ? split_folder (buf, sep) : nullptr;
+ char * first = split_folder(buf, sep);
+ char * second =
+ (first && first > buf) ? split_folder(buf, sep) : nullptr;
// skip common strings and avoid duplicates
- for (auto skip : (const char *[]) {"~", "music", artist, album, get_str (Genre)})
+ for (auto skip :
+ (const char *[]){"~", "music", artist, album, get_str(Genre)})
{
- if (first && skip && ! strcmp_nocase (first, skip))
+ if (first && skip && !strcmp_nocase(first, skip))
{
first = second;
second = nullptr;
}
- if (second && skip && ! strcmp_nocase (second, skip))
+ if (second && skip && !strcmp_nocase(second, skip))
second = nullptr;
}
if (first)
{
- if (second && ! artist && ! album)
+ if (second && !artist && !album)
{
- data->set_str (FallbackArtist, second);
- data->set_str (FallbackAlbum, first);
+ data->set_str(FallbackArtist, second);
+ data->set_str(FallbackAlbum, first);
}
else
- data->set_str (artist ? FallbackAlbum : FallbackArtist, first);
+ data->set_str(artist ? FallbackAlbum : FallbackArtist, first);
}
}
}
-EXPORT void Tuple::generate_title ()
+EXPORT void Tuple::generate_title()
{
- if (! data)
+ if (!data)
return;
- auto title = get_str (Title);
+ auto title = get_str(Title);
if (title)
return;
- data = TupleData::copy_on_write (data);
+ data = TupleData::copy_on_write(data);
- auto filepath = get_str (Path);
- if (filepath && ! strcmp (filepath, "cdda://"))
+ auto filepath = get_str(Path);
+ if (filepath && !strcmp(filepath, "cdda://"))
{
// audio CD:
// use "Track N" as the title
- int subtune = get_int (Subtune);
+ int subtune = get_int(Subtune);
if (subtune >= 0)
- data->set_str (FallbackTitle, str_printf (_("Track %d"), subtune));
+ data->set_str(FallbackTitle, str_printf(_("Track %d"), subtune));
}
else
{
- auto filename = get_str (Basename);
- data->set_str (FallbackTitle, filename ? (const char *) filename : _("(unknown title)"));
+ auto filename = get_str(Basename);
+ data->set_str(FallbackTitle,
+ filename ? (const char *)filename : _("(unknown title)"));
}
}
-EXPORT void Tuple::delete_fallbacks ()
+EXPORT void Tuple::delete_fallbacks()
{
- if (! data)
+ if (!data)
return;
- data = TupleData::copy_on_write (data);
- data->lookup (FallbackTitle, false, true);
- data->lookup (FallbackArtist, false, true);
- data->lookup (FallbackAlbum, false, true);
+ data = TupleData::copy_on_write(data);
+ data->lookup(FallbackTitle, false, true);
+ data->lookup(FallbackArtist, false, true);
+ data->lookup(FallbackAlbum, false, true);
}
diff --git a/src/libaudcore/tuple.h b/src/libaudcore/tuple.h
index b7766d6..0ec1ac1 100644
--- a/src/libaudcore/tuple.h
+++ b/src/libaudcore/tuple.h
@@ -1,6 +1,6 @@
/*
* tuple.h
- * Copyright 2007-2013 William Pitcock, Christian Birchinger, Matti Hämäläinen,
+ * Copyright 2007-2013 Ariadne Conill, Christian Birchinger, Matti Hämäläinen,
* Giacomo Lozito, Eugene Zagidullin, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
@@ -39,55 +39,58 @@ public:
/* Smart pointer to the actual TupleData struct.
* Uses create-on-write and copy-on-write. */
- enum State {
- Initial, /* Song info has not yet been read */
- Valid, /* Song info has been successfully read */
- Failed /* Song info could not be read */
+ enum State
+ {
+ Initial, /* Song info has not yet been read */
+ Valid, /* Song info has been successfully read */
+ Failed /* Song info could not be read */
};
- enum Field {
+ enum Field
+ {
Invalid = -1,
- Title = 0, /* Song title */
- Artist, /* Song artist */
- Album, /* Album name */
- AlbumArtist, /* Artist for entire album, if different than song artist */
- Comment, /* Freeform comment */
- Genre, /* Song's genre */
- Year, /* Year of production, performance, etc. */
-
- Composer, /* Composer, if different than artist */
- Performer, /* Performer, if different than artist */
- Copyright, /* Copyright declaration */
- Date, /* Date of production, performance, etc. */
-
- Track, /* Track number */
- Length, /* Track length in milliseconds */
-
- Bitrate, /* Bitrate in kilobits (1000 bits)/sec */
- Codec, /* Codec name, such as "Ogg Vorbis" */
- Quality, /* String representing quality, such as "Stereo, 44 kHz" */
-
- Basename, /* Base filename, not including the folder path */
- Path, /* Folder path, including the trailing "/" */
- Suffix, /* Filename extension, not including the "." */
-
- AudioFile, /* URI of audio file, if different from the nominal URI
- * (e.g. for a cuesheet entry, where the nominal URI
- * points to the .cue file) */
-
- Subtune, /* Index number of subtune */
- NumSubtunes, /* Total number of subtunes in the file */
-
- StartTime, /* Playback start point (used for cuesheets) */
- EndTime, /* Playback end point (used for cuesheets) */
-
- /* Preserving replay gain information accurately is a challenge since there
- * are several differents formats around. We use an integer fraction, with
- * the denominator stored in the *Divisor fields. For example, if AlbumGain
- * is 512 and GainDivisor is 256, then the album gain is +2 dB. If TrackPeak
- * is 787 and PeakDivisor is 1000, then the peak volume is 0.787 in a -1.0 to
- * 1.0 range. */
+ Title = 0, /* Song title */
+ Artist, /* Song artist */
+ Album, /* Album name */
+ AlbumArtist, /* Artist for entire album, if different than song artist
+ */
+ Comment, /* Freeform comment */
+ Genre, /* Song's genre */
+ Year, /* Year of production, performance, etc. */
+
+ Composer, /* Composer, if different than artist */
+ Performer, /* Performer, if different than artist */
+ Copyright, /* Copyright declaration */
+ Date, /* Date of production, performance, etc. */
+
+ Track, /* Track number */
+ Length, /* Track length in milliseconds */
+
+ Bitrate, /* Bitrate in kilobits (1000 bits)/sec */
+ Codec, /* Codec name, such as "Ogg Vorbis" */
+ Quality, /* String representing quality, such as "Stereo, 44 kHz" */
+
+ Basename, /* Base filename, not including the folder path */
+ Path, /* Folder path, including the trailing "/" */
+ Suffix, /* Filename extension, not including the "." */
+
+ AudioFile, /* URI of audio file, if different from the nominal URI
+ * (e.g. for a cuesheet entry, where the nominal URI
+ * points to the .cue file) */
+
+ Subtune, /* Index number of subtune */
+ NumSubtunes, /* Total number of subtunes in the file */
+
+ StartTime, /* Playback start point (used for cuesheets) */
+ EndTime, /* Playback end point (used for cuesheets) */
+
+ /* Preserving replay gain information accurately is a challenge since
+ * there are several differents formats around. We use an integer
+ * fraction, with the denominator stored in the *Divisor fields. For
+ * example, if AlbumGain is 512 and GainDivisor is 256, then the album
+ * gain is +2 dB. If TrackPeak is 787 and PeakDivisor is 1000, then the
+ * peak volume is 0.787 in a -1.0 to 1.0 range. */
AlbumGain,
AlbumPeak,
TrackGain,
@@ -95,79 +98,80 @@ public:
GainDivisor,
PeakDivisor,
- /* Title formatted for display; input plugins do not need to set this field */
+ /* Title formatted for display; input plugins do not need to set this
+ field */
FormattedTitle,
+ /* TODO: reorder these at next ABI break! */
+ Description, /* Track description */
+ MusicBrainzID, /* MusicBrainz identifier */
+
n_fields
};
- typedef aud::range<Field, Field (0), Field (n_fields - 1)> all_fields;
+ typedef aud::range<Field, Field(0), Field(n_fields - 1)> all_fields;
- enum ValueType {
+ enum ValueType
+ {
String,
Int,
Empty
};
- static Field field_by_name (const char * name);
- static const char * field_get_name (Field field);
- static ValueType field_get_type (Field field);
+ static Field field_by_name(const char * name);
+ static const char * field_get_name(Field field);
+ static ValueType field_get_type(Field field);
+
+ constexpr Tuple() : data(nullptr) {}
- constexpr Tuple () :
- data (nullptr) {}
+ ~Tuple();
- ~Tuple ();
+ Tuple(Tuple && b) : data(b.data) { b.data = nullptr; }
- Tuple (Tuple && b) :
- data (b.data)
+ Tuple & operator=(Tuple && b)
{
- b.data = nullptr;
+ return aud::move_assign(*this, std::move(b));
}
- Tuple & operator= (Tuple && b)
- { return aud::move_assign (* this, std::move (b)); }
-
- bool operator== (const Tuple & b) const;
- bool operator!= (const Tuple & b) const
- { return ! operator== (b); }
+ bool operator==(const Tuple & b) const;
+ bool operator!=(const Tuple & b) const { return !operator==(b); }
- Tuple ref () const;
+ Tuple ref() const;
/* Gets/sets the state of the song info. Before setting the state to Valid,
* you should ensure that, at a minimum, set_filename() has been called. */
- State state () const;
- void set_state (State st);
+ State state() const;
+ void set_state(State st);
/* Returns the value type of a field if set, otherwise Empty. */
- ValueType get_value_type (Field field) const;
+ ValueType get_value_type(Field field) const;
/* Convenience functions */
- bool valid () const
- { return state () == Valid; }
- bool is_set (Field field) const
- { return get_value_type (field) != Empty; }
+ bool valid() const { return state() == Valid; }
+ bool is_set(Field field) const { return get_value_type(field) != Empty; }
/* Returns the integer value of a field if set, otherwise -1. If you need
* to distinguish between a value of -1 and an unset value, use
* get_value_type(). */
- int get_int (Field field) const;
+ int get_int(Field field) const;
/* Returns the string value of a field if set, otherwise null. */
- ::String get_str (Field field) const;
+ ::String get_str(Field field) const;
/* Sets a field to the integer value <x>. */
- void set_int (Field field, int x);
+ void set_int(Field field, int x);
/* Sets a field to the string value <str>. If <str> is not valid UTF-8, it
* will be converted according to the user's character set detection rules.
* Equivalent to unset() if <str> is null. */
- void set_str (Field field, const char * str);
+ void set_str(Field field, const char * str);
/* Clears any value that a field is currently set to. */
- void unset (Field field);
+ void unset(Field field);
- /* Parses the URI <filename> and sets Basename, Path, Suffix, and Subtune accordingly. */
- void set_filename (const char * filename);
+ /* Parses the URI <filename> and sets Basename, Path, Suffix, and Subtune
+ * accordingly. */
+ void set_filename(const char * filename);
/* Fills in format-related fields (specifically Codec, Quality,
* and Bitrate). Plugins should use this function instead of setting
@@ -175,44 +179,45 @@ public:
* formats. <format> should be a brief description such as "Ogg Vorbis",
* "MPEG-1 layer 3", "Audio CD", and so on. <samplerate> is in Hertz.
* <bitrate> is in (decimal) kbps. */
- void set_format (const char * format, int channels, int samplerate, int bitrate);
+ void set_format(const char * format, int channels, int samplerate,
+ int bitrate);
/* In addition to the normal fields, tuples contain an integer array of
* subtune ID numbers. This function sets that array. It also sets
* NumSubtunes to the value <n_subtunes>. */
- void set_subtunes (short n_subtunes, const short * subtunes);
+ void set_subtunes(short n_subtunes, const short * subtunes);
/* Returns the length of the subtune array. If the array has not been set,
* returns zero. Note that if NumSubtunes is changed after
* set_subtunes() is called, this function returns the value <n_subtunes>
* passed to set_subtunes(), not the value of NumSubtunes. */
- short get_n_subtunes () const;
+ short get_n_subtunes() const;
/* Returns the <n>th member of the subtune array. */
- short get_nth_subtune (short n) const;
+ short get_nth_subtune(short n) const;
/* Sets a Replay Gain field pair from a decimal string. */
- void set_gain (Field field, Field unit_field, const char * str);
+ void set_gain(Field field, Field unit_field, const char * str);
/* Returns true if minimal ReplayGainInfo is present. */
- bool has_replay_gain () const;
+ bool has_replay_gain() const;
/* Fills ReplayGainInfo struct from various fields. */
- ReplayGainInfo get_replay_gain () const;
+ ReplayGainInfo get_replay_gain() const;
/* Set various fields based on the ICY metadata of <stream>. Returns true
* if any fields were changed. */
- bool fetch_stream_info (VFSFile & stream);
+ bool fetch_stream_info(VFSFile & stream);
/* Guesses the song title, artist, and album, if not already set, from the
* filename. */
- void generate_fallbacks ();
+ void generate_fallbacks();
/* Guesses only the song title, if not already set, from the filename. */
- void generate_title ();
+ void generate_title();
/* Removes guesses made by generate_fallbacks(). This function should be
* called, for example, before writing a song tag from the tuple. */
- void delete_fallbacks ();
+ void delete_fallbacks();
private:
TupleData * data;
@@ -225,8 +230,7 @@ struct PlaylistAddItem
Tuple tuple;
PluginHandle * decoder;
- PlaylistAddItem copy () const
- { return {filename, tuple.ref (), decoder}; }
+ PlaylistAddItem copy() const { return {filename, tuple.ref(), decoder}; }
};
#endif /* LIBAUDCORE_TUPLE_H */
diff --git a/src/libaudcore/util.cc b/src/libaudcore/util.cc
index 4d92ded..96390c9 100644
--- a/src/libaudcore/util.cc
+++ b/src/libaudcore/util.cc
@@ -1,6 +1,6 @@
/*
* util.c
- * Copyright 2009-2013 John Lindgren and Michał Lipski
+ * Copyright 2009-2019 John Lindgren and Michał Lipski
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -18,9 +18,10 @@
*/
#include "internal.h"
+#include "visualizer.h"
#include <errno.h>
-#include <pthread.h>
+#include <math.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
@@ -29,87 +30,91 @@
#include "audstrings.h"
#include "runtime.h"
+#include "threads.h"
-const char * get_home_utf8 ()
+const char * get_home_utf8()
{
- static pthread_once_t once = PTHREAD_ONCE_INIT;
+ static std::once_flag once;
static char * home_utf8;
- auto init = [] ()
- { home_utf8 = g_filename_to_utf8 (g_get_home_dir (), -1, nullptr, nullptr, nullptr); };
+ auto init = []() {
+ home_utf8 =
+ g_filename_to_utf8(g_get_home_dir(), -1, nullptr, nullptr, nullptr);
+ };
- pthread_once (& once, init);
+ std::call_once(once, init);
return home_utf8;
}
-bool dir_foreach (const char * path, DirForeachFunc func, void * user)
+bool dir_foreach(const char * path, DirForeachFunc func, void * user)
{
- GDir * dir = g_dir_open (path, 0, nullptr);
- if (! dir)
+ GDir * dir = g_dir_open(path, 0, nullptr);
+ if (!dir)
return false;
const char * name;
- while ((name = g_dir_read_name (dir)))
+ while ((name = g_dir_read_name(dir)))
{
- if (func (filename_build ({path, name}), name, user))
+ if (func(filename_build({path, name}), name, user))
break;
}
- g_dir_close (dir);
+ g_dir_close(dir);
return true;
}
-String write_temp_file (const void * data, int64_t len)
+String write_temp_file(const void * data, int64_t len)
{
- StringBuf name = filename_build ({g_get_tmp_dir (), "audacious-temp-XXXXXX"});
+ StringBuf name = filename_build({g_get_tmp_dir(), "audacious-temp-XXXXXX"});
- int handle = g_mkstemp (name);
+ int handle = g_mkstemp(name);
if (handle < 0)
{
- AUDERR ("Error creating temporary file: %s\n", strerror (errno));
- return String ();
+ AUDERR("Error creating temporary file: %s\n", strerror(errno));
+ return String();
}
while (len)
{
- int64_t written = write (handle, data, len);
+ int64_t written = write(handle, data, len);
if (written < 0)
{
- AUDERR ("Error writing %s: %s\n", (const char *) name, strerror (errno));
- close (handle);
- return String ();
+ AUDERR("Error writing %s: %s\n", (const char *)name,
+ strerror(errno));
+ close(handle);
+ return String();
}
- data = (char *) data + written;
+ data = (char *)data + written;
len -= written;
}
- if (close (handle) < 0)
+ if (close(handle) < 0)
{
- AUDERR ("Error closing %s: %s\n", (const char *) name, strerror (errno));
- return String ();
+ AUDERR("Error closing %s: %s\n", (const char *)name, strerror(errno));
+ return String();
}
- return String (name);
+ return String(name);
}
-bool same_basename (const char * a, const char * b)
+bool same_basename(const char * a, const char * b)
{
- const char * dot_a = strrchr (a, '.');
- const char * dot_b = strrchr (b, '.');
- int len_a = dot_a ? dot_a - a : strlen (a);
- int len_b = dot_b ? dot_b - b : strlen (b);
+ const char * dot_a = strrchr(a, '.');
+ const char * dot_b = strrchr(b, '.');
+ int len_a = dot_a ? dot_a - a : strlen(a);
+ int len_b = dot_b ? dot_b - b : strlen(b);
- return len_a == len_b && ! strcmp_nocase (a, b, len_a);
+ return len_a == len_b && !strcmp_nocase(a, b, len_a);
}
-const char * last_path_element (const char * path)
+const char * last_path_element(const char * path)
{
- const char * slash = strrchr (path, G_DIR_SEPARATOR);
+ const char * slash = strrchr(path, G_DIR_SEPARATOR);
return (slash && slash[1]) ? slash + 1 : nullptr;
}
-void cut_path_element (char * path, int pos)
+void cut_path_element(char * path, int pos)
{
#ifdef _WIN32
if (pos > 3)
@@ -121,31 +126,32 @@ void cut_path_element (char * path, int pos)
path[pos] = 0; /* leave [drive letter and] leading slash */
}
-bool is_cuesheet_entry (const char * filename)
+bool is_cuesheet_entry(const char * filename)
{
- const char * ext, * sub;
- uri_parse (filename, nullptr, & ext, & sub, nullptr);
- return sub[0] && sub - ext == 4 && ! strcmp_nocase (ext, ".cue", 4);
+ const char *ext, *sub;
+ uri_parse(filename, nullptr, &ext, &sub, nullptr);
+ return sub[0] && sub - ext == 4 && !strcmp_nocase(ext, ".cue", 4);
}
-bool is_subtune (const char * filename)
+bool is_subtune(const char * filename)
{
const char * sub;
- uri_parse (filename, nullptr, nullptr, & sub, nullptr);
+ uri_parse(filename, nullptr, nullptr, &sub, nullptr);
return sub[0];
}
-StringBuf strip_subtune (const char * filename)
+StringBuf strip_subtune(const char * filename)
{
const char * sub;
- uri_parse (filename, nullptr, nullptr, & sub, nullptr);
- return str_copy (filename, sub - filename);
+ uri_parse(filename, nullptr, nullptr, &sub, nullptr);
+ return str_copy(filename, sub - filename);
}
/* Thomas Wang's 32-bit mix function. See:
- * http://web.archive.org/web/20070307172248/http://www.concentric.net/~Ttwang/tech/inthash.htm */
+ * http://web.archive.org/web/20070307172248/http://www.concentric.net/~Ttwang/tech/inthash.htm
+ */
-unsigned int32_hash (unsigned val)
+unsigned int32_hash(unsigned val)
{
val = ~val + (val << 15);
val = val ^ (val >> 12);
@@ -156,9 +162,42 @@ unsigned int32_hash (unsigned val)
return val;
}
-unsigned ptr_hash (const void * ptr)
+unsigned ptr_hash(const void * ptr)
+{
+ unsigned addr_low = (uint64_t)(uintptr_t)ptr;
+ unsigned addr_high = (uint64_t)(uintptr_t)ptr >> 32;
+ return int32_hash(addr_low + addr_high);
+}
+
+EXPORT void Visualizer::compute_log_xscale(float * xscale, int bands)
+{
+ for (int i = 0; i <= bands; i++)
+ xscale[i] = powf(256, (float)i / bands) - 0.5f;
+}
+
+EXPORT float Visualizer::compute_freq_band(const float * freq,
+ const float * xscale, int band,
+ int bands)
{
- unsigned addr_low = (uint64_t) (uintptr_t) ptr;
- unsigned addr_high = (uint64_t) (uintptr_t) ptr >> 32;
- return int32_hash (addr_low + addr_high);
+ int a = ceilf(xscale[band]);
+ int b = floorf(xscale[band + 1]);
+ float n = 0;
+
+ if (b < a)
+ n += freq[b] * (xscale[band + 1] - xscale[band]);
+ else
+ {
+ if (a > 0)
+ n += freq[a - 1] * (a - xscale[band]);
+ for (; a < b; a++)
+ n += freq[a];
+ if (b < 256)
+ n += freq[b] * (xscale[band + 1] - b);
+ }
+
+ /* fudge factor to make the graph have the same overall height as a
+ 12-band one no matter how many bands there are */
+ n *= (float)bands / 12;
+
+ return 20 * log10f(n);
}
diff --git a/src/libaudcore/vfs.cc b/src/libaudcore/vfs.cc
index ccbd1aa..2005e54 100644
--- a/src/libaudcore/vfs.cc
+++ b/src/libaudcore/vfs.cc
@@ -1,6 +1,6 @@
/*
* vfs.c
- * Copyright 2006-2013 William Pitcock, Daniel Barkalow, Ralf Ertzinger,
+ * Copyright 2006-2013 Ariadne Conill, Daniel Barkalow, Ralf Ertzinger,
* Yoshiki Yazawa, Matti Hämäläinen, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
@@ -37,24 +37,24 @@
static LocalTransport local_transport;
static StdinTransport stdin_transport;
-static TransportPlugin * lookup_transport (const char * filename,
- String & error, bool * custom_input = nullptr)
+static TransportPlugin * lookup_transport(const char * filename, String & error,
+ bool * custom_input = nullptr)
{
- StringBuf scheme = uri_get_scheme (filename);
+ StringBuf scheme = uri_get_scheme(filename);
- if (! scheme || ! strcmp (scheme, "file"))
- return & local_transport;
- if (! strcmp (scheme, "stdin"))
- return & stdin_transport;
+ if (!scheme || !strcmp(scheme, "file"))
+ return &local_transport;
+ if (!strcmp(scheme, "stdin"))
+ return &stdin_transport;
- for (PluginHandle * plugin : aud_plugin_list (PluginType::Transport))
+ for (PluginHandle * plugin : aud_plugin_list(PluginType::Transport))
{
- if (! aud_plugin_get_enabled (plugin))
+ if (!aud_plugin_get_enabled(plugin))
continue;
- if (transport_plugin_has_scheme (plugin, scheme))
+ if (transport_plugin_has_scheme(plugin, scheme))
{
- auto tp = (TransportPlugin *) aud_plugin_get_header (plugin);
+ auto tp = (TransportPlugin *)aud_plugin_get_header(plugin);
if (tp)
return tp;
}
@@ -62,21 +62,21 @@ static TransportPlugin * lookup_transport (const char * filename,
if (custom_input)
{
- for (PluginHandle * plugin : aud_plugin_list (PluginType::Input))
+ for (PluginHandle * plugin : aud_plugin_list(PluginType::Input))
{
- if (! aud_plugin_get_enabled (plugin))
+ if (!aud_plugin_get_enabled(plugin))
continue;
- if (input_plugin_has_key (plugin, InputKey::Scheme, scheme))
+ if (input_plugin_has_key(plugin, InputKey::Scheme, scheme))
{
- * custom_input = true;
+ *custom_input = true;
return nullptr;
}
}
}
- AUDERR ("Unknown URI scheme: %s://\n", (const char *) scheme);
- error = String (_("Unknown URI scheme"));
+ AUDERR("Unknown URI scheme: %s://\n", (const char *)scheme);
+ error = String(_("Unknown URI scheme"));
return nullptr;
}
@@ -88,29 +88,29 @@ static TransportPlugin * lookup_transport (const char * filename,
* @param mode The preferred access privileges (not guaranteed).
* @return On success, a #VFSFile object representing the stream.
*/
-EXPORT VFSFile::VFSFile (const char * filename, const char * mode)
+EXPORT VFSFile::VFSFile(const char * filename, const char * mode)
{
- auto tp = lookup_transport (filename, m_error);
- if (! tp)
+ auto tp = lookup_transport(filename, m_error);
+ if (!tp)
return;
- VFSImpl * impl = tp->fopen (strip_subtune (filename), mode, m_error);
- if (! impl)
+ VFSImpl * impl = tp->fopen(strip_subtune(filename), mode, m_error);
+ if (!impl)
return;
/* enable buffering for read-only handles */
- if (mode[0] == 'r' && ! strchr (mode, '+'))
- impl = new ProbeBuffer (filename, impl);
+ if (mode[0] == 'r' && !strchr(mode, '+'))
+ impl = new ProbeBuffer(filename, impl);
- AUDINFO ("<%p> open (mode %s) %s\n", impl, mode, filename);
- m_filename = String (filename);
- m_impl.capture (impl);
+ AUDINFO("<%p> open (mode %s) %s\n", impl, mode, filename);
+ m_filename = String(filename);
+ m_impl.capture(impl);
}
-EXPORT VFSFile VFSFile::tmpfile ()
+EXPORT VFSFile VFSFile::tmpfile()
{
VFSFile file;
- file.m_impl.capture (vfs_tmpfile (file.m_error));
+ file.m_impl.capture(vfs_tmpfile(file.m_error));
return file;
}
@@ -123,12 +123,12 @@ EXPORT VFSFile VFSFile::tmpfile ()
* @param file #VFSFile object that represents the VFS stream.
* @return The number of elements succesfully read.
*/
-EXPORT int64_t VFSFile::fread (void * ptr, int64_t size, int64_t nmemb)
+EXPORT int64_t VFSFile::fread(void * ptr, int64_t size, int64_t nmemb)
{
- int64_t readed = m_impl->fread (ptr, size, nmemb);
+ int64_t readed = m_impl->fread(ptr, size, nmemb);
- AUDDBG ("<%p> read %" PRId64 " elements of size %" PRId64 " = %" PRId64 "\n",
- m_impl.get (), nmemb, size, readed);
+ AUDDBG("<%p> read %" PRId64 " elements of size %" PRId64 " = %" PRId64 "\n",
+ m_impl.get(), nmemb, size, readed);
return readed;
}
@@ -142,12 +142,13 @@ EXPORT int64_t VFSFile::fread (void * ptr, int64_t size, int64_t nmemb)
* @param file #VFSFile object that represents the VFS stream.
* @return The number of elements succesfully written.
*/
-EXPORT int64_t VFSFile::fwrite (const void * ptr, int64_t size, int64_t nmemb)
+EXPORT int64_t VFSFile::fwrite(const void * ptr, int64_t size, int64_t nmemb)
{
- int64_t written = m_impl->fwrite (ptr, size, nmemb);
+ int64_t written = m_impl->fwrite(ptr, size, nmemb);
- AUDDBG ("<%p> write %" PRId64 " elements of size %" PRId64 " = %" PRId64 "\n",
- m_impl.get (), nmemb, size, written);
+ AUDDBG("<%p> write %" PRId64 " elements of size %" PRId64 " = %" PRId64
+ "\n",
+ m_impl.get(), nmemb, size, written);
return written;
}
@@ -165,16 +166,19 @@ EXPORT int64_t VFSFile::fwrite (const void * ptr, int64_t size, int64_t nmemb)
* @param whence Type of the seek: SEEK_CUR, SEEK_SET or SEEK_END.
* @return On success, 0. Otherwise, -1.
*/
-EXPORT int VFSFile::fseek (int64_t offset, VFSSeekType whence)
+EXPORT int VFSFile::fseek(int64_t offset, VFSSeekType whence)
{
- AUDDBG ("<%p> seek to %" PRId64 " from %s\n", m_impl.get (), offset,
- whence == VFS_SEEK_CUR ? "current" : whence == VFS_SEEK_SET ? "beginning" :
- whence == VFS_SEEK_END ? "end" : "invalid");
-
- if (m_impl->fseek (offset, whence) == 0)
+ AUDDBG("<%p> seek to %" PRId64 " from %s\n", m_impl.get(), offset,
+ whence == VFS_SEEK_CUR
+ ? "current"
+ : whence == VFS_SEEK_SET
+ ? "beginning"
+ : whence == VFS_SEEK_END ? "end" : "invalid");
+
+ if (m_impl->fseek(offset, whence) == 0)
return 0;
- AUDDBG ("<%p> seek failed!\n", m_impl.get ());
+ AUDDBG("<%p> seek failed!\n", m_impl.get());
return -1;
}
@@ -185,11 +189,11 @@ EXPORT int VFSFile::fseek (int64_t offset, VFSSeekType whence)
* @param file #VFSFile object that represents the VFS stream.
* @return On success, the current position. Otherwise, -1.
*/
-EXPORT int64_t VFSFile::ftell ()
+EXPORT int64_t VFSFile::ftell()
{
- int64_t told = m_impl->ftell ();
+ int64_t told = m_impl->ftell();
- AUDDBG ("<%p> tell = %" PRId64 "\n", m_impl.get (), told);
+ AUDDBG("<%p> tell = %" PRId64 "\n", m_impl.get(), told);
return told;
}
@@ -198,13 +202,14 @@ EXPORT int64_t VFSFile::ftell ()
* Returns whether or not the VFS stream has reached EOF.
*
* @param file #VFSFile object that represents the VFS stream.
- * @return On success, whether or not the VFS stream is at EOF. Otherwise, false.
+ * @return On success, whether or not the VFS stream is at EOF. Otherwise,
+ * false.
*/
-EXPORT bool VFSFile::feof ()
+EXPORT bool VFSFile::feof()
{
- bool eof = m_impl->feof ();
+ bool eof = m_impl->feof();
- AUDDBG ("<%p> eof = %s\n", m_impl.get (), eof ? "yes" : "no");
+ AUDDBG("<%p> eof = %s\n", m_impl.get(), eof ? "yes" : "no");
return eof;
}
@@ -216,26 +221,26 @@ EXPORT bool VFSFile::feof ()
* @param length The length to truncate at.
* @return On success, 0. Otherwise, -1.
*/
-EXPORT int VFSFile::ftruncate (int64_t length)
+EXPORT int VFSFile::ftruncate(int64_t length)
{
- AUDDBG ("<%p> truncate to %" PRId64 "\n", m_impl.get (), length);
+ AUDDBG("<%p> truncate to %" PRId64 "\n", m_impl.get(), length);
- if (m_impl->ftruncate (length) == 0)
+ if (m_impl->ftruncate(length) == 0)
return 0;
- AUDDBG ("<%p> truncate failed!\n", m_impl.get ());
+ AUDDBG("<%p> truncate failed!\n", m_impl.get());
return -1;
}
-EXPORT int VFSFile::fflush ()
+EXPORT int VFSFile::fflush()
{
- AUDDBG ("<%p> flush\n", m_impl.get ());
+ AUDDBG("<%p> flush\n", m_impl.get());
- if (m_impl->fflush () == 0)
+ if (m_impl->fflush() == 0)
return 0;
- AUDDBG ("<%p> flush failed!\n", m_impl.get ());
+ AUDDBG("<%p> flush failed!\n", m_impl.get());
return -1;
}
@@ -246,11 +251,11 @@ EXPORT int VFSFile::fflush ()
* @param file #VFSFile object that represents the VFS stream.
* @return On success, the size of the file in bytes. Otherwise, -1.
*/
-EXPORT int64_t VFSFile::fsize ()
+EXPORT int64_t VFSFile::fsize()
{
- int64_t size = m_impl->fsize ();
+ int64_t size = m_impl->fsize();
- AUDDBG ("<%p> size = %" PRId64 "\n", m_impl.get (), size);
+ AUDDBG("<%p> size = %" PRId64 "\n", m_impl.get(), size);
return size;
}
@@ -262,76 +267,76 @@ EXPORT int64_t VFSFile::fsize ()
* @param field The string constant field name to get.
* @return On success, a copy of the value of the field. Otherwise, nullptr.
*/
-EXPORT String VFSFile::get_metadata (const char * field)
+EXPORT String VFSFile::get_metadata(const char * field)
{
- return m_impl->get_metadata (field);
+ return m_impl->get_metadata(field);
}
-EXPORT void VFSFile::set_limit_to_buffer (bool limit)
+EXPORT void VFSFile::set_limit_to_buffer(bool limit)
{
- auto buffer = dynamic_cast<ProbeBuffer *> (m_impl.get ());
+ auto buffer = dynamic_cast<ProbeBuffer *>(m_impl.get());
if (buffer)
- buffer->set_limit_to_buffer (limit);
+ buffer->set_limit_to_buffer(limit);
else
- AUDERR ("<%p> buffering not supported!\n", m_impl.get ());
+ AUDERR("<%p> buffering not supported!\n", m_impl.get());
}
-EXPORT Index<char> VFSFile::read_all ()
+EXPORT Index<char> VFSFile::read_all()
{
constexpr int maxbuf = 16777216;
constexpr int pagesize = 4096;
Index<char> buf;
- int64_t size = fsize ();
- int64_t pos = ftell ();
+ int64_t size = fsize();
+ int64_t pos = ftell();
if (size >= 0 && pos >= 0 && pos <= size)
{
- buf.insert (0, aud::min (size - pos, (int64_t) maxbuf));
- size = fread (buf.begin (), 1, buf.len ());
+ buf.insert(0, aud::min(size - pos, (int64_t)maxbuf));
+ size = fread(buf.begin(), 1, buf.len());
}
else
{
size = 0;
- buf.insert (0, pagesize);
+ buf.insert(0, pagesize);
int64_t readsize;
- while ((readsize = fread (& buf[size], 1, buf.len () - size)))
+ while ((readsize = fread(&buf[size], 1, buf.len() - size)))
{
size += readsize;
- if (size == buf.len ())
+ if (size == buf.len())
{
- if (buf.len () > maxbuf - pagesize)
+ if (buf.len() > maxbuf - pagesize)
break;
- buf.insert (-1, pagesize);
+ buf.insert(-1, pagesize);
}
}
}
- buf.remove (size, -1);
+ buf.remove(size, -1);
return buf;
}
-EXPORT bool VFSFile::copy_from (VFSFile & source, int64_t size)
+EXPORT bool VFSFile::copy_from(VFSFile & source, int64_t size)
{
constexpr int bufsize = 65536;
Index<char> buf;
- buf.resize (bufsize);
+ buf.resize(bufsize);
while (size < 0 || size > 0)
{
int64_t to_read = (size > 0 && size < bufsize) ? size : bufsize;
- int64_t readsize = source.fread (buf.begin (), 1, to_read);
+ int64_t readsize = source.fread(buf.begin(), 1, to_read);
if (size > 0)
size -= readsize;
- if (fwrite (buf.begin (), 1, readsize) != readsize)
+ if (fwrite(buf.begin(), 1, readsize) != readsize)
return false;
if (readsize < to_read)
@@ -340,80 +345,104 @@ EXPORT bool VFSFile::copy_from (VFSFile & source, int64_t size)
/* if a fixed size was requested, return true only if all the data was read.
* otherwise, return true only if the end of the source file was reached. */
- return size == 0 || (size < 0 && source.feof ());
+ return size == 0 || (size < 0 && source.feof());
}
-EXPORT bool VFSFile::replace_with (VFSFile & source)
+EXPORT bool VFSFile::replace_with(VFSFile & source)
{
- if (source.fseek (0, VFS_SEEK_SET) < 0)
+ if (source.fseek(0, VFS_SEEK_SET) < 0)
return false;
- if (fseek (0, VFS_SEEK_SET) < 0)
+ if (fseek(0, VFS_SEEK_SET) < 0)
return false;
- if (ftruncate (0) < 0)
+ if (ftruncate(0) < 0)
return false;
- return copy_from (source, -1);
+ return copy_from(source, -1);
}
-EXPORT bool VFSFile::test_file (const char * filename, VFSFileTest test)
+EXPORT bool VFSFile::test_file(const char * filename, VFSFileTest test)
{
- String error; /* discarded */
- return test_file (filename, test, error) == test;
+ String error; /* discarded */
+ return test_file(filename, test, error) == test;
}
-EXPORT VFSFileTest VFSFile::test_file (const char * filename, VFSFileTest test, String & error)
+EXPORT VFSFileTest VFSFile::test_file(const char * filename, VFSFileTest test,
+ String & error)
{
bool custom_input = false;
- auto tp = lookup_transport (filename, error, & custom_input);
+ auto tp = lookup_transport(filename, error, &custom_input);
/* for URI schemes handled by input plugins, return 0, indicating that we
* have no way of testing file attributes */
if (custom_input)
- return VFSFileTest (0);
+ return VFSFileTest(0);
/* for unsupported URI schemes, return VFS_NO_ACCESS */
- if (! tp)
- return VFSFileTest (test & VFS_NO_ACCESS);
+ if (!tp)
+ return VFSFileTest(test & VFS_NO_ACCESS);
- return tp->test_file (strip_subtune (filename), test, error);
+ return tp->test_file(strip_subtune(filename), test, error);
}
-EXPORT Index<String> VFSFile::read_folder (const char * filename, String & error)
+EXPORT Index<String> VFSFile::read_folder(const char * filename, String & error)
{
- auto tp = lookup_transport (filename, error);
- return tp ? tp->read_folder (filename, error) : Index<String> ();
+ auto tp = lookup_transport(filename, error);
+ return tp ? tp->read_folder(filename, error) : Index<String>();
}
-EXPORT Index<char> VFSFile::read_file (const char * filename, VFSReadOptions options)
+EXPORT Index<char> VFSFile::read_file(const char * filename,
+ VFSReadOptions options)
{
Index<char> text;
- if (! (options & VFS_IGNORE_MISSING) || test_file (filename, VFS_EXISTS))
+ if (!(options & VFS_IGNORE_MISSING) || test_file(filename, VFS_EXISTS))
{
- VFSFile file (filename, "r");
+ VFSFile file(filename, "r");
if (file)
- text = file.read_all ();
+ text = file.read_all();
else
- AUDERR ("Cannot open %s for reading: %s\n", filename, file.error ());
+ AUDERR("Cannot open %s for reading: %s\n", filename, file.error());
}
if ((options & VFS_APPEND_NULL))
- text.append (0);
+ text.append(0);
return text;
}
-EXPORT bool VFSFile::write_file (const char * filename, const void * data, int64_t len)
+EXPORT bool VFSFile::write_file(const char * filename, const void * data,
+ int64_t len)
{
bool written = false;
- VFSFile file (filename, "w");
+ VFSFile file(filename, "w");
if (file)
- written = (file.fwrite (data, 1, len) == len && file.fflush () == 0);
+ written = (file.fwrite(data, 1, len) == len && file.fflush() == 0);
else
- AUDERR ("Cannot open %s for writing: %s\n", filename, file.error ());
+ AUDERR("Cannot open %s for writing: %s\n", filename, file.error());
return written;
}
+
+EXPORT Index<const char *> VFSFile::supported_uri_schemes()
+{
+ Index<const char *> schemes;
+
+ schemes.append("file");
+ schemes.append("stdin");
+
+ for (PluginHandle * plugin : aud_plugin_list(PluginType::Transport))
+ {
+ if (!aud_plugin_get_enabled(plugin))
+ continue;
+
+ for (auto s : transport_plugin_get_schemes(plugin))
+ schemes.append((const char *)s);
+ }
+
+ schemes.append(nullptr);
+
+ return schemes;
+}
diff --git a/src/libaudcore/vfs.h b/src/libaudcore/vfs.h
index e7f9ecd..33c5a65 100644
--- a/src/libaudcore/vfs.h
+++ b/src/libaudcore/vfs.h
@@ -1,6 +1,6 @@
/*
* vfs.h
- * Copyright 2006-2013 William Pitcock, Daniel Barkalow, Ralf Ertzinger,
+ * Copyright 2006-2013 Ariadne Conill, Daniel Barkalow, Ralf Ertzinger,
* Yoshiki Yazawa, Matti Hämäläinen, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
@@ -33,21 +33,24 @@
#include <libaudcore/index.h>
#include <libaudcore/objects.h>
-enum VFSFileTest {
- VFS_IS_REGULAR = (1 << 0),
- VFS_IS_SYMLINK = (1 << 1),
- VFS_IS_DIR = (1 << 2),
+enum VFSFileTest
+{
+ VFS_IS_REGULAR = (1 << 0),
+ VFS_IS_SYMLINK = (1 << 1),
+ VFS_IS_DIR = (1 << 2),
VFS_IS_EXECUTABLE = (1 << 3),
- VFS_EXISTS = (1 << 4),
- VFS_NO_ACCESS = (1 << 5)
+ VFS_EXISTS = (1 << 4),
+ VFS_NO_ACCESS = (1 << 5)
};
-enum VFSReadOptions {
- VFS_APPEND_NULL = (1 << 0),
+enum VFSReadOptions
+{
+ VFS_APPEND_NULL = (1 << 0),
VFS_IGNORE_MISSING = (1 << 1)
};
-enum VFSSeekType {
+enum VFSSeekType
+{
VFS_SEEK_SET = 0,
VFS_SEEK_CUR = 1,
VFS_SEEK_END = 2
@@ -57,18 +60,22 @@ enum VFSSeekType {
#include <stdio.h>
-constexpr int from_vfs_seek_type (VFSSeekType whence)
+constexpr int from_vfs_seek_type(VFSSeekType whence)
{
- return (whence == VFS_SEEK_SET) ? SEEK_SET :
- (whence == VFS_SEEK_CUR) ? SEEK_CUR :
- (whence == VFS_SEEK_END) ? SEEK_END : -1;
+ return (whence == VFS_SEEK_SET)
+ ? SEEK_SET
+ : (whence == VFS_SEEK_CUR)
+ ? SEEK_CUR
+ : (whence == VFS_SEEK_END) ? SEEK_END : -1;
}
-constexpr VFSSeekType to_vfs_seek_type (int whence)
+constexpr VFSSeekType to_vfs_seek_type(int whence)
{
- return (whence == SEEK_SET) ? VFS_SEEK_SET :
- (whence == SEEK_CUR) ? VFS_SEEK_CUR :
- (whence == SEEK_END) ? VFS_SEEK_END : (VFSSeekType) -1;
+ return (whence == SEEK_SET)
+ ? VFS_SEEK_SET
+ : (whence == SEEK_CUR)
+ ? VFS_SEEK_CUR
+ : (whence == SEEK_END) ? VFS_SEEK_END : (VFSSeekType)-1;
}
#endif // WANT_VFS_STDIO_COMPAT
@@ -86,91 +93,98 @@ constexpr VFSSeekType to_vfs_seek_type (int whence)
class LIBAUDCORE_PUBLIC VFSImpl
{
public:
- VFSImpl () {}
- virtual ~VFSImpl () {}
+ VFSImpl() {}
+ virtual ~VFSImpl() {}
- VFSImpl (const VFSImpl &) = delete;
- VFSImpl & operator= (const VFSImpl &) = delete;
+ VFSImpl(const VFSImpl &) = delete;
+ VFSImpl & operator=(const VFSImpl &) = delete;
- virtual int64_t fread (void * ptr, int64_t size, int64_t nmemb) = 0;
- virtual int fseek (int64_t offset, VFSSeekType whence) = 0;
+ virtual int64_t fread(void * ptr, int64_t size, int64_t nmemb) = 0;
+ virtual int fseek(int64_t offset, VFSSeekType whence) = 0;
- virtual int64_t ftell () = 0;
- virtual int64_t fsize () = 0;
- virtual bool feof () = 0;
+ virtual int64_t ftell() = 0;
+ virtual int64_t fsize() = 0;
+ virtual bool feof() = 0;
- virtual int64_t fwrite (const void * ptr, int64_t size, int64_t nmemb) = 0;
- virtual int ftruncate (int64_t length) = 0;
- virtual int fflush () = 0;
+ virtual int64_t fwrite(const void * ptr, int64_t size, int64_t nmemb) = 0;
+ virtual int ftruncate(int64_t length) = 0;
+ virtual int fflush() = 0;
- virtual String get_metadata (const char * field) { return String (); }
+ virtual String get_metadata(const char * field) { return String(); }
};
class VFSFile
{
public:
- VFSFile () {}
+ VFSFile() {}
- VFSFile (const char * filename, VFSImpl * impl) :
- m_filename (filename),
- m_impl (impl) {}
+ VFSFile(const char * filename, VFSImpl * impl)
+ : m_filename(filename), m_impl(impl)
+ {
+ }
- VFSFile (const char * filename, const char * mode);
+ VFSFile(const char * filename, const char * mode);
/* creates a temporary file (deleted when closed) */
- static VFSFile tmpfile ();
+ static VFSFile tmpfile();
- explicit operator bool () const
- { return (bool) m_impl; }
- const char * filename () const
- { return m_filename; }
- const char * error () const
- { return m_error; }
+ explicit operator bool() const { return (bool)m_impl; }
+ const char * filename() const { return m_filename; }
+ const char * error() const { return m_error; }
/* basic operations */
- int64_t fread (void * ptr, int64_t size, int64_t nmemb) __attribute__ ((warn_unused_result));
- int fseek (int64_t offset, VFSSeekType whence) __attribute__ ((warn_unused_result));
+ int64_t fread(void * ptr, int64_t size, int64_t nmemb)
+ __attribute__((warn_unused_result));
+ int fseek(int64_t offset, VFSSeekType whence)
+ __attribute__((warn_unused_result));
- int64_t ftell ();
- int64_t fsize ();
- bool feof ();
+ int64_t ftell();
+ int64_t fsize();
+ bool feof();
- int64_t fwrite (const void * ptr, int64_t size, int64_t nmemb) __attribute__ ((warn_unused_result));
- int ftruncate (int64_t length) __attribute__ ((warn_unused_result));
- int fflush () __attribute__ ((warn_unused_result));
+ int64_t fwrite(const void * ptr, int64_t size, int64_t nmemb)
+ __attribute__((warn_unused_result));
+ int ftruncate(int64_t length) __attribute__((warn_unused_result));
+ int fflush() __attribute__((warn_unused_result));
/* used to read e.g. ICY metadata */
- String get_metadata (const char * field);
+ String get_metadata(const char * field);
/* the VFS layer buffers up to 256 KB of data at the beginning of files
* opened in read-only mode; this function disallows reading outside the
* buffered region (useful for probing the file type) */
- void set_limit_to_buffer (bool limit);
+ void set_limit_to_buffer(bool limit);
/* utility functions */
/* reads the entire file into memory (limited to 16 MB) */
- Index<char> read_all ();
+ Index<char> read_all();
/* reads data from another open file and appends it to this one */
- bool copy_from (VFSFile & source, int64_t size = -1);
+ bool copy_from(VFSFile & source, int64_t size = -1);
/* overwrites the entire file with the contents of another */
- bool replace_with (VFSFile & source);
+ bool replace_with(VFSFile & source);
/* tests certain attributes of a file without opening it.
* the 2-argument version returns true if all requested tests passed.
- * the 3-argument version returns a bitmask indicating which tests passed. */
- static bool test_file (const char * filename, VFSFileTest test);
- static VFSFileTest test_file (const char * filename, VFSFileTest test, String & error);
+ * the 3-argument version returns a bitmask indicating which tests passed.
+ */
+ static bool test_file(const char * filename, VFSFileTest test);
+ static VFSFileTest test_file(const char * filename, VFSFileTest test,
+ String & error);
/* returns a sorted list of folder entries (as full URIs) */
- static Index<String> read_folder (const char * filename, String & error);
+ static Index<String> read_folder(const char * filename, String & error);
/* convenience functions to read/write entire files */
- static Index<char> read_file (const char * filename, VFSReadOptions options);
- static bool write_file (const char * filename, const void * data, int64_t len);
+ static Index<char> read_file(const char * filename, VFSReadOptions options);
+ static bool write_file(const char * filename, const void * data,
+ int64_t len);
+
+ /* returns a list of supported URI schemes */
+ static Index<const char *> supported_uri_schemes();
private:
String m_filename, m_error;
diff --git a/src/libaudcore/vfs_async.cc b/src/libaudcore/vfs_async.cc
index 8939236..3c22910 100644
--- a/src/libaudcore/vfs_async.cc
+++ b/src/libaudcore/vfs_async.cc
@@ -1,6 +1,6 @@
/*
* vfs_async.cc
- * Copyright 2010-2014 William Pitcock and John Lindgren
+ * Copyright 2010-2014 Ariadne Conill and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -17,75 +17,77 @@
* the use of this software.
*/
-#include <pthread.h>
-
+#include "vfs_async.h"
#include "list.h"
#include "mainloop.h"
+#include "threads.h"
#include "vfs.h"
-#include "vfs_async.h"
struct QueuedData : public ListNode
{
const String filename;
- const VFSConsumer cons_f;
- void * const user;
-
- pthread_t thread;
+ const VFSConsumer2 cons_f;
+ std::thread thread;
Index<char> buf;
- QueuedData (const char * filename, VFSConsumer cons_f, void * user) :
- filename (filename),
- cons_f (cons_f),
- user (user) {}
+ QueuedData(const char * filename, VFSConsumer2 cons_f)
+ : filename(filename), cons_f(cons_f)
+ {
+ }
};
static QueuedFunc queued_func;
static List<QueuedData> queue;
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static aud::mutex mutex;
-static void send_data (void *)
+static void send_data(void *)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
QueuedData * data;
- while ((data = queue.head ()))
+ while ((data = queue.head()))
{
- queue.remove (data);
+ queue.remove(data);
- pthread_mutex_unlock (& mutex);
+ mh.unlock();
- pthread_join (data->thread, nullptr);
- data->cons_f (data->filename, data->buf, data->user);
+ data->thread.join();
+ data->cons_f(data->filename, data->buf);
delete data;
- pthread_mutex_lock (& mutex);
+ mh.lock();
}
-
- pthread_mutex_unlock (& mutex);
}
-static void * read_worker (void * data0)
+static void read_worker(QueuedData * data)
{
- auto data = (QueuedData *) data0;
-
- VFSFile file (data->filename, "r");
+ VFSFile file(data->filename, "r");
if (file)
- data->buf = file.read_all ();
+ data->buf = file.read_all();
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- if (! queue.head ())
- queued_func.queue (send_data, nullptr);
+ if (!queue.head())
+ queued_func.queue(send_data, nullptr);
- queue.append (data);
+ queue.append(data);
+}
- pthread_mutex_unlock (& mutex);
- return nullptr;
+EXPORT void vfs_async_file_get_contents(const char * filename,
+ VFSConsumer2 cons_f)
+{
+ auto data = new QueuedData(filename, cons_f);
+ data->thread = std::thread(read_worker, data);
}
-EXPORT void vfs_async_file_get_contents (const char * filename, VFSConsumer cons_f, void * user)
+EXPORT void vfs_async_file_get_contents(const char * filename,
+ VFSConsumer cons_f, void * user)
{
- auto data = new QueuedData (filename, cons_f, user);
- pthread_create (& data->thread, nullptr, read_worker, data);
+ auto functor = [cons_f, user](const char * filename,
+ const Index<char> & buf) {
+ cons_f(filename, buf, user);
+ };
+
+ vfs_async_file_get_contents(filename, functor);
}
diff --git a/src/libaudcore/vfs_async.h b/src/libaudcore/vfs_async.h
index b77f88b..5969555 100644
--- a/src/libaudcore/vfs_async.h
+++ b/src/libaudcore/vfs_async.h
@@ -1,6 +1,6 @@
/*
* vfs_async.c
- * Copyright 2010 William Pitcock
+ * Copyright 2010 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -20,10 +20,17 @@
#ifndef LIBAUDCORE_VFS_ASYNC_H
#define LIBAUDCORE_VFS_ASYNC_H
+#include <functional>
#include <libaudcore/index.h>
-typedef void (* VFSConsumer) (const char * filename, const Index<char> & buf, void * user);
+using VFSConsumer2 =
+ std::function<void(const char * filename, const Index<char> & buf)>;
+void vfs_async_file_get_contents(const char * filename, VFSConsumer2 cons_f);
-void vfs_async_file_get_contents (const char * filename, VFSConsumer cons_f, void * user);
+/* old version -- remove this at next hard API break */
+typedef void (*VFSConsumer)(const char * filename, const Index<char> & buf,
+ void * user);
+void vfs_async_file_get_contents(const char * filename, VFSConsumer cons_f,
+ void * user);
#endif
diff --git a/src/libaudcore/vfs_local.cc b/src/libaudcore/vfs_local.cc
index 7af685f..d21d3c0 100644
--- a/src/libaudcore/vfs_local.cc
+++ b/src/libaudcore/vfs_local.cc
@@ -36,9 +36,10 @@
#define ftello ftello64
#endif
-#define perror(s) AUDERR ("%s: %s\n", (const char *) (s), strerror (errno))
+#define perror(s) AUDERR("%s: %s\n", (const char *)(s), strerror(errno))
-enum LocalOp {
+enum LocalOp
+{
OP_NONE,
OP_READ,
OP_WRITE
@@ -47,26 +48,25 @@ enum LocalOp {
class LocalFile : public VFSImpl
{
public:
- LocalFile (const char * path, FILE * stream) :
- m_path (path),
- m_stream (stream),
- m_cached_pos (0),
- m_cached_size (-1),
- m_last_op (OP_NONE) {}
+ LocalFile(const char * path, FILE * stream)
+ : m_path(path), m_stream(stream), m_cached_pos(0), m_cached_size(-1),
+ m_last_op(OP_NONE)
+ {
+ }
- ~LocalFile ();
+ ~LocalFile();
protected:
- int64_t fread (void * ptr, int64_t size, int64_t nmemb);
- int fseek (int64_t offset, VFSSeekType whence);
+ int64_t fread(void * ptr, int64_t size, int64_t nmemb);
+ int fseek(int64_t offset, VFSSeekType whence);
- int64_t ftell ();
- int64_t fsize ();
- bool feof ();
+ int64_t ftell();
+ int64_t fsize();
+ bool feof();
- int64_t fwrite (const void * ptr, int64_t size, int64_t nmemb);
- int ftruncate (int64_t length);
- int fflush ();
+ int64_t fwrite(const void * ptr, int64_t size, int64_t nmemb);
+ int ftruncate(int64_t length);
+ int fflush();
private:
String m_path;
@@ -76,31 +76,32 @@ private:
LocalOp m_last_op;
};
-VFSImpl * LocalTransport::fopen (const char * uri, const char * mode, String & error)
+VFSImpl * LocalTransport::fopen(const char * uri, const char * mode,
+ String & error)
{
- StringBuf path = uri_to_filename (uri);
+ StringBuf path = uri_to_filename(uri);
- if (! path)
+ if (!path)
{
- error = String (_("Invalid file name"));
+ error = String(_("Invalid file name"));
return nullptr;
}
const char * suffix = "";
#ifdef _WIN32
- if (! strchr (mode, 'b')) /* binary mode (Windows) */
+ if (!strchr(mode, 'b')) /* binary mode (Windows) */
suffix = "b";
#else
- if (! strchr (mode, 'e')) /* close on exec (POSIX) */
+ if (!strchr(mode, 'e')) /* close on exec (POSIX) */
suffix = "e";
#endif
- StringBuf mode2 = str_concat ({mode, suffix});
+ StringBuf mode2 = str_concat({mode, suffix});
- FILE * stream = ::g_fopen (path, mode2);
+ FILE * stream = ::g_fopen(path, mode2);
- if (! stream)
+ if (!stream)
{
int errsave = errno;
@@ -109,73 +110,74 @@ VFSImpl * LocalTransport::fopen (const char * uri, const char * mode, String & e
* 2) UTF-8 filesystem mounted on legacy system */
if (errsave == ENOENT)
{
- StringBuf path2 = uri_to_filename (uri, false);
- if (path2 && strcmp (path, path2))
- stream = ::g_fopen (path2, mode2);
+ StringBuf path2 = uri_to_filename(uri, false);
+ if (path2 && strcmp(path, path2))
+ stream = ::g_fopen(path2, mode2);
}
- if (! stream)
+ if (!stream)
{
- perror (path);
- error = String (strerror (errsave));
+ perror(path);
+ error = String(strerror(errsave));
return nullptr;
}
}
- return new LocalFile (path, stream);
+ return new LocalFile(path, stream);
}
-VFSImpl * StdinTransport::fopen (const char * uri, const char * mode, String & error)
+VFSImpl * StdinTransport::fopen(const char * uri, const char * mode,
+ String & error)
{
- if (mode[0] != 'r' || strchr (mode, '+'))
+ if (mode[0] != 'r' || strchr(mode, '+'))
{
- error = String (_("Invalid access mode"));
+ error = String(_("Invalid access mode"));
return nullptr;
}
- return new LocalFile ("(stdin)", stdin);
+ return new LocalFile("(stdin)", stdin);
}
-VFSImpl * vfs_tmpfile (String & error)
+VFSImpl * vfs_tmpfile(String & error)
{
- FILE * stream = tmpfile ();
+ FILE * stream = tmpfile();
- if (! stream)
+ if (!stream)
{
int errsave = errno;
- perror ("(tmpfile)");
- error = String (strerror (errsave));
+ perror("(tmpfile)");
+ error = String(strerror(errsave));
return nullptr;
}
- return new LocalFile ("(tmpfile)", stream);
+ return new LocalFile("(tmpfile)", stream);
}
-LocalFile::~LocalFile ()
+LocalFile::~LocalFile()
{
// do not close stdin
- if (m_stream != stdin && fclose (m_stream) < 0)
- perror (m_path);
+ if (m_stream != stdin && fclose(m_stream) < 0)
+ perror(m_path);
}
-int64_t LocalFile::fread (void * ptr, int64_t size, int64_t nitems)
+int64_t LocalFile::fread(void * ptr, int64_t size, int64_t nitems)
{
if (m_last_op == OP_WRITE)
{
- if (::fflush (m_stream) < 0)
+ if (::fflush(m_stream) < 0)
{
- perror (m_path);
+ perror(m_path);
return 0;
}
}
m_last_op = OP_READ;
- clearerr (m_stream);
+ clearerr(m_stream);
- int64_t result = ::fread (ptr, size, nitems, m_stream);
- if (result < nitems && ferror (m_stream))
- perror (m_path);
+ int64_t result = ::fread(ptr, size, nitems, m_stream);
+ if (result < nitems && ferror(m_stream))
+ perror(m_path);
if (m_cached_pos >= 0)
m_cached_pos += size * result;
@@ -183,41 +185,41 @@ int64_t LocalFile::fread (void * ptr, int64_t size, int64_t nitems)
return result;
}
-int64_t LocalFile::fwrite (const void * ptr, int64_t size, int64_t nitems)
+int64_t LocalFile::fwrite(const void * ptr, int64_t size, int64_t nitems)
{
if (m_last_op == OP_READ)
{
- if (::fflush (m_stream) < 0)
+ if (::fflush(m_stream) < 0)
{
- perror (m_path);
+ perror(m_path);
return 0;
}
}
m_last_op = OP_WRITE;
- clearerr (m_stream);
+ clearerr(m_stream);
- int64_t result = ::fwrite (ptr, size, nitems, m_stream);
- if (result < nitems && ferror (m_stream))
- perror (m_path);
+ int64_t result = ::fwrite(ptr, size, nitems, m_stream);
+ if (result < nitems && ferror(m_stream))
+ perror(m_path);
if (m_cached_pos >= 0)
m_cached_pos += size * result;
if (m_cached_size >= 0 && m_cached_pos >= 0)
- m_cached_size = aud::max (m_cached_size, m_cached_pos);
+ m_cached_size = aud::max(m_cached_size, m_cached_pos);
else
m_cached_size = -1;
return result;
}
-int LocalFile::fseek (int64_t offset, VFSSeekType whence)
+int LocalFile::fseek(int64_t offset, VFSSeekType whence)
{
- int result = fseeko (m_stream, offset, from_vfs_seek_type (whence));
+ int result = fseeko(m_stream, offset, from_vfs_seek_type(whence));
if (result < 0)
- perror (m_path);
+ perror(m_path);
if (result == 0)
{
@@ -234,33 +236,30 @@ int LocalFile::fseek (int64_t offset, VFSSeekType whence)
return result;
}
-int64_t LocalFile::ftell ()
+int64_t LocalFile::ftell()
{
if (m_cached_pos < 0)
- m_cached_pos = ftello (m_stream);
+ m_cached_pos = ftello(m_stream);
return m_cached_pos;
}
-bool LocalFile::feof ()
-{
- return ::feof (m_stream);
-}
+bool LocalFile::feof() { return ::feof(m_stream); }
-int LocalFile::ftruncate (int64_t length)
+int LocalFile::ftruncate(int64_t length)
{
if (m_last_op != OP_NONE)
{
- if (::fflush (m_stream) < 0)
+ if (::fflush(m_stream) < 0)
{
- perror (m_path);
+ perror(m_path);
return -1;
}
}
- int result = ::ftruncate (fileno (m_stream), length);
+ int result = ::ftruncate(fileno(m_stream), length);
if (result < 0)
- perror (m_path);
+ perror(m_path);
if (result == 0)
{
@@ -271,14 +270,14 @@ int LocalFile::ftruncate (int64_t length)
return result;
}
-int LocalFile::fflush ()
+int LocalFile::fflush()
{
if (m_last_op != OP_WRITE)
return 0;
- int result = ::fflush (m_stream);
+ int result = ::fflush(m_stream);
if (result < 0)
- perror (m_path);
+ perror(m_path);
if (result == 0)
m_last_op = OP_NONE;
@@ -286,7 +285,7 @@ int LocalFile::fflush ()
return result;
}
-int64_t LocalFile::fsize ()
+int64_t LocalFile::fsize()
{
// size of stdin is unknown
if (m_stream == stdin)
@@ -294,21 +293,21 @@ int64_t LocalFile::fsize ()
if (m_cached_size < 0)
{
- int64_t saved_pos = ftell ();
+ int64_t saved_pos = ftell();
if (saved_pos < 0)
goto ERR;
- if (fseek (0, VFS_SEEK_END) < 0)
+ if (fseek(0, VFS_SEEK_END) < 0)
goto ERR;
m_last_op = OP_NONE;
m_cached_pos = -1;
- int64_t length = ftello (m_stream);
+ int64_t length = ftello(m_stream);
if (length < 0)
goto ERR;
- if (fseek (saved_pos, VFS_SEEK_SET) < 0)
+ if (fseek(saved_pos, VFS_SEEK_SET) < 0)
goto ERR;
m_cached_pos = saved_pos;
@@ -318,17 +317,18 @@ int64_t LocalFile::fsize ()
return m_cached_size;
ERR:
- perror (m_path);
+ perror(m_path);
return -1;
}
-VFSFileTest LocalTransport::test_file (const char * uri, VFSFileTest test, String & error)
+VFSFileTest LocalTransport::test_file(const char * uri, VFSFileTest test,
+ String & error)
{
- StringBuf path = uri_to_filename (uri);
- if (! path)
+ StringBuf path = uri_to_filename(uri);
+ if (!path)
{
- error = String (_("Invalid file name"));
- return VFSFileTest (test & VFS_NO_ACCESS);
+ error = String(_("Invalid file name"));
+ return VFSFileTest(test & VFS_NO_ACCESS);
}
int passed = 0;
@@ -338,32 +338,33 @@ VFSFileTest LocalTransport::test_file (const char * uri, VFSFileTest test, Strin
#ifdef S_ISLNK
if (test & VFS_IS_SYMLINK)
{
- if (g_lstat (path, & st) < 0)
+ if (g_lstat(path, &st) < 0)
{
- error = String (strerror (errno));
+ error = String(strerror(errno));
passed |= VFS_NO_ACCESS;
goto out;
}
- if (S_ISLNK (st.st_mode))
+ if (S_ISLNK(st.st_mode))
passed |= VFS_IS_SYMLINK;
else
need_stat = false;
}
#endif
- if (test & (VFS_IS_REGULAR | VFS_IS_DIR | VFS_IS_EXECUTABLE | VFS_EXISTS | VFS_NO_ACCESS))
+ if (test & (VFS_IS_REGULAR | VFS_IS_DIR | VFS_IS_EXECUTABLE | VFS_EXISTS |
+ VFS_NO_ACCESS))
{
- if (need_stat && g_stat (path, & st) < 0)
+ if (need_stat && g_stat(path, &st) < 0)
{
- error = String (strerror (errno));
+ error = String(strerror(errno));
passed |= VFS_NO_ACCESS;
goto out;
}
- if (S_ISREG (st.st_mode))
+ if (S_ISREG(st.st_mode))
passed |= VFS_IS_REGULAR;
- if (S_ISDIR (st.st_mode))
+ if (S_ISDIR(st.st_mode))
passed |= VFS_IS_DIR;
if (st.st_mode & S_IXUSR)
passed |= VFS_IS_EXECUTABLE;
@@ -372,34 +373,34 @@ VFSFileTest LocalTransport::test_file (const char * uri, VFSFileTest test, Strin
}
out:
- return VFSFileTest (test & passed);
+ return VFSFileTest(test & passed);
}
-Index<String> LocalTransport::read_folder (const char * uri, String & error)
+Index<String> LocalTransport::read_folder(const char * uri, String & error)
{
Index<String> entries;
- StringBuf path = uri_to_filename (uri);
- if (! path)
+ StringBuf path = uri_to_filename(uri);
+ if (!path)
{
- error = String (_("Invalid file name"));
+ error = String(_("Invalid file name"));
return entries;
}
GError * gerr = nullptr;
- GDir * folder = g_dir_open (path, 0, & gerr);
- if (! folder)
+ GDir * folder = g_dir_open(path, 0, &gerr);
+ if (!folder)
{
- error = String (gerr->message);
- g_error_free (gerr);
+ error = String(gerr->message);
+ g_error_free(gerr);
return entries;
}
const char * name;
- while ((name = g_dir_read_name (folder)))
- entries.append (String (filename_to_uri (filename_build ({path, name}))));
+ while ((name = g_dir_read_name(folder)))
+ entries.append(String(filename_to_uri(filename_build({path, name}))));
- g_dir_close (folder);
+ g_dir_close(folder);
return entries;
}
diff --git a/src/libaudcore/vfs_local.h b/src/libaudcore/vfs_local.h
index 071c0d9..e5a9a1c 100644
--- a/src/libaudcore/vfs_local.h
+++ b/src/libaudcore/vfs_local.h
@@ -25,21 +25,22 @@
class LocalTransport : public TransportPlugin
{
public:
- constexpr LocalTransport () : TransportPlugin (PluginInfo (), nullptr) {}
+ constexpr LocalTransport() : TransportPlugin(PluginInfo(), nullptr) {}
- VFSImpl * fopen (const char * filename, const char * mode, String & error);
- VFSFileTest test_file (const char * filename, VFSFileTest test, String & error);
- Index<String> read_folder (const char * filename, String & error);
+ VFSImpl * fopen(const char * filename, const char * mode, String & error);
+ VFSFileTest test_file(const char * filename, VFSFileTest test,
+ String & error);
+ Index<String> read_folder(const char * filename, String & error);
};
class StdinTransport : public TransportPlugin
{
public:
- constexpr StdinTransport () : TransportPlugin (PluginInfo (), nullptr) {}
+ constexpr StdinTransport() : TransportPlugin(PluginInfo(), nullptr) {}
- VFSImpl * fopen (const char * filename, const char * mode, String & error);
+ VFSImpl * fopen(const char * filename, const char * mode, String & error);
};
-VFSImpl * vfs_tmpfile (String & error);
+VFSImpl * vfs_tmpfile(String & error);
#endif /* LIBAUDCORE_VFS_LOCAL_H */
diff --git a/src/libaudcore/vis-runner.cc b/src/libaudcore/vis-runner.cc
index 4f142ca..dde486a 100644
--- a/src/libaudcore/vis-runner.cc
+++ b/src/libaudcore/vis-runner.cc
@@ -20,7 +20,6 @@
#include "internal.h"
#include <assert.h>
-#include <pthread.h>
#include <stdint.h>
#include <string.h>
@@ -28,26 +27,27 @@
#include "list.h"
#include "mainloop.h"
#include "output.h"
+#include "threads.h"
#define INTERVAL 33 /* milliseconds */
#define FRAMES_PER_NODE 512
struct VisNode : public ListNode
{
- VisNode (int channels, int time) :
- channels (channels),
- time (time),
- data (new float[channels * FRAMES_PER_NODE]) {}
+ VisNode(int channels, int time)
+ : channels(channels), time(time),
+ data(new float[channels * FRAMES_PER_NODE])
+ {
+ }
- ~VisNode ()
- { delete[] data; }
+ ~VisNode() { delete[] data; }
const int channels;
int time;
float * data;
};
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static aud::mutex mutex;
static bool enabled = false;
static bool playing = false, paused = false;
static VisNode * current_node = nullptr;
@@ -56,23 +56,20 @@ static List<VisNode> vis_list;
static List<VisNode> vis_pool;
static QueuedFunc queued_clear;
-static void send_audio (void *)
+static void send_audio(void *)
{
/* call before locking mutex to avoid deadlock */
- int outputted = output_get_raw_time ();
+ int outputted = output_get_raw_time();
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- if (! enabled || ! playing || paused)
- {
- pthread_mutex_unlock (& mutex);
+ if (!enabled || !playing || paused)
return;
- }
VisNode * node = nullptr;
VisNode * next;
- while ((next = vis_list.head ()))
+ while ((next = vis_list.head()))
{
/* If we are considering a node, stop searching and use it if it is the
* most recent (that is, the next one is in the future). Otherwise,
@@ -82,80 +79,72 @@ static void send_audio (void *)
break;
if (node)
- vis_pool.prepend (node);
+ vis_pool.prepend(node);
node = next;
- vis_list.remove (node);
+ vis_list.remove(node);
}
- pthread_mutex_unlock (& mutex);
-
- if (! node)
+ if (!node)
return;
- vis_send_audio (node->data, node->channels);
+ mh.unlock();
+ vis_send_audio(node->data, node->channels);
+ mh.lock();
- pthread_mutex_lock (& mutex);
- vis_pool.prepend (node);
- pthread_mutex_unlock (& mutex);
+ vis_pool.prepend(node);
}
-static void send_clear (void *)
-{
- vis_send_clear ();
-}
+static void send_clear(void *) { vis_send_clear(); }
-static void flush_locked ()
+static void flush(aud::mutex::holder &)
{
delete current_node;
current_node = nullptr;
- vis_list.clear ();
- vis_pool.clear ();
+ vis_list.clear();
+ vis_pool.clear();
if (enabled)
- queued_clear.queue (send_clear, nullptr);
+ queued_clear.queue(send_clear, nullptr);
}
-void vis_runner_flush ()
+void vis_runner_flush()
{
- pthread_mutex_lock (& mutex);
- flush_locked ();
- pthread_mutex_unlock (& mutex);
+ auto mh = mutex.take();
+ flush(mh);
}
-static void start_stop_locked (bool new_playing, bool new_paused)
+static void start_stop(aud::mutex::holder & mh, bool new_playing,
+ bool new_paused)
{
playing = new_playing;
paused = new_paused;
- queued_clear.stop ();
+ queued_clear.stop();
- if (! enabled || ! playing)
- flush_locked ();
+ if (!enabled || !playing)
+ flush(mh);
- if (enabled && playing && ! paused)
- timer_add (TimerRate::Hz30, send_audio);
+ if (enabled && playing && !paused)
+ timer_add(TimerRate::Hz30, send_audio);
else
- timer_remove (TimerRate::Hz30, send_audio);
+ timer_remove(TimerRate::Hz30, send_audio);
}
-void vis_runner_start_stop (bool new_playing, bool new_paused)
+void vis_runner_start_stop(bool new_playing, bool new_paused)
{
- pthread_mutex_lock (& mutex);
- start_stop_locked (new_playing, new_paused);
- pthread_mutex_unlock (& mutex);
+ auto mh = mutex.take();
+ start_stop(mh, new_playing, new_paused);
}
-void vis_runner_pass_audio (int time, const Index<float> & data, int channels, int rate)
+void vis_runner_pass_audio(int time, const Index<float> & data, int channels,
+ int rate)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
- if (! enabled || ! playing)
- {
- pthread_mutex_unlock (& mutex);
+ if (!enabled || !playing)
return;
- }
/* We can build a single node from multiple calls; we can also build
* multiple nodes from the same call. If current_node is present, it was
@@ -166,7 +155,7 @@ void vis_runner_pass_audio (int time, const Index<float> & data, int channels, i
while (1)
{
if (current_node)
- assert (current_node->channels == channels);
+ assert(current_node->channels == channels);
else
{
int node_time = time;
@@ -178,27 +167,27 @@ void vis_runner_pass_audio (int time, const Index<float> & data, int channels, i
* queue, we are at the beginning of the song or had an underrun,
* and we want to copy the earliest audio data we have. */
- VisNode * tail = vis_list.tail ();
+ VisNode * tail = vis_list.tail();
if (tail)
node_time = tail->time + INTERVAL;
- at = channels * (int) ((int64_t) (node_time - time) * rate / 1000);
+ at = channels * (int)((int64_t)(node_time - time) * rate / 1000);
if (at < 0)
at = 0;
- if (at >= data.len ())
+ if (at >= data.len())
break;
- current_node = vis_pool.head ();
+ current_node = vis_pool.head();
if (current_node)
{
- assert (current_node->channels == channels);
- vis_pool.remove (current_node);
+ assert(current_node->channels == channels);
+ vis_pool.remove(current_node);
current_node->time = node_time;
}
else
- current_node = new VisNode (channels, node_time);
+ current_node = new VisNode(channels, node_time);
current_frames = 0;
}
@@ -208,24 +197,23 @@ void vis_runner_pass_audio (int time, const Index<float> & data, int channels, i
* wait for more data to be passed in the next call. If we do fill the
* node, we loop and start building a new one. */
- int copy = aud::min (data.len () - at, channels * (FRAMES_PER_NODE - current_frames));
- memcpy (current_node->data + channels * current_frames, & data[at], sizeof (float) * copy);
+ int copy = aud::min(data.len() - at,
+ channels * (FRAMES_PER_NODE - current_frames));
+ memcpy(current_node->data + channels * current_frames, &data[at],
+ sizeof(float) * copy);
current_frames += copy / channels;
if (current_frames < FRAMES_PER_NODE)
break;
- vis_list.append (current_node);
+ vis_list.append(current_node);
current_node = nullptr;
}
-
- pthread_mutex_unlock (& mutex);
}
-void vis_runner_enable (bool enable)
+void vis_runner_enable(bool enable)
{
- pthread_mutex_lock (& mutex);
+ auto mh = mutex.take();
enabled = enable;
- start_stop_locked (playing, paused);
- pthread_mutex_unlock (& mutex);
+ start_stop(mh, playing, paused);
}
diff --git a/src/libaudcore/visualization.cc b/src/libaudcore/visualization.cc
index 2f7a768..1122658 100644
--- a/src/libaudcore/visualization.cc
+++ b/src/libaudcore/visualization.cc
@@ -31,60 +31,58 @@ static Index<Visualizer *> visualizers;
static int running = false;
static int num_enabled = 0;
-EXPORT void aud_visualizer_add (Visualizer * vis)
+EXPORT void aud_visualizer_add(Visualizer * vis)
{
- visualizers.append (vis);
+ visualizers.append(vis);
- num_enabled ++;
+ num_enabled++;
if (num_enabled == 1)
- vis_runner_enable (true);
+ vis_runner_enable(true);
}
-EXPORT void aud_visualizer_remove (Visualizer * vis)
+EXPORT void aud_visualizer_remove(Visualizer * vis)
{
int num_disabled = 0;
- auto is_match = [&] (Visualizer * vis2)
- {
+ auto is_match = [&](Visualizer * vis2) {
if (vis2 != vis)
return false;
- num_disabled ++;
+ num_disabled++;
return true;
};
- visualizers.remove_if (is_match, true);
+ visualizers.remove_if(is_match, true);
num_enabled -= num_disabled;
- if (! num_enabled)
- vis_runner_enable (false);
+ if (!num_enabled)
+ vis_runner_enable(false);
}
-void vis_send_clear ()
+void vis_send_clear()
{
for (Visualizer * vis : visualizers)
- vis->clear ();
+ vis->clear();
}
-static void pcm_to_mono (const float * data, float * mono, int channels)
+static void pcm_to_mono(const float * data, float * mono, int channels)
{
if (channels == 1)
- memcpy (mono, data, sizeof (float) * 512);
+ memcpy(mono, data, sizeof(float) * 512);
else
{
float * set = mono;
- while (set < & mono[512])
+ while (set < &mono[512])
{
- * set ++ = (data[0] + data[1]) / 2;
+ *set++ = (data[0] + data[1]) / 2;
data += channels;
}
}
}
-void vis_send_audio (const float * data, int channels)
+void vis_send_audio(const float * data, int channels)
{
- auto is_active = [] (int type_mask)
- {
+ auto is_active = [](int type_mask) {
for (Visualizer * vis : visualizers)
{
if ((vis->type_mask & type_mask))
@@ -97,83 +95,83 @@ void vis_send_audio (const float * data, int channels)
float mono[512];
float freq[256];
- if (is_active (Visualizer::MonoPCM | Visualizer::Freq))
- pcm_to_mono (data, mono, channels);
- if (is_active (Visualizer::Freq))
- calc_freq (mono, freq);
+ if (is_active(Visualizer::MonoPCM | Visualizer::Freq))
+ pcm_to_mono(data, mono, channels);
+ if (is_active(Visualizer::Freq))
+ calc_freq(mono, freq);
for (Visualizer * vis : visualizers)
{
if ((vis->type_mask & Visualizer::MonoPCM))
- vis->render_mono_pcm (mono);
+ vis->render_mono_pcm(mono);
if ((vis->type_mask & Visualizer::MultiPCM))
- vis->render_multi_pcm (data, channels);
+ vis->render_multi_pcm(data, channels);
if ((vis->type_mask & Visualizer::Freq))
- vis->render_freq (freq);
+ vis->render_freq(freq);
}
}
-static bool vis_load (PluginHandle * plugin)
+static bool vis_load(PluginHandle * plugin)
{
- AUDINFO ("Activating %s.\n", aud_plugin_get_name (plugin));
- VisPlugin * header = (VisPlugin *) aud_plugin_get_header (plugin);
- if (! header)
+ AUDINFO("Activating %s.\n", aud_plugin_get_name(plugin));
+ VisPlugin * header = (VisPlugin *)aud_plugin_get_header(plugin);
+ if (!header)
return false;
- aud_visualizer_add (header);
+ aud_visualizer_add(header);
return true;
}
-static void vis_unload (PluginHandle * plugin)
+static void vis_unload(PluginHandle * plugin)
{
- AUDINFO ("Deactivating %s.\n", aud_plugin_get_name (plugin));
- VisPlugin * header = (VisPlugin *) aud_plugin_get_header (plugin);
- if (! header)
+ AUDINFO("Deactivating %s.\n", aud_plugin_get_name(plugin));
+ VisPlugin * header = (VisPlugin *)aud_plugin_get_header(plugin);
+ if (!header)
return;
- header->clear ();
- aud_visualizer_remove (header);
+ header->clear();
+ aud_visualizer_remove(header);
}
-void vis_activate (bool activate)
+void vis_activate(bool activate)
{
- if (! activate == ! running)
+ if (!activate == !running)
return;
- for (PluginHandle * plugin : aud_plugin_list (PluginType::Vis))
+ for (PluginHandle * plugin : aud_plugin_list(PluginType::Vis))
{
- if (! aud_plugin_get_enabled (plugin))
+ if (!aud_plugin_get_enabled(plugin))
continue;
if (activate)
- vis_load (plugin);
+ vis_load(plugin);
else
- vis_unload (plugin);
+ vis_unload(plugin);
}
running = activate;
}
-bool vis_plugin_start (PluginHandle * plugin)
+bool vis_plugin_start(PluginHandle * plugin)
{
- VisPlugin * vp = (VisPlugin *) aud_plugin_get_header (plugin);
- if (! vp || ! vp->init ())
+ VisPlugin * vp = (VisPlugin *)aud_plugin_get_header(plugin);
+ if (!vp || !vp->init())
return false;
if (running)
- vis_load (plugin);
+ vis_load(plugin);
return true;
}
-void vis_plugin_stop (PluginHandle * plugin)
+void vis_plugin_stop(PluginHandle * plugin)
{
- VisPlugin * vp = (VisPlugin *) aud_plugin_get_header (plugin);
- if (! vp)
+ VisPlugin * vp = (VisPlugin *)aud_plugin_get_header(plugin);
+ if (!vp)
return;
if (running)
- vis_unload (plugin);
+ vis_unload(plugin);
- vp->cleanup ();
+ vp->cleanup();
}
diff --git a/src/libaudcore/visualizer.h b/src/libaudcore/visualizer.h
index 5c825e6..1a82bd7 100644
--- a/src/libaudcore/visualizer.h
+++ b/src/libaudcore/visualizer.h
@@ -25,27 +25,32 @@
class LIBAUDCORE_PUBLIC Visualizer
{
public:
- enum {
+ enum
+ {
MonoPCM = (1 << 0),
MultiPCM = (1 << 1),
Freq = (1 << 2)
};
const int type_mask;
- constexpr Visualizer (int type_mask) :
- type_mask (type_mask) {}
+ constexpr Visualizer(int type_mask) : type_mask(type_mask) {}
/* reset internal state and clear display */
- virtual void clear () = 0;
+ virtual void clear() = 0;
/* 512 frames of a single-channel PCM signal */
- virtual void render_mono_pcm (const float * pcm) {}
+ virtual void render_mono_pcm(const float * pcm) {}
/* 512 frames of an interleaved multi-channel PCM signal */
- virtual void render_multi_pcm (const float * pcm, int channels) {}
+ virtual void render_multi_pcm(const float * pcm, int channels) {}
/* intensity of frequencies 1/512, 2/512, ..., 256/512 of sample rate */
- virtual void render_freq (const float * freq) {}
+ virtual void render_freq(const float * freq) {}
+
+ /* common math for rendering a frequency graph (see util.cc) */
+ static void compute_log_xscale(float * xscale, int bands);
+ static float compute_freq_band(const float * freq, const float * xscale,
+ int band, int bands);
};
#endif /* LIBAUDCORE_VISUALIZER_H */
diff --git a/src/libaudgui/Makefile b/src/libaudgui/Makefile
index c0589ce..081bd01 100644
--- a/src/libaudgui/Makefile
+++ b/src/libaudgui/Makefile
@@ -1,6 +1,6 @@
SHARED_LIB = ${LIB_PREFIX}audgui${LIB_SUFFIX}
LIB_MAJOR = 5
-LIB_MINOR = 0
+LIB_MINOR = 1
SRCS = about.cc \
confirm.cc \
@@ -52,7 +52,9 @@ CPPFLAGS := -I.. -I../.. \
CFLAGS += ${LIB_CFLAGS}
-LIBS := -L../libaudcore -laudcore \
+LIB_LDFLAGS := -L../libaudcore $(LIB_LDFLAGS)
+
+LIBS := -laudcore \
${LIBS} -lm \
${GLIB_LIBS} \
${GTK_LIBS}
diff --git a/src/libaudgui/eq-preset.cc b/src/libaudgui/eq-preset.cc
index 159fef9..cdffa77 100644
--- a/src/libaudgui/eq-preset.cc
+++ b/src/libaudgui/eq-preset.cc
@@ -20,8 +20,10 @@
#include <string.h>
#include <libaudcore/equalizer.h>
+#include <libaudcore/hook.h>
#include <libaudcore/i18n.h>
#include <libaudcore/index.h>
+#include <libaudcore/interface.h>
#include <libaudcore/runtime.h>
#include "internal.h"
@@ -65,11 +67,16 @@ static void select_all (void *, bool selected)
item.selected = selected;
}
+static void activate_preset (const EqualizerPreset & preset)
+{
+ aud_eq_apply_preset (preset);
+ aud_set_bool ("equalizer_active", true);
+}
+
static void activate_row (void *, int row)
{
g_return_if_fail (row >= 0 && row < preset_list.len ());
- aud_eq_apply_preset (preset_list[row].preset);
- aud_set_bool (nullptr, "equalizer_active", true);
+ activate_preset (preset_list[row].preset);
}
static void focus_change (void *, int row)
@@ -124,6 +131,30 @@ static int find_by_name (const char * name)
return -1;
}
+static const EqualizerPreset * find_one_selected ()
+{
+ const EqualizerPreset * preset = nullptr;
+
+ for (PresetItem & item : preset_list)
+ {
+ if (item.selected)
+ {
+ if (preset)
+ {
+ preset = nullptr;
+ break;
+ }
+
+ preset = & item.preset;
+ }
+ }
+
+ if (! preset)
+ aud_ui_show_error (_("Please select one preset to export."));
+
+ return preset;
+}
+
static void text_changed ()
{
const char * name = gtk_entry_get_text ((GtkEntry *) entry);
@@ -186,6 +217,20 @@ static void revert_changes ()
gtk_widget_set_sensitive (revert, false);
}
+static void do_save_file (void)
+{
+ auto preset = find_one_selected ();
+ if (preset)
+ eq_preset_save_file (* preset);
+}
+
+static void do_save_eqf (void)
+{
+ auto preset = find_one_selected ();
+ if (preset)
+ eq_preset_save_eqf (* preset);
+}
+
static void cleanup_eq_preset_window ()
{
// also hide the preset browser window
@@ -209,14 +254,12 @@ static GtkWidget * create_menu_bar ()
{
static const AudguiMenuItem import_items[] = {
MenuCommand (N_("Preset File ..."), nullptr, 0, (GdkModifierType) 0, eq_preset_load_file),
- MenuCommand (N_("EQF File ..."), nullptr, 0, (GdkModifierType) 0, eq_preset_load_eqf),
- MenuSep (),
- MenuCommand (N_("Winamp Presets ..."), nullptr, 0, (GdkModifierType) 0, eq_preset_import_winamp)
+ MenuCommand (N_("EQF File ..."), nullptr, 0, (GdkModifierType) 0, eq_preset_load_eqf)
};
static const AudguiMenuItem export_items[] = {
- MenuCommand (N_("Preset File ..."), nullptr, 0, (GdkModifierType) 0, eq_preset_save_file),
- MenuCommand (N_("EQF File ..."), nullptr, 0, (GdkModifierType) 0, eq_preset_save_eqf)
+ MenuCommand (N_("Preset File ..."), nullptr, 0, (GdkModifierType) 0, do_save_file),
+ MenuCommand (N_("EQF File ..."), nullptr, 0, (GdkModifierType) 0, do_save_eqf)
};
static const AudguiMenuItem menus[] = {
@@ -309,8 +352,17 @@ static void merge_presets (const Index<EqualizerPreset> & presets)
preset_list.remove_if (is_duplicate);
}
+ /* deselect existing presets */
+ for (auto & item : preset_list)
+ item.selected = false;
+
+ /* append and select new presets */
for (const EqualizerPreset & preset : presets)
- preset_list.append (preset, false);
+ preset_list.append (preset, true);
+
+ /* if a single preset was imported, activate it */
+ if (presets.len () == 1)
+ activate_preset (presets[0]);
}
EXPORT void audgui_import_eq_presets (const Index<EqualizerPreset> & presets)
@@ -322,6 +374,7 @@ EXPORT void audgui_import_eq_presets (const Index<EqualizerPreset> & presets)
audgui_list_delete_rows (list, 0, preset_list.len ());
merge_presets (presets);
audgui_list_insert_rows (list, 0, preset_list.len ());
+ audgui_list_set_focus (list, preset_list.len () - 1);
changes_made = true;
gtk_widget_set_sensitive (revert, true);
diff --git a/src/libaudgui/equalizer.cc b/src/libaudgui/equalizer.cc
index 207f8a7..a6d6640 100644
--- a/src/libaudgui/equalizer.cc
+++ b/src/libaudgui/equalizer.cc
@@ -31,7 +31,7 @@
static void on_off_cb (GtkToggleButton * on_off)
{
- aud_set_bool (nullptr, "equalizer_active", gtk_toggle_button_get_active (on_off));
+ aud_set_bool ("equalizer_active", gtk_toggle_button_get_active (on_off));
}
static void on_off_update (void *, GtkWidget * on_off)
@@ -61,7 +61,7 @@ static void slider_moved (GtkRange * slider)
double value = round (gtk_range_get_value (slider));
if (band == -1)
- aud_set_double (nullptr, "equalizer_preamp", value);
+ aud_set_double ("equalizer_preamp", value);
else
aud_eq_set_band (band, value);
}
@@ -99,7 +99,7 @@ static void set_slider (GtkWidget * slider, double value)
static void update_sliders (void *, GtkWidget * window)
{
GtkWidget * preamp = (GtkWidget *) g_object_get_data ((GObject *) window, "preamp");
- set_slider (preamp, aud_get_double (nullptr, "equalizer_preamp"));
+ set_slider (preamp, aud_get_double ("equalizer_preamp"));
double values[AUD_EQ_NBANDS];
aud_eq_get_bands (values);
diff --git a/src/libaudgui/images.gresource.xml b/src/libaudgui/images.gresource.xml
index 2a5dacf..83441eb 100644
--- a/src/libaudgui/images.gresource.xml
+++ b/src/libaudgui/images.gresource.xml
@@ -51,6 +51,7 @@
<file>media-skip-backward.svg</file>
<file>media-skip-forward.svg</file>
<file>multimedia-volume-control.svg</file>
+ <file>preferences-desktop-font.svg</file>
<file>preferences-system.svg</file>
<file>process-stop.svg</file>
<file>system-run.svg</file>
diff --git a/src/libaudgui/infopopup.cc b/src/libaudgui/infopopup.cc
index bdefdd5..8de01c9 100644
--- a/src/libaudgui/infopopup.cc
+++ b/src/libaudgui/infopopup.cc
@@ -1,6 +1,6 @@
/*
* infopopup.c
- * Copyright 2006-2012 William Pitcock, Giacomo Lozito, John Lindgren, and
+ * Copyright 2006-2012 Ariadne Conill, Giacomo Lozito, John Lindgren, and
* Thomas Lange
*
* Redistribution and use in source and binary forms, with or without
@@ -91,7 +91,7 @@ static void infopopup_progress_cb (void *)
time = aud_drct_get_time ();
}
- if (aud_get_bool (nullptr, "filepopup_showprogressbar") && filename &&
+ if (aud_get_bool ("filepopup_showprogressbar") && filename &&
current_file && ! strcmp (filename, current_file) && length > 0)
{
gtk_progress_bar_set_fraction ((GtkProgressBar *) widgets.progress, time / (float) length);
@@ -109,32 +109,14 @@ static void infopopup_realized (GtkWidget * widget)
infopopup_move_to_mouse (widget);
}
-/* borrowed from the gtkui infoarea */
static gboolean infopopup_draw_bg (GtkWidget * widget)
{
- double r = 1, g = 1, b = 1;
-
- /* In a dark theme, try to match the tone of the base color */
- auto & c = (gtk_widget_get_style (widget))->base[GTK_STATE_NORMAL];
- int v = aud::max (aud::max (c.red, c.green), c.blue);
-
- if (v >= 10*256 && v < 80*256)
- {
- r = (double)c.red / v;
- g = (double)c.green / v;
- b = (double)c.blue / v;
- }
-
GtkAllocation alloc;
gtk_widget_get_allocation (widget, & alloc);
cairo_t * cr = gdk_cairo_create (gtk_widget_get_window (widget));
-
- cairo_pattern_t * gradient = cairo_pattern_create_linear (0, 0, 0, alloc.height);
- cairo_pattern_add_color_stop_rgb (gradient, 0, 0.25 * r, 0.25 * g, 0.25 * b);
- cairo_pattern_add_color_stop_rgb (gradient, 0.5, 0.15 * r, 0.15 * g, 0.15 * b);
- cairo_pattern_add_color_stop_rgb (gradient, 0.5, 0.1 * r, 0.1 * g, 0.1 * b);
- cairo_pattern_add_color_stop_rgb (gradient, 1, 0, 0, 0);
+ auto & c = (gtk_widget_get_style (widget))->base[GTK_STATE_NORMAL];
+ cairo_pattern_t * gradient = audgui_dark_bg_gradient (c, alloc.height);
cairo_set_source (cr, gradient);
cairo_rectangle (cr, 0, 0, alloc.width, alloc.height);
diff --git a/src/libaudgui/infowin.cc b/src/libaudgui/infowin.cc
index 8f62856..63bb3fa 100644
--- a/src/libaudgui/infowin.cc
+++ b/src/libaudgui/infowin.cc
@@ -1,6 +1,6 @@
/*
* infowin.c
- * Copyright 2006-2013 William Pitcock, Tomasz Moń, Eugene Zagidullin,
+ * Copyright 2006-2013 Ariadne Conill, Tomasz Moń, Eugene Zagidullin,
* John Lindgren, and Thomas Lange
*
* Redistribution and use in source and binary forms, with or without
@@ -65,7 +65,7 @@ static struct {
GtkWidget * image;
GtkWidget * codec[3];
GtkWidget * apply;
- GtkWidget * clear;
+ GtkWidget * autofill;
GtkWidget * ministatus;
} widgets;
@@ -192,7 +192,7 @@ static void set_field_int_from_entry (Tuple & tuple, Tuple::Field field, GtkWidg
tuple.unset (field);
}
-static void entry_changed (GtkEditable * editable)
+static void entry_changed ()
{
if (can_write)
gtk_widget_set_sensitive (widgets.apply, true);
@@ -201,12 +201,12 @@ static void entry_changed (GtkEditable * editable)
static void ministatus_display_message (const char * text)
{
gtk_label_set_text ((GtkLabel *) widgets.ministatus, text);
- gtk_widget_hide (widgets.clear);
+ gtk_widget_hide (widgets.autofill);
gtk_widget_show (widgets.ministatus);
ministatus_timer.queue (AUDGUI_STATUS_TIMEOUT, [] (void *) {
gtk_widget_hide (widgets.ministatus);
- gtk_widget_show (widgets.clear);
+ gtk_widget_show (widgets.autofill);
}, nullptr);
}
@@ -231,11 +231,9 @@ static void infowin_update_tuple ()
ministatus_display_message (_("Save error"));
}
-static void infowin_next ()
+static void infowin_select_entry (int entry)
{
- int entry = current_entry + 1;
-
- if (entry < current_playlist.n_entries ())
+ if (entry >= 0 && entry < current_playlist.n_entries ())
{
current_playlist.select_all (false);
current_playlist.select_entry (entry, true);
@@ -246,6 +244,16 @@ static void infowin_next ()
audgui_infowin_hide ();
}
+static void infowin_prev ()
+{
+ infowin_select_entry (current_entry - 1);
+}
+
+static void infowin_next ()
+{
+ infowin_select_entry (current_entry + 1);
+}
+
static void genre_fill (GtkWidget * combo)
{
GList * list = nullptr;
@@ -262,9 +270,9 @@ static void genre_fill (GtkWidget * combo)
g_list_free (list);
}
-static void clear_toggled (GtkToggleButton * toggle)
+static void autofill_toggled (GtkToggleButton * toggle)
{
- aud_set_bool ("audgui", "clear_song_fields", gtk_toggle_button_get_active (toggle));
+ aud_set_bool ("audgui", "clear_song_fields", ! gtk_toggle_button_get_active (toggle));
}
static void infowin_display_image (const char * filename)
@@ -386,16 +394,15 @@ static void create_infowin ()
gtk_table_attach ((GtkTable *) main_grid, bottom_hbox, 0, 2, 3, 4,
GTK_FILL, GTK_FILL, 0, 0);
- widgets.clear = gtk_check_button_new_with_mnemonic
- (_("Clea_r fields when moving to next song"));
+ widgets.autofill = gtk_check_button_new_with_mnemonic (_("_Auto-fill empty fields"));
- gtk_toggle_button_set_active ((GtkToggleButton *) widgets.clear,
- aud_get_bool ("audgui", "clear_song_fields"));
- g_signal_connect (widgets.clear, "toggled", (GCallback) clear_toggled, nullptr);
+ gtk_toggle_button_set_active ((GtkToggleButton *) widgets.autofill,
+ ! aud_get_bool ("audgui", "clear_song_fields"));
+ g_signal_connect (widgets.autofill, "toggled", (GCallback) autofill_toggled, nullptr);
- gtk_widget_set_no_show_all (widgets.clear, true);
- gtk_widget_show (widgets.clear);
- gtk_box_pack_start ((GtkBox *) bottom_hbox, widgets.clear, false, false, 0);
+ gtk_widget_set_no_show_all (widgets.autofill, true);
+ gtk_widget_show (widgets.autofill);
+ gtk_box_pack_start ((GtkBox *) bottom_hbox, widgets.autofill, false, false, 0);
widgets.ministatus = small_label_new (nullptr);
gtk_widget_set_no_show_all (widgets.ministatus, true);
@@ -407,12 +414,16 @@ static void create_infowin ()
GtkWidget * close_button = audgui_button_new (_("_Close"), "window-close",
(AudguiCallback) audgui_infowin_hide, nullptr);
+ GtkWidget * prev_button = audgui_button_new (_("_Previous"), "go-previous",
+ (AudguiCallback) infowin_prev, nullptr);
+
GtkWidget * next_button = audgui_button_new (_("_Next"), "go-next",
(AudguiCallback) infowin_next, nullptr);
gtk_box_pack_end ((GtkBox *) bottom_hbox, close_button, false, false, 0);
- gtk_box_pack_end ((GtkBox *) bottom_hbox, next_button, false, false, 0);
gtk_box_pack_end ((GtkBox *) bottom_hbox, widgets.apply, false, false, 0);
+ gtk_box_pack_end ((GtkBox *) bottom_hbox, next_button, false, false, 0);
+ gtk_box_pack_end ((GtkBox *) bottom_hbox, prev_button, false, false, 0);
audgui_destroy_on_escape (infowin);
g_signal_connect (infowin, "destroy", (GCallback) infowin_destroyed, nullptr);
diff --git a/src/libaudgui/init.cc b/src/libaudgui/init.cc
index c3d3a76..36ad24d 100644
--- a/src/libaudgui/init.cc
+++ b/src/libaudgui/init.cc
@@ -361,7 +361,9 @@ EXPORT void audgui_init ()
hook_associate ("playlist set playing", playlist_set_playing_cb, nullptr);
hook_associate ("playlist position", playlist_position_cb, nullptr);
+#ifndef _WIN32
gtk_window_set_default_icon_name ("audacious");
+#endif
}
EXPORT void audgui_cleanup ()
diff --git a/src/libaudgui/libaudgui-gtk.h b/src/libaudgui/libaudgui-gtk.h
index f98ba27..e0b321b 100644
--- a/src/libaudgui/libaudgui-gtk.h
+++ b/src/libaudgui/libaudgui-gtk.h
@@ -88,4 +88,8 @@ GtkWidget * audgui_dialog_new (GtkMessageType type, const char * title,
const char * text, GtkWidget * button1, GtkWidget * button2);
void audgui_dialog_add_widget (GtkWidget * dialog, GtkWidget * widget);
+cairo_pattern_t * audgui_dark_bg_gradient (const GdkColor & base, int height);
+void audgui_vis_bar_color (const GdkColor & hue, int bar, int n_bars,
+ float & r, float & g, float & b);
+
#endif
diff --git a/src/libaudgui/playlists.cc b/src/libaudgui/playlists.cc
index 6f00008..37c693a 100644
--- a/src/libaudgui/playlists.cc
+++ b/src/libaudgui/playlists.cc
@@ -64,7 +64,7 @@ static void finish_job (void * data)
ImportExportJob * job = (ImportExportJob *) data;
Playlist::GetMode mode = Playlist::Wait;
- if (aud_get_bool (nullptr, "metadata_on_play"))
+ if (aud_get_bool ("metadata_on_play"))
mode = Playlist::NoWait;
if (job->list.exists ())
diff --git a/src/libaudgui/prefs-widget.cc b/src/libaudgui/prefs-widget.cc
index c240ece..7fba25f 100644
--- a/src/libaudgui/prefs-widget.cc
+++ b/src/libaudgui/prefs-widget.cc
@@ -1,6 +1,6 @@
/*
* prefs-widget.c
- * Copyright 2007-2014 Tomasz Moń, William Pitcock, and John Lindgren
+ * Copyright 2007-2014 Tomasz Moń, Ariadne Conill, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
diff --git a/src/libaudgui/prefs-window.cc b/src/libaudgui/prefs-window.cc
index bf839a2..aa81891 100644
--- a/src/libaudgui/prefs-window.cc
+++ b/src/libaudgui/prefs-window.cc
@@ -1,6 +1,6 @@
/*
* prefs-window.cc
- * Copyright 2006-2014 William Pitcock, Tomasz Moń, Michael Färber, and
+ * Copyright 2006-2014 Ariadne Conill, Tomasz Moń, Michael Färber, and
* John Lindgren
*
* Redistribution and use in source and binary forms, with or without
@@ -107,6 +107,7 @@ static const TitleFieldTag title_field_tags[] = {
{ N_("File name") , "${file-name}" },
{ N_("File path") , "${file-path}" },
{ N_("Date") , "${date}" },
+ { N_("Description") , "${description}" },
{ N_("Year") , "${year}" },
{ N_("Comment") , "${comment}" },
{ N_("Codec") , "${codec}" },
@@ -268,6 +269,16 @@ static const PreferencesWidget connectivity_page_widgets[] = {
WidgetCheck (N_("Use authentication with proxy"),
WidgetBool (0, "use_proxy_auth")),
WidgetTable ({{proxy_auth_elements}},
+ WIDGET_CHILD),
+ WidgetCheck (N_("Use SOCKS proxy"),
+ WidgetBool (0, "socks_proxy")),
+ WidgetRadio (N_("SOCKS v4a"),
+ WidgetInt (0, "socks_type"),
+ {0},
+ WIDGET_CHILD),
+ WidgetRadio (N_("SOCKS v5"),
+ WidgetInt (0, "socks_type"),
+ {1},
WIDGET_CHILD)
};
@@ -350,7 +361,14 @@ static const PreferencesWidget advanced_page_widgets[] = {
WidgetCheck (N_("Do not load metadata for songs until played"),
WidgetBool (0, "metadata_on_play")),
WidgetCheck (N_("Probe content of files with no recognized file name extension"),
- WidgetBool (0, "slow_probe"))
+ WidgetBool (0, "slow_probe")),
+ WidgetLabel (N_("<b>Miscellaneous</b>")),
+ WidgetSpin (N_("Step forward/backward by:"),
+ WidgetInt (0, "step_size"),
+ {1, 60, 1, N_("seconds")}),
+ WidgetSpin (N_("Adjust volume by:"),
+ WidgetInt (0, "volume_delta"),
+ {1, 25, 1, N_("percent")})
};
#define TITLESTRING_NPRESETS 8
@@ -454,7 +472,7 @@ static void update_titlestring_cbox (GtkComboBox * cbox, const char * format)
static void on_titlestring_entry_changed (GtkEntry * entry, GtkComboBox * cbox)
{
const char * format = gtk_entry_get_text (entry);
- aud_set_str (nullptr, "generic_title_format", format);
+ aud_set_str ("generic_title_format", format);
update_titlestring_cbox (cbox, format);
}
@@ -536,7 +554,7 @@ static void create_titlestring_widgets (GtkWidget * * cbox, GtkWidget * * entry)
* entry = gtk_entry_new ();
- String format = aud_get_str (nullptr, "generic_title_format");
+ String format = aud_get_str ("generic_title_format");
update_titlestring_cbox ((GtkComboBox *) * cbox, format);
gtk_entry_set_text ((GtkEntry *) * entry, format);
diff --git a/src/libaudgui/preset-browser.cc b/src/libaudgui/preset-browser.cc
index 5b5c78d..c67b3f2 100644
--- a/src/libaudgui/preset-browser.cc
+++ b/src/libaudgui/preset-browser.cc
@@ -26,25 +26,28 @@
#include <libaudcore/audstrings.h>
#include <libaudcore/drct.h>
-#include <libaudcore/equalizer.h>
#include <libaudcore/i18n.h>
#include <libaudcore/vfs.h>
-typedef void (* FilebrowserCallback) (const char * filename);
+typedef void (* PresetAction) (const char * filename, const EqualizerPreset * preset);
static void browser_response (GtkWidget * dialog, int response, void * data)
{
if (response == GTK_RESPONSE_ACCEPT)
{
CharPtr filename (gtk_file_chooser_get_uri ((GtkFileChooser *) dialog));
- ((FilebrowserCallback) data) (filename);
+ auto preset = (const EqualizerPreset *)
+ g_object_get_data ((GObject *) dialog, "eq-preset");
+
+ ((PresetAction) data) (filename, preset);
}
gtk_widget_destroy (dialog);
}
static void show_preset_browser (const char * title, gboolean save,
- const char * default_filename, FilebrowserCallback callback)
+ const char * default_filename, PresetAction callback,
+ const EqualizerPreset * preset)
{
GtkWidget * browser = gtk_file_chooser_dialog_new (title, nullptr, save ?
GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN, _("Cancel"),
@@ -56,87 +59,74 @@ static void show_preset_browser (const char * title, gboolean save,
if (default_filename)
gtk_file_chooser_set_current_name ((GtkFileChooser *) browser, default_filename);
+ if (preset)
+ g_object_set_data_full ((GObject *) browser, "eq-preset",
+ new EqualizerPreset (* preset), aud::delete_obj<EqualizerPreset>);
+
g_signal_connect (browser, "response", (GCallback) browser_response, (void *) callback);
audgui_show_unique_window (AUDGUI_PRESET_BROWSER_WINDOW, browser);
}
-static void do_load_file (const char * filename)
+static void do_load_file (const char * filename, const EqualizerPreset *)
{
- EqualizerPreset preset;
+ Index<EqualizerPreset> presets;
+ presets.append ();
VFSFile file (filename, "r");
- if (! file || ! aud_load_preset_file (preset, file))
+ if (! file || ! aud_load_preset_file (presets[0], file))
return;
- aud_eq_apply_preset (preset);
+ audgui_import_eq_presets (presets);
}
void eq_preset_load_file ()
{
- show_preset_browser (_("Load Preset File"), false, nullptr, do_load_file);
+ show_preset_browser (_("Load Preset File"), false, nullptr, do_load_file, nullptr);
}
-static void do_load_eqf (const char * filename)
+static void do_load_eqf (const char * filename, const EqualizerPreset *)
{
VFSFile file (filename, "r");
if (! file)
return;
- Index<EqualizerPreset> presets = aud_import_winamp_presets (file);
-
- if (presets.len ())
- aud_eq_apply_preset (presets[0]);
+ audgui_import_eq_presets (aud_import_winamp_presets (file));
}
void eq_preset_load_eqf ()
{
- show_preset_browser (_("Load EQF File"), false, nullptr, do_load_eqf);
+ show_preset_browser (_("Load EQF File"), false, nullptr, do_load_eqf, nullptr);
}
-static void do_save_file (const char * filename)
+static void do_save_file (const char * filename, const EqualizerPreset * preset)
{
- EqualizerPreset preset;
- aud_eq_update_preset (preset);
+ g_return_if_fail (preset);
VFSFile file (filename, "w");
if (file)
- aud_save_preset_file (preset, file);
+ aud_save_preset_file (* preset, file);
}
-void eq_preset_save_file ()
+void eq_preset_save_file (const EqualizerPreset & preset)
{
- show_preset_browser (_("Save Preset File"), true, _("<name>.preset"), do_save_file);
+ StringBuf name = str_concat ({preset.name, ".preset"});
+ show_preset_browser (_("Save Preset File"), true, name, do_save_file, & preset);
}
-static void do_save_eqf (const char * filename)
+static void do_save_eqf (const char * filename, const EqualizerPreset * preset)
{
- VFSFile file (filename, "w");
- if (! file)
- return;
+ g_return_if_fail (preset);
- EqualizerPreset preset = EqualizerPreset ();
- preset.name = String ("Preset1");
-
- aud_eq_update_preset (preset);
- aud_export_winamp_preset (preset, file);
-}
-
-void eq_preset_save_eqf ()
-{
- show_preset_browser (_("Save EQF File"), true, _("<name>.eqf"), do_save_eqf);
-}
-
-static void do_import_winamp (const char * filename)
-{
- VFSFile file (filename, "r");
+ VFSFile file (filename, "w");
if (! file)
return;
- audgui_import_eq_presets (aud_import_winamp_presets (file));
+ aud_export_winamp_preset (* preset, file);
}
-void eq_preset_import_winamp ()
+void eq_preset_save_eqf (const EqualizerPreset & preset)
{
- show_preset_browser (_("Import Winamp Presets"), false, nullptr, do_import_winamp);
+ StringBuf name = str_concat ({preset.name, ".eqf"});
+ show_preset_browser (_("Save EQF File"), true, name, do_save_eqf, & preset);
}
diff --git a/src/libaudgui/preset-browser.h b/src/libaudgui/preset-browser.h
index b2d6796..3d6a9ce 100644
--- a/src/libaudgui/preset-browser.h
+++ b/src/libaudgui/preset-browser.h
@@ -20,10 +20,11 @@
#ifndef AUDGUI_PRESET_BROWSER_H
#define AUDGUI_PRESET_BROWSER_H
+#include <libaudcore/equalizer.h>
+
void eq_preset_load_file ();
void eq_preset_load_eqf ();
-void eq_preset_save_file ();
-void eq_preset_save_eqf ();
-void eq_preset_import_winamp ();
+void eq_preset_save_file (const EqualizerPreset & preset);
+void eq_preset_save_eqf (const EqualizerPreset & preset);
#endif // AUDGUI_PRESET_BROWSER_H
diff --git a/src/libaudgui/url-opener.cc b/src/libaudgui/url-opener.cc
index 6c5c5cd..c994b7a 100644
--- a/src/libaudgui/url-opener.cc
+++ b/src/libaudgui/url-opener.cc
@@ -38,7 +38,7 @@ static void open_cb (void * entry)
else
aud_drct_pl_add (text, -1);
- if (aud_get_bool (nullptr, "save_url_history"))
+ if (aud_get_bool ("save_url_history"))
aud_history_add (text);
}
diff --git a/src/libaudgui/util.cc b/src/libaudgui/util.cc
index 2994c89..72cd9c5 100644
--- a/src/libaudgui/util.cc
+++ b/src/libaudgui/util.cc
@@ -190,8 +190,8 @@ EXPORT GtkWidget * audgui_file_entry_new (GtkFileChooserAction action, const cha
GtkWidget * entry = gtk_entry_new ();
auto data = new FileEntryData {action, String (title)};
- auto destroy_cb = [] (void * data) { delete (FileEntryData *) data; };
- g_object_set_data_full ((GObject *) entry, "file-entry-data", data, destroy_cb);
+ g_object_set_data_full ((GObject *) entry, "file-entry-data", data,
+ aud::delete_obj<FileEntryData>);
gtk_entry_set_icon_from_icon_name ((GtkEntry *) entry,
GTK_ENTRY_ICON_SECONDARY, "document-open");
@@ -303,3 +303,92 @@ EXPORT void audgui_simple_message (GtkWidget * * widget, GtkMessageType type,
gtk_widget_show_all (* widget);
}
}
+
+EXPORT cairo_pattern_t * audgui_dark_bg_gradient (const GdkColor & base, int height)
+{
+ float r = 1, g = 1, b = 1;
+
+ /* in a dark theme, try to match the tone of the base color */
+ int v = aud::max (aud::max (base.red, base.green), base.blue);
+
+ if (v >= 10*256 && v < 80*256)
+ {
+ r = (float) base.red / v;
+ g = (float) base.green / v;
+ b = (float) base.blue / v;
+ }
+
+ cairo_pattern_t * gradient = cairo_pattern_create_linear (0, 0, 0, height);
+ cairo_pattern_add_color_stop_rgb (gradient, 0, 0.16 * r, 0.16 * g, 0.16 * b);
+ cairo_pattern_add_color_stop_rgb (gradient, 0.45, 0.11 * r, 0.11 * g, 0.11 * b);
+ cairo_pattern_add_color_stop_rgb (gradient, 0.55, 0.06 * r, 0.06 * g, 0.06 * b);
+ cairo_pattern_add_color_stop_rgb (gradient, 1, 0.09 * r, 0.09 * g, 0.09 * b);
+ return gradient;
+}
+
+static void rgb_to_hsv (float r, float g, float b, float * h, float * s, float * v)
+{
+ float max = aud::max (aud::max (r, g), b);
+ float min = aud::min (aud::min (r, g), b);
+
+ * v = max;
+
+ if (max == min)
+ {
+ * h = 0;
+ * s = 0;
+ return;
+ }
+
+ if (r == max)
+ * h = 1 + (g - b) / (max - min);
+ else if (g == max)
+ * h = 3 + (b - r) / (max - min);
+ else
+ * h = 5 + (r - g) / (max - min);
+
+ * s = (max - min) / max;
+}
+
+static void hsv_to_rgb (float h, float s, float v, float * r, float * g, float * b)
+{
+ for (; h >= 2; h -= 2)
+ {
+ float * p = r;
+ r = g;
+ g = b;
+ b = p;
+ }
+
+ if (h < 1)
+ {
+ * r = 1;
+ * g = 0;
+ * b = 1 - h;
+ }
+ else
+ {
+ * r = 1;
+ * g = h - 1;
+ * b = 0;
+ }
+
+ * r = v * (1 - s * (1 - * r));
+ * g = v * (1 - s * (1 - * g));
+ * b = v * (1 - s * (1 - * b));
+}
+
+EXPORT void audgui_vis_bar_color (const GdkColor & hue, int bar, int n_bars,
+ float & r, float & g, float & b)
+{
+ float h, s, v;
+ rgb_to_hsv (hue.red / 65535.0, hue.green / 65535.0, hue.blue / 65535.0, & h, & s, & v);
+
+ if (s < 0.1) /* monochrome theme? use blue instead */
+ h = 4.6;
+
+ s = 1 - 0.9 * bar / (n_bars - 1);
+ v = 0.75 + 0.25 * bar / (n_bars - 1);
+
+ hsv_to_rgb (h, s, v, & r, & g, & b);
+}
diff --git a/src/libaudqt/Makefile b/src/libaudqt/Makefile
index fa9e7bf..bd3ef16 100644
--- a/src/libaudqt/Makefile
+++ b/src/libaudqt/Makefile
@@ -1,12 +1,16 @@
SHARED_LIB = ${LIB_PREFIX}audqt${LIB_SUFFIX}
LIB_MAJOR = 2
-LIB_MINOR = 1
+LIB_MINOR = 2
SRCS = about-qt.cc \
art-qt.cc \
audqt.cc \
+ colorbutton.cc \
+ eq-preset-qt.cc \
equalizer-qt.cc \
+ file-entry.cc \
fileopener.cc \
+ font-entry.cc \
images.cc \
infopopup-qt.cc \
infowin-qt.cc \
@@ -23,13 +27,16 @@ SRCS = about-qt.cc \
queue-manager-qt.cc \
url-opener-qt.cc \
util-qt.cc \
+ treeview.cc \
volumebutton.cc
-INCLUDES = export.h \
+INCLUDES = colorbutton.h \
+ export.h \
iface.h \
info-widget.h \
libaudqt.h \
- menu.h
+ menu.h \
+ treeview.h
include ../../buildsys.mk
include ../../extra.mk
@@ -45,7 +52,9 @@ CPPFLAGS := -I.. -I../.. \
CFLAGS += ${LIB_CFLAGS}
-LIBS := -L../libaudcore -laudcore \
+LIB_LDFLAGS := -L../libaudcore $(LIB_LDFLAGS)
+
+LIBS := -laudcore \
${LIBS} -lm \
${QT_LIBS}
diff --git a/src/libaudqt/about-qt.cc b/src/libaudqt/about-qt.cc
index fe0a9de..4496e59 100644
--- a/src/libaudqt/about-qt.cc
+++ b/src/libaudqt/about-qt.cc
@@ -1,6 +1,6 @@
/*
* about.cc
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -30,79 +30,81 @@
#include "libaudqt.h"
-static QTabWidget * buildCreditsNotebook (QWidget * parent)
+static QTabWidget * buildCreditsNotebook(QWidget * parent)
{
- const char * data_dir = aud_get_path (AudPath::DataDir);
+ const char * data_dir = aud_get_path(AudPath::DataDir);
const char * titles[2] = {N_("Credits"), N_("License")};
const char * filenames[2] = {"AUTHORS", "COPYING"};
- auto tabs = new QTabWidget (parent);
- tabs->setDocumentMode (true);
- tabs->setMinimumSize (6 * audqt::sizes.OneInch, 2 * audqt::sizes.OneInch);
+ auto tabs = new QTabWidget(parent);
+ tabs->setDocumentMode(true);
+ tabs->setMinimumSize(6 * audqt::sizes.OneInch, 2 * audqt::sizes.OneInch);
- for (int i = 0; i < 2; i ++)
+ for (int i = 0; i < 2; i++)
{
- auto text = VFSFile::read_file (filename_build ({data_dir, filenames[i]}), VFS_APPEND_NULL);
- auto edit = new QPlainTextEdit (text.begin (), parent);
- edit->setReadOnly (true);
- edit->setFrameStyle (QFrame::NoFrame);
- tabs->addTab (edit, _(titles[i]));
+ auto text = VFSFile::read_file(filename_build({data_dir, filenames[i]}),
+ VFS_APPEND_NULL);
+ auto edit = new QPlainTextEdit(text.begin(), parent);
+ edit->setReadOnly(true);
+ edit->setFrameStyle(QFrame::NoFrame);
+ tabs->addTab(edit, _(titles[i]));
}
return tabs;
}
-static QDialog * buildAboutWindow ()
+static QDialog * buildAboutWindow()
{
- const char * about_text = "<big><b>Audacious " VERSION "</b></big><br>" COPYRIGHT;
+ const char * about_text =
+ "<big><b>Audacious " VERSION "</b></big><br>" COPYRIGHT;
const char * website = "https://audacious-media-player.org";
auto window = new QDialog;
- window->setWindowTitle (_("About Audacious"));
+ window->setWindowTitle(_("About Audacious"));
- auto logo = new QLabel (window);
- int logo_size = audqt::to_native_dpi (400);
- logo->setPixmap (QIcon (":/about-logo.svg").pixmap (logo_size, logo_size));
- logo->setAlignment (Qt::AlignHCenter);
+ auto logo = new QLabel(window);
+ int logo_size = audqt::to_native_dpi(400);
+ logo->setPixmap(QIcon(":/about-logo.svg").pixmap(logo_size, logo_size));
+ logo->setAlignment(Qt::AlignHCenter);
- auto text = new QLabel (about_text, window);
- text->setAlignment (Qt::AlignHCenter);
+ auto text = new QLabel(about_text, window);
+ text->setAlignment(Qt::AlignHCenter);
- auto anchor = QString ("<a href='%1'>%1</a>").arg (website);
- auto link_label = new QLabel (anchor, window);
- link_label->setAlignment (Qt::AlignHCenter);
- link_label->setOpenExternalLinks (true);
+ auto anchor = QString("<a href='%1'>%1</a>").arg(website);
+ auto link_label = new QLabel(anchor, window);
+ link_label->setAlignment(Qt::AlignHCenter);
+ link_label->setOpenExternalLinks(true);
- auto layout = audqt::make_vbox (window);
- layout->addSpacing (audqt::sizes.EightPt);
- layout->addWidget (logo);
- layout->addWidget (text);
- layout->addWidget (link_label);
- layout->addWidget (buildCreditsNotebook (window));
+ auto layout = audqt::make_vbox(window);
+ layout->addSpacing(audqt::sizes.EightPt);
+ layout->addWidget(logo);
+ layout->addWidget(text);
+ layout->addWidget(link_label);
+ layout->addWidget(buildCreditsNotebook(window));
return window;
}
static QDialog * s_aboutwin = nullptr;
-namespace audqt {
+namespace audqt
+{
-EXPORT void aboutwindow_show ()
+EXPORT void aboutwindow_show()
{
- if (! s_aboutwin)
+ if (!s_aboutwin)
{
- s_aboutwin = buildAboutWindow ();
- s_aboutwin->setAttribute (Qt::WA_DeleteOnClose);
+ s_aboutwin = buildAboutWindow();
+ s_aboutwin->setAttribute(Qt::WA_DeleteOnClose);
- QObject::connect (s_aboutwin, & QObject::destroyed, [] () {
- s_aboutwin = nullptr;
- });
+ QObject::connect(s_aboutwin, &QObject::destroyed,
+ []() { s_aboutwin = nullptr; });
}
- window_bring_to_front (s_aboutwin);
+ window_bring_to_front(s_aboutwin);
}
-EXPORT void aboutwindow_hide ()
+EXPORT void aboutwindow_hide()
{
if (s_aboutwin)
delete s_aboutwin;
diff --git a/src/libaudqt/art-qt.cc b/src/libaudqt/art-qt.cc
index 3327d91..3c3bad9 100644
--- a/src/libaudqt/art-qt.cc
+++ b/src/libaudqt/art-qt.cc
@@ -1,6 +1,6 @@
/*
* art.cc
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -18,9 +18,9 @@
*/
#include <QApplication>
-#include <QPixmap>
#include <QIcon>
#include <QImage>
+#include <QPixmap>
#include <libaudcore/audstrings.h>
#include <libaudcore/drct.h>
@@ -28,48 +28,55 @@
#include <libaudcore/runtime.h>
#include <libaudqt/libaudqt.h>
-namespace audqt {
+namespace audqt
+{
-EXPORT QImage art_request (const char * filename, bool * queued)
+EXPORT QImage art_request(const char * filename, bool * queued)
{
- AudArtPtr art = aud_art_request (filename, AUD_ART_DATA, queued);
+ AudArtPtr art = aud_art_request(filename, AUD_ART_DATA, queued);
- auto data = art.data ();
- return data ? QImage::fromData ((const uchar *) data->begin (), data->len ()) : QImage ();
+ auto data = art.data();
+ return data ? QImage::fromData((const uchar *)data->begin(), data->len())
+ : QImage();
}
-EXPORT QPixmap art_scale (const QImage & image, unsigned int w, unsigned int h, bool want_hidpi)
+EXPORT QPixmap art_scale(const QImage & image, unsigned int w, unsigned int h,
+ bool want_hidpi)
{
// return original image if requested size is zero,
// or original size is smaller than requested size
- if ((w == 0 && h == 0) || ((unsigned) image.width () <= w && (unsigned) image.height () <= h))
- return QPixmap::fromImage (image);
+ if ((w == 0 && h == 0) ||
+ ((unsigned)image.width() <= w && (unsigned)image.height() <= h))
+ return QPixmap::fromImage(image);
- qreal r = want_hidpi ? qApp->devicePixelRatio () : 1;
- auto pixmap = QPixmap::fromImage (image.scaled (w * r, h * r,
- Qt::KeepAspectRatio, Qt::SmoothTransformation));
+ qreal r = want_hidpi ? qApp->devicePixelRatio() : 1;
+ auto pixmap = QPixmap::fromImage(image.scaled(
+ w * r, h * r, Qt::KeepAspectRatio, Qt::SmoothTransformation));
- pixmap.setDevicePixelRatio (r);
+ pixmap.setDevicePixelRatio(r);
return pixmap;
}
-EXPORT QPixmap art_request (const char * filename, unsigned int w, unsigned int h, bool want_hidpi)
+EXPORT QPixmap art_request(const char * filename, unsigned int w,
+ unsigned int h, bool want_hidpi)
{
- auto img = art_request (filename);
- if (! img.isNull ())
- return art_scale (img, w, h, want_hidpi);
+ auto img = art_request(filename);
+ if (!img.isNull())
+ return art_scale(img, w, h, want_hidpi);
- unsigned size = to_native_dpi (48);
- return get_icon ("audio-x-generic").pixmap (aud::min (w, size), aud::min (h, size));
+ unsigned size = to_native_dpi(48);
+ return get_icon("audio-x-generic")
+ .pixmap(aud::min(w, size), aud::min(h, size));
}
-EXPORT QPixmap art_request_current (unsigned int w, unsigned int h, bool want_hidpi)
+EXPORT QPixmap art_request_current(unsigned int w, unsigned int h,
+ bool want_hidpi)
{
- String filename = aud_drct_get_filename ();
- if (! filename)
- return QPixmap ();
+ String filename = aud_drct_get_filename();
+ if (!filename)
+ return QPixmap();
- return art_request (filename, w, h, want_hidpi);
+ return art_request(filename, w, h, want_hidpi);
}
} // namespace audqt
diff --git a/src/libaudqt/audqt.cc b/src/libaudqt/audqt.cc
index 0677b96..c81eb20 100644
--- a/src/libaudqt/audqt.cc
+++ b/src/libaudqt/audqt.cc
@@ -1,6 +1,6 @@
/*
* util.cc
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -31,7 +31,8 @@
#include "libaudqt-internal.h"
#include "libaudqt.h"
-namespace audqt {
+namespace audqt
+{
static int init_count;
@@ -41,124 +42,160 @@ static PixelMargins margins_local;
EXPORT const PixelSizes & sizes = sizes_local;
EXPORT const PixelMargins & margins = margins_local;
-EXPORT void init ()
+EXPORT void init()
{
- if (init_count ++)
+ if (init_count++)
return;
static char app_name[] = "audacious";
static int dummy_argc = 1;
static char * dummy_argv[] = {app_name, nullptr};
- auto qapp = new QApplication (dummy_argc, dummy_argv);
+ auto qapp = new QApplication(dummy_argc, dummy_argv);
- qapp->setAttribute (Qt::AA_UseHighDpiPixmaps);
+ qapp->setAttribute(Qt::AA_UseHighDpiPixmaps);
#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0)
- qapp->setAttribute (Qt::AA_ForceRasterWidgets);
+ qapp->setAttribute(Qt::AA_ForceRasterWidgets);
#endif
#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
- qapp->setAttribute (Qt::AA_UseStyleSheetPropagationInWidgetStyles);
+ qapp->setAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
#endif
- qapp->setApplicationName (_("Audacious"));
- if (qapp->windowIcon ().isNull ())
- qapp->setWindowIcon (audqt::get_icon (app_name));
+ qapp->setApplicationName(_("Audacious"));
+ if (qapp->windowIcon().isNull())
+ qapp->setWindowIcon(audqt::get_icon(app_name));
+
+ qapp->setQuitOnLastWindowClosed(false);
+
+ auto desktop = qapp->desktop();
+ sizes_local.OneInch =
+ aud::max(96, (desktop->logicalDpiX() + desktop->logicalDpiY()) / 2);
+ sizes_local.TwoPt = aud::rescale(2, 72, sizes_local.OneInch);
+ sizes_local.FourPt = aud::rescale(4, 72, sizes_local.OneInch);
+ sizes_local.EightPt = aud::rescale(8, 72, sizes_local.OneInch);
+
+ margins_local.TwoPt =
+ QMargins(sizes.TwoPt, sizes.TwoPt, sizes.TwoPt, sizes.TwoPt);
+ margins_local.FourPt =
+ QMargins(sizes.FourPt, sizes.FourPt, sizes.FourPt, sizes.FourPt);
+ margins_local.EightPt =
+ QMargins(sizes.EightPt, sizes.EightPt, sizes.EightPt, sizes.EightPt);
+
+#ifdef Q_OS_MAC // Mac-specific font tweaks
+ QApplication::setFont(QApplication::font("QSmallFont"), "QDialog");
+ QApplication::setFont(QApplication::font("QSmallFont"), "QTreeView");
+ QApplication::setFont(QApplication::font("QTipLabel"), "QStatusBar");
+#endif
- qapp->setQuitOnLastWindowClosed (false);
+ log_init();
+}
- auto desktop = qapp->desktop ();
- sizes_local.OneInch = aud::max (96, (desktop->logicalDpiX () + desktop->logicalDpiY ()) / 2);
- sizes_local.TwoPt = aud::rescale (2, 72, sizes_local.OneInch);
- sizes_local.FourPt = aud::rescale (4, 72, sizes_local.OneInch);
- sizes_local.EightPt = aud::rescale (8, 72, sizes_local.OneInch);
+EXPORT void run() { qApp->exec(); }
- margins_local.TwoPt = QMargins (sizes.TwoPt, sizes.TwoPt, sizes.TwoPt, sizes.TwoPt);
- margins_local.FourPt = QMargins (sizes.FourPt, sizes.FourPt, sizes.FourPt, sizes.FourPt);
- margins_local.EightPt = QMargins (sizes.EightPt, sizes.EightPt, sizes.EightPt, sizes.EightPt);
+EXPORT void quit() { qApp->quit(); }
-#ifdef Q_OS_MAC // Mac-specific font tweaks
- QApplication::setFont (QApplication::font ("QSmallFont"), "QDialog");
- QApplication::setFont (QApplication::font ("QSmallFont"), "QTreeView");
- QApplication::setFont (QApplication::font ("QTipLabel"), "QStatusBar");
-#endif
+EXPORT void cleanup()
+{
+ if (--init_count)
+ return;
- log_init ();
-}
+ aboutwindow_hide();
+ eq_presets_hide();
+ equalizer_hide();
+ infopopup_hide_now();
+ infowin_hide();
+ log_inspector_hide();
+ prefswin_hide();
+ queue_manager_hide();
-EXPORT void run ()
-{
- qApp->exec ();
+ log_cleanup();
+
+ delete qApp;
}
-EXPORT void quit ()
+EXPORT QIcon get_icon(const char * name)
{
- qApp->quit ();
+ auto icon = QIcon::fromTheme(name);
+
+ if (icon.isNull())
+ icon = QIcon(QString(":/") + name + ".svg");
+
+ return icon;
}
-EXPORT void cleanup ()
+EXPORT QGradientStops dark_bg_gradient(const QColor & base)
{
- if (-- init_count)
- return;
+ constexpr int s[4] = {40, 28, 16, 24};
+
+ QColor c[4];
+ for (int i = 0; i < 4; i++)
+ c[i] = QColor(s[i], s[i], s[i]);
- aboutwindow_hide ();
- equalizer_hide ();
- infopopup_hide_now ();
- infowin_hide ();
- log_inspector_hide ();
- prefswin_hide ();
- queue_manager_hide ();
+ /* in a dark theme, try to match the tone of the base color */
+ int v = base.value();
+ if (v >= 10 && v < 80)
+ {
+ int r = base.red(), g = base.green(), b = base.blue();
- log_cleanup ();
+ for (int i = 0; i < 4; i++)
+ {
+ c[i] = QColor(r * s[i] / v, g * s[i] / v, b * s[i] / v);
+ }
+ }
- delete qApp;
+ return {{0, c[0]}, {0.45, c[1]}, {0.55, c[2]}, {1, c[3]}};
}
-EXPORT QIcon get_icon (const char * name)
+EXPORT QColor vis_bar_color(const QColor & hue, int bar, int n_bars)
{
- auto icon = QIcon::fromTheme (name);
+ qreal h, s, v;
+ hue.getHsvF(&h, &s, &v);
- if (icon.isNull ())
- icon = QIcon (QString (":/") + name + ".svg");
+ if (s < 0.1) /* monochrome? use blue instead */
+ h = 0.67;
- return icon;
+ s = 1 - 0.9 * bar / (n_bars - 1);
+ v = 0.75 + 0.25 * bar / (n_bars - 1);
+
+ return QColor::fromHsvF(h, s, v);
}
-EXPORT QHBoxLayout * make_hbox (QWidget * parent, int spacing)
+EXPORT QHBoxLayout * make_hbox(QWidget * parent, int spacing)
{
- auto layout = new QHBoxLayout (parent);
- layout->setContentsMargins (0, 0, 0, 0);
- layout->setSpacing (spacing);
+ auto layout = new QHBoxLayout(parent);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(spacing);
return layout;
}
-EXPORT QVBoxLayout * make_vbox (QWidget * parent, int spacing)
+EXPORT QVBoxLayout * make_vbox(QWidget * parent, int spacing)
{
- auto layout = new QVBoxLayout (parent);
- layout->setContentsMargins (0, 0, 0, 0);
- layout->setSpacing (spacing);
+ auto layout = new QVBoxLayout(parent);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(spacing);
return layout;
}
-EXPORT void enable_layout (QLayout * layout, bool enabled)
+EXPORT void enable_layout(QLayout * layout, bool enabled)
{
- int count = layout->count ();
- for (int i = 0; i < count; i ++)
+ int count = layout->count();
+ for (int i = 0; i < count; i++)
{
- auto item = layout->itemAt (i);
- if (QLayout * layout2 = item->layout ())
- enable_layout (layout2, enabled);
- if (QWidget * widget = item->widget ())
- widget->setEnabled (enabled);
+ auto item = layout->itemAt(i);
+ if (QLayout * layout2 = item->layout())
+ enable_layout(layout2, enabled);
+ if (QWidget * widget = item->widget())
+ widget->setEnabled(enabled);
}
}
-EXPORT void clear_layout (QLayout * layout)
+EXPORT void clear_layout(QLayout * layout)
{
- while (QLayoutItem * item = layout->takeAt (0))
+ while (QLayoutItem * item = layout->takeAt(0))
{
- if (QLayout * layout2 = item->layout ())
- clear_layout (layout2);
- if (QWidget * widget = item->widget ())
+ if (QLayout * layout2 = item->layout())
+ clear_layout(layout2);
+ if (QWidget * widget = item->widget())
delete widget;
delete item;
@@ -166,42 +203,43 @@ EXPORT void clear_layout (QLayout * layout)
}
/* the goal is to force a window to come to the front on any Qt platform */
-EXPORT void window_bring_to_front (QWidget * window)
+EXPORT void window_bring_to_front(QWidget * window)
{
- window->show ();
+ window->show();
- Qt::WindowStates state = window->windowState ();
+ Qt::WindowStates state = window->windowState();
state &= ~Qt::WindowMinimized;
state |= Qt::WindowActive;
- window->setWindowState (state);
- window->raise ();
- window->activateWindow ();
+ window->setWindowState(state);
+ window->raise();
+ window->activateWindow();
}
-EXPORT void simple_message (const char * title, const char * text)
+EXPORT void simple_message(const char * title, const char * text)
{
- simple_message (title, text, QMessageBox::NoIcon);
+ simple_message(title, text, QMessageBox::NoIcon);
}
-EXPORT void simple_message (const char * title, const char * text, QMessageBox::Icon icon)
+EXPORT void simple_message(const char * title, const char * text,
+ QMessageBox::Icon icon)
{
- auto msgbox = new QMessageBox (icon, title, text, QMessageBox::Close);
- msgbox->button (QMessageBox::Close)->setText (translate_str (N_("_Close")));
- msgbox->setAttribute (Qt::WA_DeleteOnClose);
- msgbox->show ();
+ auto msgbox = new QMessageBox(icon, title, text, QMessageBox::Close);
+ msgbox->button(QMessageBox::Close)->setText(translate_str(N_("_Close")));
+ msgbox->setAttribute(Qt::WA_DeleteOnClose);
+ msgbox->show();
}
/* translate GTK+ accelerators and also handle dgettext() */
-EXPORT QString translate_str (const char * str, const char * domain)
+EXPORT QString translate_str(const char * str, const char * domain)
{
/* handle null and empty strings */
- if (! str || ! str[0])
- return QString (str);
+ if (!str || !str[0])
+ return QString(str);
/* translate the GTK+ accelerator (_) into a Qt accelerator (&) */
- return QString (dgettext (domain, str)).replace ('_', '&');
+ return QString(dgettext(domain, str)).replace('_', '&');
}
} // namespace audqt
diff --git a/src/libaudqt/colorbutton.cc b/src/libaudqt/colorbutton.cc
new file mode 100644
index 0000000..a3d631a
--- /dev/null
+++ b/src/libaudqt/colorbutton.cc
@@ -0,0 +1,62 @@
+/*
+ * colorbutton.h
+ * Copyright 2019 Ariadne Conill
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions, and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions, and the following disclaimer in the documentation
+ * provided with the distribution.
+ *
+ * This software is provided "as is" and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising from
+ * the use of this software.
+ */
+
+#include "colorbutton.h"
+#include "libaudqt.h"
+
+#include <QColorDialog>
+#include <QPainter>
+
+namespace audqt
+{
+
+ColorButton::ColorButton(QWidget * parent) : QPushButton(parent)
+{
+ connect(this, &QPushButton::clicked, [this]() {
+ auto dialog = findChild<QColorDialog *>();
+ if (!dialog)
+ {
+ dialog = new QColorDialog(m_color, this);
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ connect(dialog, &QColorDialog::colorSelected, this,
+ &ColorButton::setColor);
+ }
+
+ window_bring_to_front(dialog);
+ });
+}
+
+void ColorButton::setColor(const QColor & color)
+{
+ if (color != m_color)
+ {
+ m_color = color;
+ update();
+
+ onColorChanged();
+ }
+}
+
+void ColorButton::paintEvent(QPaintEvent * event)
+{
+ QPushButton::paintEvent(event);
+ QPainter(this).fillRect(rect() - margins.FourPt, m_color);
+}
+
+} // namespace audqt
diff --git a/src/libaudqt/colorbutton.h b/src/libaudqt/colorbutton.h
new file mode 100644
index 0000000..da8803b
--- /dev/null
+++ b/src/libaudqt/colorbutton.h
@@ -0,0 +1,52 @@
+/*
+ * colorbutton.h
+ * Copyright 2019 Ariadne Conill
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions, and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions, and the following disclaimer in the documentation
+ * provided with the distribution.
+ *
+ * This software is provided "as is" and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising from
+ * the use of this software.
+ */
+
+#ifndef LIBAUDQT_COLORBUTTON_H
+#define LIBAUDQT_COLORBUTTON_H
+
+#include "libaudqt/export.h"
+
+#include <QColor>
+#include <QPushButton>
+
+namespace audqt
+{
+
+class LIBAUDQT_PUBLIC ColorButton : public QPushButton
+{
+public:
+ ColorButton(QWidget * parent = nullptr);
+ ~ColorButton(){};
+
+ void setColor(const QColor &);
+
+ QColor color() const { return m_color; }
+
+protected:
+ virtual void onColorChanged(){};
+
+private:
+ void paintEvent(QPaintEvent *) override;
+
+ QColor m_color;
+};
+
+} // namespace audqt
+
+#endif
diff --git a/src/libaudqt/eq-preset-qt.cc b/src/libaudqt/eq-preset-qt.cc
new file mode 100644
index 0000000..33f2196
--- /dev/null
+++ b/src/libaudqt/eq-preset-qt.cc
@@ -0,0 +1,414 @@
+/*
+ * eq-preset-qt.cc
+ * Copyright 2018 John Lindgren
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions, and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions, and the following disclaimer in the documentation
+ * provided with the distribution.
+ *
+ * This software is provided "as is" and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising from
+ * the use of this software.
+ */
+
+#include "libaudqt.h"
+#include "treeview.h"
+
+#include <QBoxLayout>
+#include <QDialog>
+#include <QLineEdit>
+#include <QPointer>
+#include <QPushButton>
+#include <QStandardItemModel>
+
+#include "libaudcore/audstrings.h"
+#include "libaudcore/equalizer.h"
+#include "libaudcore/i18n.h"
+#include "libaudcore/interface.h"
+#include "libaudcore/runtime.h"
+#include "libaudcore/vfs.h"
+
+namespace audqt
+{
+
+class PresetItem : public QStandardItem
+{
+public:
+ explicit PresetItem(const EqualizerPreset & preset)
+ : QStandardItem((const char *)preset.name), preset(preset)
+ {
+ }
+
+ const EqualizerPreset preset;
+};
+
+class PresetModel : public QStandardItemModel
+{
+public:
+ explicit PresetModel(QObject * parent) : QStandardItemModel(0, 1, parent) {}
+
+ void load_all();
+ void save_all();
+
+ QModelIndex add_preset(const EqualizerPreset & preset);
+ QModelIndex add_preset(const char * name);
+ void apply_preset(int row);
+
+ const EqualizerPreset * preset_at(int row) const
+ {
+ auto pitem = static_cast<PresetItem *>(item(row));
+ return pitem ? &pitem->preset : nullptr;
+ }
+
+ bool removeRows(int row, int count,
+ const QModelIndex & parent = QModelIndex()) override
+ {
+ bool removed = QStandardItemModel::removeRows(row, count, parent);
+ m_changed = m_changed || removed;
+ return removed;
+ }
+
+private:
+ bool m_changed = false;
+};
+
+void PresetModel::load_all()
+{
+ clear();
+
+ auto presets = aud_eq_read_presets("eq.preset");
+ for (const EqualizerPreset & preset : presets)
+ appendRow(new PresetItem(preset));
+
+ m_changed = false;
+}
+
+void PresetModel::save_all()
+{
+ if (!m_changed)
+ return;
+
+ Index<EqualizerPreset> presets;
+ for (int row = 0; row < rowCount(); row++)
+ presets.append(*preset_at(row));
+
+ presets.sort([](const EqualizerPreset & a, const EqualizerPreset & b) {
+ return strcmp(a.name, b.name);
+ });
+
+ aud_eq_write_presets(presets, "eq.preset");
+ m_changed = false;
+}
+
+QModelIndex PresetModel::add_preset(const EqualizerPreset & preset)
+{
+ int insert_idx = rowCount();
+ for (int row = 0; row < rowCount(); row++)
+ {
+ if (preset_at(row)->name == preset.name)
+ {
+ insert_idx = row;
+ break;
+ }
+ }
+
+ setItem(insert_idx, new PresetItem(preset));
+ m_changed = true;
+
+ return index(insert_idx, 0);
+}
+
+QModelIndex PresetModel::add_preset(const char * name)
+{
+ EqualizerPreset preset{String(name)};
+ aud_eq_update_preset(preset);
+ return add_preset(preset);
+}
+
+void PresetModel::apply_preset(int row)
+{
+ auto preset = preset_at(row);
+ if (!preset)
+ return;
+
+ aud_eq_apply_preset(*preset);
+ aud_set_bool("equalizer_active", true);
+}
+
+class PresetView : public TreeView
+{
+public:
+ PresetView(QPushButton * export_btn) : m_export_btn(export_btn)
+ {
+ setEditTriggers(QTreeView::NoEditTriggers);
+ setHeaderHidden(true);
+ setIndentation(0);
+ setSelectionMode(QTreeView::ExtendedSelection);
+ setUniformRowHeights(true);
+
+ auto pmodel = new PresetModel(this);
+ pmodel->load_all();
+ setModel(pmodel);
+ }
+
+ PresetModel * pmodel() const { return static_cast<PresetModel *>(model()); }
+
+ void add_imported(const Index<EqualizerPreset> & presets);
+
+ const EqualizerPreset * preset_for_export() const
+ {
+ auto idxs = selectionModel()->selectedIndexes();
+ if (idxs.size() != 1)
+ return nullptr;
+
+ return pmodel()->preset_at(idxs[0].row());
+ }
+
+protected:
+ void activate(const QModelIndex & index) override
+ {
+ pmodel()->apply_preset(index.row());
+ }
+
+ void selectionChanged(const QItemSelection & selected,
+ const QItemSelection & deselected) override
+ {
+ TreeView::selectionChanged(selected, deselected);
+
+ auto idxs = selectionModel()->selectedIndexes();
+ m_export_btn->setEnabled(idxs.size() == 1);
+ }
+
+private:
+ QPushButton * m_export_btn;
+};
+
+void PresetView::add_imported(const Index<EqualizerPreset> & presets)
+{
+ QItemSelection sel;
+ for (auto & preset : presets)
+ {
+ auto idx = pmodel()->add_preset(preset);
+ sel.select(idx, idx);
+ }
+
+ selectionModel()->select(sel, QItemSelectionModel::Clear |
+ QItemSelectionModel::SelectCurrent);
+
+ if (presets.len() == 1)
+ {
+ aud_eq_apply_preset(presets[0]);
+ aud_set_bool("equalizer_active", true);
+ }
+}
+
+static Index<EqualizerPreset> import_file(const char * filename)
+{
+ VFSFile file(filename, "r");
+ if (!file)
+ return Index<EqualizerPreset>();
+
+ if (str_has_suffix_nocase(filename, ".eqf") ||
+ str_has_suffix_nocase(filename, ".q1"))
+ {
+ return aud_import_winamp_presets(file);
+ }
+
+ /* assume everything else is a native preset file */
+ Index<EqualizerPreset> presets;
+ presets.append();
+
+ if (!aud_load_preset_file(presets[0], file))
+ presets.clear();
+
+ return presets;
+}
+
+static bool export_file(const char * filename, const EqualizerPreset & preset)
+{
+ VFSFile file(filename, "w");
+ if (!file)
+ return false;
+
+ if (str_has_suffix_nocase(filename, ".eqf") ||
+ str_has_suffix_nocase(filename, ".q1"))
+ {
+ return aud_export_winamp_preset(preset, file);
+ }
+
+ /* assume everything else is a native preset file */
+ return aud_save_preset_file(preset, file);
+}
+
+static const char * name_filter = N_("Preset files (*.preset *.eqf *.q1)");
+
+static void show_import_dialog(QDialog * parent, PresetView * view)
+{
+ auto dialog = new QFileDialog(parent, _("Load Preset File"));
+
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->setFileMode(QFileDialog::ExistingFile);
+ dialog->setLabelText(QFileDialog::Accept, _("Load"));
+ dialog->setNameFilter(_(name_filter));
+
+ QObject::connect(dialog, &QFileDialog::accepted, [dialog, view]() {
+ auto urls = dialog->selectedUrls();
+ if (urls.size() != 1)
+ return;
+
+ auto filename = urls[0].toEncoded();
+ auto presets = import_file(filename);
+
+ if (presets.len())
+ {
+ view->add_imported(presets);
+ dialog->deleteLater();
+ }
+ else
+ {
+ aud_ui_show_error(
+ str_printf(_("Error loading %s."), filename.constData()));
+ }
+ });
+
+ window_bring_to_front(dialog);
+}
+
+static void show_export_dialog(QDialog * parent, const EqualizerPreset & preset)
+{
+ auto dialog = new QFileDialog(parent, _("Save Preset File"));
+
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->setAcceptMode(QFileDialog::AcceptSave);
+ dialog->setFileMode(QFileDialog::AnyFile);
+ dialog->setLabelText(QFileDialog::Accept, _("Save"));
+ dialog->setNameFilter(_(name_filter));
+
+ /* TODO: replace other illegal characters on Win32 */
+ auto safe =
+ QString(preset.name).replace(QLatin1Char('/'), QLatin1Char('_'));
+ dialog->selectFile(safe + ".preset");
+
+ QObject::connect(dialog, &QFileDialog::accepted, [dialog, preset]() {
+ auto urls = dialog->selectedUrls();
+ if (urls.size() != 1)
+ return;
+
+ auto filename = urls[0].toEncoded();
+
+ if (export_file(filename, preset))
+ dialog->deleteLater();
+ else
+ aud_ui_show_error(
+ str_printf(_("Error saving %s."), filename.constData()));
+ });
+
+ window_bring_to_front(dialog);
+}
+
+static QDialog * create_preset_win()
+{
+ auto win = new QDialog;
+ win->setAttribute(Qt::WA_DeleteOnClose);
+ win->setWindowTitle(_("Equalizer Presets"));
+ win->setContentsMargins(margins.TwoPt);
+
+ auto edit = new QLineEdit;
+ auto save_btn = new QPushButton(_("Save Preset"));
+ save_btn->setIcon(get_icon("document-save"));
+ save_btn->setDisabled(true);
+
+ auto hbox = make_hbox(nullptr);
+ hbox->addWidget(edit);
+ hbox->addWidget(save_btn);
+
+ auto import_btn = new QPushButton(_("Import"));
+ import_btn->setIcon(get_icon("document-open"));
+
+ auto export_btn = new QPushButton(_("Export"));
+ export_btn->setIcon(get_icon("document-save"));
+
+ auto view = new PresetView(export_btn);
+
+ auto hbox2 = make_hbox(nullptr);
+ hbox2->addWidget(import_btn);
+ hbox2->addWidget(export_btn);
+ hbox2->addStretch(1);
+
+ auto revert_btn = new QPushButton(_("Revert Changes"));
+ revert_btn->setIcon(get_icon("edit-undo"));
+ revert_btn->setDisabled(true);
+
+ auto close_btn = new QPushButton(_("Close"));
+ close_btn->setIcon(get_icon("window-close"));
+
+ auto hbox3 = make_hbox(nullptr);
+ hbox3->addWidget(revert_btn);
+ hbox3->addStretch(1);
+ hbox3->addWidget(close_btn);
+
+ auto vbox = make_vbox(win);
+ vbox->addLayout(hbox);
+ vbox->addWidget(view);
+ vbox->addLayout(hbox2);
+ vbox->addLayout(hbox3);
+
+ auto pmodel = view->pmodel();
+
+ QObject::connect(edit, &QLineEdit::textChanged,
+ [save_btn](const QString & text) {
+ save_btn->setEnabled(!text.isEmpty());
+ });
+
+ QObject::connect(save_btn, &QPushButton::clicked,
+ [view, pmodel, edit, revert_btn]() {
+ auto added = pmodel->add_preset(edit->text().toUtf8());
+ view->setCurrentIndex(added);
+ revert_btn->setDisabled(false);
+ });
+
+ QObject::connect(import_btn, &QPushButton::clicked,
+ [win, view]() { show_import_dialog(win, view); });
+
+ QObject::connect(export_btn, &QPushButton::clicked, [win, view]() {
+ auto preset = view->preset_for_export();
+ if (preset != nullptr)
+ show_export_dialog(win, *preset);
+ });
+
+ QObject::connect(pmodel, &PresetModel::rowsRemoved,
+ [revert_btn]() { revert_btn->setDisabled(false); });
+
+ QObject::connect(revert_btn, &QPushButton::clicked, [pmodel, revert_btn]() {
+ pmodel->load_all();
+ revert_btn->setDisabled(true);
+ });
+
+ QObject::connect(close_btn, &QPushButton::clicked, win,
+ &QObject::deleteLater);
+
+ QObject::connect(win, &QObject::destroyed,
+ [pmodel]() { pmodel->save_all(); });
+
+ return win;
+}
+
+static QPointer<QDialog> s_preset_win;
+
+EXPORT void eq_presets_show()
+{
+ if (!s_preset_win)
+ s_preset_win = create_preset_win();
+
+ window_bring_to_front(s_preset_win);
+}
+
+EXPORT void eq_presets_hide() { delete s_preset_win; }
+
+} // namespace audqt
diff --git a/src/libaudqt/equalizer-qt.cc b/src/libaudqt/equalizer-qt.cc
index 01907ce..e603c94 100644
--- a/src/libaudqt/equalizer-qt.cc
+++ b/src/libaudqt/equalizer-qt.cc
@@ -1,6 +1,6 @@
/*
* equalizer.cc
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -23,6 +23,7 @@
#include <QHBoxLayout>
#include <QLabel>
#include <QPainter>
+#include <QPushButton>
#include <QSlider>
#include <QStyle>
#include <QVBoxLayout>
@@ -37,29 +38,31 @@
class VLabel : public QLabel
{
public:
- VLabel (const QString & text, QWidget * parent = nullptr) :
- QLabel (text, parent) {}
+ VLabel(const QString & text, QWidget * parent = nullptr)
+ : QLabel(text, parent)
+ {
+ }
- QSize minimumSizeHint () const
+ QSize minimumSizeHint() const
{
- QSize s = QLabel::minimumSizeHint ();
- return QSize (s.height (), s.width ());
+ QSize s = QLabel::minimumSizeHint();
+ return QSize(s.height(), s.width());
}
- QSize sizeHint () const
+ QSize sizeHint() const
{
- QSize s = QLabel::sizeHint ();
- return QSize (s.height (), s.width ());
+ QSize s = QLabel::sizeHint();
+ return QSize(s.height(), s.width());
}
- void paintEvent (QPaintEvent *)
+ void paintEvent(QPaintEvent *)
{
- QPainter p (this);
- p.rotate (270);
+ QPainter p(this);
+ p.rotate(270);
- QRect box (-height (), 0, height (), width ());
- style ()->drawItemText (& p, box, (int) alignment (), palette (),
- isEnabled (), text (), QPalette::Foreground);
+ QRect box(-height(), 0, height(), width());
+ style()->drawItemText(&p, box, (int)alignment(), palette(), isEnabled(),
+ text(), QPalette::Foreground);
}
};
@@ -68,24 +71,23 @@ class EqualizerSlider : public QWidget
public:
QSlider slider;
- EqualizerSlider (const char * label, QWidget * parent) :
- QWidget (parent),
- slider (Qt::Vertical)
+ EqualizerSlider(const char * label, QWidget * parent)
+ : QWidget(parent), slider(Qt::Vertical)
{
- slider.setMinimumHeight (audqt::sizes.OneInch);
- slider.setRange (-AUD_EQ_MAX_GAIN, AUD_EQ_MAX_GAIN);
- slider.setTickInterval (AUD_EQ_MAX_GAIN >> 1);
- slider.setTickPosition (QSlider::TicksBothSides);
+ slider.setMinimumHeight(audqt::sizes.OneInch);
+ slider.setRange(-AUD_EQ_MAX_GAIN, AUD_EQ_MAX_GAIN);
+ slider.setTickInterval(AUD_EQ_MAX_GAIN >> 1);
+ slider.setTickPosition(QSlider::TicksBothSides);
- auto layout = audqt::make_vbox (this);
- auto value_label = new QLabel ("0");
+ auto layout = audqt::make_vbox(this);
+ auto value_label = new QLabel("0");
- layout->addWidget (new VLabel (label, this), 1, Qt::AlignCenter);
- layout->addWidget (& slider, 0, Qt::AlignCenter);
- layout->addWidget (value_label, 0, Qt::AlignCenter);
+ layout->addWidget(new VLabel(label, this), 1, Qt::AlignCenter);
+ layout->addWidget(&slider, 0, Qt::AlignCenter);
+ layout->addWidget(value_label, 0, Qt::AlignCenter);
- connect (& slider, & QSlider::valueChanged, [value_label] (int value) {
- value_label->setText (QString::number (value));
+ connect(&slider, &QSlider::valueChanged, [value_label](int value) {
+ value_label->setText(QString::number(value));
});
}
};
@@ -93,119 +95,128 @@ public:
class EqualizerWindow : public QDialog
{
public:
- EqualizerWindow ();
+ EqualizerWindow();
private:
QCheckBox m_onoff_checkbox;
EqualizerSlider * m_preamp_slider;
EqualizerSlider * m_sliders[AUD_EQ_NBANDS];
- void updateActive ();
- void updatePreamp ();
- void updateBands ();
+ void updateActive();
+ void updatePreamp();
+ void updateBands();
- const HookReceiver<EqualizerWindow>
- hook1 {"set equalizer_active", this, & EqualizerWindow::updateActive},
- hook2 {"set equalizer_preamp", this, & EqualizerWindow::updatePreamp},
- hook3 {"set equalizer_bands", this, & EqualizerWindow::updateBands};
+ const HookReceiver<EqualizerWindow> hook1{"set equalizer_active", this,
+ &EqualizerWindow::updateActive},
+ hook2{"set equalizer_preamp", this, &EqualizerWindow::updatePreamp},
+ hook3{"set equalizer_bands", this, &EqualizerWindow::updateBands};
};
-EqualizerWindow::EqualizerWindow () :
- m_onoff_checkbox (audqt::translate_str (N_("_Enable")))
+EqualizerWindow::EqualizerWindow()
+ : m_onoff_checkbox(audqt::translate_str(N_("_Enable")))
{
- const char * const names[AUD_EQ_NBANDS] = {N_("31 Hz"), N_("63 Hz"),
- N_("125 Hz"), N_("250 Hz"), N_("500 Hz"), N_("1 kHz"), N_("2 kHz"),
- N_("4 kHz"), N_("8 kHz"), N_("16 kHz")};
+ const char * const names[AUD_EQ_NBANDS] = {
+ N_("31 Hz"), N_("63 Hz"), N_("125 Hz"), N_("250 Hz"), N_("500 Hz"),
+ N_("1 kHz"), N_("2 kHz"), N_("4 kHz"), N_("8 kHz"), N_("16 kHz")};
- auto slider_container = new QWidget (this);
- auto slider_layout = audqt::make_hbox (slider_container, audqt::sizes.TwoPt);
+ auto slider_container = new QWidget(this);
+ auto slider_layout = audqt::make_hbox(slider_container, audqt::sizes.TwoPt);
- m_preamp_slider = new EqualizerSlider (_("Preamp"), this);
- slider_layout->addWidget (m_preamp_slider);
+ m_preamp_slider = new EqualizerSlider(_("Preamp"), this);
+ slider_layout->addWidget(m_preamp_slider);
- auto line = new QFrame (this);
- line->setFrameShape (QFrame::VLine);
- line->setFrameShadow (QFrame::Sunken);
- slider_layout->addWidget (line);
+ auto line = new QFrame(this);
+ line->setFrameShape(QFrame::VLine);
+ line->setFrameShadow(QFrame::Sunken);
+ slider_layout->addWidget(line);
- for (int i = 0; i < AUD_EQ_NBANDS; i ++)
+ for (int i = 0; i < AUD_EQ_NBANDS; i++)
{
- m_sliders[i] = new EqualizerSlider (_(names[i]), this);
- slider_layout->addWidget (m_sliders[i]);
+ m_sliders[i] = new EqualizerSlider(_(names[i]), this);
+ slider_layout->addWidget(m_sliders[i]);
}
- auto layout = audqt::make_vbox (this);
- layout->setSizeConstraint (QLayout::SetFixedSize);
- layout->addWidget (& m_onoff_checkbox);
- layout->addWidget (slider_container);
+ auto zero_button = new QPushButton(_("Reset to Zero"), this);
+ auto preset_button = new QPushButton(_("Presets ..."), this);
- setWindowTitle (_("Equalizer"));
- setContentsMargins (audqt::margins.EightPt);
+ auto hbox = audqt::make_hbox(nullptr);
+ hbox->addWidget(&m_onoff_checkbox);
+ hbox->addStretch(1);
+ hbox->addWidget(zero_button);
+ hbox->addWidget(preset_button);
- m_onoff_checkbox.setFocus ();
+ auto layout = audqt::make_vbox(this);
+ layout->setSizeConstraint(QLayout::SetFixedSize);
+ layout->addLayout(hbox);
+ layout->addWidget(slider_container);
- updateActive ();
- updatePreamp ();
- updateBands ();
+ setWindowTitle(_("Equalizer"));
+ setContentsMargins(audqt::margins.EightPt);
- connect (& m_onoff_checkbox, & QCheckBox::stateChanged, [] (int state) {
- aud_set_bool (nullptr, "equalizer_active", (state == Qt::Checked));
- });
+ m_onoff_checkbox.setFocus();
- connect (& m_preamp_slider->slider, & QSlider::valueChanged, [] (int value) {
- aud_set_int (nullptr, "equalizer_preamp", value);
+ updateActive();
+ updatePreamp();
+ updateBands();
+
+ connect(&m_onoff_checkbox, &QCheckBox::stateChanged, [](int state) {
+ aud_set_bool("equalizer_active", (state == Qt::Checked));
});
- for (int i = 0; i < AUD_EQ_NBANDS; i ++)
+ connect(zero_button, &QPushButton::clicked,
+ []() { aud_eq_apply_preset(EqualizerPreset()); });
+
+ connect(preset_button, &QPushButton::clicked, audqt::eq_presets_show);
+
+ connect(&m_preamp_slider->slider, &QSlider::valueChanged,
+ [](int value) { aud_set_int("equalizer_preamp", value); });
+
+ for (int i = 0; i < AUD_EQ_NBANDS; i++)
{
- connect (& m_sliders[i]->slider, & QSlider::valueChanged, [i] (int value) {
- aud_eq_set_band (i, value);
- });
+ connect(&m_sliders[i]->slider, &QSlider::valueChanged,
+ [i](int value) { aud_eq_set_band(i, value); });
}
}
-void EqualizerWindow::updateActive ()
+void EqualizerWindow::updateActive()
{
- bool active = aud_get_bool (nullptr, "equalizer_active");
- m_onoff_checkbox.setCheckState (active ? Qt::Checked : Qt::Unchecked);
+ bool active = aud_get_bool("equalizer_active");
+ m_onoff_checkbox.setCheckState(active ? Qt::Checked : Qt::Unchecked);
}
-void EqualizerWindow::updatePreamp ()
+void EqualizerWindow::updatePreamp()
{
- m_preamp_slider->slider.setValue (aud_get_int (nullptr, "equalizer_preamp"));
+ m_preamp_slider->slider.setValue(aud_get_int("equalizer_preamp"));
}
-void EqualizerWindow::updateBands ()
+void EqualizerWindow::updateBands()
{
double values[AUD_EQ_NBANDS];
- aud_eq_get_bands (values);
+ aud_eq_get_bands(values);
- for (int i = 0; i < AUD_EQ_NBANDS; i ++)
- m_sliders[i]->slider.setValue (values[i]);
+ for (int i = 0; i < AUD_EQ_NBANDS; i++)
+ m_sliders[i]->slider.setValue(values[i]);
}
static EqualizerWindow * s_equalizer = nullptr;
-namespace audqt {
+namespace audqt
+{
-EXPORT void equalizer_show ()
+EXPORT void equalizer_show()
{
- if (! s_equalizer)
+ if (!s_equalizer)
{
s_equalizer = new EqualizerWindow;
- s_equalizer->setAttribute (Qt::WA_DeleteOnClose);
+ s_equalizer->setAttribute(Qt::WA_DeleteOnClose);
- QObject::connect (s_equalizer, & QObject::destroyed, [] () {
- s_equalizer = nullptr;
- });
+ QObject::connect(s_equalizer, &QObject::destroyed,
+ []() { s_equalizer = nullptr; });
}
- window_bring_to_front (s_equalizer);
+ window_bring_to_front(s_equalizer);
}
-EXPORT void equalizer_hide ()
-{
- delete s_equalizer;
-}
+EXPORT void equalizer_hide() { delete s_equalizer; }
} // namespace audqt
diff --git a/src/libaudqt/export.h b/src/libaudqt/export.h
index 457e848..8662a73 100644
--- a/src/libaudqt/export.h
+++ b/src/libaudqt/export.h
@@ -21,13 +21,13 @@
#define LIBAUDQT_EXPORT_H
#ifdef _WIN32
- #ifdef LIBAUDQT_BUILD
- #define LIBAUDQT_PUBLIC __declspec(dllexport)
- #else
- #define LIBAUDQT_PUBLIC __declspec(dllimport)
- #endif
+#ifdef LIBAUDQT_BUILD
+#define LIBAUDQT_PUBLIC __declspec(dllexport)
#else
- #define LIBAUDQT_PUBLIC __attribute__ ((visibility ("default")))
+#define LIBAUDQT_PUBLIC __declspec(dllimport)
+#endif
+#else
+#define LIBAUDQT_PUBLIC __attribute__((visibility("default")))
#endif
#endif // LIBAUDQT_EXPORT_H
diff --git a/src/libaudqt/file-entry.cc b/src/libaudqt/file-entry.cc
new file mode 100644
index 0000000..9c04068
--- /dev/null
+++ b/src/libaudqt/file-entry.cc
@@ -0,0 +1,128 @@
+/*
+ * file-entry.cc
+ * Copyright 2018 John Lindgren
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions, and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions, and the following disclaimer in the documentation
+ * provided with the distribution.
+ *
+ * This software is provided "as is" and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising from
+ * the use of this software.
+ */
+
+#include "libaudqt.h"
+
+#include <QAction>
+#include <QLineEdit>
+#include <QPointer>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+
+namespace audqt
+{
+
+class FileEntry : public QLineEdit
+{
+public:
+ FileEntry(QWidget * parent, const char * title,
+ QFileDialog::FileMode file_mode,
+ QFileDialog::AcceptMode accept_mode)
+ : QLineEdit(parent), m_title(title), m_file_mode(file_mode),
+ m_accept_mode(accept_mode),
+ m_action(get_icon("document-open"), _("Browse"), nullptr)
+ {
+ addAction(&m_action, TrailingPosition);
+ connect(&m_action, &QAction::triggered, this, &FileEntry::show_dialog);
+ }
+
+private:
+ QFileDialog * create_dialog();
+ void show_dialog();
+
+ const QString m_title;
+ const QFileDialog::FileMode m_file_mode;
+ const QFileDialog::AcceptMode m_accept_mode;
+
+ QAction m_action;
+ QPointer<QFileDialog> m_dialog;
+};
+
+QFileDialog * FileEntry::create_dialog()
+{
+ auto dialog = new QFileDialog(this, m_title);
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->setFileMode(m_file_mode);
+ dialog->setAcceptMode(m_accept_mode);
+
+ String uri = file_entry_get_uri(this);
+ if (uri)
+ {
+ // As of Qt 5.11, selectUrl() works fine with the built-in Qt dialog
+ // but has no effect on the GTK-based dialog. As a workaround, try to
+ // get a local file path and use selectFile() instead.
+ StringBuf local = uri_to_filename(uri);
+ if (local)
+ dialog->selectFile((const char *)local);
+ else
+ dialog->selectUrl(QUrl((const char *)uri));
+ }
+
+ QObject::connect(dialog, &QFileDialog::accepted, [this, dialog]() {
+ auto urls = dialog->selectedUrls();
+ if (urls.length() == 1)
+ file_entry_set_uri(this, urls[0].toEncoded().constData());
+ });
+
+ return dialog;
+}
+
+void FileEntry::show_dialog()
+{
+ if (!m_dialog)
+ m_dialog = create_dialog();
+
+ window_bring_to_front(m_dialog);
+}
+
+EXPORT QLineEdit * file_entry_new(QWidget * parent, const char * title,
+ QFileDialog::FileMode file_mode,
+ QFileDialog::AcceptMode accept_mode)
+{
+ return new FileEntry(parent, title, file_mode, accept_mode);
+}
+
+EXPORT String file_entry_get_uri(QLineEdit * entry)
+{
+ QByteArray text = entry->text().toUtf8();
+
+ if (text.isEmpty())
+ return String();
+ else if (strstr(text, "://"))
+ return String(text);
+ else
+ return String(filename_to_uri(
+ filename_normalize(filename_expand(str_copy(text)))));
+}
+
+EXPORT void file_entry_set_uri(QLineEdit * entry, const char * uri)
+{
+ if (!uri || !uri[0])
+ {
+ entry->clear();
+ return;
+ }
+
+ StringBuf path = uri_to_filename(uri, false);
+ entry->setText(path ? filename_contract(std::move(path)) : uri);
+ entry->end(false);
+}
+
+} // namespace audqt
diff --git a/src/libaudqt/fileopener.cc b/src/libaudqt/fileopener.cc
index dc5691f..1ab1e29 100644
--- a/src/libaudqt/fileopener.cc
+++ b/src/libaudqt/fileopener.cc
@@ -26,110 +26,100 @@
#include <libaudqt/libaudqt.h>
-namespace audqt {
+namespace audqt
+{
static aud::array<FileMode, QFileDialog *> s_dialogs;
-static void import_playlist (Playlist playlist, const String & filename)
+static void import_playlist(Playlist playlist, const String & filename)
{
- playlist.set_filename (filename);
- playlist.remove_all_entries ();
- playlist.insert_entry (0, filename, Tuple (), false);
+ playlist.set_filename(filename);
+ playlist.remove_all_entries();
+ playlist.insert_entry(0, filename, Tuple(), false);
}
-static void export_playlist (Playlist playlist, const String & filename)
+static void export_playlist(Playlist playlist, const String & filename)
{
Playlist::GetMode mode = Playlist::Wait;
- if (aud_get_bool (nullptr, "metadata_on_play"))
+ if (aud_get_bool("metadata_on_play"))
mode = Playlist::NoWait;
- playlist.set_filename (filename);
- playlist.save_to_file (filename, mode);
+ playlist.set_filename(filename);
+ playlist.save_to_file(filename, mode);
}
-EXPORT void fileopener_show (FileMode mode)
+EXPORT void fileopener_show(FileMode mode)
{
- QFileDialog * & dialog = s_dialogs[mode];
+ QFileDialog *& dialog = s_dialogs[mode];
- if (! dialog)
+ if (!dialog)
{
- static constexpr aud::array<FileMode, const char *> titles {
- N_("Open Files"),
- N_("Open Folder"),
- N_("Add Files"),
- N_("Add Folder"),
- N_("Import Playlist"),
- N_("Export Playlist")
- };
-
- static constexpr aud::array<FileMode, const char *> labels {
- N_("Open"),
- N_("Open"),
- N_("Add"),
- N_("Add"),
- N_("Import"),
- N_("Export")
- };
-
- static constexpr aud::array<FileMode, QFileDialog::FileMode> modes {
- QFileDialog::ExistingFiles,
- QFileDialog::Directory,
- QFileDialog::ExistingFiles,
- QFileDialog::Directory,
- QFileDialog::ExistingFile,
- QFileDialog::AnyFile
- };
-
- String path = aud_get_str ("audgui", "filesel_path");
- dialog = new QFileDialog (nullptr, _(titles[mode]), QString (path));
-
- dialog->setAttribute (Qt::WA_DeleteOnClose);
- dialog->setFileMode (modes[mode]);
- dialog->setLabelText (QFileDialog::Accept, _(labels[mode]));
+ static constexpr aud::array<FileMode, const char *> titles{
+ N_("Open Files"), N_("Open Folder"), N_("Add Files"),
+ N_("Add Folder"), N_("Import Playlist"), N_("Export Playlist")};
+
+ static constexpr aud::array<FileMode, const char *> labels{
+ N_("Open"), N_("Open"), N_("Add"),
+ N_("Add"), N_("Import"), N_("Export")};
+
+ static constexpr aud::array<FileMode, QFileDialog::FileMode> modes{
+ QFileDialog::ExistingFiles, QFileDialog::Directory,
+ QFileDialog::ExistingFiles, QFileDialog::Directory,
+ QFileDialog::ExistingFile, QFileDialog::AnyFile};
+
+ String path = aud_get_str("audgui", "filesel_path");
+ dialog = new QFileDialog(nullptr, _(titles[mode]), QString(path));
+
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->setFileMode(modes[mode]);
+ dialog->setLabelText(QFileDialog::Accept, _(labels[mode]));
if (mode == FileMode::ExportPlaylist)
- dialog->setAcceptMode (QFileDialog::AcceptSave);
-
- QObject::connect (dialog, & QFileDialog::directoryEntered, [] (const QString & path)
- { aud_set_str ("audgui", "filesel_path", path.toUtf8 ().constData ()); });
-
- auto playlist = Playlist::active_playlist ();
-
- QObject::connect (dialog, & QFileDialog::accepted, [dialog, mode, playlist] ()
- {
- Index<PlaylistAddItem> files;
- for (const QUrl & url : dialog->selectedUrls ())
- files.append (String (url.toEncoded ().constData ()));
-
- switch (mode)
- {
- case FileMode::Add:
- case FileMode::AddFolder:
- aud_drct_pl_add_list (std::move (files), -1);
- break;
- case FileMode::Open:
- case FileMode::OpenFolder:
- aud_drct_pl_open_list (std::move (files));
- break;
- case FileMode::ImportPlaylist:
- if (files.len () == 1)
- import_playlist (playlist, files[0].filename);
- break;
- case FileMode::ExportPlaylist:
- if (files.len () == 1)
- export_playlist (playlist, files[0].filename);
- break;
- default:
- /* not reached */
- break;
- }
- });
-
- QObject::connect (dialog, & QObject::destroyed, [& dialog] ()
- { dialog = nullptr; });
+ dialog->setAcceptMode(QFileDialog::AcceptSave);
+
+ QObject::connect(dialog, &QFileDialog::directoryEntered,
+ [](const QString & path) {
+ aud_set_str("audgui", "filesel_path",
+ path.toUtf8().constData());
+ });
+
+ auto playlist = Playlist::active_playlist();
+
+ QObject::connect(
+ dialog, &QFileDialog::accepted, [dialog, mode, playlist]() {
+ Index<PlaylistAddItem> files;
+ for (const QUrl & url : dialog->selectedUrls())
+ files.append(String(url.toEncoded().constData()));
+
+ switch (mode)
+ {
+ case FileMode::Add:
+ case FileMode::AddFolder:
+ aud_drct_pl_add_list(std::move(files), -1);
+ break;
+ case FileMode::Open:
+ case FileMode::OpenFolder:
+ aud_drct_pl_open_list(std::move(files));
+ break;
+ case FileMode::ImportPlaylist:
+ if (files.len() == 1)
+ import_playlist(playlist, files[0].filename);
+ break;
+ case FileMode::ExportPlaylist:
+ if (files.len() == 1)
+ export_playlist(playlist, files[0].filename);
+ break;
+ default:
+ /* not reached */
+ break;
+ }
+ });
+
+ QObject::connect(dialog, &QObject::destroyed,
+ [&dialog]() { dialog = nullptr; });
}
- window_bring_to_front (dialog);
+ window_bring_to_front(dialog);
}
} // namespace audqt
diff --git a/src/libaudqt/font-entry.cc b/src/libaudqt/font-entry.cc
new file mode 100644
index 0000000..95b4ff5
--- /dev/null
+++ b/src/libaudqt/font-entry.cc
@@ -0,0 +1,167 @@
+/*
+ * font-entry.cc
+ * Copyright 2015 John Lindgren
+ * Copyright 2019 Ariadne Conill
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions, and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions, and the following disclaimer in the documentation
+ * provided with the distribution.
+ *
+ * This software is provided "as is" and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising from
+ * the use of this software.
+ */
+
+#include "libaudqt.h"
+
+#include <QAction>
+#include <QFontDialog>
+#include <QLineEdit>
+#include <QPointer>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+
+namespace audqt
+{
+
+class FontEntry : public QLineEdit
+{
+public:
+ FontEntry(QWidget * parent = nullptr, const char * font = nullptr)
+ : QLineEdit(parent),
+ m_action(get_icon("preferences-desktop-font"), _("Set Font"), nullptr)
+ {
+ addAction(&m_action, TrailingPosition);
+ connect(&m_action, &QAction::triggered, this, &FontEntry::show_dialog);
+
+ if (font)
+ setText(font);
+
+ end(false);
+ }
+
+private:
+ void show_dialog();
+
+ QAction m_action;
+ QPointer<QFontDialog> m_dialog;
+};
+
+/* parse a subset of Pango font descriptions */
+EXPORT QFont qfont_from_string(const char * name)
+{
+ auto family = str_copy(name);
+ int size = 0;
+ QFont::Weight weight = QFont::Normal;
+ QFont::Style style = QFont::StyleNormal;
+ QFont::Stretch stretch = QFont::Unstretched;
+
+ while (1)
+ {
+ /* check for attributes */
+ bool attr_found = false;
+ const char * space = strrchr(family, ' ');
+
+ if (space)
+ {
+ const char * attr = space + 1;
+ int num = str_to_int(attr);
+
+ attr_found = true;
+
+ if (num > 0)
+ size = num;
+ else if (!strcmp(attr, "Light"))
+ weight = QFont::Light;
+ else if (!strcmp(attr, "Bold"))
+ weight = QFont::Bold;
+ else if (!strcmp(attr, "Oblique"))
+ style = QFont::StyleOblique;
+ else if (!strcmp(attr, "Italic"))
+ style = QFont::StyleItalic;
+ else if (!strcmp(attr, "Condensed"))
+ stretch = QFont::Condensed;
+ else if (!strcmp(attr, "Expanded"))
+ stretch = QFont::Expanded;
+ else
+ attr_found = false;
+ }
+
+ if (!attr_found)
+ {
+ QFont font((const char *)family);
+
+ if (size > 0)
+ font.setPointSize(size);
+ if (weight != QFont::Normal)
+ font.setWeight(weight);
+ if (style != QFont::StyleNormal)
+ font.setStyle(style);
+ if (stretch != QFont::Unstretched)
+ font.setStretch(stretch);
+
+ return font;
+ }
+
+ family.resize(space - family);
+ }
+}
+
+EXPORT StringBuf qfont_to_string(const QFont & font)
+{
+ StringBuf font_str = str_copy(font.family().toUtf8());
+
+ auto weight = font.weight();
+ auto style = font.style();
+ auto stretch = font.stretch();
+
+ if (weight == QFont::Light)
+ font_str.insert(-1, " Light");
+ else if (weight == QFont::Bold)
+ font_str.insert(-1, " Bold");
+
+ if (style == QFont::StyleOblique)
+ font_str.insert(-1, " Oblique");
+ else if (style == QFont::StyleItalic)
+ font_str.insert(-1, " Italic");
+
+ if (stretch == QFont::Condensed)
+ font_str.insert(-1, " Condensed");
+ else if (stretch == QFont::Expanded)
+ font_str.insert(-1, " Expanded");
+
+ str_append_printf(font_str, " %d", font.pointSize());
+
+ return font_str;
+}
+
+void FontEntry::show_dialog()
+{
+ if (!m_dialog)
+ {
+ m_dialog = new QFontDialog(this);
+
+ QObject::connect(m_dialog, &QFontDialog::fontSelected,
+ [this](const QFont & font) {
+ setText((const char *)qfont_to_string(font));
+ end(false);
+ });
+ }
+
+ m_dialog->setCurrentFont(qfont_from_string(text().toUtf8()));
+ window_bring_to_front(m_dialog);
+}
+
+EXPORT QLineEdit * font_entry_new(QWidget * parent, const char * font)
+{
+ return new FontEntry(parent, font);
+}
+
+} // namespace audqt
diff --git a/src/libaudqt/iface.h b/src/libaudqt/iface.h
index fe36766..99b0ff4 100644
--- a/src/libaudqt/iface.h
+++ b/src/libaudqt/iface.h
@@ -1,6 +1,6 @@
/*
* iface.h
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -25,29 +25,37 @@
#include <libaudqt/libaudqt.h>
#include <libaudqt/menu.h>
-namespace audqt {
+namespace audqt
+{
class LIBAUDQT_PUBLIC QtIfacePlugin : public IfacePlugin
{
public:
- constexpr QtIfacePlugin (PluginInfo info) : IfacePlugin (info) {}
-
- void show_about_window () { aboutwindow_show (); }
- void hide_about_window () { aboutwindow_hide (); }
-
- void show_filebrowser (bool open)
- { fileopener_show (open ? FileMode::Open : FileMode::Add); }
-
- void hide_filebrowser () {}
- void show_jump_to_song () {}
- void hide_jump_to_song () {}
- void show_prefs_window () { prefswin_show (); }
- void hide_prefs_window () { prefswin_hide (); }
-
- void plugin_menu_add (AudMenuID id, void func (), const char * name, const char * icon)
- { menu_add (id, func, name, icon); }
- void plugin_menu_remove (AudMenuID id, void func ())
- { menu_remove (id, func); }
+ constexpr QtIfacePlugin(PluginInfo info) : IfacePlugin(info) {}
+
+ void show_about_window() { aboutwindow_show(); }
+ void hide_about_window() { aboutwindow_hide(); }
+
+ void show_filebrowser(bool open)
+ {
+ fileopener_show(open ? FileMode::Open : FileMode::Add);
+ }
+
+ void hide_filebrowser() {}
+ void show_jump_to_song() {}
+ void hide_jump_to_song() {}
+ void show_prefs_window() { prefswin_show(); }
+ void hide_prefs_window() { prefswin_hide(); }
+
+ void plugin_menu_add(AudMenuID id, void func(), const char * name,
+ const char * icon)
+ {
+ menu_add(id, func, name, icon);
+ }
+ void plugin_menu_remove(AudMenuID id, void func())
+ {
+ menu_remove(id, func);
+ }
};
} // namespace audqt
diff --git a/src/libaudqt/images.qrc b/src/libaudqt/images.qrc
index 93c2ebd..a5f18ef 100644
--- a/src/libaudqt/images.qrc
+++ b/src/libaudqt/images.qrc
@@ -50,6 +50,7 @@
<file alias="media-skip-backward.svg">../../images/media-skip-backward.svg</file>
<file alias="media-skip-forward.svg">../../images/media-skip-forward.svg</file>
<file alias="multimedia-volume-control.svg">../../images/multimedia-volume-control.svg</file>
+ <file alias="preferences-desktop-font.svg">../../images/preferences-desktop-font.svg</file>
<file alias="preferences-system.svg">../../images/preferences-system.svg</file>
<file alias="process-stop.svg">../../images/process-stop.svg</file>
<file alias="system-run.svg">../../images/system-run.svg</file>
diff --git a/src/libaudqt/info-widget.cc b/src/libaudqt/info-widget.cc
index c1eb083..0baa2fd 100644
--- a/src/libaudqt/info-widget.cc
+++ b/src/libaudqt/info-widget.cc
@@ -1,7 +1,7 @@
/*
* info-widget.h
* Copyright 2006-2017 René Bertin, Thomas Lange, John Lindgren,
- * William Pitcock, Tomasz Moń, and Eugene Zagidullin
+ * Ariadne Conill, Tomasz Moń, and Eugene Zagidullin
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -19,32 +19,40 @@
*/
#include "info-widget.h"
-#include "libaudqt.h"
#include "libaudqt-internal.h"
+#include "libaudqt.h"
#include <QHeaderView>
+#include <QKeyEvent>
+#include <QPointer>
#include <libaudcore/i18n.h>
#include <libaudcore/probe.h>
+#include <libaudcore/runtime.h>
#include <libaudcore/tuple.h>
-namespace audqt {
+namespace audqt
+{
-struct TupleFieldMap {
+struct TupleFieldMap
+{
const char * name;
Tuple::Field field;
bool editable;
};
+static const char * varied_str = N_("<various>");
+
static const TupleFieldMap tuple_field_map[] = {
{N_("Metadata"), Tuple::Invalid, false},
+ {N_("Title"), Tuple::Title, true},
{N_("Artist"), Tuple::Artist, true},
{N_("Album"), Tuple::Album, true},
- {N_("Title"), Tuple::Title, true},
+ {N_("Album Artist"), Tuple::AlbumArtist, true},
{N_("Track Number"), Tuple::Track, true},
{N_("Genre"), Tuple::Genre, true},
{N_("Comment"), Tuple::Comment, true},
- {N_("Album Artist"), Tuple::AlbumArtist, true},
+ {N_("Description"), Tuple::Description, true},
{N_("Composer"), Tuple::Composer, true},
{N_("Performer"), Tuple::Performer, true},
{N_("Recording Year"), Tuple::Year, true},
@@ -56,160 +64,356 @@ static const TupleFieldMap tuple_field_map[] = {
{N_("Codec"), Tuple::Codec, false},
{N_("Quality"), Tuple::Quality, false},
{N_("Bitrate"), Tuple::Bitrate, false},
-};
+ {N_("MusicBrainz ID"), Tuple::MusicBrainzID, false}};
+
+static const TupleFieldMap * to_field_map(const QModelIndex & index)
+{
+ int row = index.row();
+ if (row < 0 || row >= aud::n_elems(tuple_field_map))
+ return nullptr;
+
+ return &tuple_field_map[row];
+}
+
+static QModelIndex sibling_field_index(const QModelIndex & current,
+ int direction)
+{
+ QModelIndex index = current;
+
+ while (1)
+ {
+ index = index.sibling(index.row() + direction, index.column());
+ auto map = to_field_map(index);
+
+ if (!map)
+ return QModelIndex();
+ if (map->field != Tuple::Invalid)
+ return index;
+ }
+}
+
+static QString tuple_field_to_str(const Tuple & tuple, Tuple::Field field)
+{
+ switch (tuple.get_value_type(field))
+ {
+ case Tuple::String:
+ return QString(tuple.get_str(field));
+ case Tuple::Int:
+ return QString::number(tuple.get_int(field));
+ default:
+ return QString();
+ }
+}
+
+static void tuple_field_set_from_str(Tuple & tuple, Tuple::Field field,
+ const QString & str)
+{
+ if (str.isEmpty())
+ tuple.unset(field);
+ else if (Tuple::field_get_type(field) == Tuple::String)
+ tuple.set_str(field, str.toUtf8());
+ else
+ tuple.set_int(field, str.toInt());
+}
+
+static bool tuple_field_is_same(const Tuple & a, const Tuple & b,
+ Tuple::Field field)
+{
+ auto a_type = a.get_value_type(field);
+ if (a_type != b.get_value_type(field))
+ return false;
+
+ switch (a_type)
+ {
+ case Tuple::String:
+ return (a.get_str(field) == b.get_str(field));
+ case Tuple::Int:
+ return (a.get_int(field) == b.get_int(field));
+ default:
+ return true;
+ }
+}
+
+static void tuple_field_copy(Tuple & dest, const Tuple & src,
+ Tuple::Field field)
+{
+ switch (src.get_value_type(field))
+ {
+ case Tuple::String:
+ dest.set_str(field, src.get_str(field));
+ break;
+ case Tuple::Int:
+ dest.set_int(field, src.get_int(field));
+ break;
+ default:
+ dest.unset(field);
+ break;
+ }
+}
class InfoModel : public QAbstractTableModel
{
public:
- InfoModel (QObject * parent = nullptr) :
- QAbstractTableModel (parent) {}
+ enum
+ {
+ Col_Name = 0,
+ Col_Value = 1
+ };
+
+ InfoModel(QObject * parent = nullptr) : QAbstractTableModel(parent) {}
+
+ int rowCount(const QModelIndex &) const override
+ {
+ return aud::n_elems(tuple_field_map);
+ }
+ int columnCount(const QModelIndex &) const override { return 2; }
- int rowCount (const QModelIndex & parent = QModelIndex ()) const
- { return aud::n_elems (tuple_field_map); }
- int columnCount (const QModelIndex & parent = QModelIndex ()) const
- { return 2; }
+ QVariant data(const QModelIndex & index, int role) const override;
+ bool setData(const QModelIndex & index, const QVariant & value,
+ int role) override;
+ Qt::ItemFlags flags(const QModelIndex & index) const override;
- QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const;
- bool setData (const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
- Qt::ItemFlags flags (const QModelIndex & index) const;
+ void setItems(Index<PlaylistAddItem> && items)
+ {
+ m_items = std::move(items);
+ revertTupleData();
+ }
- void setTupleData (const Tuple & tuple, String filename, PluginHandle * plugin)
+ void linkEnabled(QWidget * widget)
{
- m_tuple = tuple.ref ();
- m_filename = filename;
- m_plugin = plugin;
- m_dirty = false;
+ widget->setEnabled(m_changed_mask != 0);
+ m_linked_widgets.append(widget);
}
- bool updateFile () const;
+ void revertTupleData();
+ bool updateFile() const;
private:
+ void updateEnabled()
+ {
+ for (auto & widget : m_linked_widgets)
+ {
+ if (widget)
+ widget->setEnabled(m_changed_mask != 0);
+ }
+ }
+
+ /* set of filenames, original tuples, decoders */
+ Index<PlaylistAddItem> m_items;
+ /* local (possibly edited) tuple */
Tuple m_tuple;
- String m_filename;
- PluginHandle * m_plugin = nullptr;
- bool m_dirty = false;
+ /* bitmask of fields which vary between tuples and will be preserved */
+ uint64_t m_varied_mask = 0;
+ /* bitmask of fields which have been edited */
+ uint64_t m_changed_mask = 0;
+ /* list of widgets to enable when edits have been made */
+ QList<QPointer<QWidget>> m_linked_widgets;
};
-EXPORT InfoWidget::InfoWidget (QWidget * parent) :
- QTreeView (parent),
- m_model (new InfoModel (this))
+EXPORT InfoWidget::InfoWidget(QWidget * parent)
+ : QTreeView(parent), m_model(new InfoModel(this))
{
- setModel (m_model);
- header ()->hide ();
- setIndentation (0);
- resizeColumnToContents (0);
- setContextMenuPolicy (Qt::CustomContextMenu);
+ setModel(m_model);
+ header()->hide();
+ setIndentation(0);
+ resizeColumnToContents(0);
+ setContextMenuPolicy(Qt::CustomContextMenu);
+
+ connect(this, &QWidget::customContextMenuRequested,
+ [this](const QPoint & pos) {
+ auto index = indexAt(pos);
+ if (index.column() != InfoModel::Col_Value)
+ return;
+ auto text = m_model->data(index, Qt::DisplayRole).toString();
+ if (!text.isEmpty())
+ show_copy_context_menu(this, mapToGlobal(pos), text);
+ });
+}
- connect (this, & QWidget::customContextMenuRequested, [this] (const QPoint & pos)
- {
- auto index = indexAt (pos);
- if (index.column () != 1)
- return;
- auto text = m_model->data (index, Qt::DisplayRole).toString ();
- if (! text.isEmpty ())
- show_copy_context_menu (this, mapToGlobal (pos), text);
- });
+EXPORT InfoWidget::~InfoWidget() {}
+
+EXPORT void InfoWidget::fillInfo(const char * filename, const Tuple & tuple,
+ PluginHandle * decoder, bool updating_enabled)
+{
+ Index<PlaylistAddItem> items;
+ items.append(String(filename), tuple.ref(), decoder);
+ fillInfo(std::move(items), updating_enabled);
+}
+
+EXPORT void InfoWidget::fillInfo(Index<PlaylistAddItem> && items,
+ bool updating_enabled)
+{
+ m_model->setItems(std::move(items));
+ reset();
+
+ setEditTriggers(updating_enabled ? QAbstractItemView::AllEditTriggers
+ : QAbstractItemView::NoEditTriggers);
+
+ auto initial_index = m_model->index(1 /* title */, InfoModel::Col_Value);
+ setCurrentIndex(initial_index);
+}
+
+EXPORT void InfoWidget::linkEnabled(QWidget * widget)
+{
+ m_model->linkEnabled(widget);
}
-EXPORT InfoWidget::~InfoWidget ()
+EXPORT void InfoWidget::revertInfo()
{
+ m_model->revertTupleData();
+ reset();
}
-EXPORT void InfoWidget::fillInfo (const char * filename, const Tuple & tuple,
- PluginHandle * decoder, bool updating_enabled)
+EXPORT bool InfoWidget::updateFile() { return m_model->updateFile(); }
+
+void InfoWidget::keyPressEvent(QKeyEvent * event)
{
- m_model->setTupleData (tuple, String (filename), decoder);
- reset ();
- setEditTriggers (updating_enabled ? QAbstractItemView::SelectedClicked : QAbstractItemView::NoEditTriggers);
+ if (event->type() == QEvent::KeyPress &&
+ (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down))
+ {
+ auto index = sibling_field_index(currentIndex(),
+ (event->key() == Qt::Key_Up) ? -1 : 1);
+ if (index.isValid())
+ setCurrentIndex(index);
+
+ event->accept();
+ return;
+ }
+
+ QTreeView::keyPressEvent(event);
}
-EXPORT bool InfoWidget::updateFile ()
+void InfoModel::revertTupleData()
{
- return m_model->updateFile ();
+ m_tuple = (m_items.len() > 0) ? m_items[0].tuple.ref() : Tuple();
+ m_varied_mask = 0;
+ m_changed_mask = 0;
+
+ for (auto & item : m_items)
+ {
+ for (auto field : Tuple::all_fields())
+ {
+ if (!tuple_field_is_same(item.tuple, m_tuple, field))
+ m_varied_mask |= (uint64_t)1 << (int)field;
+ }
+ }
+
+ updateEnabled();
}
-bool InfoModel::updateFile () const
+bool InfoModel::updateFile() const
{
- if (! m_dirty)
+ if (m_changed_mask == 0)
return true;
- return aud_file_write_tuple (m_filename, m_plugin, m_tuple);
+ int n_saved = 0;
+
+ for (auto & item : m_items)
+ {
+ auto new_tuple = item.tuple.ref();
+
+ for (auto field : Tuple::all_fields())
+ {
+ uint64_t mask = ((uint64_t)1 << (int)field);
+ if ((m_changed_mask & mask) != 0)
+ tuple_field_copy(new_tuple, m_tuple, field);
+ }
+
+ if (aud_file_write_tuple(item.filename, item.decoder, new_tuple))
+ n_saved++;
+ }
+
+ return (n_saved == m_items.len());
}
-bool InfoModel::setData (const QModelIndex & index, const QVariant & value, int role)
+bool InfoModel::setData(const QModelIndex & index, const QVariant & value,
+ int role)
{
if (role != Qt::EditRole)
return false;
- Tuple::Field field_id = tuple_field_map [index.row ()].field;
- if (field_id == Tuple::Invalid)
+ auto map = to_field_map(index);
+ if (!map || map->field == Tuple::Invalid)
return false;
- m_dirty = true;
+ uint64_t mask = ((uint64_t)1 << (int)map->field);
+ auto str = value.toString();
- auto t = Tuple::field_get_type (field_id);
- auto str = value.toString ();
+ /* prevent accidental overwrite of varied values */
+ if ((m_varied_mask & mask) != 0 && str == _(varied_str))
+ return false;
- if (str.isEmpty ())
- m_tuple.unset (field_id);
- else if (t == Tuple::String)
- m_tuple.set_str (field_id, str.toUtf8 ());
- else /* t == Tuple::Int */
- m_tuple.set_int (field_id, str.toInt ());
+ if ((m_varied_mask & mask) != 0 ||
+ str != tuple_field_to_str(m_tuple, map->field))
+ {
+ tuple_field_set_from_str(m_tuple, map->field, str);
+ m_varied_mask &= ~mask;
+ m_changed_mask |= mask;
+ updateEnabled();
+ }
- emit dataChanged (index, index, {role});
+ emit dataChanged(index, index, {role});
return true;
}
-QVariant InfoModel::data (const QModelIndex & index, int role) const
+QVariant InfoModel::data(const QModelIndex & index, int role) const
{
- Tuple::Field field_id = tuple_field_map [index.row ()].field;
+ auto map = to_field_map(index);
+ if (!map)
+ return QVariant();
+
+ uint64_t mask = 0;
+ if (map->field != Tuple::Invalid)
+ mask = ((uint64_t)1 << (int)map->field);
if (role == Qt::DisplayRole || role == Qt::EditRole)
{
- if (index.column () == 0)
- return translate_str (tuple_field_map [index.row ()].name);
- else if (index.column () == 1)
+ if (index.column() == InfoModel::Col_Name)
+ return translate_str(map->name);
+ else if (index.column() == InfoModel::Col_Value)
{
- if (field_id == Tuple::Invalid)
- return QVariant ();
-
- switch (m_tuple.get_value_type (field_id))
- {
- case Tuple::String:
- return QString (m_tuple.get_str (field_id));
- case Tuple::Int:
- /* convert to string so Qt allows clearing the field */
- return QString::number (m_tuple.get_int (field_id));
- default:
- return QVariant ();
- }
+ if (map->field == Tuple::Invalid)
+ return QVariant();
+
+ if ((m_varied_mask & mask) != 0)
+ return QString(_(varied_str));
+
+ return tuple_field_to_str(m_tuple, map->field);
}
}
else if (role == Qt::FontRole)
{
- if (field_id == Tuple::Invalid)
+ if ((index.column() == Col_Name && map->field == Tuple::Invalid) ||
+ (index.column() == Col_Value && (m_changed_mask & mask) != 0))
+ {
+ QFont f;
+ f.setBold(true);
+ return f;
+ }
+ else if (index.column() == Col_Value && (m_varied_mask & mask) != 0)
{
QFont f;
- f.setBold (true);
+ f.setItalic(true);
return f;
}
- return QVariant ();
+
+ return QVariant();
}
- return QVariant ();
+ return QVariant();
}
-Qt::ItemFlags InfoModel::flags (const QModelIndex & index) const
+Qt::ItemFlags InfoModel::flags(const QModelIndex & index) const
{
- if (index.column () == 1)
+ if (index.column() == InfoModel::Col_Value)
{
- auto & t = tuple_field_map [index.row ()];
+ auto map = to_field_map(index);
- if (t.field == Tuple::Invalid)
+ if (!map || map->field == Tuple::Invalid)
return Qt::ItemNeverHasChildren;
- else if (t.editable)
- return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
+ else if (map->editable)
+ return Qt::ItemIsSelectable | Qt::ItemIsEditable |
+ Qt::ItemIsEnabled;
return Qt::ItemIsEnabled;
}
diff --git a/src/libaudqt/info-widget.h b/src/libaudqt/info-widget.h
index 80e0483..40f3d2d 100644
--- a/src/libaudqt/info-widget.h
+++ b/src/libaudqt/info-widget.h
@@ -1,6 +1,6 @@
/*
* info-widget.h
- * Copyright 2006-2014 William Pitcock, Tomasz Moń, Eugene Zagidullin,
+ * Copyright 2006-2014 Ariadne Conill, Tomasz Moń, Eugene Zagidullin,
* John Lindgren, and Thomas Lange
*
* Redistribution and use in source and binary forms, with or without
@@ -22,24 +22,33 @@
#define LIBAUDQT_INFO_WIDGET_H
#include <QTreeView>
+#include <libaudcore/index.h>
#include <libaudqt/export.h>
+struct PlaylistAddItem;
class PluginHandle;
class Tuple;
-namespace audqt {
+namespace audqt
+{
class InfoModel;
class LIBAUDQT_PUBLIC InfoWidget : public QTreeView
{
public:
- InfoWidget (QWidget * parent = nullptr);
- ~InfoWidget ();
-
- void fillInfo (const char * filename, const Tuple & tuple,
- PluginHandle * decoder, bool updating_enabled);
- bool updateFile ();
+ InfoWidget(QWidget * parent = nullptr);
+ ~InfoWidget();
+
+ void fillInfo(const char * filename, const Tuple & tuple,
+ PluginHandle * decoder, bool updating_enabled);
+ void fillInfo(Index<PlaylistAddItem> && items, bool updating_enabled);
+ void linkEnabled(QWidget * widget);
+ void revertInfo();
+ bool updateFile();
+
+protected:
+ void keyPressEvent(QKeyEvent * event) override;
private:
InfoModel * m_model;
diff --git a/src/libaudqt/infopopup-qt.cc b/src/libaudqt/infopopup-qt.cc
index de6d7b7..30c1e39 100644
--- a/src/libaudqt/infopopup-qt.cc
+++ b/src/libaudqt/infopopup-qt.cc
@@ -23,31 +23,32 @@
#include <libaudcore/playlist.h>
#include <libaudcore/tuple.h>
-#include "libaudqt.h"
#include "libaudqt-internal.h"
+#include "libaudqt.h"
#include <QBoxLayout>
#include <QGridLayout>
#include <QLabel>
#include <QPainter>
-namespace audqt {
+namespace audqt
+{
class InfoPopup : public PopupWidget
{
public:
- InfoPopup (const String & filename, const Tuple & tuple);
+ InfoPopup(const String & filename, const Tuple & tuple);
private:
- void add_field (int row, const char * field, const char * value);
- void add_fields (const Tuple & tuple);
- void art_ready (const char * filename);
- void finish_loading ();
+ void add_field(int row, const char * field, const char * value);
+ void add_fields(const Tuple & tuple);
+ void art_ready(const char * filename);
+ void finish_loading();
- void paintEvent (QPaintEvent *) override;
+ void paintEvent(QPaintEvent *) override;
- HookReceiver<InfoPopup, const char *> art_ready_hook
- {"art ready", this, & InfoPopup::art_ready};
+ HookReceiver<InfoPopup, const char *> art_ready_hook{"art ready", this,
+ &InfoPopup::art_ready};
const String m_filename;
const QGradientStops m_stops;
@@ -57,165 +58,141 @@ private:
bool m_queued = false;
};
-static QGradientStops get_stops (const QColor & base)
-{
- QColor mid = QColor (64, 64, 64);
- QColor dark = QColor (38, 38, 38);
- QColor darker = QColor (26, 26, 26);
-
- /* In a dark theme, try to match the tone of the base color */
- int v = base.value ();
- if (v >= 10 && v < 80)
- {
- int r = base.red (), g = base.green (), b = base.blue ();
- mid = QColor (r * 64 / v, g * 64 / v, b * 64 / v);
- dark = QColor (r * 38 / v, g * 38 / v, b * 38 / v);
- darker = QColor (r * 26 / v, g * 26 / v, b * 26 / v);
- }
-
- return {
- {0, mid},
- {0.499, dark},
- {0.5, darker},
- {1, Qt::black}
- };
-}
-
-InfoPopup::InfoPopup (const String & filename, const Tuple & tuple) :
- m_filename (filename),
- m_stops (get_stops (palette ().color (QPalette::Window)))
+InfoPopup::InfoPopup(const String & filename, const Tuple & tuple)
+ : m_filename(filename),
+ m_stops(dark_bg_gradient(palette().color(QPalette::Window)))
{
- setWindowFlags (Qt::ToolTip);
+ setWindowFlags(Qt::ToolTip);
- m_hbox.setMargin (sizes.TwoPt);
- m_hbox.setSpacing (sizes.FourPt);
- setLayout (& m_hbox);
+ m_hbox.setMargin(sizes.TwoPt);
+ m_hbox.setSpacing(sizes.FourPt);
+ setLayout(&m_hbox);
- m_grid.setMargin (0);
- m_grid.setHorizontalSpacing (sizes.FourPt);
- m_grid.setVerticalSpacing (0);
- m_hbox.addLayout (& m_grid);
+ m_grid.setMargin(0);
+ m_grid.setHorizontalSpacing(sizes.FourPt);
+ m_grid.setVerticalSpacing(0);
+ m_hbox.addLayout(&m_grid);
- add_fields (tuple);
- finish_loading ();
+ add_fields(tuple);
+ finish_loading();
}
-void InfoPopup::add_fields (const Tuple & tuple)
+void InfoPopup::add_fields(const Tuple & tuple)
{
- String title = tuple.get_str (Tuple::Title);
- String artist = tuple.get_str (Tuple::Artist);
- String album = tuple.get_str (Tuple::Album);
- String genre = tuple.get_str (Tuple::Genre);
-
- int year = tuple.get_int (Tuple::Year);
- int track = tuple.get_int (Tuple::Track);
- int length = tuple.get_int (Tuple::Length);
+ String title = tuple.get_str(Tuple::Title);
+ String artist = tuple.get_str(Tuple::Artist);
+ String album = tuple.get_str(Tuple::Album);
+ String genre = tuple.get_str(Tuple::Genre);
+
+ int year = tuple.get_int(Tuple::Year);
+ int track = tuple.get_int(Tuple::Track);
+ int length = tuple.get_int(Tuple::Length);
int row = 0;
if (title)
- add_field (row ++, _("Title"), title);
+ add_field(row++, _("Title"), title);
if (artist)
- add_field (row ++, _("Artist"), artist);
+ add_field(row++, _("Artist"), artist);
if (album)
- add_field (row ++, _("Album"), album);
+ add_field(row++, _("Album"), album);
if (genre)
- add_field (row ++, _("Genre"), genre);
+ add_field(row++, _("Genre"), genre);
if (year > 0)
- add_field (row ++, _("Year"), int_to_str (year));
+ add_field(row++, _("Year"), int_to_str(year));
if (track > 0)
- add_field (row ++, _("Track"), int_to_str (track));
+ add_field(row++, _("Track"), int_to_str(track));
if (length > 0)
- add_field (row ++, _("Length"), str_format_time (length));
+ add_field(row++, _("Length"), str_format_time(length));
}
-void InfoPopup::add_field (int row, const char * field, const char * value)
+void InfoPopup::add_field(int row, const char * field, const char * value)
{
- auto header = new QLabel (this);
- header->setTextFormat (Qt::RichText);
- header->setText (QString ("<i><font color=\"#a0a0a0\">%1</font></i>").arg (field));
- m_grid.addWidget (header, row, 0, Qt::AlignRight);
-
- auto label = new QLabel (this);
- header->setTextFormat (Qt::RichText);
- auto html = QString (value).toHtmlEscaped ();
- label->setText (QString ("<font color=\"#ffffff\">%1</font>").arg (html));
- m_grid.addWidget (label, row, 1, Qt::AlignLeft);
+ auto header = new QLabel(this);
+ header->setTextFormat(Qt::RichText);
+ header->setText(
+ QString("<i><font color=\"#a0a0a0\">%1</font></i>").arg(field));
+ m_grid.addWidget(header, row, 0, Qt::AlignRight);
+
+ auto label = new QLabel(this);
+ header->setTextFormat(Qt::RichText);
+ auto html = QString(value).toHtmlEscaped();
+ label->setText(QString("<font color=\"#ffffff\">%1</font>").arg(html));
+ m_grid.addWidget(label, row, 1, Qt::AlignLeft);
}
-void InfoPopup::art_ready (const char * filename)
+void InfoPopup::art_ready(const char * filename)
{
- if (m_queued && strcmp (filename, m_filename) == 0)
- finish_loading ();
+ if (m_queued && strcmp(filename, m_filename) == 0)
+ finish_loading();
}
-void InfoPopup::finish_loading ()
+void InfoPopup::finish_loading()
{
- QImage image = art_request (m_filename, & m_queued);
+ QImage image = art_request(m_filename, &m_queued);
- if (! image.isNull ())
+ if (!image.isNull())
{
- auto label = new QLabel (this);
- label->setPixmap (art_scale (image, sizes.OneInch, sizes.OneInch));
- m_hbox.insertWidget (0, label);
+ auto label = new QLabel(this);
+ label->setPixmap(art_scale(image, sizes.OneInch, sizes.OneInch));
+ m_hbox.insertWidget(0, label);
}
- if (! m_queued)
- show ();
+ if (!m_queued)
+ show();
}
-void InfoPopup::paintEvent (QPaintEvent *)
+void InfoPopup::paintEvent(QPaintEvent *)
{
- QLinearGradient grad (0, 0, 0, height ());
- grad.setStops (m_stops);
+ QLinearGradient grad(0, 0, 0, height());
+ grad.setStops(m_stops);
- QPainter p (this);
- p.fillRect (rect (), grad);
+ QPainter p(this);
+ p.fillRect(rect(), grad);
}
static InfoPopup * s_infopopup;
-static void infopopup_show (const String & filename, const Tuple & tuple)
+static void infopopup_show(const String & filename, const Tuple & tuple)
{
if (s_infopopup)
- s_infopopup->deleteLater ();
+ s_infopopup->deleteLater();
- s_infopopup = new InfoPopup (filename, tuple);
+ s_infopopup = new InfoPopup(filename, tuple);
- QObject::connect (s_infopopup, & QObject::destroyed, [] () {
- s_infopopup = nullptr;
- });
+ QObject::connect(s_infopopup, &QObject::destroyed,
+ []() { s_infopopup = nullptr; });
}
-EXPORT void infopopup_show (Playlist playlist, int entry)
+EXPORT void infopopup_show(Playlist playlist, int entry)
{
- String filename = playlist.entry_filename (entry);
- Tuple tuple = playlist.entry_tuple (entry);
+ String filename = playlist.entry_filename(entry);
+ Tuple tuple = playlist.entry_tuple(entry);
- if (filename && tuple.valid ())
- infopopup_show (filename, tuple);
+ if (filename && tuple.valid())
+ infopopup_show(filename, tuple);
}
-EXPORT void infopopup_show_current ()
+EXPORT void infopopup_show_current()
{
- auto playlist = Playlist::playing_playlist ();
- if (playlist == Playlist ())
- playlist = Playlist::active_playlist ();
+ auto playlist = Playlist::playing_playlist();
+ if (playlist == Playlist())
+ playlist = Playlist::active_playlist();
- int position = playlist.get_position ();
+ int position = playlist.get_position();
if (position >= 0)
- infopopup_show (playlist, position);
+ infopopup_show(playlist, position);
}
-EXPORT void infopopup_hide ()
+EXPORT void infopopup_hide()
{
/* This function can be called from an enter/leave event, and Qt does not
* like widgets being deleted from such events. This is debatably a bug in
* Qt, but deleteLater() is an effective workaround. */
if (s_infopopup)
- s_infopopup->deleteLater ();
+ s_infopopup->deleteLater();
}
-void infopopup_hide_now ()
+void infopopup_hide_now()
{
/* On exit, we really do want to delete the widget immediately. */
delete s_infopopup;
diff --git a/src/libaudqt/infowin-qt.cc b/src/libaudqt/infowin-qt.cc
index 2f4161c..853e0cc 100644
--- a/src/libaudqt/infowin-qt.cc
+++ b/src/libaudqt/infowin-qt.cc
@@ -1,6 +1,6 @@
/*
* infowin.cc
- * Copyright 2006-2014 William Pitcock, Tomasz Moń, Eugene Zagidullin,
+ * Copyright 2006-2014 Ariadne Conill, Tomasz Moń, Eugene Zagidullin,
* John Lindgren, and Thomas Lange
*
* Redistribution and use in source and binary forms, with or without
@@ -26,8 +26,8 @@
#include <QHBoxLayout>
#include <QImage>
#include <QLabel>
-#include <QPixmap>
#include <QPainter>
+#include <QPixmap>
#include <QPushButton>
#include <QTextDocument>
#include <QVBoxLayout>
@@ -40,10 +40,11 @@
#include <libaudcore/probe.h>
#include "info-widget.h"
-#include "libaudqt.h"
#include "libaudqt-internal.h"
+#include "libaudqt.h"
-namespace audqt {
+namespace audqt
+{
/* This class remedies some of the deficiencies of QLabel (such as lack
* of proper wrapping). It can be expanded and/or made more visible if
@@ -51,47 +52,43 @@ namespace audqt {
class TextWidget : public QWidget
{
public:
- TextWidget ()
- {
- m_doc.setDefaultFont (font ());
- }
+ TextWidget() { m_doc.setDefaultFont(font()); }
- void setText (const QString & text)
+ void setText(const QString & text)
{
- m_doc.setPlainText (text);
- updateGeometry ();
+ m_doc.setPlainText(text);
+ updateGeometry();
}
- void setWidth (int width)
+ void setWidth(int width)
{
- m_doc.setTextWidth (width);
- updateGeometry ();
+ m_doc.setTextWidth(width);
+ updateGeometry();
}
protected:
- QSize sizeHint () const override
+ QSize sizeHint() const override
{
- qreal width = m_doc.idealWidth ();
- qreal height = m_doc.size ().height ();
- return QSize (ceil (width), ceil (height));
+ qreal width = m_doc.idealWidth();
+ qreal height = m_doc.size().height();
+ return QSize(ceil(width), ceil(height));
}
- QSize minimumSizeHint () const override
- { return sizeHint (); }
+ QSize minimumSizeHint() const override { return sizeHint(); }
- void changeEvent (QEvent * event) override
+ void changeEvent(QEvent * event) override
{
- if (event->type () == QEvent::FontChange)
+ if (event->type() == QEvent::FontChange)
{
- m_doc.setDefaultFont (font ());
- updateGeometry ();
+ m_doc.setDefaultFont(font());
+ updateGeometry();
}
}
- void paintEvent (QPaintEvent * event) override
+ void paintEvent(QPaintEvent * event) override
{
- QPainter painter (this);
- m_doc.drawContents (& painter);
+ QPainter painter(this);
+ m_doc.drawContents(&painter);
}
private:
@@ -101,140 +98,202 @@ private:
class InfoWindow : public QDialog
{
public:
- InfoWindow (QWidget * parent = nullptr);
+ InfoWindow(QWidget * parent = nullptr);
- void fillInfo (const char * filename, const Tuple & tuple,
- PluginHandle * decoder, bool updating_enabled);
+ void fillInfo(Index<PlaylistAddItem> && items, bool updating_enabled);
private:
String m_filename;
QLabel m_image;
TextWidget m_uri_label;
InfoWidget m_infowidget;
+ QPushButton * m_save_btn;
- void displayImage (const char * filename);
+ void displayImage(const char * filename);
- const HookReceiver<InfoWindow, const char *>
- art_hook {"art ready", this, & InfoWindow::displayImage};
+ const HookReceiver<InfoWindow, const char *> art_hook{
+ "art ready", this, &InfoWindow::displayImage};
};
-InfoWindow::InfoWindow (QWidget * parent) : QDialog (parent)
+InfoWindow::InfoWindow(QWidget * parent) : QDialog(parent)
{
- setWindowTitle (_("Song Info"));
- setContentsMargins (margins.TwoPt);
-
- m_image.setAlignment (Qt::AlignCenter);
- m_uri_label.setWidth (2 * audqt::sizes.OneInch);
- m_uri_label.setContextMenuPolicy (Qt::CustomContextMenu);
-
- connect (& m_uri_label, & QWidget::customContextMenuRequested, [this] (const QPoint & pos) {
- show_copy_context_menu (this, m_uri_label.mapToGlobal (pos), QString (m_filename));
+ setWindowTitle(_("Song Info"));
+ setContentsMargins(margins.TwoPt);
+
+ m_image.setAlignment(Qt::AlignCenter);
+ m_uri_label.setWidth(2 * audqt::sizes.OneInch);
+ m_uri_label.setContextMenuPolicy(Qt::CustomContextMenu);
+
+ connect(&m_uri_label, &QWidget::customContextMenuRequested,
+ [this](const QPoint & pos) {
+ show_copy_context_menu(this, m_uri_label.mapToGlobal(pos),
+ QString(m_filename));
+ });
+
+ auto left_vbox = make_vbox(nullptr);
+ left_vbox->addWidget(&m_image);
+ left_vbox->addWidget(&m_uri_label);
+ left_vbox->setStretch(0, 1);
+ left_vbox->setStretch(1, 0);
+
+ auto hbox = make_hbox(nullptr);
+ hbox->addLayout(left_vbox);
+ hbox->addWidget(&m_infowidget);
+
+ auto vbox = make_vbox(this);
+ vbox->addLayout(hbox);
+
+ auto bbox =
+ new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Close |
+ QDialogButtonBox::Reset,
+ this);
+
+ m_save_btn = bbox->button(QDialogButtonBox::Save);
+ auto close_btn = bbox->button(QDialogButtonBox::Close),
+ revert_btn = bbox->button(QDialogButtonBox::Reset);
+
+ close_btn->setText(translate_str(N_("_Close")));
+ revert_btn->setText(translate_str(N_("_Revert")));
+
+ m_infowidget.linkEnabled(m_save_btn);
+ m_infowidget.linkEnabled(revert_btn);
+
+ vbox->addWidget(bbox);
+
+ connect(bbox, &QDialogButtonBox::accepted, [this]() {
+ if (m_infowidget.updateFile())
+ deleteLater();
+ else
+ aud_ui_show_error(str_printf(_("Error writing tag(s).")));
});
- auto left_vbox = make_vbox (nullptr);
- left_vbox->addWidget (& m_image);
- left_vbox->addWidget (& m_uri_label);
- left_vbox->setStretch (0, 1);
- left_vbox->setStretch (1, 0);
-
- auto hbox = make_hbox (nullptr);
- hbox->addLayout (left_vbox);
- hbox->addWidget (& m_infowidget);
-
- auto vbox = make_vbox (this);
- vbox->addLayout (hbox);
-
- auto bbox = new QDialogButtonBox (QDialogButtonBox::Save | QDialogButtonBox::Close, this);
- bbox->button (QDialogButtonBox::Save)->setText (translate_str (N_("_Save")));
- bbox->button (QDialogButtonBox::Close)->setText (translate_str (N_("_Close")));
- vbox->addWidget (bbox);
-
- connect (bbox, & QDialogButtonBox::accepted, [this] () {
- m_infowidget.updateFile ();
- deleteLater ();
- });
-
- connect (bbox, & QDialogButtonBox::rejected, this, & QObject::deleteLater);
+ connect(bbox, &QDialogButtonBox::rejected, this, &QObject::deleteLater);
+ connect(revert_btn, &QPushButton::clicked, &m_infowidget,
+ &InfoWidget::revertInfo);
}
-void InfoWindow::fillInfo (const char * filename, const Tuple & tuple,
- PluginHandle * decoder, bool updating_enabled)
+void InfoWindow::fillInfo(Index<PlaylistAddItem> && items,
+ bool updating_enabled)
{
- m_filename = String (filename);
- m_uri_label.setText ((QString) uri_to_display (filename));
- displayImage (filename);
- m_infowidget.fillInfo (filename, tuple, decoder, updating_enabled);
+ if (items.len() == 1)
+ {
+ m_filename = String(items[0].filename);
+ m_uri_label.setText((QString)uri_to_display(m_filename));
+ displayImage(m_filename);
+ m_save_btn->setText(translate_str(N_("_Save")));
+ }
+ else
+ {
+ m_filename = String();
+ m_uri_label.setText(
+ translate_str(N_("%1 files selected")).arg(items.len()));
+ m_image.setPixmap(
+ get_icon("audio-x-generic").pixmap(to_native_dpi(48)));
+ m_save_btn->setText(
+ translate_str(N_("_Save %1 files")).arg(items.len()));
+ }
+
+ m_infowidget.fillInfo(std::move(items), updating_enabled);
}
-void InfoWindow::displayImage (const char * filename)
+void InfoWindow::displayImage(const char * filename)
{
- if (! strcmp_safe (filename, m_filename))
- m_image.setPixmap (art_request (filename, 2 * sizes.OneInch, 2 * sizes.OneInch));
+ if (!strcmp_safe(filename, m_filename))
+ m_image.setPixmap(
+ art_request(filename, 2 * sizes.OneInch, 2 * sizes.OneInch));
}
static InfoWindow * s_infowin = nullptr;
-static void show_infowin (const char * filename,
- const Tuple & tuple, PluginHandle * decoder, bool can_write)
+static void show_infowin(Index<PlaylistAddItem> && items, bool can_write)
{
- if (! s_infowin)
+ if (!s_infowin)
{
s_infowin = new InfoWindow;
- s_infowin->setAttribute (Qt::WA_DeleteOnClose);
+ s_infowin->setAttribute(Qt::WA_DeleteOnClose);
- QObject::connect (s_infowin, & QObject::destroyed, [] () {
- s_infowin = nullptr;
- });
+ QObject::connect(s_infowin, &QObject::destroyed,
+ []() { s_infowin = nullptr; });
}
- s_infowin->fillInfo (filename, tuple, decoder, can_write);
- s_infowin->resize (6 * sizes.OneInch, 3 * sizes.OneInch);
- window_bring_to_front (s_infowin);
+ s_infowin->fillInfo(std::move(items), can_write);
+ s_infowin->resize(6 * sizes.OneInch, 3 * sizes.OneInch);
+ window_bring_to_front(s_infowin);
}
-EXPORT void infowin_show (Playlist playlist, int entry)
+static void fetch_entry(Playlist playlist, int entry,
+ Index<PlaylistAddItem> & items, bool & can_write)
{
- String filename = playlist.entry_filename (entry);
- if (! filename)
+ String filename = playlist.entry_filename(entry);
+ if (!filename)
return;
String error;
- PluginHandle * decoder = playlist.entry_decoder (entry, Playlist::Wait, & error);
- Tuple tuple = decoder ? playlist.entry_tuple (entry, Playlist::Wait, & error) : Tuple ();
+ PluginHandle * decoder =
+ playlist.entry_decoder(entry, Playlist::Wait, &error);
+ Tuple tuple =
+ decoder ? playlist.entry_tuple(entry, Playlist::Wait, &error) : Tuple();
- if (decoder && tuple.valid () && ! aud_custom_infowin (filename, decoder))
+ if (decoder && tuple.valid())
{
/* cuesheet entries cannot be updated */
- bool can_write = aud_file_can_write_tuple (filename, decoder) &&
- ! tuple.is_set (Tuple::StartTime);
+ can_write = (can_write && aud_file_can_write_tuple(filename, decoder) &&
+ !tuple.is_set(Tuple::StartTime));
- tuple.delete_fallbacks ();
- show_infowin (filename, tuple, decoder, can_write);
+ tuple.delete_fallbacks();
+ items.append(filename, std::move(tuple), decoder);
}
- else
- infowin_hide ();
if (error)
- aud_ui_show_error (str_printf (_("Error opening %s:\n%s"),
- (const char *) filename, (const char *) error));
+ aud_ui_show_error(str_printf(_("Error opening %s:\n%s"),
+ (const char *)filename,
+ (const char *)error));
}
-EXPORT void infowin_show_current ()
+EXPORT void infowin_show(Playlist playlist, int entry)
{
- auto playlist = Playlist::playing_playlist ();
- if (playlist == Playlist ())
- playlist = Playlist::active_playlist ();
+ Index<PlaylistAddItem> items;
+ bool can_write = true;
- int position = playlist.get_position ();
- if (position < 0)
- return;
+ fetch_entry(playlist, entry, items, can_write);
- infowin_show (playlist, position);
+ if (items.len())
+ show_infowin(std::move(items), can_write);
+ else
+ infowin_hide();
}
-EXPORT void infowin_hide ()
+EXPORT void infowin_show_selected(Playlist playlist)
{
- delete s_infowin;
+ Index<PlaylistAddItem> items;
+ bool can_write = true;
+
+ int n_entries = playlist.n_entries();
+ for (int entry = 0; entry < n_entries; entry++)
+ {
+ if (playlist.entry_selected(entry))
+ fetch_entry(playlist, entry, items, can_write);
+ }
+
+ if (items.len())
+ show_infowin(std::move(items), can_write);
+ else
+ infowin_hide();
}
+EXPORT void infowin_show_current()
+{
+ auto playlist = Playlist::playing_playlist();
+ if (playlist == Playlist())
+ playlist = Playlist::active_playlist();
+
+ int position = playlist.get_position();
+ if (position < 0)
+ return;
+
+ infowin_show(playlist, position);
+}
+
+EXPORT void infowin_hide() { delete s_infowin; }
+
} // namespace audqt
diff --git a/src/libaudqt/libaudqt-internal.h b/src/libaudqt/libaudqt-internal.h
index 19dded2..3dd1398 100644
--- a/src/libaudqt/libaudqt-internal.h
+++ b/src/libaudqt/libaudqt-internal.h
@@ -26,28 +26,29 @@ class QPoint;
class QScreen;
class QString;
-namespace audqt {
+namespace audqt
+{
/* infopopup.cc */
-void infopopup_hide_now ();
+void infopopup_hide_now();
/* log-inspector.cc */
-void log_init ();
-void log_cleanup ();
+void log_init();
+void log_cleanup();
/* util-qt.cc */
class PopupWidget : public QWidget
{
public:
- PopupWidget (QWidget * parent = nullptr);
+ PopupWidget(QWidget * parent = nullptr);
protected:
- bool eventFilter (QObject *, QEvent * e) override;
- void showEvent (QShowEvent *) override;
+ bool eventFilter(QObject *, QEvent * e) override;
+ void showEvent(QShowEvent *) override;
};
-void show_copy_context_menu (QWidget * parent, const QPoint & global_pos,
- const QString & text_to_copy);
+void show_copy_context_menu(QWidget * parent, const QPoint & global_pos,
+ const QString & text_to_copy);
} // namespace audqt
diff --git a/src/libaudqt/libaudqt.h b/src/libaudqt/libaudqt.h
index e2a23de..54f902d 100644
--- a/src/libaudqt/libaudqt.h
+++ b/src/libaudqt/libaudqt.h
@@ -1,6 +1,6 @@
/*
* libaudqt.h
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -20,19 +20,20 @@
#ifndef LIBAUDQT_H
#define LIBAUDQT_H
+#include <QFileDialog>
#include <QMargins>
#include <QMessageBox>
#include <QString>
#include <libaudcore/objects.h>
-class QIcon;
-class QLayout;
class QBoxLayout;
class QHBoxLayout;
-class QVBoxLayout;
-
+class QIcon;
+class QLayout;
+class QLineEdit;
class QPixmap;
class QToolButton;
+class QVBoxLayout;
class QWidget;
enum class PluginType;
@@ -40,9 +41,11 @@ class Playlist;
class PluginHandle;
struct PreferencesWidget;
-namespace audqt {
+namespace audqt
+{
-enum class FileMode {
+enum class FileMode
+{
Open,
OpenFolder,
Add,
@@ -52,14 +55,16 @@ enum class FileMode {
count
};
-struct PixelSizes {
+struct PixelSizes
+{
int OneInch;
int TwoPt;
int FourPt;
int EightPt;
};
-struct PixelMargins {
+struct PixelMargins
+{
QMargins TwoPt;
QMargins FourPt;
QMargins EightPt;
@@ -68,94 +73,124 @@ struct PixelMargins {
struct MenuItem;
/* about.cc */
-void aboutwindow_show ();
-void aboutwindow_hide ();
+void aboutwindow_show();
+void aboutwindow_hide();
/* playlist-management.cc */
-void playlist_show_rename (Playlist playlist);
-void playlist_confirm_delete (Playlist playlist);
+void playlist_show_rename(Playlist playlist);
+void playlist_confirm_delete(Playlist playlist);
/* equalizer.cc */
-void equalizer_show ();
-void equalizer_hide ();
+void equalizer_show();
+void equalizer_hide();
+
+/* eq-preset-qt.cc */
+void eq_presets_show();
+void eq_presets_hide();
/* fileopener.cc */
-void fileopener_show (FileMode mode);
+void fileopener_show(FileMode mode);
/* url-opener.cc */
-void urlopener_show (bool open);
-
-/* util.cc */
+void urlopener_show(bool open);
+/* audqt.cc */
extern const PixelSizes & sizes;
extern const PixelMargins & margins;
-static inline int to_native_dpi (int x)
- { return aud::rescale (x, 96, sizes.OneInch); }
-static inline int to_portable_dpi (int x)
- { return aud::rescale (x, sizes.OneInch, 96); }
+static inline int to_native_dpi(int x)
+{
+ return aud::rescale(x, 96, sizes.OneInch);
+}
+static inline int to_portable_dpi(int x)
+{
+ return aud::rescale(x, sizes.OneInch, 96);
+}
-void init ();
-void run ();
-void quit ();
-void cleanup ();
+void init();
+void run();
+void quit();
+void cleanup();
-QIcon get_icon (const char * name);
+QIcon get_icon(const char * name);
-QHBoxLayout * make_hbox (QWidget * parent, int spacing = sizes.FourPt);
-QVBoxLayout * make_vbox (QWidget * parent, int spacing = sizes.FourPt);
+QGradientStops dark_bg_gradient(const QColor & base);
+QColor vis_bar_color(const QColor & hue, int bar, int n_bars);
-void enable_layout (QLayout * layout, bool enabled);
-void clear_layout (QLayout * layout);
-void window_bring_to_front (QWidget * win);
-void simple_message (const char * title, const char * text);
-void simple_message (const char * title, const char * text, QMessageBox::Icon icon);
-QString translate_str (const char * str, const char * domain);
+QHBoxLayout * make_hbox(QWidget * parent, int spacing = sizes.FourPt);
+QVBoxLayout * make_vbox(QWidget * parent, int spacing = sizes.FourPt);
+
+void enable_layout(QLayout * layout, bool enabled);
+void clear_layout(QLayout * layout);
+void window_bring_to_front(QWidget * win);
+void simple_message(const char * title, const char * text);
+void simple_message(const char * title, const char * text,
+ QMessageBox::Icon icon);
+QString translate_str(const char * str, const char * domain);
#ifdef PACKAGE
-static inline QString translate_str (const char * str)
- { return translate_str (str, PACKAGE); }
+static inline QString translate_str(const char * str)
+{
+ return translate_str(str, PACKAGE);
+}
#endif
+/* file-entry.cc */
+QLineEdit * file_entry_new(QWidget * parent, const char * title,
+ QFileDialog::FileMode file_mode,
+ QFileDialog::AcceptMode accept_mode);
+String file_entry_get_uri(QLineEdit * entry);
+void file_entry_set_uri(QLineEdit * entry, const char * uri);
+
+/* font-entry.cc */
+QLineEdit * font_entry_new(QWidget * parent, const char * font);
+QFont qfont_from_string(const char * name);
+StringBuf qfont_to_string(const QFont & font);
+
/* prefs-builder.cc */
-void prefs_populate (QBoxLayout * layout, ArrayRef<PreferencesWidget> widgets, const char * domain);
+void prefs_populate(QBoxLayout * layout, ArrayRef<PreferencesWidget> widgets,
+ const char * domain);
/* prefs-plugin.cc */
-void plugin_about (PluginHandle * ph);
-void plugin_prefs (PluginHandle * ph);
+void plugin_about(PluginHandle * ph);
+void plugin_prefs(PluginHandle * ph);
/* prefs-window.cc */
-void prefswin_show ();
-void prefswin_hide ();
-void prefswin_show_page (int id, bool show = true);
-void prefswin_show_plugin_page (PluginType type);
+void prefswin_show();
+void prefswin_hide();
+void prefswin_show_page(int id, bool show = true);
+void prefswin_show_plugin_page(PluginType type);
/* log-inspector.cc */
-void log_inspector_show ();
-void log_inspector_hide ();
+void log_inspector_show();
+void log_inspector_hide();
/* art-qt.cc */
-QImage art_request (const char * filename, bool * queued = nullptr);
-QPixmap art_scale (const QImage & image, unsigned int w, unsigned int h, bool want_hidpi = true);
-QPixmap art_request (const char * filename, unsigned int w, unsigned int h, bool want_hidpi = true);
-QPixmap art_request_current (unsigned int w, unsigned int h, bool want_hidpi = true);
+QImage art_request(const char * filename, bool * queued = nullptr);
+QPixmap art_scale(const QImage & image, unsigned int w, unsigned int h,
+ bool want_hidpi = true);
+QPixmap art_request(const char * filename, unsigned int w, unsigned int h,
+ bool want_hidpi = true);
+QPixmap art_request_current(unsigned int w, unsigned int h,
+ bool want_hidpi = true);
/* infopopup-qt.cc */
-void infopopup_show (Playlist playlist, int entry);
-void infopopup_show_current ();
-void infopopup_hide ();
+void infopopup_show(Playlist playlist, int entry);
+void infopopup_show_current();
+void infopopup_hide();
/* infowin.cc */
-void infowin_show (Playlist playlist, int entry);
-void infowin_show_current ();
-void infowin_hide ();
+void infowin_show(Playlist playlist, int entry);
+void infowin_show_selected(Playlist playlist);
+void infowin_show_current();
+void infowin_hide();
/* queue-manager.cc */
-void queue_manager_show ();
-void queue_manager_hide ();
+void queue_manager_show();
+void queue_manager_hide();
/* volumebutton.cc */
-QToolButton * volume_button_new (QWidget * parent = nullptr);
+QToolButton * volume_button_new(QWidget * parent = nullptr);
} // namespace audqt
diff --git a/src/libaudqt/log-inspector.cc b/src/libaudqt/log-inspector.cc
index e582a29..460c178 100644
--- a/src/libaudqt/log-inspector.cc
+++ b/src/libaudqt/log-inspector.cc
@@ -1,6 +1,6 @@
/*
* log-inspector.cc
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -17,17 +17,17 @@
* the use of this software.
*/
-#include "libaudqt.h"
#include "libaudqt-internal.h"
+#include "libaudqt.h"
#include <QComboBox>
#include <QDialog>
#include <QDialogButtonBox>
#include <QHBoxLayout>
#include <QLabel>
-#include <QVBoxLayout>
#include <QPushButton>
#include <QTreeView>
+#include <QVBoxLayout>
#include <QWidget>
#include <libaudcore/audstrings.h>
@@ -38,16 +38,19 @@
#define LOGENTRY_MAX 1024
-namespace audqt {
+namespace audqt
+{
-enum LogEntryColumn {
+enum LogEntryColumn
+{
Level,
Function,
Message,
Count
};
-struct LogEntry {
+struct LogEntry
+{
audlog::Level level;
String function;
String message;
@@ -56,220 +59,228 @@ struct LogEntry {
class LogEntryModel : public QAbstractListModel
{
public:
- LogEntryModel (QObject * parent = nullptr) :
- QAbstractListModel (parent) {}
+ LogEntryModel(QObject * parent = nullptr) : QAbstractListModel(parent) {}
+
+ void cleanup();
- void cleanup ();
protected:
- int rowCount (const QModelIndex & parent = QModelIndex ()) const
- { return m_entries.len (); }
- int columnCount (const QModelIndex & parent = QModelIndex ()) const
- { return LogEntryColumn::Count; }
+ int rowCount(const QModelIndex & parent = QModelIndex()) const
+ {
+ return m_entries.len();
+ }
+ int columnCount(const QModelIndex & parent = QModelIndex()) const
+ {
+ return LogEntryColumn::Count;
+ }
- QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const;
- QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
+ QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const;
private:
RingBuf<LogEntry> m_entries;
- void addEntry (const LogEntry * entry);
- HookReceiver<LogEntryModel, const LogEntry *>
- log_hook {"audqt log entry", this, & LogEntryModel::addEntry};
+ void addEntry(const LogEntry * entry);
+ HookReceiver<LogEntryModel, const LogEntry *> log_hook{
+ "audqt log entry", this, &LogEntryModel::addEntry};
};
-void LogEntryModel::cleanup ()
+void LogEntryModel::cleanup()
{
- if (m_entries.len () > 0)
+ if (m_entries.len() > 0)
{
- beginRemoveRows (QModelIndex (), 0, m_entries.len () - 1);
- m_entries.destroy ();
- endRemoveRows ();
+ beginRemoveRows(QModelIndex(), 0, m_entries.len() - 1);
+ m_entries.destroy();
+ endRemoveRows();
}
}
/* log entry model */
-void LogEntryModel::addEntry (const LogEntry * entry)
+void LogEntryModel::addEntry(const LogEntry * entry)
{
- if (! m_entries.space ())
+ if (!m_entries.space())
{
- if (m_entries.len () < LOGENTRY_MAX)
- m_entries.alloc (aud::max (16, 2 * m_entries.len ()));
+ if (m_entries.len() < LOGENTRY_MAX)
+ m_entries.alloc(aud::max(16, 2 * m_entries.len()));
else
{
- beginRemoveRows (QModelIndex (), 0, 0);
- m_entries.pop ();
- endRemoveRows ();
+ beginRemoveRows(QModelIndex(), 0, 0);
+ m_entries.pop();
+ endRemoveRows();
}
}
- beginInsertRows (QModelIndex (), m_entries.len (), m_entries.len ());
- m_entries.push (* entry);
- endInsertRows ();
+ beginInsertRows(QModelIndex(), m_entries.len(), m_entries.len());
+ m_entries.push(*entry);
+ endInsertRows();
}
-QVariant LogEntryModel::data (const QModelIndex & index, int role) const
+QVariant LogEntryModel::data(const QModelIndex & index, int role) const
{
- int row = index.row ();
- if (row < 0 || row >= m_entries.len ())
- return QVariant ();
+ int row = index.row();
+ if (row < 0 || row >= m_entries.len())
+ return QVariant();
auto & e = m_entries[row];
if (role == Qt::DisplayRole)
{
- switch (index.column ())
+ switch (index.column())
{
- case LogEntryColumn::Level: return QString (audlog::get_level_name (e.level));
- case LogEntryColumn::Function: return QString (e.function);
- case LogEntryColumn::Message: return QString (e.message);
+ case LogEntryColumn::Level:
+ return QString(audlog::get_level_name(e.level));
+ case LogEntryColumn::Function:
+ return QString(e.function);
+ case LogEntryColumn::Message:
+ return QString(e.message);
}
}
- return QVariant ();
+ return QVariant();
}
-QVariant LogEntryModel::headerData (int section, Qt::Orientation orientation, int role) const
+QVariant LogEntryModel::headerData(int section, Qt::Orientation orientation,
+ int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
{
switch (section)
{
- case LogEntryColumn::Level: return QString (_("Level"));
- case LogEntryColumn::Function: return QString (_("Function"));
- case LogEntryColumn::Message: return QString (_("Message"));
+ case LogEntryColumn::Level:
+ return QString(_("Level"));
+ case LogEntryColumn::Function:
+ return QString(_("Function"));
+ case LogEntryColumn::Message:
+ return QString(_("Message"));
}
}
- return QVariant ();
+ return QVariant();
}
/* static model */
static SmartPtr<LogEntryModel> s_model;
static audlog::Level s_level = audlog::Warning;
-static void log_handler (audlog::Level level, const char * file, int line,
- const char * func, const char * message)
+static void log_handler(audlog::Level level, const char * file, int line,
+ const char * func, const char * message)
{
- auto messages = str_list_to_index (message, "\n");
+ auto messages = str_list_to_index(message, "\n");
for (auto & message : messages)
{
auto entry = new LogEntry;
entry->level = level;
- entry->function = String (str_printf ("%s (%s:%d)", func, file, line));
- entry->message = std::move (message);
+ entry->function = String(str_printf("%s (%s:%d)", func, file, line));
+ entry->message = std::move(message);
- event_queue ("audqt log entry", entry, aud::delete_obj<LogEntry>);
+ event_queue("audqt log entry", entry, aud::delete_obj<LogEntry>);
}
}
-void log_init ()
+void log_init()
{
- s_model.capture (new LogEntryModel);
- audlog::subscribe (log_handler, s_level);
+ s_model.capture(new LogEntryModel);
+ audlog::subscribe(log_handler, s_level);
}
-void log_cleanup ()
+void log_cleanup()
{
- audlog::unsubscribe (log_handler);
- event_queue_cancel ("audqt log entry");
- s_model.clear ();
+ audlog::unsubscribe(log_handler);
+ event_queue_cancel("audqt log entry");
+ s_model.clear();
}
/* log entry inspector */
class LogEntryInspector : public QDialog
{
public:
- LogEntryInspector (QWidget * parent = nullptr);
+ LogEntryInspector(QWidget * parent = nullptr);
private:
QComboBox m_level_combobox;
- void setLogLevel (audlog::Level level);
+ void setLogLevel(audlog::Level level);
};
-LogEntryInspector::LogEntryInspector (QWidget * parent) :
- QDialog (parent)
+LogEntryInspector::LogEntryInspector(QWidget * parent) : QDialog(parent)
{
- setWindowTitle (_("Log Inspector"));
- setContentsMargins (margins.TwoPt);
+ setWindowTitle(_("Log Inspector"));
+ setContentsMargins(margins.TwoPt);
- auto view = new QTreeView (this);
- view->setModel (s_model.get ());
+ auto view = new QTreeView(this);
+ view->setModel(s_model.get());
- view->setAllColumnsShowFocus (true);
- view->setIndentation (0);
- view->setUniformRowHeights (true);
- view->scrollToBottom ();
+ view->setAllColumnsShowFocus(true);
+ view->setIndentation(0);
+ view->setUniformRowHeights(true);
+ view->scrollToBottom();
- m_level_combobox.addItem (_("Debug"), audlog::Debug);
- m_level_combobox.addItem (_("Info"), audlog::Info);
- m_level_combobox.addItem (_("Warning"), audlog::Warning);
- m_level_combobox.addItem (_("Error"), audlog::Error);
+ m_level_combobox.addItem(_("Debug"), audlog::Debug);
+ m_level_combobox.addItem(_("Info"), audlog::Info);
+ m_level_combobox.addItem(_("Warning"), audlog::Warning);
+ m_level_combobox.addItem(_("Error"), audlog::Error);
- m_level_combobox.setCurrentIndex (s_level);
+ m_level_combobox.setCurrentIndex(s_level);
- QObject::connect (& m_level_combobox,
- static_cast <void (QComboBox::*) (int)> (&QComboBox::currentIndexChanged),
- [this] (int idx) { setLogLevel ((audlog::Level) idx); });
+ QObject::connect(
+ &m_level_combobox,
+ static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ [this](int idx) { setLogLevel((audlog::Level)idx); });
- auto btnbox = new QDialogButtonBox (this);
+ auto btnbox = new QDialogButtonBox(this);
- auto btn1 = btnbox->addButton (translate_str (N_("Cl_ear")), QDialogButtonBox::ActionRole);
- btn1->setIcon (audqt::get_icon ("edit-clear-all"));
- btn1->setAutoDefault (false);
- QObject::connect (btn1, & QPushButton::clicked, [] () {
- s_model.get ()->cleanup ();
- });
+ auto btn1 = btnbox->addButton(translate_str(N_("Cl_ear")),
+ QDialogButtonBox::ActionRole);
+ btn1->setIcon(audqt::get_icon("edit-clear-all"));
+ btn1->setAutoDefault(false);
+ QObject::connect(btn1, &QPushButton::clicked,
+ []() { s_model.get()->cleanup(); });
- auto btn2 = btnbox->addButton (QDialogButtonBox::Close);
- btn2->setText (translate_str (N_("_Close")));
- btn2->setAutoDefault (false);
- QObject::connect (btn2, & QPushButton::clicked, this, & QDialog::close);
+ auto btn2 = btnbox->addButton(QDialogButtonBox::Close);
+ btn2->setText(translate_str(N_("_Close")));
+ btn2->setAutoDefault(false);
+ QObject::connect(btn2, &QPushButton::clicked, this, &QDialog::close);
- auto hbox = make_hbox (nullptr);
- hbox->addWidget (new QLabel (_("Log Level:"), this));
- hbox->addWidget (& m_level_combobox);
- hbox->addWidget (btnbox);
+ auto hbox = make_hbox(nullptr);
+ hbox->addWidget(new QLabel(_("Log Level:"), this));
+ hbox->addWidget(&m_level_combobox);
+ hbox->addWidget(btnbox);
- auto vbox = make_vbox (this);
- vbox->addWidget (view);
- vbox->addLayout (hbox);
+ auto vbox = make_vbox(this);
+ vbox->addWidget(view);
+ vbox->addLayout(hbox);
- resize (6 * sizes.OneInch, 3 * sizes.OneInch);
+ resize(6 * sizes.OneInch, 3 * sizes.OneInch);
}
static LogEntryInspector * s_inspector = nullptr;
-void LogEntryInspector::setLogLevel (audlog::Level level)
+void LogEntryInspector::setLogLevel(audlog::Level level)
{
s_level = level;
- audlog::unsubscribe (log_handler);
- audlog::subscribe (log_handler, level);
+ audlog::unsubscribe(log_handler);
+ audlog::subscribe(log_handler, level);
- m_level_combobox.setCurrentIndex (level);
+ m_level_combobox.setCurrentIndex(level);
}
-EXPORT void log_inspector_show ()
+EXPORT void log_inspector_show()
{
- if (! s_inspector)
+ if (!s_inspector)
{
s_inspector = new LogEntryInspector;
- s_inspector->setAttribute (Qt::WA_DeleteOnClose);
+ s_inspector->setAttribute(Qt::WA_DeleteOnClose);
- QObject::connect (s_inspector, & QObject::destroyed, [] () {
- s_inspector = nullptr;
- });
+ QObject::connect(s_inspector, &QObject::destroyed,
+ []() { s_inspector = nullptr; });
}
- window_bring_to_front (s_inspector);
+ window_bring_to_front(s_inspector);
}
-EXPORT void log_inspector_hide ()
-{
- delete s_inspector;
-}
+EXPORT void log_inspector_hide() { delete s_inspector; }
} // namespace audqt
diff --git a/src/libaudqt/menu-qt.cc b/src/libaudqt/menu-qt.cc
index 2ce34de..ca08ece 100644
--- a/src/libaudqt/menu-qt.cc
+++ b/src/libaudqt/menu-qt.cc
@@ -1,6 +1,6 @@
/*
* menu.h
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,104 +28,109 @@
#include <libaudcore/hook.h>
#include <libaudcore/runtime.h>
-namespace audqt {
+namespace audqt
+{
class MenuAction : public QAction
{
public:
- MenuAction (const MenuItem & item, const char * domain, QWidget * parent);
+ MenuAction(const MenuItem & item, const char * domain, QWidget * parent);
private:
- void toggle (bool checked);
- void update ();
+ void toggle(bool checked);
+ void update();
const MenuItem & m_item;
SmartPtr<HookReceiver<MenuAction>> m_hook;
};
-MenuAction::MenuAction (const MenuItem & item, const char * domain, QWidget * parent) :
- QAction (parent),
- m_item (item)
+MenuAction::MenuAction(const MenuItem & item, const char * domain,
+ QWidget * parent)
+ : QAction(parent), m_item(item)
{
if (item.sep)
{
- setSeparator (true);
+ setSeparator(true);
return;
}
- setText (translate_str (item.text.name, domain));
+ setText(translate_str(item.text.name, domain));
if (item.cfg.name)
{
- setCheckable (true);
- setChecked (aud_get_bool (item.cfg.sect, item.cfg.name));
+ setCheckable(true);
+ setChecked(aud_get_bool(item.cfg.sect, item.cfg.name));
- QObject::connect (this, & QAction::toggled, this, & MenuAction::toggle);
+ QObject::connect(this, &QAction::toggled, this, &MenuAction::toggle);
if (item.cfg.hook)
- m_hook.capture (new HookReceiver<MenuAction> (item.cfg.hook, this, & MenuAction::update));
+ m_hook.capture(new HookReceiver<MenuAction>(item.cfg.hook, this,
+ &MenuAction::update));
}
else if (item.func)
- QObject::connect (this, & QAction::triggered, item.func);
+ QObject::connect(this, &QAction::triggered, item.func);
else if (item.items.len)
- setMenu (menu_build (item.items, domain, parent));
+ setMenu(menu_build(item.items, domain, parent));
else if (item.submenu)
- setMenu (item.submenu ());
+ setMenu(item.submenu());
#ifndef Q_OS_MAC
- if (item.text.icon && QIcon::hasThemeIcon (item.text.icon))
- setIcon (audqt::get_icon (item.text.icon));
+ if (item.text.icon && QIcon::hasThemeIcon(item.text.icon))
+ setIcon(audqt::get_icon(item.text.icon));
#endif
if (item.text.shortcut)
- setShortcut (QString (item.text.shortcut));
+ setShortcut(QString(item.text.shortcut));
if (parent)
- parent->addAction (this);
+ parent->addAction(this);
}
-void MenuAction::toggle (bool checked)
+void MenuAction::toggle(bool checked)
{
- if (aud_get_bool (m_item.cfg.sect, m_item.cfg.name) != checked)
+ if (aud_get_bool(m_item.cfg.sect, m_item.cfg.name) != checked)
{
- aud_set_bool (m_item.cfg.sect, m_item.cfg.name, checked);
+ aud_set_bool(m_item.cfg.sect, m_item.cfg.name, checked);
if (m_item.func)
- m_item.func ();
+ m_item.func();
}
}
-void MenuAction::update ()
+void MenuAction::update()
{
- setChecked (aud_get_bool (m_item.cfg.sect, m_item.cfg.name));
+ setChecked(aud_get_bool(m_item.cfg.sect, m_item.cfg.name));
}
-EXPORT QAction * menu_action (const MenuItem & menu_item, const char * domain, QWidget * parent)
+EXPORT QAction * menu_action(const MenuItem & menu_item, const char * domain,
+ QWidget * parent)
{
- return new MenuAction (menu_item, domain, parent);
+ return new MenuAction(menu_item, domain, parent);
}
-EXPORT QMenu * menu_build (ArrayRef<MenuItem> menu_items, const char * domain, QWidget * parent)
+EXPORT QMenu * menu_build(ArrayRef<MenuItem> menu_items, const char * domain,
+ QWidget * parent)
{
- QMenu * m = new QMenu (parent);
+ QMenu * m = new QMenu(parent);
for (auto & it : menu_items)
- m->addAction (new MenuAction (it, domain, parent));
+ m->addAction(new MenuAction(it, domain, parent));
return m;
}
-EXPORT QMenuBar * menubar_build (ArrayRef<MenuItem> menu_items, const char * domain, QWidget * parent)
+EXPORT QMenuBar * menubar_build(ArrayRef<MenuItem> menu_items,
+ const char * domain, QWidget * parent)
{
#ifdef Q_OS_MAC
- QMenuBar * m = new QMenuBar (nullptr);
+ QMenuBar * m = new QMenuBar(nullptr);
#else
- QMenuBar * m = new QMenuBar (parent);
- m->setContextMenuPolicy (Qt::PreventContextMenu);
+ QMenuBar * m = new QMenuBar(parent);
+ m->setContextMenuPolicy(Qt::PreventContextMenu);
#endif
for (auto & it : menu_items)
- m->addAction (new MenuAction (it, domain, parent));
+ m->addAction(new MenuAction(it, domain, parent));
return m;
}
diff --git a/src/libaudqt/menu.h b/src/libaudqt/menu.h
index 3478291..b93daa3 100644
--- a/src/libaudqt/menu.h
+++ b/src/libaudqt/menu.h
@@ -1,6 +1,6 @@
/*
* menu.h
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -31,25 +31,29 @@ class QWidget;
enum class AudMenuID;
-namespace audqt {
+namespace audqt
+{
-typedef void (* MenuFunc) ();
+typedef void (*MenuFunc)();
-struct MenuItemText {
+struct MenuItemText
+{
const char * name;
const char * icon;
const char * shortcut;
};
-struct MenuItemConfig {
+struct MenuItemConfig
+{
const char * sect;
const char * name;
const char * hook;
};
-struct MenuItem {
+struct MenuItem
+{
MenuItemText text;
- void (* func) ();
+ void (*func)();
/* for toggle items */
MenuItemConfig cfg;
@@ -58,39 +62,60 @@ struct MenuItem {
ArrayRef<MenuItem> items;
/* for custom submenus */
- QMenu * (* submenu) ();
+ QMenu * (*submenu)();
/* for separators */
bool sep;
};
-constexpr MenuItem MenuCommand (MenuItemText text, MenuFunc func)
- { return {text, func}; }
-constexpr MenuItem MenuToggle (MenuItemText text, MenuItemConfig cfg, MenuFunc func = nullptr)
- { return {text, func, cfg}; }
-constexpr MenuItem MenuSub (MenuItemText text, ArrayRef<MenuItem> items)
- { return {text, nullptr, {}, items}; }
-constexpr MenuItem MenuSub (MenuItemText text, QMenu * (* submenu) ())
- { return {text, nullptr, {}, nullptr, submenu}; }
-constexpr MenuItem MenuSep ()
- { return {{}, nullptr, {}, nullptr, nullptr, true}; }
+constexpr MenuItem MenuCommand(MenuItemText text, MenuFunc func)
+{
+ return {text, func};
+}
+constexpr MenuItem MenuToggle(MenuItemText text, MenuItemConfig cfg,
+ MenuFunc func = nullptr)
+{
+ return {text, func, cfg};
+}
+constexpr MenuItem MenuSub(MenuItemText text, ArrayRef<MenuItem> items)
+{
+ return {text, nullptr, {}, items};
+}
+constexpr MenuItem MenuSub(MenuItemText text, QMenu * (*submenu)())
+{
+ return {text, nullptr, {}, nullptr, submenu};
+}
+constexpr MenuItem MenuSep()
+{
+ return {{}, nullptr, {}, nullptr, nullptr, true};
+}
/* menu.cc */
-QAction * menu_action (const MenuItem & menu_item, const char * domain, QWidget * parent = nullptr);
-QMenu * menu_build (ArrayRef<MenuItem> menu_items, const char * domain, QWidget * parent = nullptr);
-QMenuBar * menubar_build (ArrayRef<MenuItem> menu_items, const char * domain, QWidget * parent = nullptr);
+QAction * menu_action(const MenuItem & menu_item, const char * domain,
+ QWidget * parent = nullptr);
+QMenu * menu_build(ArrayRef<MenuItem> menu_items, const char * domain,
+ QWidget * parent = nullptr);
+QMenuBar * menubar_build(ArrayRef<MenuItem> menu_items, const char * domain,
+ QWidget * parent = nullptr);
#ifdef PACKAGE
-static inline QMenu * menu_build (ArrayRef<MenuItem> menu_items, QWidget * parent = nullptr)
- { return menu_build (menu_items, PACKAGE, parent); }
-static inline QMenuBar * menubar_build (ArrayRef<MenuItem> menu_items, QWidget * parent = nullptr)
- { return menubar_build (menu_items, PACKAGE, parent); }
+static inline QMenu * menu_build(ArrayRef<MenuItem> menu_items,
+ QWidget * parent = nullptr)
+{
+ return menu_build(menu_items, PACKAGE, parent);
+}
+static inline QMenuBar * menubar_build(ArrayRef<MenuItem> menu_items,
+ QWidget * parent = nullptr)
+{
+ return menubar_build(menu_items, PACKAGE, parent);
+}
#endif
/* plugin-menu.cc */
-QMenu * menu_get_by_id (AudMenuID id);
-void menu_add (AudMenuID id, MenuFunc func, const char * name, const char * icon);
-void menu_remove (AudMenuID id, MenuFunc func);
+QMenu * menu_get_by_id(AudMenuID id);
+void menu_add(AudMenuID id, MenuFunc func, const char * name,
+ const char * icon);
+void menu_remove(AudMenuID id, MenuFunc func);
} // namespace audqt
diff --git a/src/libaudqt/meson.build b/src/libaudqt/meson.build
new file mode 100644
index 0000000..6aff2c9
--- /dev/null
+++ b/src/libaudqt/meson.build
@@ -0,0 +1,58 @@
+libaudqt_sources = [
+ 'about-qt.cc',
+ 'art-qt.cc',
+ 'audqt.cc',
+ 'colorbutton.cc',
+ 'eq-preset-qt.cc',
+ 'equalizer-qt.cc',
+ 'file-entry.cc',
+ 'fileopener.cc',
+ 'font-entry.cc',
+ 'infopopup-qt.cc',
+ 'infowin-qt.cc',
+ 'info-widget.cc',
+ 'log-inspector.cc',
+ 'menu-qt.cc',
+ 'playlist-management.cc',
+ 'plugin-menu-qt.cc',
+ 'prefs-builder.cc',
+ 'prefs-plugin.cc',
+ 'prefs-widget-qt.cc',
+ 'prefs-window-qt.cc',
+ 'prefs-pluginlist-model.cc',
+ 'queue-manager-qt.cc',
+ 'url-opener-qt.cc',
+ 'util-qt.cc',
+ 'treeview.cc',
+ 'volumebutton.cc'
+]
+
+
+libaudqt_headers = [
+ 'colorbutton.h',
+ 'export.h',
+ 'iface.h',
+ 'info-widget.h',
+ 'libaudqt.h',
+ 'menu.h',
+ 'treeview.h'
+]
+
+
+images_src = qt5.preprocess(qresources: 'images.qrc')
+
+
+install_headers(libaudqt_headers, subdir: 'libaudqt')
+
+
+libaudqt_lib = library('audqt',
+ libaudqt_sources,
+ images_src,
+ cpp_args: ['-DLIBAUDQT_BUILD'],
+ include_directories: [src_inc],
+ dependencies: [qt_dep],
+ link_with: [libaudcore_lib],
+ soversion: '2',
+ version: '2.2.0',
+ install: true
+)
diff --git a/src/libaudqt/playlist-management.cc b/src/libaudqt/playlist-management.cc
index c6e0899..d373801 100644
--- a/src/libaudqt/playlist-management.cc
+++ b/src/libaudqt/playlist-management.cc
@@ -1,6 +1,6 @@
/*
* playlist-management.cc
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -20,101 +20,87 @@
#include "libaudqt.h"
#include <QCheckBox>
-#include <QDialog>
-#include <QDialogButtonBox>
-#include <QLabel>
-#include <QLineEdit>
+#include <QInputDialog>
#include <QPushButton>
-#include <QVBoxLayout>
#include <libaudcore/audstrings.h>
#include <libaudcore/i18n.h>
-#include <libaudcore/runtime.h>
#include <libaudcore/playlist.h>
+#include <libaudcore/runtime.h>
-namespace audqt {
-
-static QDialog * buildRenameDialog (Playlist playlist)
+namespace audqt
{
- auto dialog = new QDialog;
- auto prompt = new QLabel (_("What would you like to call this playlist?"), dialog);
- auto entry = new QLineEdit ((const char *) playlist.get_title (), dialog);
- auto rename = new QPushButton (translate_str (N_("_Rename")), dialog);
- auto cancel = new QPushButton (translate_str (N_("_Cancel")), dialog);
-
- auto buttonbox = new QDialogButtonBox (dialog);
- buttonbox->addButton (rename, QDialogButtonBox::AcceptRole);
- buttonbox->addButton (cancel, QDialogButtonBox::RejectRole);
-
- QObject::connect (buttonbox, & QDialogButtonBox::accepted, [dialog, entry, playlist] () {
- playlist.set_title (entry->text ().toUtf8 ());
- dialog->close ();
- });
- QObject::connect (buttonbox, & QDialogButtonBox::rejected, dialog, & QDialog::close);
-
- auto layout = make_vbox (dialog);
- layout->addWidget (prompt);
- layout->addWidget (entry);
- layout->addStretch (1);
- layout->addWidget (buttonbox);
-
- dialog->setWindowTitle (_("Rename Playlist"));
- dialog->setContentsMargins (margins.EightPt);
-
- entry->selectAll ();
+static QDialog * buildRenameDialog(Playlist playlist)
+{
+ auto dialog = new QInputDialog;
+ dialog->setInputMode(QInputDialog::TextInput);
+ dialog->setWindowTitle(_("Rename Playlist"));
+ dialog->setLabelText(_("What would you like to call this playlist?"));
+ dialog->setOkButtonText(translate_str(N_("_Rename")));
+ dialog->setCancelButtonText(translate_str(N_("_Cancel")));
+ dialog->setTextValue((const char *)playlist.get_title());
+
+ QObject::connect(dialog, &QInputDialog::textValueSelected,
+ [dialog, playlist](const QString & text) {
+ playlist.set_title(text.toUtf8());
+ dialog->close();
+ });
return dialog;
}
-static QDialog * buildDeleteDialog (Playlist playlist)
+static QDialog * buildDeleteDialog(Playlist playlist)
{
auto dialog = new QMessageBox;
- auto skip_prompt = new QCheckBox (translate_str (N_("_Don’t ask again")), dialog);
- auto remove = new QPushButton (translate_str (N_("_Remove")), dialog);
- auto cancel = new QPushButton (translate_str (N_("_Cancel")), dialog);
-
- dialog->setIcon (QMessageBox::Question);
- dialog->setWindowTitle (_("Remove Playlist"));
- dialog->setText ((const char *) str_printf (_("Do you want to permanently remove “%s”?"),
- (const char *) playlist.get_title ()));
- dialog->setCheckBox (skip_prompt);
- dialog->addButton (remove, QMessageBox::AcceptRole);
- dialog->addButton (cancel, QMessageBox::RejectRole);
-
- remove->setIcon (audqt::get_icon ("edit-delete"));
- cancel->setIcon (audqt::get_icon ("process-stop"));
-
- QObject::connect (skip_prompt, & QCheckBox::stateChanged, [] (int state) {
- aud_set_bool ("audgui", "no_confirm_playlist_delete", (state == Qt::Checked));
+ auto skip_prompt =
+ new QCheckBox(translate_str(N_("_Don’t ask again")), dialog);
+ auto remove = new QPushButton(translate_str(N_("_Remove")), dialog);
+ auto cancel = new QPushButton(translate_str(N_("_Cancel")), dialog);
+
+ dialog->setIcon(QMessageBox::Question);
+ dialog->setWindowTitle(_("Remove Playlist"));
+ dialog->setText(
+ (const char *)str_printf(_("Do you want to permanently remove “%s”?"),
+ (const char *)playlist.get_title()));
+ dialog->setCheckBox(skip_prompt);
+ dialog->addButton(remove, QMessageBox::AcceptRole);
+ dialog->addButton(cancel, QMessageBox::RejectRole);
+
+ remove->setIcon(audqt::get_icon("edit-delete"));
+ cancel->setIcon(audqt::get_icon("process-stop"));
+
+ QObject::connect(skip_prompt, &QCheckBox::stateChanged, [](int state) {
+ aud_set_bool("audgui", "no_confirm_playlist_delete",
+ (state == Qt::Checked));
});
- QObject::connect (remove, & QPushButton::clicked, [dialog, playlist] () {
- playlist.remove_playlist ();
- dialog->close ();
+ QObject::connect(remove, &QPushButton::clicked, [dialog, playlist]() {
+ playlist.remove_playlist();
+ dialog->close();
});
return dialog;
}
-EXPORT void playlist_show_rename (Playlist playlist)
+EXPORT void playlist_show_rename(Playlist playlist)
{
- auto dialog = buildRenameDialog (playlist);
- dialog->setAttribute (Qt::WA_DeleteOnClose);
- dialog->show ();
+ auto dialog = buildRenameDialog(playlist);
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->show();
}
-EXPORT void playlist_confirm_delete (Playlist playlist)
+EXPORT void playlist_confirm_delete(Playlist playlist)
{
- if (aud_get_bool ("audgui", "no_confirm_playlist_delete"))
+ if (aud_get_bool("audgui", "no_confirm_playlist_delete"))
{
- playlist.remove_playlist ();
+ playlist.remove_playlist();
return;
}
- auto dialog = buildDeleteDialog (playlist);
- dialog->setAttribute (Qt::WA_DeleteOnClose);
- dialog->show ();
+ auto dialog = buildDeleteDialog(playlist);
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->show();
}
} // namespace audqt
diff --git a/src/libaudqt/plugin-menu-qt.cc b/src/libaudqt/plugin-menu-qt.cc
index 344ad7e..a886258 100644
--- a/src/libaudqt/plugin-menu-qt.cc
+++ b/src/libaudqt/plugin-menu-qt.cc
@@ -1,6 +1,6 @@
/*
* plugin-menu.cc
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -26,9 +26,11 @@
#include <libaudcore/interface.h>
#include <libaudcore/plugins.h>
-namespace audqt {
+namespace audqt
+{
-struct ItemData {
+struct ItemData
+{
MenuItem item;
SmartPtr<QAction> action;
};
@@ -36,57 +38,54 @@ struct ItemData {
static aud::array<AudMenuID, Index<ItemData>> items;
static aud::array<AudMenuID, QMenu *> menus;
-static void show_prefs ()
-{
- prefswin_show_plugin_page (PluginType::General);
-}
+static void show_prefs() { prefswin_show_plugin_page(PluginType::General); }
MenuItem default_menu_items[] = {
- MenuCommand ({N_("_Plugins ..."), "preferences-system"}, show_prefs),
+ MenuCommand({N_("_Plugins ..."), "preferences-system"}, show_prefs),
};
-void menu_rebuild (AudMenuID id)
+void menu_rebuild(AudMenuID id)
{
if (menus[id])
- menus[id]->clear ();
+ menus[id]->clear();
else
- menus[id] = new QMenu (_("Services"));
+ menus[id] = new QMenu(_("Services"));
for (auto & item : items[id])
{
- item.action.capture (menu_action (item.item, nullptr));
- menus[id]->addAction (item.action.get ());
+ item.action.capture(menu_action(item.item, nullptr));
+ menus[id]->addAction(item.action.get());
}
- if (! menus[id]->isEmpty ())
- menus[id]->addAction (menu_action (MenuSep (), PACKAGE, menus[id]));
+ if (!menus[id]->isEmpty())
+ menus[id]->addAction(menu_action(MenuSep(), PACKAGE, menus[id]));
for (auto & item : default_menu_items)
- menus[id]->addAction (menu_action (item, PACKAGE, menus[id]));
+ menus[id]->addAction(menu_action(item, PACKAGE, menus[id]));
}
-EXPORT QMenu * menu_get_by_id (AudMenuID id)
+EXPORT QMenu * menu_get_by_id(AudMenuID id)
{
- if (! menus[id])
- menu_rebuild (id);
+ if (!menus[id])
+ menu_rebuild(id);
return menus[id];
}
-EXPORT void menu_add (AudMenuID id, MenuFunc func, const char * name, const char * icon)
+EXPORT void menu_add(AudMenuID id, MenuFunc func, const char * name,
+ const char * icon)
{
- items[id].append (MenuCommand ({name, icon}, func));
+ items[id].append(MenuCommand({name, icon}, func));
menu_rebuild(id);
}
-EXPORT void menu_remove (AudMenuID id, MenuFunc func)
+EXPORT void menu_remove(AudMenuID id, MenuFunc func)
{
- auto is_match = [func] (ItemData & item)
- { return item.item.func == func; };
+ auto is_match = [func](ItemData & item) { return item.item.func == func; };
- if (items[id].remove_if (is_match, true))
- menu_rebuild (id);
+ if (items[id].remove_if(is_match, true))
+ menu_rebuild(id);
}
} // namespace audqt
diff --git a/src/libaudqt/prefs-builder.cc b/src/libaudqt/prefs-builder.cc
index 2bcdd24..ca9d111 100644
--- a/src/libaudqt/prefs-builder.cc
+++ b/src/libaudqt/prefs-builder.cc
@@ -1,6 +1,6 @@
/*
* prefs-builder.cc
- * Copyright 2014 William Pitcock and John Lindgren
+ * Copyright 2014 Ariadne Conill and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,9 +28,11 @@
#include <libaudcore/preferences.h>
#include <libaudcore/runtime.h>
-namespace audqt {
+namespace audqt
+{
-void prefs_populate (QBoxLayout * layout, ArrayRef<PreferencesWidget> widgets, const char * domain)
+void prefs_populate(QBoxLayout * layout, ArrayRef<PreferencesWidget> widgets,
+ const char * domain)
{
/* layout prior to header label */
QBoxLayout * orig_layout = layout;
@@ -46,27 +48,27 @@ void prefs_populate (QBoxLayout * layout, ArrayRef<PreferencesWidget> widgets, c
{
if (w.child)
{
- if (! parent_layout)
+ if (!parent_layout)
{
/* save prior layouts */
parent_layout = layout;
parent_orig_layout = orig_layout;
/* create new layout for child widgets */
- if (dynamic_cast<QHBoxLayout *> (parent_layout))
- layout = make_hbox (nullptr, sizes.TwoPt);
+ if (dynamic_cast<QHBoxLayout *>(parent_layout))
+ layout = make_hbox(nullptr, sizes.TwoPt);
else
{
- layout = make_vbox (nullptr, sizes.TwoPt);
- layout->setContentsMargins (sizes.EightPt, 0, 0, 0);
+ layout = make_vbox(nullptr, sizes.TwoPt);
+ layout->setContentsMargins(sizes.EightPt, 0, 0, 0);
}
- parent_layout->addLayout (layout);
+ parent_layout->addLayout(layout);
orig_layout = layout;
if (parent_widget)
- parent_widget->set_child_layout (layout);
+ parent_widget->set_child_layout(layout);
}
}
else
@@ -83,28 +85,28 @@ void prefs_populate (QBoxLayout * layout, ArrayRef<PreferencesWidget> widgets, c
/* enable/disable child widgets */
if (parent_widget)
- parent_widget->update_from_cfg ();
+ parent_widget->update_from_cfg();
parent_widget = nullptr;
}
if (w.type != PreferencesWidget::RadioButton)
radio_btn_group[w.child] = nullptr;
- if (! w.child)
+ if (!w.child)
radio_btn_group[true] = nullptr;
switch (w.type)
{
case PreferencesWidget::Button:
- layout->addWidget (new ButtonWidget (& w, domain));
+ layout->addWidget(new ButtonWidget(&w, domain));
break;
case PreferencesWidget::CheckButton:
{
- auto checkbox = new BooleanWidget (& w, domain);
- layout->addWidget (checkbox);
+ auto checkbox = new BooleanWidget(&w, domain);
+ layout->addWidget(checkbox);
- if (! w.child)
+ if (!w.child)
parent_widget = checkbox;
break;
@@ -112,23 +114,23 @@ void prefs_populate (QBoxLayout * layout, ArrayRef<PreferencesWidget> widgets, c
case PreferencesWidget::Label:
{
- auto label = new QLabel (translate_str (w.label, domain));
+ auto label = new QLabel(translate_str(w.label, domain));
- if (strstr (w.label, "<b>"))
+ if (strstr(w.label, "<b>"))
{
/* extra spacing above a header */
- if (orig_layout->itemAt (0))
- orig_layout->addSpacing (sizes.EightPt);
+ if (orig_layout->itemAt(0))
+ orig_layout->addSpacing(sizes.EightPt);
- orig_layout->addWidget (label);
+ orig_layout->addWidget(label);
/* create indented layout below header */
- layout = make_vbox (nullptr, sizes.TwoPt);
- layout->setContentsMargins (sizes.EightPt, 0, 0, 0);
- orig_layout->addLayout (layout);
+ layout = make_vbox(nullptr, sizes.TwoPt);
+ layout->setContentsMargins(sizes.EightPt, 0, 0, 0);
+ orig_layout->addLayout(layout);
}
else
- layout->addWidget (label);
+ layout->addWidget(label);
break;
}
@@ -137,88 +139,94 @@ void prefs_populate (QBoxLayout * layout, ArrayRef<PreferencesWidget> widgets, c
switch (w.cfg.type)
{
case WidgetConfig::Int:
- layout->addWidget (new IntegerWidget (& w, domain));
+ layout->addWidget(new IntegerWidget(&w, domain));
break;
case WidgetConfig::Float:
- layout->addWidget (new DoubleWidget (& w, domain));
+ layout->addWidget(new DoubleWidget(&w, domain));
break;
default:
- AUDDBG ("encountered unhandled configuration type %d for PreferencesWidget::SpinButton\n", w.cfg.type);
+ AUDDBG("encountered unhandled configuration type %d for "
+ "PreferencesWidget::SpinButton\n",
+ w.cfg.type);
break;
}
break;
case PreferencesWidget::Entry:
- /* TODO: implement file chooser */
+ layout->addWidget(new StringWidget(&w, domain));
+ break;
+
case PreferencesWidget::FileEntry:
- layout->addWidget (new StringWidget (& w, domain));
+ layout->addWidget(new FileWidget(&w, domain));
+ break;
+
+ case PreferencesWidget::FontButton:
+ layout->addWidget(new FontWidget(&w, domain));
break;
case PreferencesWidget::RadioButton:
{
- if (! radio_btn_group[w.child])
+ if (!radio_btn_group[w.child])
radio_btn_group[w.child] = new QButtonGroup;
- auto radio_btn = new RadioButtonWidget (& w, domain, radio_btn_group[w.child]);
- layout->addWidget (radio_btn);
+ auto radio_btn =
+ new RadioButtonWidget(&w, domain, radio_btn_group[w.child]);
+ layout->addWidget(radio_btn);
- if (! w.child)
+ if (!w.child)
parent_widget = radio_btn;
break;
}
- case PreferencesWidget::FontButton:
- /* XXX: unimplemented */
- AUDDBG ("font buttons are unimplemented\n");
- break;
-
case PreferencesWidget::ComboBox:
- layout->addWidget (new ComboBoxWidget (& w, domain));
+ layout->addWidget(new ComboBoxWidget(&w, domain));
break;
case PreferencesWidget::CustomQt:
if (w.data.populate)
- layout->addWidget ((QWidget *) w.data.populate ());
+ layout->addWidget((QWidget *)w.data.populate());
break;
/* layout widgets follow */
case PreferencesWidget::Box:
- layout->addWidget (new BoxWidget (& w, domain,
- (bool) dynamic_cast<QHBoxLayout *> (layout)));
+ layout->addWidget(new BoxWidget(
+ &w, domain, (bool)dynamic_cast<QHBoxLayout *>(layout)));
break;
case PreferencesWidget::Table:
- layout->addWidget (new TableWidget (& w, domain));
+ layout->addWidget(new TableWidget(&w, domain));
break;
case PreferencesWidget::Notebook:
- layout->addWidget (new NotebookWidget (& w, domain));
+ layout->addWidget(new NotebookWidget(&w, domain));
break;
case PreferencesWidget::Separator:
{
QFrame * f = new QFrame;
- f->setFrameShape (w.data.separator.horizontal ? QFrame::HLine : QFrame::VLine);
- f->setFrameShadow (QFrame::Sunken);
+ f->setFrameShape(w.data.separator.horizontal ? QFrame::HLine
+ : QFrame::VLine);
+ f->setFrameShadow(QFrame::Sunken);
- layout->addSpacing (sizes.FourPt);
- layout->addWidget (f);
- layout->addSpacing (sizes.FourPt);
+ layout->addSpacing(sizes.FourPt);
+ layout->addWidget(f);
+ layout->addSpacing(sizes.FourPt);
break;
}
/* stub handler */
default:
- AUDDBG ("invoked stub handler for PreferencesWidget type %d\n", w.type);
+ AUDDBG("invoked stub handler for PreferencesWidget type %d\n",
+ w.type);
break;
}
}
/* enable/disable child widgets */
if (parent_widget)
- parent_widget->update_from_cfg ();
+ parent_widget->update_from_cfg();
}
} // namespace audqt
diff --git a/src/libaudqt/prefs-plugin.cc b/src/libaudqt/prefs-plugin.cc
index 03fa53d..473d9bc 100644
--- a/src/libaudqt/prefs-plugin.cc
+++ b/src/libaudqt/prefs-plugin.cc
@@ -1,6 +1,6 @@
/*
* prefs-plugin.cc
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -31,39 +31,42 @@
#include "libaudqt.h"
-namespace audqt {
+namespace audqt
+{
-EXPORT void plugin_about (PluginHandle * ph)
+EXPORT void plugin_about(PluginHandle * ph)
{
- Plugin * header = (Plugin *) aud_plugin_get_header (ph);
+ Plugin * header = (Plugin *)aud_plugin_get_header(ph);
- if (! header)
+ if (!header)
return;
const char * name = header->info.name;
const char * text = header->info.about;
- if (! text)
+ if (!text)
return;
if (header->info.domain)
{
- name = dgettext (header->info.domain, name);
- text = dgettext (header->info.domain, text);
+ name = dgettext(header->info.domain, name);
+ text = dgettext(header->info.domain, text);
}
- AUDDBG ("name = %s\n", name);
+ AUDDBG("name = %s\n", name);
- simple_message (str_printf (_("About %s"), name), text, QMessageBox::Information);
+ simple_message(str_printf(_("About %s"), name), text,
+ QMessageBox::Information);
}
-struct ConfigWindow {
+struct ConfigWindow
+{
PluginHandle * ph;
QDialog * root;
};
static Index<ConfigWindow *> config_windows;
-static ConfigWindow * find_config_window (PluginHandle * ph)
+static ConfigWindow * find_config_window(PluginHandle * ph)
{
for (ConfigWindow * cw : config_windows)
{
@@ -74,78 +77,82 @@ static ConfigWindow * find_config_window (PluginHandle * ph)
return nullptr;
}
-EXPORT void plugin_prefs (PluginHandle * ph)
+EXPORT void plugin_prefs(PluginHandle * ph)
{
- ConfigWindow * cw = find_config_window (ph);
+ ConfigWindow * cw = find_config_window(ph);
if (cw && cw->root)
{
- window_bring_to_front (cw->root);
+ window_bring_to_front(cw->root);
return;
}
- Plugin * header = (Plugin *) aud_plugin_get_header (ph);
- if (! header)
+ Plugin * header = (Plugin *)aud_plugin_get_header(ph);
+ if (!header)
return;
const PluginPreferences * p = header->info.prefs;
- if (! p)
+ if (!p)
return;
- if (! cw)
+ if (!cw)
{
- cw = new ConfigWindow {ph};
- config_windows.append (cw);
+ cw = new ConfigWindow{ph};
+ config_windows.append(cw);
}
cw->root = new QDialog;
- cw->root->setAttribute (Qt::WA_DeleteOnClose);
- cw->root->setContentsMargins (margins.FourPt);
+ cw->root->setAttribute(Qt::WA_DeleteOnClose);
+ cw->root->setContentsMargins(margins.FourPt);
if (p->init)
- p->init ();
+ p->init();
- QObject::connect (cw->root, & QObject::destroyed, [p, cw] () {
+ QObject::connect(cw->root, &QObject::destroyed, [p, cw]() {
if (p->cleanup)
- p->cleanup ();
+ p->cleanup();
cw->root = nullptr;
});
const char * name = header->info.name;
if (header->info.domain)
- name = dgettext (header->info.domain, name);
+ name = dgettext(header->info.domain, name);
- cw->root->setWindowTitle ((const char *) str_printf(_("%s Settings"), name));
+ cw->root->setWindowTitle((const char *)str_printf(_("%s Settings"), name));
- auto vbox = make_vbox (cw->root, sizes.TwoPt);
- prefs_populate (vbox, p->widgets, header->info.domain);
- vbox->addStretch (1);
+ auto vbox = make_vbox(cw->root, sizes.TwoPt);
+ prefs_populate(vbox, p->widgets, header->info.domain);
+ vbox->addStretch(1);
QDialogButtonBox * bbox = new QDialogButtonBox;
if (p->apply)
{
- bbox->setStandardButtons (QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
- bbox->button (QDialogButtonBox::Ok)->setText (translate_str (N_("_Set")));
- bbox->button (QDialogButtonBox::Cancel)->setText (translate_str (N_("_Cancel")));
-
- QObject::connect (bbox, & QDialogButtonBox::accepted, [p, cw] () {
- p->apply ();
- cw->root->deleteLater ();
+ bbox->setStandardButtons(QDialogButtonBox::Ok |
+ QDialogButtonBox::Cancel);
+ bbox->button(QDialogButtonBox::Ok)->setText(translate_str(N_("_Set")));
+ bbox->button(QDialogButtonBox::Cancel)
+ ->setText(translate_str(N_("_Cancel")));
+
+ QObject::connect(bbox, &QDialogButtonBox::accepted, [p, cw]() {
+ p->apply();
+ cw->root->deleteLater();
});
}
else
{
- bbox->setStandardButtons (QDialogButtonBox::Close);
- bbox->button (QDialogButtonBox::Close)->setText (translate_str (N_("_Close")));
+ bbox->setStandardButtons(QDialogButtonBox::Close);
+ bbox->button(QDialogButtonBox::Close)
+ ->setText(translate_str(N_("_Close")));
}
- QObject::connect (bbox, & QDialogButtonBox::rejected, cw->root, & QObject::deleteLater);
+ QObject::connect(bbox, &QDialogButtonBox::rejected, cw->root,
+ &QObject::deleteLater);
- vbox->addWidget (bbox);
+ vbox->addWidget(bbox);
- window_bring_to_front (cw->root);
+ window_bring_to_front(cw->root);
}
} // namespace audqt
diff --git a/src/libaudqt/prefs-pluginlist-model.cc b/src/libaudqt/prefs-pluginlist-model.cc
index ea82f43..df6fd4a 100644
--- a/src/libaudqt/prefs-pluginlist-model.cc
+++ b/src/libaudqt/prefs-pluginlist-model.cc
@@ -1,6 +1,6 @@
/*
* prefs-pluginlist-model.cc
- * Copyright 2014-2017 John Lindgren and William Pitcock
+ * Copyright 2014-2017 John Lindgren and Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -26,23 +26,24 @@
#include <libaudcore/runtime.h>
#include <libaudqt/libaudqt.h>
-namespace audqt {
+namespace audqt
+{
-struct PluginCategory {
+struct PluginCategory
+{
PluginType type;
const char * name;
};
static const PluginCategory categories[] = {
- { PluginType::General, N_("General") },
- { PluginType::Effect, N_("Effect") },
- { PluginType::Vis, N_("Visualization") },
- { PluginType::Input, N_("Input") },
- { PluginType::Playlist, N_("Playlist") },
- { PluginType::Transport, N_("Transport") }
-};
+ {PluginType::General, N_("General")},
+ {PluginType::Effect, N_("Effect")},
+ {PluginType::Vis, N_("Visualization")},
+ {PluginType::Input, N_("Input")},
+ {PluginType::Playlist, N_("Playlist")},
+ {PluginType::Transport, N_("Transport")}};
-static constexpr int n_categories = aud::n_elems (categories);
+static constexpr int n_categories = aud::n_elems(categories);
// The model hierarchy is as follows:
//
@@ -55,136 +56,139 @@ static constexpr int n_categories = aud::n_elems (categories);
// + Effect plugin ...
// + More categories ...
-QModelIndex PluginListModel::index (int row, int column, const QModelIndex & parent) const
+QModelIndex PluginListModel::index(int row, int column,
+ const QModelIndex & parent) const
{
// is parent the root node?
- if (! parent.isValid ())
- return createIndex (row, column, nullptr);
+ if (!parent.isValid())
+ return createIndex(row, column, nullptr);
// is parent a plugin node?
- if (parent.internalPointer () != nullptr)
- return QModelIndex ();
+ if (parent.internalPointer() != nullptr)
+ return QModelIndex();
// parent must be a category node
- int cat = parent.row ();
+ int cat = parent.row();
if (cat < 0 || cat >= n_categories)
- return QModelIndex ();
+ return QModelIndex();
- auto & list = aud_plugin_list (categories[cat].type);
- if (row < 0 || row >= list.len ())
- return QModelIndex ();
+ auto & list = aud_plugin_list(categories[cat].type);
+ if (row < 0 || row >= list.len())
+ return QModelIndex();
- return createIndex (row, column, list[row]);
+ return createIndex(row, column, list[row]);
}
// for a plugin node, return the category node
// for all other nodes, return an invalid index
-QModelIndex PluginListModel::parent (const QModelIndex & child) const
+QModelIndex PluginListModel::parent(const QModelIndex & child) const
{
- auto p = pluginForIndex (child);
- return p ? indexForType (aud_plugin_get_type (p)) : QModelIndex ();
+ auto p = pluginForIndex(child);
+ return p ? indexForType(aud_plugin_get_type(p)) : QModelIndex();
}
// retrieve the PluginHandle from a plugin node
-PluginHandle * PluginListModel::pluginForIndex (const QModelIndex & index) const
+PluginHandle * PluginListModel::pluginForIndex(const QModelIndex & index) const
{
- return (PluginHandle *) index.internalPointer ();
+ return (PluginHandle *)index.internalPointer();
}
// look up the category node for a given plugin type
-QModelIndex PluginListModel::indexForType (PluginType type) const
+QModelIndex PluginListModel::indexForType(PluginType type) const
{
- for (int cat = 0; cat < n_categories; cat ++)
+ for (int cat = 0; cat < n_categories; cat++)
{
if (categories[cat].type == type)
- return createIndex (cat, 0, nullptr);
+ return createIndex(cat, 0, nullptr);
}
- return QModelIndex ();
+ return QModelIndex();
}
-int PluginListModel::rowCount (const QModelIndex & parent) const
+int PluginListModel::rowCount(const QModelIndex & parent) const
{
// for the root node, return the # of categories
- if (! parent.isValid ())
+ if (!parent.isValid())
return n_categories;
// for a plugin node, return 0 (no children)
- if (parent.internalPointer () != nullptr)
+ if (parent.internalPointer() != nullptr)
return 0;
// for a category node, return the # of plugins
- int cat = parent.row ();
+ int cat = parent.row();
if (cat < 0 || cat >= n_categories)
return 0;
- return aud_plugin_list (categories[cat].type).len ();
+ return aud_plugin_list(categories[cat].type).len();
}
-int PluginListModel::columnCount (const QModelIndex & parent) const
+int PluginListModel::columnCount(const QModelIndex & parent) const
{
return NumColumns;
}
-QVariant PluginListModel::data (const QModelIndex & index, int role) const
+QVariant PluginListModel::data(const QModelIndex & index, int role) const
{
- auto p = pluginForIndex (index);
+ auto p = pluginForIndex(index);
- if (! p) // category node?
+ if (!p) // category node?
{
- if (role != Qt::DisplayRole || index.column () != 0)
- return QVariant ();
+ if (role != Qt::DisplayRole || index.column() != 0)
+ return QVariant();
- int cat = index.row ();
+ int cat = index.row();
if (cat < 0 || cat >= n_categories)
- return QVariant ();
+ return QVariant();
- return QString (_(categories[cat].name));
+ return QString(_(categories[cat].name));
}
- bool enabled = aud_plugin_get_enabled (p);
+ bool enabled = aud_plugin_get_enabled(p);
- switch (index.column ())
+ switch (index.column())
{
case NameColumn:
if (role == Qt::DisplayRole)
- return QString (aud_plugin_get_name (p));
+ return QString(aud_plugin_get_name(p));
if (role == Qt::CheckStateRole)
return enabled ? Qt::Checked : Qt::Unchecked;
break;
case AboutColumn:
- if (role == Qt::DecorationRole && enabled && aud_plugin_has_about (p))
- return audqt::get_icon ("dialog-information");
+ if (role == Qt::DecorationRole && enabled && aud_plugin_has_about(p))
+ return audqt::get_icon("dialog-information");
break;
case SettingsColumn:
- if (role == Qt::DecorationRole && enabled && aud_plugin_has_configure (p))
- return audqt::get_icon ("preferences-system");
+ if (role == Qt::DecorationRole && enabled &&
+ aud_plugin_has_configure(p))
+ return audqt::get_icon("preferences-system");
break;
}
- return QVariant ();
+ return QVariant();
}
-bool PluginListModel::setData (const QModelIndex &index, const QVariant &value, int role)
+bool PluginListModel::setData(const QModelIndex & index, const QVariant & value,
+ int role)
{
if (role != Qt::CheckStateRole)
return false;
- auto p = pluginForIndex (index);
- if (! p)
+ auto p = pluginForIndex(index);
+ if (!p)
return false;
- aud_plugin_enable (p, value.toUInt () != Qt::Unchecked);
- emit dataChanged (index, index.sibling (index.row (), NumColumns - 1));
+ aud_plugin_enable(p, value.toUInt() != Qt::Unchecked);
+ emit dataChanged(index, index.sibling(index.row(), NumColumns - 1));
return true;
}
-Qt::ItemFlags PluginListModel::flags (const QModelIndex & index) const
+Qt::ItemFlags PluginListModel::flags(const QModelIndex & index) const
{
return (Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
}
diff --git a/src/libaudqt/prefs-pluginlist-model.h b/src/libaudqt/prefs-pluginlist-model.h
index adb0130..74438a9 100644
--- a/src/libaudqt/prefs-pluginlist-model.h
+++ b/src/libaudqt/prefs-pluginlist-model.h
@@ -1,6 +1,6 @@
/*
* prefs-pluginlist-model.h
- * Copyright 2014-2017 John Lindgren and William Pitcock
+ * Copyright 2014-2017 John Lindgren and Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -25,12 +25,14 @@
enum class PluginType;
class PluginHandle;
-namespace audqt {
+namespace audqt
+{
class PluginListModel : public QAbstractItemModel
{
public:
- enum {
+ enum
+ {
NameColumn,
AboutColumn,
SettingsColumn,
@@ -38,20 +40,20 @@ public:
NumColumns
};
- PluginListModel (QObject * parent) : QAbstractItemModel (parent) {}
+ PluginListModel(QObject * parent) : QAbstractItemModel(parent) {}
- QModelIndex index (int row, int column, const QModelIndex & parent) const;
- QModelIndex parent (const QModelIndex & child) const;
+ QModelIndex index(int row, int column, const QModelIndex & parent) const;
+ QModelIndex parent(const QModelIndex & child) const;
- PluginHandle * pluginForIndex (const QModelIndex & index) const;
- QModelIndex indexForType (PluginType type) const;
+ PluginHandle * pluginForIndex(const QModelIndex & index) const;
+ QModelIndex indexForType(PluginType type) const;
- int rowCount (const QModelIndex & parent) const;
- int columnCount (const QModelIndex & parent) const;
+ int rowCount(const QModelIndex & parent) const;
+ int columnCount(const QModelIndex & parent) const;
- QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const;
- bool setData (const QModelIndex & index, const QVariant & value, int role);
- Qt::ItemFlags flags (const QModelIndex & parent) const;
+ QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
+ bool setData(const QModelIndex & index, const QVariant & value, int role);
+ Qt::ItemFlags flags(const QModelIndex & parent) const;
};
} // namespace audqt
diff --git a/src/libaudqt/prefs-widget-qt.cc b/src/libaudqt/prefs-widget-qt.cc
index c67280f..1a21b06 100644
--- a/src/libaudqt/prefs-widget-qt.cc
+++ b/src/libaudqt/prefs-widget-qt.cc
@@ -1,6 +1,6 @@
/*
* prefs-widget.cc
- * Copyright 2007-2014 Tomasz Moń, William Pitcock, and John Lindgren
+ * Copyright 2007-2014 Tomasz Moń, Ariadne Conill, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -17,8 +17,8 @@
* the use of this software.
*/
-#include "prefs-widget.h"
#include "libaudqt.h"
+#include "prefs-widget.h"
#include <assert.h>
#include <math.h>
@@ -33,215 +33,291 @@
#include <libaudcore/audstrings.h>
#include <libaudcore/i18n.h>
-namespace audqt {
+namespace audqt
+{
-HookableWidget::HookableWidget (const PreferencesWidget * parent, const char * domain) :
- m_parent (parent), m_domain (domain)
+HookableWidget::HookableWidget(const PreferencesWidget * parent,
+ const char * domain)
+ : m_parent(parent), m_domain(domain)
{
if (m_parent->cfg.hook)
- hook.capture (new HookReceiver<HookableWidget>
- {m_parent->cfg.hook, this, & HookableWidget::update_from_cfg});
+ hook.capture(new HookReceiver<HookableWidget>{
+ m_parent->cfg.hook, this, &HookableWidget::update_from_cfg});
}
-void HookableWidget::update_from_cfg ()
+void HookableWidget::update_from_cfg()
{
m_updating = true;
- update ();
+ update();
m_updating = false;
}
/* button */
-ButtonWidget::ButtonWidget (const PreferencesWidget * parent, const char * domain) :
- QPushButton (translate_str (parent->label, domain))
+ButtonWidget::ButtonWidget(const PreferencesWidget * parent,
+ const char * domain)
+ : QPushButton(translate_str(parent->label, domain))
{
- QObject::connect (this, & QPushButton::clicked, parent->data.button.callback);
+ setAutoDefault(false);
+ QObject::connect(this, &QPushButton::clicked, parent->data.button.callback);
}
/* boolean widget (checkbox) */
-BooleanWidget::BooleanWidget (const PreferencesWidget * parent, const char * domain) :
- QCheckBox (translate_str (parent->label, domain)),
- ParentWidget (parent, domain)
+BooleanWidget::BooleanWidget(const PreferencesWidget * parent,
+ const char * domain)
+ : QCheckBox(translate_str(parent->label, domain)),
+ ParentWidget(parent, domain)
{
- update ();
+ update();
- QObject::connect (this, & QCheckBox::stateChanged, [this] (int state) {
+ QObject::connect(this, &QCheckBox::stateChanged, [this](int state) {
if (m_updating)
return;
- m_parent->cfg.set_bool (state != Qt::Unchecked);
+ m_parent->cfg.set_bool(state != Qt::Unchecked);
if (m_child_layout)
- enable_layout (m_child_layout, state != Qt::Unchecked);
+ enable_layout(m_child_layout, state != Qt::Unchecked);
});
}
-void BooleanWidget::update ()
+void BooleanWidget::update()
{
- bool on = m_parent->cfg.get_bool ();
- setCheckState (on ? Qt::Checked : Qt::Unchecked);
+ bool on = m_parent->cfg.get_bool();
+ setCheckState(on ? Qt::Checked : Qt::Unchecked);
if (m_child_layout)
- enable_layout (m_child_layout, on);
+ enable_layout(m_child_layout, on);
}
/* integer (radio button) */
-RadioButtonWidget::RadioButtonWidget (const PreferencesWidget * parent,
- const char * domain, QButtonGroup * btn_group) :
- QRadioButton (translate_str (parent->label, domain)),
- ParentWidget (parent, domain)
+RadioButtonWidget::RadioButtonWidget(const PreferencesWidget * parent,
+ const char * domain,
+ QButtonGroup * btn_group)
+ : QRadioButton(translate_str(parent->label, domain)),
+ ParentWidget(parent, domain)
{
if (btn_group)
- btn_group->addButton (this, parent->data.radio_btn.value);
+ btn_group->addButton(this, parent->data.radio_btn.value);
- update ();
+ update();
- QObject::connect (this, & QAbstractButton::toggled, [this] (bool checked) {
+ QObject::connect(this, &QAbstractButton::toggled, [this](bool checked) {
if (m_updating)
return;
if (checked)
- m_parent->cfg.set_int (m_parent->data.radio_btn.value);
+ m_parent->cfg.set_int(m_parent->data.radio_btn.value);
if (m_child_layout)
- enable_layout (m_child_layout, checked);
+ enable_layout(m_child_layout, checked);
});
}
-void RadioButtonWidget::update ()
+void RadioButtonWidget::update()
{
- bool checked = (m_parent->cfg.get_int () == m_parent->data.radio_btn.value);
+ bool checked = (m_parent->cfg.get_int() == m_parent->data.radio_btn.value);
if (checked)
- setChecked (true);
+ setChecked(true);
if (m_child_layout)
- enable_layout (m_child_layout, checked);
+ enable_layout(m_child_layout, checked);
}
/* integer (spinbox) */
-IntegerWidget::IntegerWidget (const PreferencesWidget * parent, const char * domain) :
- HookableWidget (parent, domain),
- m_spinner (new QSpinBox)
+IntegerWidget::IntegerWidget(const PreferencesWidget * parent,
+ const char * domain)
+ : HookableWidget(parent, domain), m_spinner(new QSpinBox)
{
- auto layout = make_hbox (this);
+ auto layout = make_hbox(this);
if (parent->label)
- layout->addWidget (new QLabel (translate_str (parent->label, domain)));
+ layout->addWidget(new QLabel(translate_str(parent->label, domain)));
- m_spinner->setRange ((int) m_parent->data.spin_btn.min, (int) m_parent->data.spin_btn.max);
- m_spinner->setSingleStep ((int) m_parent->data.spin_btn.step);
- layout->addWidget (m_spinner);
+ m_spinner->setRange((int)m_parent->data.spin_btn.min,
+ (int)m_parent->data.spin_btn.max);
+ m_spinner->setSingleStep((int)m_parent->data.spin_btn.step);
+ layout->addWidget(m_spinner);
if (parent->data.spin_btn.right_label)
- layout->addWidget (new QLabel (translate_str (parent->data.spin_btn.right_label, domain)));
+ layout->addWidget(new QLabel(
+ translate_str(parent->data.spin_btn.right_label, domain)));
- layout->addStretch (1);
+ layout->addStretch(1);
- update ();
+ update();
/*
- * Qt has two different valueChanged signals for spin boxes. So we have to do an explicit
- * cast to the type of the correct valueChanged signal. --kaniini.
+ * Qt has two different valueChanged signals for spin boxes. So we have to
+ * do an explicit cast to the type of the correct valueChanged signal.
+ * --kaniini.
*/
- void (QSpinBox::* signal) (int) = & QSpinBox::valueChanged;
- QObject::connect (m_spinner, signal, [this] (int value) {
- if (! m_updating)
- m_parent->cfg.set_int (value);
+ void (QSpinBox::*signal)(int) = &QSpinBox::valueChanged;
+ QObject::connect(m_spinner, signal, [this](int value) {
+ if (!m_updating)
+ m_parent->cfg.set_int(value);
});
}
-void IntegerWidget::update ()
-{
- m_spinner->setValue (m_parent->cfg.get_int ());
-}
+void IntegerWidget::update() { m_spinner->setValue(m_parent->cfg.get_int()); }
/* double (spinbox) */
-DoubleWidget::DoubleWidget (const PreferencesWidget * parent, const char * domain) :
- HookableWidget (parent, domain),
- m_spinner (new QDoubleSpinBox)
+DoubleWidget::DoubleWidget(const PreferencesWidget * parent,
+ const char * domain)
+ : HookableWidget(parent, domain), m_spinner(new QDoubleSpinBox)
{
- auto layout = make_hbox (this);
+ auto layout = make_hbox(this);
if (parent->label)
- layout->addWidget (new QLabel (translate_str (parent->label, domain)));
+ layout->addWidget(new QLabel(translate_str(parent->label, domain)));
- auto decimals_for = [] (double step)
- { return aud::max (0, -(int) floor (log10 (step) + 0.01)); };
+ auto decimals_for = [](double step) {
+ return aud::max(0, -(int)floor(log10(step) + 0.01));
+ };
- m_spinner->setDecimals (decimals_for (m_parent->data.spin_btn.step));
- m_spinner->setRange (m_parent->data.spin_btn.min, m_parent->data.spin_btn.max);
- m_spinner->setSingleStep (m_parent->data.spin_btn.step);
- layout->addWidget (m_spinner);
+ m_spinner->setDecimals(decimals_for(m_parent->data.spin_btn.step));
+ m_spinner->setRange(m_parent->data.spin_btn.min,
+ m_parent->data.spin_btn.max);
+ m_spinner->setSingleStep(m_parent->data.spin_btn.step);
+ layout->addWidget(m_spinner);
if (parent->data.spin_btn.right_label)
- layout->addWidget (new QLabel (translate_str (parent->data.spin_btn.right_label, domain)));
+ layout->addWidget(new QLabel(
+ translate_str(parent->data.spin_btn.right_label, domain)));
- layout->addStretch (1);
+ layout->addStretch(1);
- update ();
+ update();
- void (QDoubleSpinBox::* signal) (double) = & QDoubleSpinBox::valueChanged;
- QObject::connect (m_spinner, signal, [this] (double value) {
- if (! m_updating)
- m_parent->cfg.set_float (value);
+ void (QDoubleSpinBox::*signal)(double) = &QDoubleSpinBox::valueChanged;
+ QObject::connect(m_spinner, signal, [this](double value) {
+ if (!m_updating)
+ m_parent->cfg.set_float(value);
});
}
-void DoubleWidget::update ()
-{
- m_spinner->setValue (m_parent->cfg.get_float ());
-}
+void DoubleWidget::update() { m_spinner->setValue(m_parent->cfg.get_float()); }
/* string (lineedit) */
-StringWidget::StringWidget (const PreferencesWidget * parent, const char * domain) :
- HookableWidget (parent, domain),
- m_lineedit (new QLineEdit)
+StringWidget::StringWidget(const PreferencesWidget * parent,
+ const char * domain)
+ : HookableWidget(parent, domain), m_lineedit(new QLineEdit)
{
- auto layout = make_hbox (this);
+ auto layout = make_hbox(this);
if (parent->label)
- layout->addWidget (new QLabel (translate_str (parent->label, domain)));
+ layout->addWidget(new QLabel(translate_str(parent->label, domain)));
if (parent->type == PreferencesWidget::Entry && parent->data.entry.password)
- m_lineedit->setEchoMode (QLineEdit::Password);
+ m_lineedit->setEchoMode(QLineEdit::Password);
- layout->addWidget (m_lineedit, 1);
+ layout->addWidget(m_lineedit, 1);
- update ();
+ update();
- QObject::connect (m_lineedit, & QLineEdit::textChanged, [this] (const QString & value) {
- if (! m_updating)
- m_parent->cfg.set_string (value.toUtf8 ());
- });
+ QObject::connect(m_lineedit, &QLineEdit::textChanged,
+ [this](const QString & value) {
+ if (!m_updating)
+ m_parent->cfg.set_string(value.toUtf8());
+ });
}
-void StringWidget::update ()
+void StringWidget::update()
{
- m_lineedit->setText ((const char *) m_parent->cfg.get_string ());
+ m_lineedit->setText((const char *)m_parent->cfg.get_string());
+}
+
+/* file widget (audqt::FileEntry) */
+FileWidget::FileWidget(const PreferencesWidget * parent, const char * domain)
+ : HookableWidget(parent, domain)
+{
+ QFileDialog::FileMode file_mode;
+ const char * title;
+
+ switch (parent->data.file_entry.mode)
+ {
+ default:
+ case FileSelectMode::File:
+ file_mode = QFileDialog::ExistingFile;
+ title = _("Choose File");
+ break;
+ case FileSelectMode::Folder:
+ file_mode = QFileDialog::Directory;
+ title = _("Choose Folder");
+ break;
+ }
+
+ m_lineedit =
+ file_entry_new(this, title, file_mode, QFileDialog::AcceptOpen);
+
+ auto layout = make_hbox(this);
+
+ if (parent->label)
+ layout->addWidget(new QLabel(translate_str(parent->label, domain)));
+
+ layout->addWidget(m_lineedit, 1);
+
+ update();
+
+ QObject::connect(
+ m_lineedit, &QLineEdit::textChanged, [this](const QString &) {
+ if (!m_updating)
+ m_parent->cfg.set_string(file_entry_get_uri(m_lineedit));
+ });
+}
+
+void FileWidget::update()
+{
+ file_entry_set_uri(m_lineedit, m_parent->cfg.get_string());
+}
+
+/* font widget (audqt::FontEntry) */
+FontWidget::FontWidget(const PreferencesWidget * parent, const char * domain)
+ : HookableWidget(parent, domain), m_lineedit(font_entry_new(this, nullptr))
+{
+ auto layout = make_hbox(this);
+
+ if (parent->label)
+ layout->addWidget(new QLabel(translate_str(parent->label, domain)));
+
+ layout->addWidget(m_lineedit, 1);
+
+ update();
+
+ QObject::connect(m_lineedit, &QLineEdit::textChanged,
+ [this](const QString & value) {
+ if (!m_updating)
+ m_parent->cfg.set_string(value.toUtf8());
+ });
+}
+
+void FontWidget::update()
+{
+ m_lineedit->setText((const char *)m_parent->cfg.get_string());
}
/* combo box widget (string or int) */
-ComboBoxWidget::ComboBoxWidget (const PreferencesWidget * parent, const char * domain) :
- HookableWidget (parent, domain),
- m_combobox (new QComboBox)
+ComboBoxWidget::ComboBoxWidget(const PreferencesWidget * parent,
+ const char * domain)
+ : HookableWidget(parent, domain), m_combobox(new QComboBox)
{
- auto layout = make_hbox (this);
+ auto layout = make_hbox(this);
if (parent->label)
- layout->addWidget (new QLabel (translate_str (parent->label, domain)));
+ layout->addWidget(new QLabel(translate_str(parent->label, domain)));
- layout->addWidget (m_combobox);
- layout->addStretch (1);
+ layout->addWidget(m_combobox);
+ layout->addStretch(1);
- update ();
+ update();
- void (QComboBox::* signal) (int) = & QComboBox::currentIndexChanged;
- QObject::connect (m_combobox, signal, [this] (int idx) {
+ void (QComboBox::*signal)(int) = &QComboBox::currentIndexChanged;
+ QObject::connect(m_combobox, signal, [this](int idx) {
if (m_updating)
return;
- QVariant data = m_combobox->itemData (idx);
+ QVariant data = m_combobox->itemData(idx);
switch (m_parent->cfg.type)
{
case WidgetConfig::Int:
- m_parent->cfg.set_int (data.toInt ());
+ m_parent->cfg.set_int(data.toInt());
break;
case WidgetConfig::String:
- m_parent->cfg.set_string (data.toString ().toUtf8 ());
+ m_parent->cfg.set_string(data.toString().toUtf8());
break;
default:
break;
@@ -249,25 +325,25 @@ ComboBoxWidget::ComboBoxWidget (const PreferencesWidget * parent, const char * d
});
}
-void ComboBoxWidget::update ()
+void ComboBoxWidget::update()
{
ArrayRef<ComboItem> items = m_parent->data.combo.elems;
if (m_parent->data.combo.fill)
- items = m_parent->data.combo.fill ();
+ items = m_parent->data.combo.fill();
- m_combobox->clear ();
+ m_combobox->clear();
/* add combobox items */
switch (m_parent->cfg.type)
{
case WidgetConfig::Int:
for (const ComboItem & item : items)
- m_combobox->addItem (dgettext (m_domain, item.label), item.num);
+ m_combobox->addItem(dgettext(m_domain, item.label), item.num);
break;
case WidgetConfig::String:
for (const ComboItem & item : items)
- m_combobox->addItem (dgettext (m_domain, item.label), item.str);
+ m_combobox->addItem(dgettext(m_domain, item.label), item.str);
break;
default:
break;
@@ -278,13 +354,13 @@ void ComboBoxWidget::update ()
{
case WidgetConfig::Int:
{
- int num = m_parent->cfg.get_int ();
+ int num = m_parent->cfg.get_int();
- for (int i = 0; i < items.len; i ++)
+ for (int i = 0; i < items.len; i++)
{
if (items.data[i].num == num)
{
- m_combobox->setCurrentIndex (i);
+ m_combobox->setCurrentIndex(i);
break;
}
}
@@ -293,13 +369,13 @@ void ComboBoxWidget::update ()
}
case WidgetConfig::String:
{
- String str = m_parent->cfg.get_string ();
+ String str = m_parent->cfg.get_string();
- for (int i = 0; i < items.len; i ++)
+ for (int i = 0; i < items.len; i++)
{
- if (! strcmp_safe (items.data[i].str, str))
+ if (!strcmp_safe(items.data[i].str, str))
{
- m_combobox->setCurrentIndex (i);
+ m_combobox->setCurrentIndex(i);
break;
}
}
@@ -312,40 +388,43 @@ void ComboBoxWidget::update ()
}
/* layout widgets */
-BoxWidget::BoxWidget (const PreferencesWidget * parent, const char * domain, bool horizontal_layout)
+BoxWidget::BoxWidget(const PreferencesWidget * parent, const char * domain,
+ bool horizontal_layout)
{
QBoxLayout * layout;
if (parent->data.box.horizontal)
- layout = make_hbox (this, sizes.TwoPt);
+ layout = make_hbox(this, sizes.TwoPt);
else
- layout = make_vbox (this, sizes.TwoPt);
+ layout = make_vbox(this, sizes.TwoPt);
- prefs_populate (layout, parent->data.box.widgets, domain);
+ prefs_populate(layout, parent->data.box.widgets, domain);
- /* only add stretch if the orientation does not match the enclosing layout */
+ /* only add stretch if the orientation does not match the enclosing layout
+ */
if (parent->data.box.horizontal != horizontal_layout)
- layout->addStretch (1);
+ layout->addStretch(1);
}
-TableWidget::TableWidget (const PreferencesWidget * parent, const char * domain)
+TableWidget::TableWidget(const PreferencesWidget * parent, const char * domain)
{
// TODO: proper table layout
- auto layout = make_vbox (this, sizes.TwoPt);
- prefs_populate (layout, parent->data.table.widgets, domain);
+ auto layout = make_vbox(this, sizes.TwoPt);
+ prefs_populate(layout, parent->data.table.widgets, domain);
}
-NotebookWidget::NotebookWidget (const PreferencesWidget * parent, const char * domain)
+NotebookWidget::NotebookWidget(const PreferencesWidget * parent,
+ const char * domain)
{
for (const NotebookTab & tab : parent->data.notebook.tabs)
{
- auto widget = new QWidget (this);
- widget->setContentsMargins (margins.FourPt);
+ auto widget = new QWidget(this);
+ widget->setContentsMargins(margins.FourPt);
- auto layout = make_vbox (widget, sizes.TwoPt);
- prefs_populate (layout, tab.widgets, domain);
- layout->addStretch (1);
+ auto layout = make_vbox(widget, sizes.TwoPt);
+ prefs_populate(layout, tab.widgets, domain);
+ layout->addStretch(1);
- addTab (widget, translate_str (tab.name, domain));
+ addTab(widget, translate_str(tab.name, domain));
}
}
diff --git a/src/libaudqt/prefs-widget.h b/src/libaudqt/prefs-widget.h
index 773945a..e796ae7 100644
--- a/src/libaudqt/prefs-widget.h
+++ b/src/libaudqt/prefs-widget.h
@@ -1,6 +1,6 @@
/*
* prefs-widget.cc
- * Copyright 2007-2014 Tomasz Moń, William Pitcock, and John Lindgren
+ * Copyright 2007-2014 Tomasz Moń, Ariadne Conill, and John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -20,8 +20,8 @@
#ifndef LIBAUDQT_PREFS_WIDGET_H
#define LIBAUDQT_PREFS_WIDGET_H
-#include <libaudcore/preferences.h>
#include <libaudcore/hook.h>
+#include <libaudcore/preferences.h>
#include <QCheckBox>
#include <QLabel>
@@ -35,30 +35,20 @@ class QDoubleSpinBox;
class QLineEdit;
class QSpinBox;
-namespace audqt {
-
-/*
- * basic idea is this. create classes which wrap the PreferencesWidgets.
- * Each should have it's own get(), set() and widget() methods. those are the
- * functions that we really care about.
- * get() and set() allow for introspection and manipulation of the underlying
- * objects. they also handle pinging the plugin which owns the PreferencesWidget,
- * i.e. calling PreferencesWidget::callback().
- * widget() builds the actual Qt side of the widget, hooks up the relevant signals
- * to slots, etc. the result of widget() is not const as it is linked into a
- * layout manager or shown or whatever.
- */
+namespace audqt
+{
/* base class which provides plumbing for hooks. */
-class HookableWidget {
+class HookableWidget
+{
public:
- void update_from_cfg ();
+ void update_from_cfg();
protected:
- HookableWidget (const PreferencesWidget * parent, const char * domain);
+ HookableWidget(const PreferencesWidget * parent, const char * domain);
- virtual ~HookableWidget () {}
- virtual void update () {}
+ virtual ~HookableWidget() {}
+ virtual void update() {}
const PreferencesWidget * const m_parent;
const char * const m_domain;
@@ -69,93 +59,134 @@ private:
};
/* shared class which allows disabling child widgets */
-class ParentWidget : public HookableWidget {
+class ParentWidget : public HookableWidget
+{
public:
- void set_child_layout (QLayout * layout)
- { m_child_layout = layout; }
+ void set_child_layout(QLayout * layout) { m_child_layout = layout; }
protected:
- ParentWidget (const PreferencesWidget * parent, const char * domain) :
- HookableWidget (parent, domain) {}
+ ParentWidget(const PreferencesWidget * parent, const char * domain)
+ : HookableWidget(parent, domain)
+ {
+ }
QLayout * m_child_layout = nullptr;
};
/* button widget */
-class ButtonWidget : public QPushButton {
+class ButtonWidget : public QPushButton
+{
public:
- ButtonWidget (const PreferencesWidget * parent, const char * domain);
+ ButtonWidget(const PreferencesWidget * parent, const char * domain);
};
/* boolean widget (checkbox) */
-class BooleanWidget : public QCheckBox, public ParentWidget {
+class BooleanWidget : public QCheckBox, public ParentWidget
+{
public:
- BooleanWidget (const PreferencesWidget * parent, const char * domain);
+ BooleanWidget(const PreferencesWidget * parent, const char * domain);
+
private:
- void update ();
+ void update();
};
/* integer widget (spinner) */
-class IntegerWidget : public QWidget, HookableWidget {
+class IntegerWidget : public QWidget, HookableWidget
+{
public:
- IntegerWidget (const PreferencesWidget * parent, const char * domain);
+ IntegerWidget(const PreferencesWidget * parent, const char * domain);
+
private:
- void update ();
+ void update();
QSpinBox * m_spinner;
};
/* integer widget (radio button) */
-class RadioButtonWidget : public QRadioButton, public ParentWidget {
+class RadioButtonWidget : public QRadioButton, public ParentWidget
+{
public:
- RadioButtonWidget (const PreferencesWidget * parent, const char * domain,
- QButtonGroup * btn_group);
+ RadioButtonWidget(const PreferencesWidget * parent, const char * domain,
+ QButtonGroup * btn_group);
+
private:
- void update ();
+ void update();
};
/* double widget (spinner) */
-class DoubleWidget : public QWidget, HookableWidget {
+class DoubleWidget : public QWidget, HookableWidget
+{
public:
- DoubleWidget (const PreferencesWidget * parent, const char * domain);
+ DoubleWidget(const PreferencesWidget * parent, const char * domain);
+
private:
- void update ();
+ void update();
QDoubleSpinBox * m_spinner;
};
/* string widget (lineedit) */
-class StringWidget : public QWidget, HookableWidget {
+class StringWidget : public QWidget, HookableWidget
+{
public:
- StringWidget (const PreferencesWidget * parent, const char * domain);
+ StringWidget(const PreferencesWidget * parent, const char * domain);
+
private:
- void update ();
+ void update();
+ QLineEdit * m_lineedit;
+};
+
+/* file widget (audqt::FileEntry) */
+class FileWidget : public QWidget, HookableWidget
+{
+public:
+ FileWidget(const PreferencesWidget * parent, const char * domain);
+
+private:
+ void update();
+ QLineEdit * m_lineedit;
+};
+
+/* font widget (audqt::FontEntry) */
+class FontWidget : public QWidget, HookableWidget
+{
+public:
+ FontWidget(const PreferencesWidget * parent, const char * domain);
+
+private:
+ void update();
QLineEdit * m_lineedit;
};
/* combo box (string or int) */
-class ComboBoxWidget : public QWidget, HookableWidget {
+class ComboBoxWidget : public QWidget, HookableWidget
+{
public:
- ComboBoxWidget (const PreferencesWidget * parent, const char * domain);
+ ComboBoxWidget(const PreferencesWidget * parent, const char * domain);
+
private:
- void update ();
+ void update();
QComboBox * m_combobox;
};
/* box container widget */
-class BoxWidget : public QWidget {
+class BoxWidget : public QWidget
+{
public:
- BoxWidget (const PreferencesWidget * parent, const char * domain, bool horizontal_layout);
+ BoxWidget(const PreferencesWidget * parent, const char * domain,
+ bool horizontal_layout);
};
/* table container widget */
-class TableWidget : public QWidget {
+class TableWidget : public QWidget
+{
public:
- TableWidget (const PreferencesWidget * parent, const char * domain);
+ TableWidget(const PreferencesWidget * parent, const char * domain);
};
/* notebook widget */
-class NotebookWidget : public QTabWidget {
+class NotebookWidget : public QTabWidget
+{
public:
- NotebookWidget (const PreferencesWidget * parent, const char * domain);
+ NotebookWidget(const PreferencesWidget * parent, const char * domain);
};
} // namespace audqt
diff --git a/src/libaudqt/prefs-window-qt.cc b/src/libaudqt/prefs-window-qt.cc
index 42f5798..8f72ba4 100644
--- a/src/libaudqt/prefs-window-qt.cc
+++ b/src/libaudqt/prefs-window-qt.cc
@@ -1,6 +1,6 @@
/*
* prefs-window.cc
- * Copyright 2006-2014 William Pitcock, Tomasz Moń, Michael Färber, and
+ * Copyright 2006-2014 Ariadne Conill, Tomasz Moń, Michael Färber, and
* John Lindgren
*
* Redistribution and use in source and binary forms, with or without
@@ -54,74 +54,93 @@
#include "libaudqt.h"
#include "prefs-pluginlist-model.h"
-namespace audqt {
+namespace audqt
+{
class PrefsWindow : public QDialog
{
public:
- static PrefsWindow * get_instance () {
- if (! instance)
- (void) new PrefsWindow;
+ static PrefsWindow * get_instance()
+ {
+ if (!instance)
+ (void)new PrefsWindow;
return instance;
}
- static void destroy_instance () {
+ static void destroy_instance()
+ {
if (instance)
delete instance;
}
- static ArrayRef<ComboItem> get_output_combo () {
- return {instance->output_combo_elements.begin (),
- instance->output_combo_elements.len ()};
+ static ArrayRef<ComboItem> get_output_combo()
+ {
+ return {instance->output_combo_elements.begin(),
+ instance->output_combo_elements.len()};
}
static int output_combo_selected;
- static void output_combo_changed () { instance->output_change (); }
+ static void output_combo_changed() { instance->output_change(); }
- static void * get_output_config_button () { return instance->output_config_button; }
- static void * get_output_about_button () { return instance->output_about_button; }
+ static void * get_output_config_button()
+ {
+ return instance->output_config_button;
+ }
+ static void * get_output_about_button()
+ {
+ return instance->output_about_button;
+ }
- static void * get_record_checkbox () { return instance->record_checkbox; }
- static void * get_record_config_button () { return instance->record_config_button; }
- static void * get_record_about_button () { return instance->record_about_button; }
+ static void * get_record_checkbox() { return instance->record_checkbox; }
+ static void * get_record_config_button()
+ {
+ return instance->record_config_button;
+ }
+ static void * get_record_about_button()
+ {
+ return instance->record_about_button;
+ }
private:
static PrefsWindow * instance;
- PrefsWindow ();
- ~PrefsWindow () { instance = nullptr; }
+ PrefsWindow();
+ ~PrefsWindow() { instance = nullptr; }
Index<ComboItem> output_combo_elements;
- QPushButton * output_config_button, * output_about_button;
+ QPushButton *output_config_button, *output_about_button;
QCheckBox * record_checkbox;
- QPushButton * record_config_button, * record_about_button;
+ QPushButton *record_config_button, *record_about_button;
- void output_setup ();
- void output_change ();
+ void output_setup();
+ void output_change();
- void record_setup ();
- void record_update ();
+ void record_setup();
+ void record_update();
- const HookReceiver<PrefsWindow>
- record_hook {"enable record", this, & PrefsWindow::record_update};
+ const HookReceiver<PrefsWindow> record_hook{"enable record", this,
+ &PrefsWindow::record_update};
};
/* static data */
PrefsWindow * PrefsWindow::instance = nullptr;
int PrefsWindow::output_combo_selected;
-struct Category {
+struct Category
+{
const char * icon;
const char * name;
};
-struct TitleFieldTag {
+struct TitleFieldTag
+{
const char * name;
const char * tag;
};
-enum {
+enum
+{
CATEGORY_APPEARANCE = 0,
CATEGORY_AUDIO,
CATEGORY_NETWORK,
@@ -133,255 +152,219 @@ enum {
};
static const Category categories[] = {
- { "applications-graphics", N_("Appearance") },
- { "audio-volume-medium", N_("Audio") },
- { "applications-internet", N_("Network") },
- { "audio-x-generic", N_("Playlist")} ,
- { "dialog-information", N_("Song Info") },
- { "applications-system", N_("Plugins") },
- { "preferences-system", N_("Advanced") }
-};
+ {"applications-graphics", N_("Appearance")},
+ {"audio-volume-medium", N_("Audio")},
+ {"applications-internet", N_("Network")},
+ {"audio-x-generic", N_("Playlist")},
+ {"dialog-information", N_("Song Info")},
+ {"applications-system", N_("Plugins")},
+ {"preferences-system", N_("Advanced")}};
static const TitleFieldTag title_field_tags[] = {
- { N_("Artist") , "${artist}" },
- { N_("Album") , "${album}" },
- { N_("Album artist"), "${album-artist}" },
- { N_("Title") , "${title}" },
- { N_("Track number"), "${track-number}" },
- { N_("Genre") , "${genre}" },
- { N_("File name") , "${file-name}" },
- { N_("File path") , "${file-path}" },
- { N_("Date") , "${date}" },
- { N_("Year") , "${year}" },
- { N_("Comment") , "${comment}" },
- { N_("Codec") , "${codec}" },
- { N_("Quality") , "${quality}" }
-};
+ {N_("Artist"), "${artist}"},
+ {N_("Album"), "${album}"},
+ {N_("Album artist"), "${album-artist}"},
+ {N_("Title"), "${title}"},
+ {N_("Track number"), "${track-number}"},
+ {N_("Genre"), "${genre}"},
+ {N_("File name"), "${file-name}"},
+ {N_("File path"), "${file-path}"},
+ {N_("Date"), "${date}"},
+ {N_("Description"), "${description}"},
+ {N_("Year"), "${year}"},
+ {N_("Comment"), "${comment}"},
+ {N_("Codec"), "${codec}"},
+ {N_("Quality"), "${quality}"}};
static const ComboItem chardet_detector_presets[] = {
- ComboItem (N_("None"), ""),
- ComboItem (N_("Arabic"), GUESS_REGION_AR),
- ComboItem (N_("Baltic"), GUESS_REGION_BL),
- ComboItem (N_("Chinese"), GUESS_REGION_CN),
- ComboItem (N_("Greek"), GUESS_REGION_GR),
- ComboItem (N_("Hebrew"), GUESS_REGION_HW),
- ComboItem (N_("Japanese"), GUESS_REGION_JP),
- ComboItem (N_("Korean"), GUESS_REGION_KR),
- ComboItem (N_("Polish"), GUESS_REGION_PL),
- ComboItem (N_("Russian"), GUESS_REGION_RU),
- ComboItem (N_("Taiwanese"), GUESS_REGION_TW),
- ComboItem (N_("Turkish"), GUESS_REGION_TR)
-};
+ ComboItem(N_("None"), ""),
+ ComboItem(N_("Arabic"), GUESS_REGION_AR),
+ ComboItem(N_("Baltic"), GUESS_REGION_BL),
+ ComboItem(N_("Chinese"), GUESS_REGION_CN),
+ ComboItem(N_("Greek"), GUESS_REGION_GR),
+ ComboItem(N_("Hebrew"), GUESS_REGION_HW),
+ ComboItem(N_("Japanese"), GUESS_REGION_JP),
+ ComboItem(N_("Korean"), GUESS_REGION_KR),
+ ComboItem(N_("Polish"), GUESS_REGION_PL),
+ ComboItem(N_("Russian"), GUESS_REGION_RU),
+ ComboItem(N_("Taiwanese"), GUESS_REGION_TW),
+ ComboItem(N_("Turkish"), GUESS_REGION_TR)};
static const ComboItem bitdepth_elements[] = {
- ComboItem (N_("Automatic"), -1),
- ComboItem ("16", 16),
- ComboItem ("24", 24),
- ComboItem ("32", 32),
- ComboItem (N_("Floating point"), 0)
-};
+ ComboItem(N_("Automatic"), -1), ComboItem("16", 16), ComboItem("24", 24),
+ ComboItem("32", 32), ComboItem(N_("Floating point"), 0)};
static const ComboItem record_elements[] = {
- ComboItem (N_("As decoded"), (int) OutputStream::AsDecoded),
- ComboItem (N_("After applying ReplayGain"), (int) OutputStream::AfterReplayGain),
- ComboItem (N_("After applying effects"), (int) OutputStream::AfterEffects),
- ComboItem (N_("After applying equalization"), (int) OutputStream::AfterEqualizer)
-};
+ ComboItem(N_("As decoded"), (int)OutputStream::AsDecoded),
+ ComboItem(N_("After applying ReplayGain"),
+ (int)OutputStream::AfterReplayGain),
+ ComboItem(N_("After applying effects"), (int)OutputStream::AfterEffects),
+ ComboItem(N_("After applying equalization"),
+ (int)OutputStream::AfterEqualizer)};
static const ComboItem replaygainmode_elements[] = {
- ComboItem (N_("Track"), (int) ReplayGainMode::Track),
- ComboItem (N_("Album"), (int) ReplayGainMode::Album),
- ComboItem (N_("Based on shuffle"), (int) ReplayGainMode::Automatic)
-};
+ ComboItem(N_("Track"), (int)ReplayGainMode::Track),
+ ComboItem(N_("Album"), (int)ReplayGainMode::Album),
+ ComboItem(N_("Based on shuffle"), (int)ReplayGainMode::Automatic)};
static Index<ComboItem> iface_combo_elements;
static int iface_combo_selected;
static QWidget * iface_prefs_box;
-static ArrayRef<ComboItem> iface_combo_fill ();
-static void iface_combo_changed ();
-static void * iface_create_prefs_box ();
+static ArrayRef<ComboItem> iface_combo_fill();
+static void iface_combo_changed();
+static void * iface_create_prefs_box();
static const PreferencesWidget appearance_page_widgets[] = {
- WidgetCombo (N_("Interface:"),
- WidgetInt (iface_combo_selected, iface_combo_changed),
- {0, iface_combo_fill}),
- WidgetSeparator ({true}),
- WidgetCustomQt (iface_create_prefs_box)
-};
+ WidgetCombo(N_("Interface:"),
+ WidgetInt(iface_combo_selected, iface_combo_changed),
+ {0, iface_combo_fill}),
+ WidgetSeparator({true}), WidgetCustomQt(iface_create_prefs_box)};
-static void output_bit_depth_changed ();
+static void output_bit_depth_changed();
static const PreferencesWidget output_combo_widgets[] = {
- WidgetCombo (N_("Output plugin:"),
- WidgetInt (PrefsWindow::output_combo_selected,
- PrefsWindow::output_combo_changed,
- "audqt update output combo"),
- {0, PrefsWindow::get_output_combo}),
- WidgetCustomQt (PrefsWindow::get_output_config_button),
- WidgetCustomQt (PrefsWindow::get_output_about_button)
-};
+ WidgetCombo(N_("Output plugin:"),
+ WidgetInt(PrefsWindow::output_combo_selected,
+ PrefsWindow::output_combo_changed,
+ "audqt update output combo"),
+ {0, PrefsWindow::get_output_combo}),
+ WidgetCustomQt(PrefsWindow::get_output_config_button),
+ WidgetCustomQt(PrefsWindow::get_output_about_button)};
static const PreferencesWidget record_buttons[] = {
- WidgetCustomQt (PrefsWindow::get_record_config_button),
- WidgetCustomQt (PrefsWindow::get_record_about_button)
-};
+ WidgetCustomQt(PrefsWindow::get_record_config_button),
+ WidgetCustomQt(PrefsWindow::get_record_about_button)};
static const PreferencesWidget gain_table[] = {
- WidgetSpin (N_("Amplify all files:"),
- WidgetFloat (0, "replay_gain_preamp"),
- {-15, 15, 0.1, N_("dB")}),
- WidgetSpin (N_("Amplify untagged files:"),
- WidgetFloat (0, "default_gain"),
- {-15, 15, 0.1, N_("dB")})
-};
+ WidgetSpin(N_("Amplify all files:"), WidgetFloat(0, "replay_gain_preamp"),
+ {-15, 15, 0.1, N_("dB")}),
+ WidgetSpin(N_("Amplify untagged files:"), WidgetFloat(0, "default_gain"),
+ {-15, 15, 0.1, N_("dB")})};
static const PreferencesWidget audio_page_widgets[] = {
- WidgetLabel (N_("<b>Output Settings</b>")),
- WidgetBox ({{output_combo_widgets}, true}),
- WidgetCombo (N_("Bit depth:"),
- WidgetInt (0, "output_bit_depth", output_bit_depth_changed),
- {{bitdepth_elements}}),
- WidgetSpin (N_("Buffer size:"),
- WidgetInt (0, "output_buffer_size"),
- {100, 10000, 1000, N_("ms")}),
- WidgetCheck (N_("Soft clipping"),
- WidgetBool (0, "soft_clipping")),
- WidgetCheck (N_("Use software volume control (not recommended)"),
- WidgetBool (0, "software_volume_control")),
- WidgetLabel (N_("<b>Recording Settings</b>")),
- WidgetCustomQt (PrefsWindow::get_record_checkbox),
- WidgetBox ({{record_buttons}, true},
- WIDGET_CHILD),
- WidgetCombo (N_("Record stream:"),
- WidgetInt (0, "record_stream"),
- {{record_elements}}),
- WidgetLabel (N_("<b>ReplayGain</b>")),
- WidgetCheck (N_("Enable ReplayGain"),
- WidgetBool (0, "enable_replay_gain")),
- WidgetCombo (N_("Mode:"),
- WidgetInt (0, "replay_gain_mode"),
- {{replaygainmode_elements}},
- WIDGET_CHILD),
- WidgetCheck (N_("Prevent clipping (recommended)"),
- WidgetBool (0, "enable_clipping_prevention"),
- WIDGET_CHILD),
- WidgetTable ({{gain_table}},
- WIDGET_CHILD)
-};
+ WidgetLabel(N_("<b>Output Settings</b>")),
+ WidgetBox({{output_combo_widgets}, true}),
+ WidgetCombo(N_("Bit depth:"),
+ WidgetInt(0, "output_bit_depth", output_bit_depth_changed),
+ {{bitdepth_elements}}),
+ WidgetSpin(N_("Buffer size:"), WidgetInt(0, "output_buffer_size"),
+ {100, 10000, 1000, N_("ms")}),
+ WidgetCheck(N_("Soft clipping"), WidgetBool(0, "soft_clipping")),
+ WidgetCheck(N_("Use software volume control (not recommended)"),
+ WidgetBool(0, "software_volume_control")),
+ WidgetLabel(N_("<b>Recording Settings</b>")),
+ WidgetCustomQt(PrefsWindow::get_record_checkbox),
+ WidgetBox({{record_buttons}, true}, WIDGET_CHILD),
+ WidgetCombo(N_("Record stream:"), WidgetInt(0, "record_stream"),
+ {{record_elements}}),
+ WidgetLabel(N_("<b>ReplayGain</b>")),
+ WidgetCheck(N_("Enable ReplayGain"), WidgetBool(0, "enable_replay_gain")),
+ WidgetCombo(N_("Mode:"), WidgetInt(0, "replay_gain_mode"),
+ {{replaygainmode_elements}}, WIDGET_CHILD),
+ WidgetCheck(N_("Prevent clipping (recommended)"),
+ WidgetBool(0, "enable_clipping_prevention"), WIDGET_CHILD),
+ WidgetTable({{gain_table}}, WIDGET_CHILD)};
static const PreferencesWidget proxy_host_port_elements[] = {
- WidgetEntry (N_("Proxy hostname:"),
- WidgetString (0, "proxy_host")),
- WidgetEntry (N_("Proxy port:"),
- WidgetString (0, "proxy_port"))
-};
+ WidgetEntry(N_("Proxy hostname:"), WidgetString(0, "proxy_host")),
+ WidgetEntry(N_("Proxy port:"), WidgetString(0, "proxy_port"))};
static const PreferencesWidget proxy_auth_elements[] = {
- WidgetEntry (N_("Proxy username:"),
- WidgetString (0, "proxy_user")),
- WidgetEntry (N_("Proxy password:"),
- WidgetString (0, "proxy_pass"),
- {true})
-};
+ WidgetEntry(N_("Proxy username:"), WidgetString(0, "proxy_user")),
+ WidgetEntry(N_("Proxy password:"), WidgetString(0, "proxy_pass"), {true})};
static const PreferencesWidget connectivity_page_widgets[] = {
- WidgetLabel (N_("<b>Network Settings</b>")),
- WidgetSpin (N_("Buffer size:"),
- WidgetInt (0, "net_buffer_kb"),
- {16, 1024, 16, N_("KiB")}),
- WidgetLabel (N_("<b>Proxy Configuration</b>")),
- WidgetCheck (N_("Enable proxy usage"),
- WidgetBool (0, "use_proxy")),
- WidgetTable ({{proxy_host_port_elements}},
- WIDGET_CHILD),
- WidgetCheck (N_("Use authentication with proxy"),
- WidgetBool (0, "use_proxy_auth")),
- WidgetTable ({{proxy_auth_elements}},
- WIDGET_CHILD)
-};
+ WidgetLabel(N_("<b>Network Settings</b>")),
+ WidgetSpin(N_("Buffer size:"), WidgetInt(0, "net_buffer_kb"),
+ {16, 1024, 16, N_("KiB")}),
+ WidgetLabel(N_("<b>Proxy Configuration</b>")),
+ WidgetCheck(N_("Enable proxy usage"), WidgetBool(0, "use_proxy")),
+ WidgetTable({{proxy_host_port_elements}}, WIDGET_CHILD),
+ WidgetCheck(N_("Use authentication with proxy"),
+ WidgetBool(0, "use_proxy_auth")),
+ WidgetTable({{proxy_auth_elements}}, WIDGET_CHILD),
+ WidgetCheck(N_("Use SOCKS proxy"), WidgetBool(0, "socks_proxy")),
+ WidgetRadio(N_("SOCKS v4a"), WidgetInt(0, "socks_type"), {0}, WIDGET_CHILD),
+ WidgetRadio(N_("SOCKS v5"), WidgetInt(0, "socks_type"), {1}, WIDGET_CHILD)};
static const PreferencesWidget chardet_elements[] = {
- WidgetCombo (N_("Auto character encoding detector for:"),
- WidgetString (0, "chardet_detector"),
- {{chardet_detector_presets}}),
- WidgetEntry (N_("Fallback character encodings:"),
- WidgetString (0, "chardet_fallback"))
-};
+ WidgetCombo(N_("Auto character encoding detector for:"),
+ WidgetString(0, "chardet_detector"),
+ {{chardet_detector_presets}}),
+ WidgetEntry(N_("Fallback character encodings:"),
+ WidgetString(0, "chardet_fallback"))};
-static void send_title_change ();
-static void * create_titlestring_table ();
+static void send_title_change();
+static void * create_titlestring_table();
static const PreferencesWidget playlist_page_widgets[] = {
- WidgetLabel (N_("<b>Behavior</b>")),
- WidgetCheck (N_("Resume playback on startup"),
- WidgetBool (0, "resume_playback_on_startup")),
- WidgetCheck (N_("Pause instead of resuming immediately"),
- WidgetBool (0, "always_resume_paused"),
- WIDGET_CHILD),
- WidgetCheck (N_("Advance when the current song is deleted"),
- WidgetBool (0, "advance_on_delete")),
- WidgetCheck (N_("Clear the playlist when opening files"),
- WidgetBool (0, "clear_playlist")),
- WidgetCheck (N_("Open files in a temporary playlist"),
- WidgetBool (0, "open_to_temporary")),
- WidgetLabel (N_("<b>Song Display</b>")),
- WidgetCheck (N_("Show song numbers"),
- WidgetBool (0, "show_numbers_in_pl", send_title_change)),
- WidgetCheck (N_("Show leading zeroes (02:00 vs. 2:00)"),
- WidgetBool (0, "leading_zero", send_title_change)),
- WidgetCheck (N_("Show hours separately (1:30:00 vs. 90:00)"),
- WidgetBool (0, "show_hours", send_title_change)),
- WidgetCustomQt (create_titlestring_table),
- WidgetLabel (N_("<b>Export</b>")),
- WidgetCheck (N_("Use relative paths when possible"),
- WidgetBool (0, "export_relative_paths"))
-};
+ WidgetLabel(N_("<b>Behavior</b>")),
+ WidgetCheck(N_("Resume playback on startup"),
+ WidgetBool(0, "resume_playback_on_startup")),
+ WidgetCheck(N_("Pause instead of resuming immediately"),
+ WidgetBool(0, "always_resume_paused"), WIDGET_CHILD),
+ WidgetCheck(N_("Advance when the current song is deleted"),
+ WidgetBool(0, "advance_on_delete")),
+ WidgetCheck(N_("Clear the playlist when opening files"),
+ WidgetBool(0, "clear_playlist")),
+ WidgetCheck(N_("Open files in a temporary playlist"),
+ WidgetBool(0, "open_to_temporary")),
+ WidgetLabel(N_("<b>Song Display</b>")),
+ WidgetCheck(N_("Show song numbers"),
+ WidgetBool(0, "show_numbers_in_pl", send_title_change)),
+ WidgetCheck(N_("Show leading zeroes (02:00 vs. 2:00)"),
+ WidgetBool(0, "leading_zero", send_title_change)),
+ WidgetCheck(N_("Show hours separately (1:30:00 vs. 90:00)"),
+ WidgetBool(0, "show_hours", send_title_change)),
+ WidgetCustomQt(create_titlestring_table),
+ WidgetLabel(N_("<b>Export</b>")),
+ WidgetCheck(N_("Use relative paths when possible"),
+ WidgetBool(0, "export_relative_paths"))};
static const PreferencesWidget song_info_page_widgets[] = {
- WidgetLabel (N_("<b>Album Art</b>")),
- WidgetLabel (N_("Search for images matching these words (comma-separated):")),
- WidgetEntry (0, WidgetString (0, "cover_name_include")),
- WidgetLabel (N_("Exclude images matching these words (comma-separated):")),
- WidgetEntry (0, WidgetString (0, "cover_name_exclude")),
- WidgetCheck (N_("Search for images matching song file name"),
- WidgetBool (0, "use_file_cover")),
- WidgetCheck (N_("Search recursively"),
- WidgetBool (0, "recurse_for_cover")),
- WidgetSpin (N_("Search depth:"),
- WidgetInt (0, "recurse_for_cover_depth"),
- {0, 100, 1},
- WIDGET_CHILD),
- WidgetLabel (N_("<b>Popup Information</b>")),
- WidgetCheck (N_("Show popup information"),
- WidgetBool (0, "show_filepopup_for_tuple")),
- WidgetSpin (N_("Popup delay (tenths of a second):"),
- WidgetInt (0, "filepopup_delay"),
- {0, 100, 1},
- WIDGET_CHILD),
- WidgetCheck (N_("Show time scale for current song"),
- WidgetBool (0, "filepopup_showprogressbar"),
- WIDGET_CHILD)
-};
+ WidgetLabel(N_("<b>Album Art</b>")),
+ WidgetLabel(
+ N_("Search for images matching these words (comma-separated):")),
+ WidgetEntry(0, WidgetString(0, "cover_name_include")),
+ WidgetLabel(N_("Exclude images matching these words (comma-separated):")),
+ WidgetEntry(0, WidgetString(0, "cover_name_exclude")),
+ WidgetCheck(N_("Search for images matching song file name"),
+ WidgetBool(0, "use_file_cover")),
+ WidgetCheck(N_("Search recursively"), WidgetBool(0, "recurse_for_cover")),
+ WidgetSpin(N_("Search depth:"), WidgetInt(0, "recurse_for_cover_depth"),
+ {0, 100, 1}, WIDGET_CHILD),
+ WidgetLabel(N_("<b>Popup Information</b>")),
+ WidgetCheck(N_("Show popup information"),
+ WidgetBool(0, "show_filepopup_for_tuple")),
+ WidgetSpin(N_("Popup delay (tenths of a second):"),
+ WidgetInt(0, "filepopup_delay"), {0, 100, 1}, WIDGET_CHILD),
+ WidgetCheck(N_("Show time scale for current song"),
+ WidgetBool(0, "filepopup_showprogressbar"), WIDGET_CHILD)};
static const PreferencesWidget advanced_page_widgets[] = {
- WidgetLabel (N_("<b>Compatibility</b>")),
- WidgetCheck (N_("Interpret \\ (backward slash) as a folder delimiter"),
- WidgetBool (0, "convert_backslash")),
- WidgetTable ({{chardet_elements}}),
- WidgetLabel (N_("<b>Playlist</b>")),
- WidgetCheck (N_("Add folders recursively"),
- WidgetBool (0, "recurse_folders")),
- WidgetCheck (N_("Add folders nested within playlist files"),
- WidgetBool (0, "folders_in_playlist")),
- WidgetLabel (N_("<b>Metadata</b>")),
- WidgetCheck (N_("Guess missing metadata from file path"),
- WidgetBool (0, "metadata_fallbacks")),
- WidgetCheck (N_("Do not load metadata for songs until played"),
- WidgetBool (0, "metadata_on_play")),
- WidgetCheck (N_("Probe content of files with no recognized file name extension"),
- WidgetBool (0, "slow_probe"))
-};
+ WidgetLabel(N_("<b>Compatibility</b>")),
+ WidgetCheck(N_("Interpret \\ (backward slash) as a folder delimiter"),
+ WidgetBool(0, "convert_backslash")),
+ WidgetTable({{chardet_elements}}),
+ WidgetLabel(N_("<b>Playlist</b>")),
+ WidgetCheck(N_("Add folders recursively"),
+ WidgetBool(0, "recurse_folders")),
+ WidgetCheck(N_("Add folders nested within playlist files"),
+ WidgetBool(0, "folders_in_playlist")),
+ WidgetLabel(N_("<b>Metadata</b>")),
+ WidgetCheck(N_("Guess missing metadata from file path"),
+ WidgetBool(0, "metadata_fallbacks")),
+ WidgetCheck(N_("Do not load metadata for songs until played"),
+ WidgetBool(0, "metadata_on_play")),
+ WidgetCheck(
+ N_("Probe content of files with no recognized file name extension"),
+ WidgetBool(0, "slow_probe")),
+ WidgetLabel(N_("<b>Miscellaneous</b>")),
+ WidgetSpin(N_("Step forward/backward by:"), WidgetInt(0, "step_size"),
+ {1, 60, 1, N_("seconds")}),
+ WidgetSpin(N_("Adjust volume by:"), WidgetInt(0, "volume_delta"),
+ {1, 25, 1, N_("percent")})};
#define TITLESTRING_NPRESETS 8
@@ -391,10 +374,11 @@ static const char * const titlestring_presets[TITLESTRING_NPRESETS] = {
"${title}${?artist: - ${artist}}${?album: - ${album}}",
"${?artist:${artist} - }${title}",
"${?artist:${artist} - }${?album:${album} - }${title}",
- "${?artist:${artist} - }${?album:${album} - }${?track-number:${track-number}. }${title}",
- "${?artist:${artist} }${?album:[ ${album} ] }${?artist:- }${?track-number:${track-number}. }${title}",
- "${?album:${album} - }${title}"
-};
+ "${?artist:${artist} - }${?album:${album} - "
+ "}${?track-number:${track-number}. }${title}",
+ "${?artist:${artist} }${?album:[ ${album} ] }${?artist:- "
+ "}${?track-number:${track-number}. }${title}",
+ "${?album:${album} - }${title}"};
static const char * const titlestring_preset_names[TITLESTRING_NPRESETS] = {
N_("TITLE"),
@@ -404,379 +388,380 @@ static const char * const titlestring_preset_names[TITLESTRING_NPRESETS] = {
N_("ARTIST - ALBUM - TITLE"),
N_("ARTIST - ALBUM - TRACK. TITLE"),
N_("ARTIST [ ALBUM ] - TRACK. TITLE"),
- N_("ALBUM - TITLE")
-};
+ N_("ALBUM - TITLE")};
-static void * create_titlestring_table ()
+static void * create_titlestring_table()
{
QWidget * w = new QWidget;
- QGridLayout * l = new QGridLayout (w);
- l->setContentsMargins (0, 0, 0, 0);
- l->setSpacing (sizes.TwoPt);
+ QGridLayout * l = new QGridLayout(w);
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(sizes.TwoPt);
- QLabel * lbl = new QLabel (_("Title format:"), w);
- l->addWidget (lbl, 0, 0);
+ QLabel * lbl = new QLabel(_("Title format:"), w);
+ l->addWidget(lbl, 0, 0);
- QComboBox * cbox = new QComboBox (w);
- l->addWidget (cbox, 0, 1);
+ QComboBox * cbox = new QComboBox(w);
+ l->addWidget(cbox, 0, 1);
- for (int i = 0; i < TITLESTRING_NPRESETS; i ++)
- cbox->addItem (translate_str (titlestring_preset_names [i]), i);
- cbox->addItem (_("Custom"), TITLESTRING_NPRESETS);
- cbox->setCurrentIndex (TITLESTRING_NPRESETS);
+ for (int i = 0; i < TITLESTRING_NPRESETS; i++)
+ cbox->addItem(translate_str(titlestring_preset_names[i]), i);
+ cbox->addItem(_("Custom"), TITLESTRING_NPRESETS);
+ cbox->setCurrentIndex(TITLESTRING_NPRESETS);
- lbl = new QLabel (_("Custom string:"), w);
- l->addWidget (lbl, 1, 0);
+ lbl = new QLabel(_("Custom string:"), w);
+ l->addWidget(lbl, 1, 0);
- QLineEdit * le = new QLineEdit (w);
- l->addWidget (le, 1, 1);
+ QLineEdit * le = new QLineEdit(w);
+ l->addWidget(le, 1, 1);
- String format = aud_get_str (nullptr, "generic_title_format");
- le->setText ((const char *) format);
- for (int i = 0; i < TITLESTRING_NPRESETS; i ++)
+ String format = aud_get_str("generic_title_format");
+ le->setText((const char *)format);
+ for (int i = 0; i < TITLESTRING_NPRESETS; i++)
{
- if (! strcmp (titlestring_presets [i], format))
- cbox->setCurrentIndex (i);
+ if (!strcmp(titlestring_presets[i], format))
+ cbox->setCurrentIndex(i);
}
- QObject::connect (le, & QLineEdit::textChanged, [] (const QString & text) {
- aud_set_str (nullptr, "generic_title_format", text.toUtf8 ().data ());
+ QObject::connect(le, &QLineEdit::textChanged, [](const QString & text) {
+ aud_set_str("generic_title_format", text.toUtf8().data());
});
- void (QComboBox::* signal) (int) = & QComboBox::currentIndexChanged;
- QObject::connect (cbox, signal, [le] (int idx) {
+ void (QComboBox::*signal)(int) = &QComboBox::currentIndexChanged;
+ QObject::connect(cbox, signal, [le](int idx) {
if (idx < TITLESTRING_NPRESETS)
- le->setText (titlestring_presets [idx]);
+ le->setText(titlestring_presets[idx]);
});
/* build menu */
- QPushButton * btn_mnu = new QPushButton (w);
- btn_mnu->setFixedWidth (btn_mnu->sizeHint ().height ());
- btn_mnu->setIcon (audqt::get_icon ("list-add"));
- l->addWidget (btn_mnu, 1, 2);
+ QPushButton * btn_mnu = new QPushButton(w);
+ btn_mnu->setFixedWidth(btn_mnu->sizeHint().height());
+ btn_mnu->setIcon(audqt::get_icon("list-add"));
+ l->addWidget(btn_mnu, 1, 2);
- QMenu * mnu_fields = new QMenu (w);
+ QMenu * mnu_fields = new QMenu(w);
for (auto & t : title_field_tags)
{
- QAction * a = mnu_fields->addAction (_(t.name));
- QObject::connect (a, & QAction::triggered, [=] () {
- le->insert (t.tag);
- });
+ QAction * a = mnu_fields->addAction(_(t.name));
+ QObject::connect(a, &QAction::triggered, [=]() { le->insert(t.tag); });
}
- QObject::connect (btn_mnu, & QAbstractButton::clicked, [=] () {
- mnu_fields->popup (btn_mnu->mapToGlobal (QPoint (0, 0)));
+ QObject::connect(btn_mnu, &QAbstractButton::clicked, [=]() {
+ mnu_fields->popup(btn_mnu->mapToGlobal(QPoint(0, 0)));
});
return w;
}
-static Index<ComboItem> fill_plugin_combo (PluginType type)
+static Index<ComboItem> fill_plugin_combo(PluginType type)
{
Index<ComboItem> elems;
int i = 0;
- for (PluginHandle * plugin : aud_plugin_list (type))
- elems.append (aud_plugin_get_name (plugin), i ++);
+ for (PluginHandle * plugin : aud_plugin_list(type))
+ elems.append(aud_plugin_get_name(plugin), i++);
return elems;
}
-static void send_title_change ()
+static void send_title_change()
{
- if (aud_drct_get_ready ())
- hook_call ("title change", nullptr);
+ if (aud_drct_get_ready())
+ hook_call("title change", nullptr);
}
-static void iface_fill_prefs_box ()
+static void iface_fill_prefs_box()
{
- Plugin * header = (Plugin *) aud_plugin_get_header (aud_plugin_get_current (PluginType::Iface));
+ Plugin * header = (Plugin *)aud_plugin_get_header(
+ aud_plugin_get_current(PluginType::Iface));
if (header && header->info.prefs)
{
- auto vbox = make_vbox (iface_prefs_box, sizes.TwoPt);
- prefs_populate (vbox, header->info.prefs->widgets, header->info.domain);
+ auto vbox = make_vbox(iface_prefs_box, sizes.TwoPt);
+ prefs_populate(vbox, header->info.prefs->widgets, header->info.domain);
}
}
-static void iface_combo_changed ()
+static void iface_combo_changed()
{
/* prevent audqt from being shut down during the switch */
- init ();
+ init();
- if (QLayout * layout = iface_prefs_box->layout ())
+ if (QLayout * layout = iface_prefs_box->layout())
{
- clear_layout (layout);
+ clear_layout(layout);
delete layout;
}
- aud_plugin_enable (aud_plugin_list (PluginType::Iface)[iface_combo_selected], true);
+ aud_plugin_enable(aud_plugin_list(PluginType::Iface)[iface_combo_selected],
+ true);
- iface_fill_prefs_box ();
- cleanup ();
+ iface_fill_prefs_box();
+ cleanup();
}
-static ArrayRef<ComboItem> iface_combo_fill ()
+static ArrayRef<ComboItem> iface_combo_fill()
{
- if (! iface_combo_elements.len ())
+ if (!iface_combo_elements.len())
{
- iface_combo_elements = fill_plugin_combo (PluginType::Iface);
- iface_combo_selected = aud_plugin_list (PluginType::Iface).
- find (aud_plugin_get_current (PluginType::Iface));
+ iface_combo_elements = fill_plugin_combo(PluginType::Iface);
+ iface_combo_selected =
+ aud_plugin_list(PluginType::Iface)
+ .find(aud_plugin_get_current(PluginType::Iface));
}
- return {iface_combo_elements.begin (), iface_combo_elements.len ()};
+ return {iface_combo_elements.begin(), iface_combo_elements.len()};
}
-static void * iface_create_prefs_box ()
+static void * iface_create_prefs_box()
{
iface_prefs_box = new QWidget;
- iface_fill_prefs_box ();
+ iface_fill_prefs_box();
return iface_prefs_box;
}
-static void output_bit_depth_changed ()
+static void output_bit_depth_changed()
{
- aud_output_reset (OutputReset::ReopenStream);
+ aud_output_reset(OutputReset::ReopenStream);
}
-static void create_category (QStackedWidget * notebook, ArrayRef<PreferencesWidget> widgets)
+static void create_category(QStackedWidget * notebook,
+ ArrayRef<PreferencesWidget> widgets)
{
QWidget * w = new QWidget;
- auto vbox = make_vbox (w, sizes.TwoPt);
- prefs_populate (vbox, widgets, nullptr);
- vbox->addStretch (1);
+ auto vbox = make_vbox(w, sizes.TwoPt);
+ prefs_populate(vbox, widgets, nullptr);
+ vbox->addStretch(1);
- notebook->addWidget (w);
+ notebook->addWidget(w);
}
static QTreeView * s_plugin_view;
static PluginListModel * s_plugin_model;
-static void create_plugin_category (QStackedWidget * parent)
+static void create_plugin_category(QStackedWidget * parent)
{
- s_plugin_view = new QTreeView (parent);
- s_plugin_model = new PluginListModel (s_plugin_view);
-
- s_plugin_view->setModel (s_plugin_model);
- s_plugin_view->setSelectionMode (QTreeView::NoSelection);
- s_plugin_view->setAlternatingRowColors (true);
-
- auto header = s_plugin_view->header ();
-
- header->hide ();
- header->setSectionResizeMode (header->ResizeToContents);
- header->setStretchLastSection (true);
-
- parent->addWidget (s_plugin_view);
-
- QObject::connect (s_plugin_view, & QAbstractItemView::clicked, [] (const QModelIndex & index)
- {
- auto p = s_plugin_model->pluginForIndex (index);
- if (! p || ! aud_plugin_get_enabled (p))
- return;
-
- switch (index.column ())
- {
- case PluginListModel::AboutColumn:
- plugin_about (p);
- break;
- case PluginListModel::SettingsColumn:
- plugin_prefs (p);
- break;
- }
- });
+ s_plugin_view = new QTreeView(parent);
+ s_plugin_model = new PluginListModel(s_plugin_view);
+
+ s_plugin_view->setModel(s_plugin_model);
+ s_plugin_view->setSelectionMode(QTreeView::NoSelection);
+ s_plugin_view->setAlternatingRowColors(true);
+
+ auto header = s_plugin_view->header();
+
+ header->hide();
+ header->setSectionResizeMode(header->ResizeToContents);
+ header->setStretchLastSection(true);
+
+ parent->addWidget(s_plugin_view);
+
+ QObject::connect(s_plugin_view, &QAbstractItemView::clicked,
+ [](const QModelIndex & index) {
+ auto p = s_plugin_model->pluginForIndex(index);
+ if (!p || !aud_plugin_get_enabled(p))
+ return;
+
+ switch (index.column())
+ {
+ case PluginListModel::AboutColumn:
+ plugin_about(p);
+ break;
+ case PluginListModel::SettingsColumn:
+ plugin_prefs(p);
+ break;
+ }
+ });
}
static QStackedWidget * s_category_notebook = nullptr;
-PrefsWindow::PrefsWindow () :
- output_combo_elements (fill_plugin_combo (PluginType::Output)),
- output_config_button (new QPushButton (translate_str (N_("_Settings")))),
- output_about_button (new QPushButton (translate_str (N_("_About")))),
- record_checkbox (new QCheckBox),
- record_config_button (new QPushButton (translate_str (N_("_Settings")))),
- record_about_button (new QPushButton (translate_str (N_("_About"))))
+PrefsWindow::PrefsWindow()
+ : output_combo_elements(fill_plugin_combo(PluginType::Output)),
+ output_config_button(new QPushButton(translate_str(N_("_Settings")))),
+ output_about_button(new QPushButton(translate_str(N_("_About")))),
+ record_checkbox(new QCheckBox),
+ record_config_button(new QPushButton(translate_str(N_("_Settings")))),
+ record_about_button(new QPushButton(translate_str(N_("_About"))))
{
/* initialize static data */
instance = this;
- output_combo_selected = aud_plugin_list (PluginType::Output)
- .find (aud_plugin_get_current (PluginType::Output));
+ output_combo_selected =
+ aud_plugin_list(PluginType::Output)
+ .find(aud_plugin_get_current(PluginType::Output));
- setAttribute (Qt::WA_DeleteOnClose);
- setWindowTitle (_("Audacious Settings"));
- setContentsMargins (0, 0, 0, 0);
+ setAttribute(Qt::WA_DeleteOnClose);
+ setWindowTitle(_("Audacious Settings"));
+ setContentsMargins(0, 0, 0, 0);
+
+ output_config_button->setAutoDefault(false);
+ output_about_button->setAutoDefault(false);
+ record_config_button->setAutoDefault(false);
+ record_about_button->setAutoDefault(false);
QToolBar * toolbar = new QToolBar;
- toolbar->setToolButtonStyle (Qt::ToolButtonTextUnderIcon);
+ toolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
QWidget * child = new QWidget;
- child->setContentsMargins (margins.FourPt);
+ child->setContentsMargins(margins.FourPt);
- auto vbox_parent = make_vbox (this);
- vbox_parent->addWidget (toolbar);
- vbox_parent->addWidget (child);
+ auto vbox_parent = make_vbox(this);
+ vbox_parent->addWidget(toolbar);
+ vbox_parent->addWidget(child);
- auto child_vbox = make_vbox (child);
+ auto child_vbox = make_vbox(child);
s_category_notebook = new QStackedWidget;
- child_vbox->addWidget (s_category_notebook);
-
- create_category (s_category_notebook, appearance_page_widgets);
- create_category (s_category_notebook, audio_page_widgets);
- create_category (s_category_notebook, connectivity_page_widgets);
- create_category (s_category_notebook, playlist_page_widgets);
- create_category (s_category_notebook, song_info_page_widgets);
- create_plugin_category (s_category_notebook);
- create_category (s_category_notebook, advanced_page_widgets);
-
- QDialogButtonBox * bbox = new QDialogButtonBox (QDialogButtonBox::Close);
- bbox->button (QDialogButtonBox::Close)->setText (translate_str (N_("_Close")));
- child_vbox->addWidget (bbox);
+ child_vbox->addWidget(s_category_notebook);
- QObject::connect (bbox, & QDialogButtonBox::rejected, this, & QObject::deleteLater);
+ create_category(s_category_notebook, appearance_page_widgets);
+ create_category(s_category_notebook, audio_page_widgets);
+ create_category(s_category_notebook, connectivity_page_widgets);
+ create_category(s_category_notebook, playlist_page_widgets);
+ create_category(s_category_notebook, song_info_page_widgets);
+ create_plugin_category(s_category_notebook);
+ create_category(s_category_notebook, advanced_page_widgets);
- QSignalMapper * mapper = new QSignalMapper (this);
+ QDialogButtonBox * bbox = new QDialogButtonBox(QDialogButtonBox::Close);
+ bbox->button(QDialogButtonBox::Close)->setText(translate_str(N_("_Close")));
+ child_vbox->addWidget(bbox);
- QObject::connect (mapper, static_cast <void (QSignalMapper::*)(int)>(&QSignalMapper::mapped),
- s_category_notebook, static_cast <void (QStackedWidget::*)(int)>(&QStackedWidget::setCurrentIndex));
+ QObject::connect(bbox, &QDialogButtonBox::rejected, this,
+ &QObject::deleteLater);
- for (int i = 0; i < CATEGORY_COUNT; i ++)
+ for (int i = 0; i < CATEGORY_COUNT; i++)
{
- auto a = new QAction (get_icon (categories[i].icon),
- translate_str (categories[i].name), toolbar);
+ auto a = new QAction(get_icon(categories[i].icon),
+ translate_str(categories[i].name), toolbar);
- toolbar->addAction (a);
- mapper->setMapping (a, i);
+ toolbar->addAction(a);
- void (QSignalMapper::* slot) () = & QSignalMapper::map;
- QObject::connect (a, & QAction::triggered, mapper, slot);
+ connect(a, &QAction::triggered,
+ [i]() { s_category_notebook->setCurrentIndex(i); });
}
- output_setup ();
- record_setup ();
- record_update ();
+ output_setup();
+ record_setup();
+ record_update();
}
-void PrefsWindow::output_setup ()
+void PrefsWindow::output_setup()
{
- auto p = aud_plugin_get_current (PluginType::Output);
+ auto p = aud_plugin_get_current(PluginType::Output);
- output_config_button->setEnabled (aud_plugin_has_configure (p));
- output_about_button->setEnabled (aud_plugin_has_about (p));
+ output_config_button->setEnabled(aud_plugin_has_configure(p));
+ output_about_button->setEnabled(aud_plugin_has_about(p));
- QObject::connect (output_config_button, & QPushButton::clicked, [] (bool) {
- plugin_prefs (aud_plugin_get_current (PluginType::Output));
+ QObject::connect(output_config_button, &QPushButton::clicked, [](bool) {
+ plugin_prefs(aud_plugin_get_current(PluginType::Output));
});
- QObject::connect (output_about_button, & QPushButton::clicked, [] (bool) {
- plugin_about (aud_plugin_get_current (PluginType::Output));
+ QObject::connect(output_about_button, &QPushButton::clicked, [](bool) {
+ plugin_about(aud_plugin_get_current(PluginType::Output));
});
}
-void PrefsWindow::output_change ()
+void PrefsWindow::output_change()
{
- auto & list = aud_plugin_list (PluginType::Output);
+ auto & list = aud_plugin_list(PluginType::Output);
auto p = list[output_combo_selected];
- if (aud_plugin_enable (p, true))
+ if (aud_plugin_enable(p, true))
{
- output_config_button->setEnabled (aud_plugin_has_configure (p));
- output_about_button->setEnabled (aud_plugin_has_about (p));
+ output_config_button->setEnabled(aud_plugin_has_configure(p));
+ output_about_button->setEnabled(aud_plugin_has_about(p));
}
else
{
/* set combo box back to current output */
- output_combo_selected = list.find (aud_plugin_get_current (PluginType::Output));
- hook_call ("audqt update output combo", nullptr);
+ output_combo_selected =
+ list.find(aud_plugin_get_current(PluginType::Output));
+ hook_call("audqt update output combo", nullptr);
}
}
-void PrefsWindow::record_setup ()
+void PrefsWindow::record_setup()
{
- QObject::connect (record_checkbox, & QCheckBox::clicked, [] (bool checked) {
- aud_drct_enable_record (checked);
- });
+ QObject::connect(record_checkbox, &QCheckBox::clicked,
+ [](bool checked) { aud_drct_enable_record(checked); });
- QObject::connect (record_config_button, & QPushButton::clicked, [] (bool) {
- if (aud_drct_get_record_enabled ())
- plugin_prefs (aud_drct_get_record_plugin ());
+ QObject::connect(record_config_button, &QPushButton::clicked, [](bool) {
+ if (aud_drct_get_record_enabled())
+ plugin_prefs(aud_drct_get_record_plugin());
});
- QObject::connect (record_about_button, & QPushButton::clicked, [] (bool) {
- if (aud_drct_get_record_enabled ())
- plugin_about (aud_drct_get_record_plugin ());
+ QObject::connect(record_about_button, &QPushButton::clicked, [](bool) {
+ if (aud_drct_get_record_enabled())
+ plugin_about(aud_drct_get_record_plugin());
});
}
-void PrefsWindow::record_update ()
+void PrefsWindow::record_update()
{
- auto p = aud_drct_get_record_plugin ();
+ auto p = aud_drct_get_record_plugin();
if (p)
{
- bool enabled = aud_drct_get_record_enabled ();
- auto text = str_printf (_("Enable audio stream recording with %s"), aud_plugin_get_name (p));
-
- record_checkbox->setEnabled (true);
- record_checkbox->setText ((const char *) text);
- record_checkbox->setChecked (enabled);
- record_config_button->setEnabled (enabled && aud_plugin_has_configure (p));
- record_about_button->setEnabled (enabled && aud_plugin_has_about (p));
+ bool enabled = aud_drct_get_record_enabled();
+ auto text = str_printf(_("Enable audio stream recording with %s"),
+ aud_plugin_get_name(p));
+
+ record_checkbox->setEnabled(true);
+ record_checkbox->setText((const char *)text);
+ record_checkbox->setChecked(enabled);
+ record_config_button->setEnabled(enabled &&
+ aud_plugin_has_configure(p));
+ record_about_button->setEnabled(enabled && aud_plugin_has_about(p));
}
else
{
- record_checkbox->setEnabled (false);
- record_checkbox->setText (_("No audio recording plugin available"));
- record_checkbox->setChecked (false);
- record_config_button->setEnabled (false);
- record_about_button->setEnabled (false);
+ record_checkbox->setEnabled(false);
+ record_checkbox->setText(_("No audio recording plugin available"));
+ record_checkbox->setChecked(false);
+ record_config_button->setEnabled(false);
+ record_about_button->setEnabled(false);
}
}
-EXPORT void prefswin_show ()
+EXPORT void prefswin_show()
{
- window_bring_to_front (PrefsWindow::get_instance ());
+ window_bring_to_front(PrefsWindow::get_instance());
}
-EXPORT void prefswin_hide ()
-{
- PrefsWindow::destroy_instance ();
-}
+EXPORT void prefswin_hide() { PrefsWindow::destroy_instance(); }
-EXPORT void prefswin_show_page (int id, bool show)
+EXPORT void prefswin_show_page(int id, bool show)
{
if (id < 0 || id > CATEGORY_COUNT)
return;
- auto win = PrefsWindow::get_instance ();
- s_category_notebook->setCurrentIndex (id);
+ auto win = PrefsWindow::get_instance();
+ s_category_notebook->setCurrentIndex(id);
if (show)
- window_bring_to_front (win);
+ window_bring_to_front(win);
}
-EXPORT void prefswin_show_plugin_page (PluginType type)
+EXPORT void prefswin_show_plugin_page(PluginType type)
{
if (type == PluginType::Iface)
- prefswin_show_page (CATEGORY_APPEARANCE);
+ prefswin_show_page(CATEGORY_APPEARANCE);
else if (type == PluginType::Output)
- prefswin_show_page (CATEGORY_AUDIO);
+ prefswin_show_page(CATEGORY_AUDIO);
else
{
- prefswin_show_page (CATEGORY_PLUGINS, false);
+ prefswin_show_page(CATEGORY_PLUGINS, false);
- s_plugin_view->collapseAll ();
+ s_plugin_view->collapseAll();
- auto index = s_plugin_model->indexForType (type);
- if (index.isValid ())
+ auto index = s_plugin_model->indexForType(type);
+ if (index.isValid())
{
- s_plugin_view->expand (index);
- s_plugin_view->scrollTo (index, QTreeView::PositionAtTop);
- s_plugin_view->setCurrentIndex (index);
+ s_plugin_view->expand(index);
+ s_plugin_view->scrollTo(index, QTreeView::PositionAtTop);
+ s_plugin_view->setCurrentIndex(index);
}
- window_bring_to_front (PrefsWindow::get_instance ());
+ window_bring_to_front(PrefsWindow::get_instance());
}
}
diff --git a/src/libaudqt/queue-manager-qt.cc b/src/libaudqt/queue-manager-qt.cc
index 11301b3..da6e646 100644
--- a/src/libaudqt/queue-manager-qt.cc
+++ b/src/libaudqt/queue-manager-qt.cc
@@ -1,6 +1,6 @@
/*
* queue-manager.cc
- * Copyright 2014 William Pitcock, John Lindgren
+ * Copyright 2014 Ariadne Conill, John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -22,119 +22,121 @@
#include <QAbstractListModel>
#include <QDialog>
#include <QDialogButtonBox>
-#include <QPushButton>
#include <QHeaderView>
#include <QItemSelectionModel>
+#include <QPushButton>
#include <QTreeView>
#include <QVBoxLayout>
#include <libaudcore/audstrings.h>
-#include <libaudcore/playlist.h>
#include <libaudcore/hook.h>
#include <libaudcore/i18n.h>
+#include <libaudcore/playlist.h>
/*
* TODO:
* - shifting of selection entries
*/
-namespace audqt {
+namespace audqt
+{
class QueueManagerModel : public QAbstractListModel
{
public:
- void update (QItemSelectionModel * sel);
- void selectionChanged (const QItemSelection & selected, const QItemSelection & deselected);
+ void update(QItemSelectionModel * sel);
+ void selectionChanged(const QItemSelection & selected,
+ const QItemSelection & deselected);
protected:
- int rowCount (const QModelIndex & parent) const { return m_rows; }
- int columnCount (const QModelIndex & parent) const { return 2; }
- QVariant data (const QModelIndex & index, int role) const;
+ int rowCount(const QModelIndex & parent) const { return m_rows; }
+ int columnCount(const QModelIndex & parent) const { return 2; }
+ QVariant data(const QModelIndex & index, int role) const;
private:
int m_rows = 0;
bool m_in_update = false;
};
-QVariant QueueManagerModel::data (const QModelIndex & index, int role) const
+QVariant QueueManagerModel::data(const QModelIndex & index, int role) const
{
if (role == Qt::DisplayRole)
{
- auto list = Playlist::active_playlist ();
- int entry = list.queue_get_entry (index.row ());
+ auto list = Playlist::active_playlist();
+ int entry = list.queue_get_entry(index.row());
- if (index.column () == 0)
+ if (index.column() == 0)
return entry + 1;
else
{
- Tuple tuple = list.entry_tuple (entry, Playlist::NoWait);
- return QString ((const char *) tuple.get_str (Tuple::FormattedTitle));
+ Tuple tuple = list.entry_tuple(entry, Playlist::NoWait);
+ return QString((const char *)tuple.get_str(Tuple::FormattedTitle));
}
}
- else if (role == Qt::TextAlignmentRole && index.column () == 0)
+ else if (role == Qt::TextAlignmentRole && index.column() == 0)
return Qt::AlignRight;
- return QVariant ();
+ return QVariant();
}
-void QueueManagerModel::update (QItemSelectionModel * sel)
+void QueueManagerModel::update(QItemSelectionModel * sel)
{
- auto list = Playlist::active_playlist ();
- int rows = list.n_queued ();
- int keep = aud::min (rows, m_rows);
+ auto list = Playlist::active_playlist();
+ int rows = list.n_queued();
+ int keep = aud::min(rows, m_rows);
m_in_update = true;
if (rows < m_rows)
{
- beginRemoveRows (QModelIndex (), rows, m_rows - 1);
+ beginRemoveRows(QModelIndex(), rows, m_rows - 1);
m_rows = rows;
- endRemoveRows ();
+ endRemoveRows();
}
else if (rows > m_rows)
{
- beginInsertRows (QModelIndex (), m_rows, rows - 1);
+ beginInsertRows(QModelIndex(), m_rows, rows - 1);
m_rows = rows;
- endInsertRows ();
+ endInsertRows();
}
if (keep > 0)
{
- auto topLeft = createIndex (0, 0);
- auto bottomRight = createIndex (keep - 1, 0);
- emit dataChanged (topLeft, bottomRight);
+ auto topLeft = createIndex(0, 0);
+ auto bottomRight = createIndex(keep - 1, 0);
+ emit dataChanged(topLeft, bottomRight);
}
- for (int i = 0; i < rows; i ++)
+ for (int i = 0; i < rows; i++)
{
- if (list.entry_selected (list.queue_get_entry (i)))
- sel->select (createIndex (i, 0), sel->Select | sel->Rows);
+ if (list.entry_selected(list.queue_get_entry(i)))
+ sel->select(createIndex(i, 0), sel->Select | sel->Rows);
else
- sel->select (createIndex (i, 0), sel->Deselect | sel->Rows);
+ sel->select(createIndex(i, 0), sel->Deselect | sel->Rows);
}
m_in_update = false;
}
-void QueueManagerModel::selectionChanged (const QItemSelection & selected,
- const QItemSelection & deselected)
+void QueueManagerModel::selectionChanged(const QItemSelection & selected,
+ const QItemSelection & deselected)
{
if (m_in_update)
return;
- auto list = Playlist::active_playlist ();
+ auto list = Playlist::active_playlist();
- for (auto & index : selected.indexes ())
- list.select_entry (list.queue_get_entry (index.row ()), true);
+ for (auto & index : selected.indexes())
+ list.select_entry(list.queue_get_entry(index.row()), true);
- for (auto & index : deselected.indexes ())
- list.select_entry (list.queue_get_entry (index.row ()), false);
+ for (auto & index : deselected.indexes())
+ list.select_entry(list.queue_get_entry(index.row()), false);
}
class QueueManagerDialog : public QDialog
{
public:
- QueueManagerDialog (QWidget * parent = nullptr);
+ QueueManagerDialog(QWidget * parent = nullptr);
private:
QTreeView m_treeview;
@@ -143,87 +145,82 @@ private:
QPushButton m_btn_close;
QueueManagerModel m_model;
- void removeSelected ();
- void update () { m_model.update (m_treeview.selectionModel ()); }
+ void removeSelected();
+ void update() { m_model.update(m_treeview.selectionModel()); }
- const HookReceiver<QueueManagerDialog>
- update_hook {"playlist update", this, & QueueManagerDialog::update},
- activate_hook {"playlist activate", this, & QueueManagerDialog::update};
+ const HookReceiver<QueueManagerDialog> update_hook{
+ "playlist update", this, &QueueManagerDialog::update},
+ activate_hook{"playlist activate", this, &QueueManagerDialog::update};
};
-QueueManagerDialog::QueueManagerDialog (QWidget * parent) :
- QDialog (parent)
+QueueManagerDialog::QueueManagerDialog(QWidget * parent) : QDialog(parent)
{
- setWindowTitle (_("Queue Manager"));
- setContentsMargins (margins.TwoPt);
+ setWindowTitle(_("Queue Manager"));
+ setContentsMargins(margins.TwoPt);
- m_btn_unqueue.setText (translate_str (N_("_Unqueue")));
- m_btn_close.setText (translate_str (N_("_Close")));
+ m_btn_unqueue.setText(translate_str(N_("_Unqueue")));
+ m_btn_close.setText(translate_str(N_("_Close")));
- connect (& m_btn_close, & QAbstractButton::clicked, this, & QWidget::hide);
- connect (& m_btn_unqueue, & QAbstractButton::clicked, this, & QueueManagerDialog::removeSelected);
+ connect(&m_btn_close, &QAbstractButton::clicked, this, &QWidget::hide);
+ connect(&m_btn_unqueue, &QAbstractButton::clicked, this,
+ &QueueManagerDialog::removeSelected);
- m_buttonbox.addButton (& m_btn_close, QDialogButtonBox::AcceptRole);
- m_buttonbox.addButton (& m_btn_unqueue, QDialogButtonBox::AcceptRole);
+ m_buttonbox.addButton(&m_btn_close, QDialogButtonBox::AcceptRole);
+ m_buttonbox.addButton(&m_btn_unqueue, QDialogButtonBox::AcceptRole);
- auto layout = make_vbox (this);
- layout->addWidget (& m_treeview);
- layout->addWidget (& m_buttonbox);
+ auto layout = make_vbox(this);
+ layout->addWidget(&m_treeview);
+ layout->addWidget(&m_buttonbox);
- m_treeview.setIndentation (0);
- m_treeview.setModel (& m_model);
- m_treeview.setSelectionMode (QAbstractItemView::ExtendedSelection);
- m_treeview.setHeaderHidden (true);
+ m_treeview.setIndentation(0);
+ m_treeview.setModel(&m_model);
+ m_treeview.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ m_treeview.setHeaderHidden(true);
- update ();
+ update();
- connect (m_treeview.selectionModel (),
- & QItemSelectionModel::selectionChanged, & m_model,
- & QueueManagerModel::selectionChanged);
+ connect(m_treeview.selectionModel(), &QItemSelectionModel::selectionChanged,
+ &m_model, &QueueManagerModel::selectionChanged);
- resize (4 * sizes.OneInch, 3 * sizes.OneInch);
+ resize(4 * sizes.OneInch, 3 * sizes.OneInch);
}
-void QueueManagerDialog::removeSelected ()
+void QueueManagerDialog::removeSelected()
{
- auto list = Playlist::active_playlist ();
- int count = list.n_queued ();
+ auto list = Playlist::active_playlist();
+ int count = list.n_queued();
- for (int i = 0; i < count; )
+ for (int i = 0; i < count;)
{
- int entry = list.queue_get_entry (i);
+ int entry = list.queue_get_entry(i);
- if (list.entry_selected (entry))
+ if (list.entry_selected(entry))
{
- list.queue_remove (i);
- list.select_entry (entry, false);
- count --;
+ list.queue_remove(i);
+ list.select_entry(entry, false);
+ count--;
}
else
- i ++;
+ i++;
}
}
static QueueManagerDialog * s_queuemgr = nullptr;
-EXPORT void queue_manager_show ()
+EXPORT void queue_manager_show()
{
- if (! s_queuemgr)
+ if (!s_queuemgr)
{
s_queuemgr = new QueueManagerDialog;
- s_queuemgr->setAttribute (Qt::WA_DeleteOnClose);
+ s_queuemgr->setAttribute(Qt::WA_DeleteOnClose);
- QObject::connect (s_queuemgr, & QObject::destroyed, [] () {
- s_queuemgr = nullptr;
- });
+ QObject::connect(s_queuemgr, &QObject::destroyed,
+ []() { s_queuemgr = nullptr; });
}
- window_bring_to_front (s_queuemgr);
+ window_bring_to_front(s_queuemgr);
}
-EXPORT void queue_manager_hide ()
-{
- delete s_queuemgr;
-}
+EXPORT void queue_manager_hide() { delete s_queuemgr; }
} // namespace audqt
diff --git a/src/libaudqt/treeview.cc b/src/libaudqt/treeview.cc
new file mode 100644
index 0000000..4e8bfaf
--- /dev/null
+++ b/src/libaudqt/treeview.cc
@@ -0,0 +1,77 @@
+/*
+ * treeview.cc
+ * Copyright 2018 John Lindgren
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions, and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions, and the following disclaimer in the documentation
+ * provided with the distribution.
+ *
+ * This software is provided "as is" and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising from
+ * the use of this software.
+ */
+
+#include "treeview.h"
+
+#include <QKeyEvent>
+#include <QMouseEvent>
+#include <libaudcore/index.h>
+
+namespace audqt
+{
+
+EXPORT TreeView::TreeView(QWidget * parent) : QTreeView(parent)
+{
+ // activate() is perhaps a bit redundant with activated()
+ connect(this, &QTreeView::activated, this, &TreeView::activate);
+}
+
+EXPORT TreeView::~TreeView() {}
+
+EXPORT void TreeView::keyPressEvent(QKeyEvent * event)
+{
+ auto CtrlShiftAlt =
+ Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier;
+ if (event->key() == Qt::Key_Delete && !(event->modifiers() & CtrlShiftAlt))
+ {
+ removeSelectedRows();
+ return;
+ }
+
+ QTreeView::keyPressEvent(event);
+}
+
+EXPORT void TreeView::removeSelectedRows()
+{
+ // get all selected rows
+ Index<int> rows;
+ for (auto & idx : selectionModel()->selectedRows())
+ rows.append(idx.row());
+
+ // sort in reverse order
+ rows.sort([](const int & a, const int & b) { return b - a; });
+
+ // remove rows in reverse order
+ auto m = model();
+ for (int row : rows)
+ m->removeRow(row);
+}
+
+// TODO: unnecessary, remove at next API break
+EXPORT void TreeView::mouseDoubleClickEvent(QMouseEvent * event)
+{
+ QTreeView::mouseDoubleClickEvent(event);
+}
+
+EXPORT void TreeView::activate(const QModelIndex & index)
+{
+ (void)index; // base implementation does nothing
+}
+
+} // namespace audqt
diff --git a/src/libaudqt/treeview.h b/src/libaudqt/treeview.h
new file mode 100644
index 0000000..565af04
--- /dev/null
+++ b/src/libaudqt/treeview.h
@@ -0,0 +1,49 @@
+/*
+ * treeview.h
+ * Copyright 2018 John Lindgren
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions, and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions, and the following disclaimer in the documentation
+ * provided with the distribution.
+ *
+ * This software is provided "as is" and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising from
+ * the use of this software.
+ */
+
+#ifndef LIBAUDQT_TREEVIEW_H
+#define LIBAUDQT_TREEVIEW_H
+
+#include <QTreeView>
+#include <libaudqt/export.h>
+
+namespace audqt
+{
+
+// This class extends QTreeView and adds a couple of features:
+// - An "activate" event (double click or Enter key)
+// - A method to remove all selected rows (Delete key)
+class LIBAUDQT_PUBLIC TreeView : public QTreeView
+{
+public:
+ TreeView(QWidget * parent = nullptr);
+ ~TreeView() override;
+
+ void removeSelectedRows();
+
+protected:
+ void keyPressEvent(QKeyEvent * event) override;
+ void mouseDoubleClickEvent(QMouseEvent * event) override;
+
+ virtual void activate(const QModelIndex & index);
+};
+
+} // namespace audqt
+
+#endif // LIBAUDQT_TREEVIEW_H
diff --git a/src/libaudqt/url-opener-qt.cc b/src/libaudqt/url-opener-qt.cc
index b5bcebf..2ea837a 100644
--- a/src/libaudqt/url-opener-qt.cc
+++ b/src/libaudqt/url-opener-qt.cc
@@ -31,16 +31,15 @@
#include "libaudqt.h"
-namespace audqt {
+namespace audqt
+{
-static QDialog * buildUrlDialog (bool open)
+static QDialog * buildUrlDialog(bool open)
{
static const PreferencesWidget widgets[] = {
- WidgetCheck (N_("_Save to history"),
- WidgetBool (0, "save_url_history"))
- };
+ WidgetCheck(N_("_Save to history"), WidgetBool(0, "save_url_history"))};
- const char * title, * verb, * icon;
+ const char *title, *verb, *icon;
if (open)
{
@@ -56,89 +55,91 @@ static QDialog * buildUrlDialog (bool open)
}
auto dialog = new QDialog;
- dialog->setWindowTitle (title);
- dialog->setContentsMargins (margins.EightPt);
+ dialog->setWindowTitle(title);
+ dialog->setContentsMargins(margins.EightPt);
- auto label = new QLabel (_("Enter URL:"), dialog);
+ auto label = new QLabel(_("Enter URL:"), dialog);
- auto combobox = new QComboBox (dialog);
- combobox->setEditable (true);
- combobox->setMinimumContentsLength (50);
+ auto combobox = new QComboBox(dialog);
+ combobox->setEditable(true);
+ combobox->setMinimumContentsLength(50);
- auto clear_button = new QPushButton (translate_str (N_("C_lear history")), dialog);
- clear_button->setIcon (audqt::get_icon ("edit-clear"));
+ auto clear_button =
+ new QPushButton(translate_str(N_("C_lear history")), dialog);
+ clear_button->setIcon(audqt::get_icon("edit-clear"));
- auto hbox = make_hbox (nullptr);
- prefs_populate (hbox, widgets, PACKAGE);
- hbox->addStretch (1);
- hbox->addWidget (clear_button);
+ auto hbox = make_hbox(nullptr);
+ prefs_populate(hbox, widgets, PACKAGE);
+ hbox->addStretch(1);
+ hbox->addWidget(clear_button);
- auto button1 = new QPushButton (translate_str (verb), dialog);
- button1->setIcon (audqt::get_icon (icon));
+ auto button1 = new QPushButton(translate_str(verb), dialog);
+ button1->setIcon(audqt::get_icon(icon));
- auto button2 = new QPushButton (translate_str (N_("_Cancel")), dialog);
- button2->setIcon (audqt::get_icon ("process-stop"));
+ auto button2 = new QPushButton(translate_str(N_("_Cancel")), dialog);
+ button2->setIcon(audqt::get_icon("process-stop"));
- auto buttonbox = new QDialogButtonBox (dialog);
- buttonbox->addButton (button1, QDialogButtonBox::AcceptRole);
- buttonbox->addButton (button2, QDialogButtonBox::RejectRole);
+ auto buttonbox = new QDialogButtonBox(dialog);
+ buttonbox->addButton(button1, QDialogButtonBox::AcceptRole);
+ buttonbox->addButton(button2, QDialogButtonBox::RejectRole);
- auto layout = make_vbox (dialog);
- layout->addWidget (label);
- layout->addWidget (combobox);
- layout->addLayout (hbox);
- layout->addStretch (1);
- layout->addWidget (buttonbox);
+ auto layout = make_vbox(dialog);
+ layout->addWidget(label);
+ layout->addWidget(combobox);
+ layout->addLayout(hbox);
+ layout->addStretch(1);
+ layout->addWidget(buttonbox);
- for (int i = 0;; i ++)
+ for (int i = 0;; i++)
{
- String item = aud_history_get (i);
- if (! item)
+ String item = aud_history_get(i);
+ if (!item)
break;
- combobox->addItem (QString (item));
+ combobox->addItem(QString(item));
}
- combobox->setCurrentIndex (-1);
+ combobox->setCurrentIndex(-1);
- QObject::connect (clear_button, & QPushButton::pressed, [combobox] () {
- combobox->clear ();
- aud_history_clear ();
+ QObject::connect(clear_button, &QPushButton::pressed, [combobox]() {
+ combobox->clear();
+ aud_history_clear();
});
- QObject::connect (buttonbox, & QDialogButtonBox::rejected, dialog, & QDialog::close);
+ QObject::connect(buttonbox, &QDialogButtonBox::rejected, dialog,
+ &QDialog::close);
- QObject::connect (buttonbox, & QDialogButtonBox::accepted, [dialog, combobox, open] () {
- QByteArray url = combobox->currentText ().toUtf8 ();
+ QObject::connect(buttonbox, &QDialogButtonBox::accepted,
+ [dialog, combobox, open]() {
+ QByteArray url = combobox->currentText().toUtf8();
- if (open)
- aud_drct_pl_open (url);
- else
- aud_drct_pl_add (url, -1);
+ if (open)
+ aud_drct_pl_open(url);
+ else
+ aud_drct_pl_add(url, -1);
- if (aud_get_bool (nullptr, "save_url_history"))
- aud_history_add (url);
+ if (aud_get_bool("save_url_history"))
+ aud_history_add(url);
- dialog->close ();
- });
+ dialog->close();
+ });
return dialog;
}
static QDialog * s_dialog = nullptr;
-EXPORT void urlopener_show (bool open)
+EXPORT void urlopener_show(bool open)
{
- if (! s_dialog)
+ if (!s_dialog)
{
- s_dialog = buildUrlDialog (open);
- s_dialog->setAttribute (Qt::WA_DeleteOnClose);
+ s_dialog = buildUrlDialog(open);
+ s_dialog->setAttribute(Qt::WA_DeleteOnClose);
- QObject::connect (s_dialog, & QObject::destroyed, [] () {
- s_dialog = nullptr;
- });
+ QObject::connect(s_dialog, &QObject::destroyed,
+ []() { s_dialog = nullptr; });
}
- window_bring_to_front (s_dialog);
+ window_bring_to_front(s_dialog);
}
} // namespace audqt
diff --git a/src/libaudqt/util-qt.cc b/src/libaudqt/util-qt.cc
index 866f3a4..9cc427a 100644
--- a/src/libaudqt/util-qt.cc
+++ b/src/libaudqt/util-qt.cc
@@ -17,8 +17,8 @@
* the use of this software.
*/
-#include "libaudqt.h"
#include "libaudqt-internal.h"
+#include "libaudqt.h"
#include <QAction>
#include <QApplication>
@@ -26,24 +26,24 @@
#include <QCursor>
#include <QMenu>
#include <QMimeData>
-#include <QWindow>
#include <QScreen>
+#include <QWindow>
#include <libaudcore/i18n.h>
-namespace audqt {
+namespace audqt
+{
-PopupWidget::PopupWidget (QWidget * parent) :
- QWidget (parent)
+PopupWidget::PopupWidget(QWidget * parent) : QWidget(parent)
{
- qApp->installEventFilter (this);
+ qApp->installEventFilter(this);
}
// This event filter mimics QToolTip by hiding the popup widget when
// certain events are received by any widget.
-bool PopupWidget::eventFilter (QObject *, QEvent * e)
+bool PopupWidget::eventFilter(QObject *, QEvent * e)
{
- switch (e->type ())
+ switch (e->type())
{
case QEvent::Leave:
case QEvent::WindowActivate:
@@ -55,7 +55,7 @@ bool PopupWidget::eventFilter (QObject *, QEvent * e)
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::Wheel:
- deleteLater ();
+ deleteLater();
break;
default:
@@ -65,18 +65,18 @@ bool PopupWidget::eventFilter (QObject *, QEvent * e)
return false;
}
-void PopupWidget::showEvent (QShowEvent *)
+void PopupWidget::showEvent(QShowEvent *)
{
- auto pos = QCursor::pos ();
- auto geom = QApplication::primaryScreen ()->geometry ();
+ auto pos = QCursor::pos();
+ auto geom = QApplication::primaryScreen()->geometry();
/* find the screen the cursor is on */
- if (! geom.contains (pos))
+ if (!geom.contains(pos))
{
- for (auto screen : QApplication::screens ())
+ for (auto screen : QApplication::screens())
{
- auto geom2 = screen->geometry ();
- if (geom2.contains (pos))
+ auto geom2 = screen->geometry();
+ if (geom2.contains(pos))
{
geom = geom2;
break;
@@ -84,46 +84,42 @@ void PopupWidget::showEvent (QShowEvent *)
}
}
- int x = pos.x ();
- int y = pos.y ();
- int w = width ();
- int h = height ();
+ int x = pos.x();
+ int y = pos.y();
+ int w = width();
+ int h = height();
/* If we show the popup right under the cursor, the underlying window gets
* a leaveEvent and immediately hides the popup again. So, we offset the
* popup slightly. */
- if (x + w > geom.x () + geom.width ())
+ if (x + w > geom.x() + geom.width())
x -= w + 3;
else
x += 3;
- if (y + h > geom.y () + geom.height ())
+ if (y + h > geom.y() + geom.height())
y -= h + 3;
else
y += 3;
- move (x, y);
+ move(x, y);
}
-void show_copy_context_menu (QWidget * parent, const QPoint & global_pos,
- const QString & text_to_copy)
+void show_copy_context_menu(QWidget * parent, const QPoint & global_pos,
+ const QString & text_to_copy)
{
- auto menu = new QMenu (parent);
- auto action = new QAction (audqt::get_icon ("edit-copy"), N_("Copy"), menu);
+ auto menu = new QMenu(parent);
+ auto action = new QAction(audqt::get_icon("edit-copy"), N_("Copy"), menu);
- QObject::connect (action, & QAction::triggered, action, [text_to_copy] () {
+ QObject::connect(action, &QAction::triggered, action, [text_to_copy]() {
auto data = new QMimeData;
- data->setText (text_to_copy);
- QApplication::clipboard ()->setMimeData (data);
- });
-
- /* delete the menu as soon as it's closed */
- QObject::connect (menu, & QMenu::aboutToHide, [menu] () {
- menu->deleteLater ();
+ data->setText(text_to_copy);
+ QApplication::clipboard()->setMimeData(data);
});
- menu->addAction (action);
- menu->popup (global_pos);
+ menu->addAction(action);
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(global_pos);
}
} // namespace audqt
diff --git a/src/libaudqt/volumebutton.cc b/src/libaudqt/volumebutton.cc
index 9455c55..8e6c5d9 100644
--- a/src/libaudqt/volumebutton.cc
+++ b/src/libaudqt/volumebutton.cc
@@ -1,6 +1,6 @@
/*
* volumebutton.cc
- * Copyright 2014 William Pitcock
+ * Copyright 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,142 +28,161 @@
#include <libaudcore/drct.h>
#include <libaudcore/hook.h>
+#include <libaudcore/runtime.h>
-namespace audqt {
+namespace audqt
+{
class VolumeButton : public QToolButton
{
public:
- VolumeButton (QWidget * parent = nullptr);
+ VolumeButton(QWidget * parent = nullptr);
private:
- void updateIcon (int val);
- void updateVolume ();
- void showSlider ();
- void setVolume (int val);
- QToolButton * newSliderButton (int delta);
+ void updateDelta();
+ void updateIcon(int val);
+ void updateVolume();
+ void showSlider();
+ void setVolume(int val);
+ QToolButton * newSliderButton(int dir);
- void wheelEvent (QWheelEvent * e);
+ void wheelEvent(QWheelEvent * e);
QSlider * m_slider;
QFrame * m_container;
+ int m_scroll_delta = 0;
+
+ HookReceiver<VolumeButton> update_hook{"set volume_delta", this,
+ &VolumeButton::updateDelta};
};
-VolumeButton::VolumeButton (QWidget * parent) :
- QToolButton (parent)
+VolumeButton::VolumeButton(QWidget * parent) : QToolButton(parent)
{
- setFocusPolicy (Qt::NoFocus);
+ setFocusPolicy(Qt::NoFocus);
+
+ m_container = new QFrame(this, Qt::Popup);
+ m_container->setFrameShape(QFrame::StyledPanel);
- m_container = new QFrame (this, Qt::Popup);
- m_container->setFrameShape (QFrame::StyledPanel);
+ m_slider = new QSlider(Qt::Vertical, this);
+ m_slider->setMinimumHeight(audqt::sizes.OneInch);
+ m_slider->setRange(0, 100);
- m_slider = new QSlider (Qt::Vertical, this);
- m_slider->setMinimumHeight (audqt::sizes.OneInch);
- m_slider->setRange (0, 100);
- m_slider->setSingleStep (2);
- m_slider->setPageStep (20);
+ updateDelta();
- auto layout = make_vbox (m_container, sizes.TwoPt);
- layout->setContentsMargins (margins.TwoPt);
+ auto layout = make_vbox(m_container, sizes.TwoPt);
+ layout->setContentsMargins(margins.TwoPt);
- layout->addWidget (newSliderButton (5));
- layout->addWidget (m_slider);
- layout->addWidget (newSliderButton (-5));
+ layout->addWidget(newSliderButton(1));
+ layout->addWidget(m_slider);
+ layout->addWidget(newSliderButton(-1));
- int val = aud_drct_get_volume_main ();
- m_slider->setValue (val);
- updateIcon (val);
+ int val = aud_drct_get_volume_main();
+ m_slider->setValue(val);
+ updateIcon(val);
- connect (this, & QAbstractButton::clicked, this, & VolumeButton::showSlider);
- connect (m_slider, & QAbstractSlider::valueChanged, this, & VolumeButton::setVolume);
+ connect(this, &QAbstractButton::clicked, this, &VolumeButton::showSlider);
+ connect(m_slider, &QAbstractSlider::valueChanged, this,
+ &VolumeButton::setVolume);
- auto timer = new Timer<VolumeButton> (TimerRate::Hz4, this, & VolumeButton::updateVolume);
- connect (this, & QObject::destroyed, [timer] () { delete timer; });
+ auto timer = new Timer<VolumeButton>(TimerRate::Hz4, this,
+ &VolumeButton::updateVolume);
+ connect(this, &QObject::destroyed, [timer]() { delete timer; });
- timer->start ();
+ timer->start();
}
-void VolumeButton::updateIcon (int val)
+void VolumeButton::updateDelta()
+{
+ int delta = aud_get_int("volume_delta");
+ m_slider->setSingleStep(delta);
+ m_slider->setPageStep(delta);
+}
+
+void VolumeButton::updateIcon(int val)
{
if (val == 0)
- setIcon (audqt::get_icon ("audio-volume-muted"));
+ setIcon(audqt::get_icon("audio-volume-muted"));
else if (val < 34)
- setIcon (audqt::get_icon ("audio-volume-low"));
+ setIcon(audqt::get_icon("audio-volume-low"));
else if (val < 67)
- setIcon (audqt::get_icon ("audio-volume-medium"));
+ setIcon(audqt::get_icon("audio-volume-medium"));
else
- setIcon (audqt::get_icon ("audio-volume-high"));
+ setIcon(audqt::get_icon("audio-volume-high"));
- setToolTip (QString ("%1 %").arg (val));
+ setToolTip(QString("%1 %").arg(val));
}
-void VolumeButton::updateVolume ()
+void VolumeButton::updateVolume()
{
- if (m_slider->isSliderDown ())
+ if (m_slider->isSliderDown())
return;
- int val = aud_drct_get_volume_main ();
- if (val != m_slider->value ())
+ int val = aud_drct_get_volume_main();
+ if (val != m_slider->value())
{
- disconnect (m_slider, nullptr, this, nullptr);
- m_slider->setValue (val);
- updateIcon (val);
- connect (m_slider, & QAbstractSlider::valueChanged, this, & VolumeButton::setVolume);
+ disconnect(m_slider, nullptr, this, nullptr);
+ m_slider->setValue(val);
+ updateIcon(val);
+ connect(m_slider, &QAbstractSlider::valueChanged, this,
+ &VolumeButton::setVolume);
}
}
-void VolumeButton::showSlider ()
+void VolumeButton::showSlider()
{
- QSize button_size = sizeHint ();
- QSize container_size = m_container->sizeHint ();
+ QSize button_size = sizeHint();
+ QSize container_size = m_container->sizeHint();
- int dx = container_size.width () / 2 - button_size.width () / 2;
- int dy = container_size.height () / 2 - button_size.height () / 2;
+ int dx = container_size.width() / 2 - button_size.width() / 2;
+ int dy = container_size.height() / 2 - button_size.height() / 2;
- QPoint pos = mapToGlobal (QPoint (0, 0));
- pos -= QPoint (dx, dy);
+ QPoint pos = mapToGlobal(QPoint(0, 0));
+ pos -= QPoint(dx, dy);
pos.setX(qMax(pos.x(), 0));
pos.setY(qMax(pos.y(), 0));
- m_container->move (pos);
- window_bring_to_front (m_container);
+ m_container->move(pos);
+ window_bring_to_front(m_container);
}
-void VolumeButton::setVolume (int val)
+void VolumeButton::setVolume(int val)
{
- aud_drct_set_volume_main (val);
- updateIcon (val);
+ aud_drct_set_volume_main(val);
+ updateIcon(val);
}
-QToolButton * VolumeButton::newSliderButton (int delta)
+QToolButton * VolumeButton::newSliderButton(int dir)
{
- auto button = new QToolButton (this);
- button->setText (delta < 0 ? "-" : "+");
- button->setAutoRaise (true);
- button->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Preferred);
-
- connect (button, & QAbstractButton::clicked, [this, delta] () {
- int val = aud_drct_get_volume_main ();
- m_slider->setValue (val + delta);
+ auto button = new QToolButton(this);
+ button->setText(dir < 0 ? "-" : "+");
+ button->setAutoRaise(true);
+ button->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
+
+ connect(button, &QAbstractButton::clicked, [this, dir]() {
+ m_slider->setValue(m_slider->value() +
+ dir * aud_get_int("volume_delta"));
});
return button;
}
-void VolumeButton::wheelEvent (QWheelEvent * e)
+void VolumeButton::wheelEvent(QWheelEvent * e)
{
- int val = m_slider->value ();
- int y = e->angleDelta ().y ();
+ m_scroll_delta += e->angleDelta().y();
- if (y < 0)
- m_slider->setValue (-- val);
- else
- m_slider->setValue (++ val);
+ /* we want discrete steps here */
+ int steps = m_scroll_delta / 120;
+ if (steps != 0)
+ {
+ m_scroll_delta -= 120 * steps;
+ m_slider->setValue(m_slider->value() +
+ steps * aud_get_int("volume_delta"));
+ }
}
-EXPORT QToolButton * volume_button_new (QWidget * parent)
+EXPORT QToolButton * volume_button_new(QWidget * parent)
{
- return new VolumeButton (parent);
+ return new VolumeButton(parent);
}
} // namespace audqt
diff --git a/src/libaudtag/Makefile b/src/libaudtag/Makefile
index 961b768..e11d814 100644
--- a/src/libaudtag/Makefile
+++ b/src/libaudtag/Makefile
@@ -24,6 +24,8 @@ CPPFLAGS := -I.. -I../.. \
CFLAGS += ${LIB_CFLAGS}
-LIBS := -L../libaudcore -laudcore \
+LIB_LDFLAGS := -L../libaudcore $(LIB_LDFLAGS)
+
+LIBS := -laudcore \
${LIBS} \
${GLIB_LIBS}
diff --git a/src/libaudtag/ape/ape.cc b/src/libaudtag/ape/ape.cc
index 5188aa8..fa93f27 100644
--- a/src/libaudtag/ape/ape.cc
+++ b/src/libaudtag/ape/ape.cc
@@ -246,19 +246,19 @@ bool APETagModule::read_tag (VFSFile & handle, Tuple & tuple, Index<char> * imag
for (const ValuePair & pair : list)
{
- if (! strcmp (pair.key, "Artist"))
+ if (! strcmp_nocase (pair.key, "Artist"))
tuple.set_str (Tuple::Artist, pair.value);
- else if (! strcmp (pair.key, "Title"))
+ else if (! strcmp_nocase (pair.key, "Title"))
tuple.set_str (Tuple::Title, pair.value);
- else if (! strcmp (pair.key, "Album"))
+ else if (! strcmp_nocase (pair.key, "Album"))
tuple.set_str (Tuple::Album, pair.value);
- else if (! strcmp (pair.key, "Comment"))
+ else if (! strcmp_nocase (pair.key, "Comment"))
tuple.set_str (Tuple::Comment, pair.value);
- else if (! strcmp (pair.key, "Genre"))
+ else if (! strcmp_nocase (pair.key, "Genre"))
tuple.set_str (Tuple::Genre, pair.value);
- else if (! strcmp (pair.key, "Track"))
+ else if (! strcmp_nocase (pair.key, "Track"))
tuple.set_int (Tuple::Track, atoi (pair.value));
- else if (! strcmp (pair.key, "Year"))
+ else if (! strcmp_nocase (pair.key, "Year"))
tuple.set_int (Tuple::Year, atoi (pair.value));
else if (! strcmp_nocase (pair.key, "REPLAYGAIN_TRACK_GAIN"))
tuple.set_gain (Tuple::TrackGain, Tuple::GainDivisor, pair.value);
@@ -387,10 +387,10 @@ bool APETagModule::write_tag (VFSFile & handle, const Tuple & tuple)
for (const ValuePair & pair : list)
{
- if (! strcmp (pair.key, "Artist") || ! strcmp (pair.key, "Title") ||
- ! strcmp (pair.key, "Album") || ! strcmp (pair.key, "Comment") ||
- ! strcmp (pair.key, "Genre") || ! strcmp (pair.key, "Track") ||
- ! strcmp (pair.key, "Year"))
+ if (! strcmp_nocase (pair.key, "Artist") || ! strcmp_nocase (pair.key, "Title") ||
+ ! strcmp_nocase (pair.key, "Album") || ! strcmp_nocase (pair.key, "Comment") ||
+ ! strcmp_nocase (pair.key, "Genre") || ! strcmp_nocase (pair.key, "Track") ||
+ ! strcmp_nocase (pair.key, "Year"))
continue;
if (! ape_write_item (handle, pair.key, pair.value, & length))
diff --git a/src/libaudtag/builtin.h b/src/libaudtag/builtin.h
index 1426def..bd5edd9 100644
--- a/src/libaudtag/builtin.h
+++ b/src/libaudtag/builtin.h
@@ -1,6 +1,6 @@
/*
* builtin.h
- * Copyright (c) 2014 William Pitcock
+ * Copyright (c) 2014 Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
diff --git a/src/libaudtag/id3/id3v22.cc b/src/libaudtag/id3/id3v22.cc
index b435faa..f850cfa 100644
--- a/src/libaudtag/id3/id3v22.cc
+++ b/src/libaudtag/id3/id3v22.cc
@@ -1,7 +1,7 @@
/*
* id3v22.c
* Copyright 2009-2014 Paula Stanciu, Tony Vroon, John Lindgren,
- * and William Pitcock
+ * and Ariadne Conill
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
diff --git a/src/libaudtag/id3/id3v24.cc b/src/libaudtag/id3/id3v24.cc
index f8ab6e9..2dda167 100644
--- a/src/libaudtag/id3/id3v24.cc
+++ b/src/libaudtag/id3/id3v24.cc
@@ -642,6 +642,8 @@ bool ID3v24TagModule::write_tag (VFSFile & f, const Tuple & tuple)
if (read_header (f, & version, & syncsafe, & offset, & header_size, & data_size, & footer_size))
read_all_frames (read_tag_data (f, data_size, syncsafe), version, dict);
+ else
+ offset = header_size = data_size = footer_size = 0;
//make the new frames from tuple and replace in the dictionary the old frames with the new ones
add_frameFromTupleStr (tuple, Tuple::Title, ID3_TITLE, dict);
diff --git a/src/libaudtag/meson.build b/src/libaudtag/meson.build
new file mode 100644
index 0000000..c766bdb
--- /dev/null
+++ b/src/libaudtag/meson.build
@@ -0,0 +1,27 @@
+libaudtag_sources = [
+ 'audtag.cc',
+ 'util.cc',
+ 'tag_module.cc',
+ 'id3/id3-common.cc',
+ 'id3/id3v1.cc',
+ 'id3/id3v22.cc',
+ 'id3/id3v24.cc',
+ 'ape/ape.cc'
+]
+
+
+libaudtag_inc = include_directories('.')
+
+
+install_headers('audtag.h', subdir: 'audacious')
+
+
+libaudtag_lib = library('audtag',
+ libaudtag_sources,
+ include_directories: src_inc,
+ dependencies: [glib_dep],
+ link_with: libaudcore_lib,
+ version: '3.0.0',
+ soversion: 3,
+ install: true
+)
diff --git a/src/libguess/meson.build b/src/libguess/meson.build
new file mode 100644
index 0000000..629341f
--- /dev/null
+++ b/src/libguess/meson.build
@@ -0,0 +1,15 @@
+libguess_sources = [
+ 'dfa.c',
+ 'guess.c',
+ 'guess_impl.c'
+]
+
+
+libguess_lib = static_library('guess',
+ libguess_sources,
+ c_args: ['-DLIBGUESS_CORE'],
+ pic: true
+)
+
+
+libguess_inc = include_directories('.')
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000..d6f738d
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,36 @@
+src_inc = include_directories('.')
+
+
+config_h = configure_file(input: 'config.h.meson',
+ output: 'config.h',
+ configuration: conf)
+
+
+config_h_full_path = join_paths(meson.current_build_dir(), 'config.h')
+
+
+if cc.get_id() == 'gcc' or cc.get_id() == 'clang'
+ add_project_arguments('-include', config_h_full_path, language: 'c')
+ add_project_arguments('-include', config_h_full_path, language: 'cpp')
+else
+ error('Please implement -include handling for your chosen compiler.')
+endif
+
+
+subdir('libguess')
+subdir('libaudcore')
+subdir('libaudtag')
+
+
+if get_option('qt')
+ subdir('libaudqt')
+endif
+
+
+if get_option('dbus')
+ subdir('dbus')
+ subdir('audtool')
+endif
+
+
+subdir('audacious')
diff --git a/win32/merge.sh b/win32/merge.sh
index fb82214..797d5e9 100644
--- a/win32/merge.sh
+++ b/win32/merge.sh
@@ -10,6 +10,8 @@ for i in `find -type f` ; do
cp /C/audacious/win32/override/$i $i
elif test -f /C/msys32/mingw32/$i ; then
cp /C/msys32/mingw32/$i $i
+ elif test -f /C/Qt/5.12.5/mingw73_32/$i ; then
+ cp /C/Qt/5.12.5/mingw73_32/$i $i
elif test -f /C/GTK/$i ; then
cp /C/GTK/$i $i
elif test -f /C/libs/$i ; then
diff --git a/win32/notes.html b/win32/notes.html
index ef5ef61..ed25426 100644..100755
--- a/win32/notes.html
+++ b/win32/notes.html
@@ -24,7 +24,7 @@ April 13, 2017</em></p>
<p>Edit <tt>C:\msys32\home\&lt;user&gt;\.bashrc</tt> and add the following lines:</p>
<blockquote><p><tt>export PATH="$PATH:/C/cmake/bin:/C/GTK/bin:/C/libs/bin:/C/aud/bin"<br>
-export PKG_CONFIG_PATH=/C/GTK/lib/pkgconfig:/C/libs/lib/pkgconfig:/C/aud/lib/pkgconfig<br>
+export PKG_CONFIG_PATH=/C/Qt/5.12.5/mingw73_32/lib/pkgconfig:/C/GTK/lib/pkgconfig:/C/libs/lib/pkgconfig:/C/aud/lib/pkgconfig<br>
export C_INCLUDE_PATH=/C/GTK/include:/C/libs/include<br>
export CPLUS_INCLUDE_PATH=/C/GTK/include:/C/libs/include<br>
export LIBRARY_PATH=/C/GTK/lib:/C/libs/lib</tt></p></blockquote>
@@ -42,6 +42,17 @@ pacman -S autoconf automake bison gperf libtool mingw-w64-i686-gcc mingw-w64-i68
<p>Install to <tt>C:\cmake</tt>.</p>
+<h3>Install Qt (for Qt builds)</h3>
+
+<p>Download and run (choose another mirror if desired):<br>
+<a href="http://qt.mirror.constant.com/archive/online_installers/3.1/qt-unified-windows-x86-3.1.1-online.exe">
+<tt>http://qt.mirror.constant.com/archive/online_installers/3.1/qt-unified-windows-x86-3.1.1-online.exe</tt></a></p>
+
+<p>Choose the following install options:<br>
+<ul><li>Skip the Qt account login page</li>
+<li>Use the default installation path (<tt>C:\Qt</tt>)</li>
+<li>Install Qt 5.12.5 for MinGW 7.3.0 32-bit</li></ul></p>
+
<h3>Install libpng</h3>
<p>Download and unzip to <tt>C:\libpng</tt>:<br>
@@ -174,7 +185,7 @@ make install</tt></p></blockquote>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/gdk-pixbuf<br>
-./configure --prefix=/C/GTK --enable-relocations --without-gdiplus --without-libtiff --with-included-loaders=jpeg,png<br>
+./configure --prefix=/C/GTK --enable-relocations --without-gdiplus --without-libtiff --with-included-loaders=bmp,jpeg,png<br>
make<br>
make install</tt></p></blockquote>
@@ -224,7 +235,8 @@ make install</tt></p></blockquote>
<p>Apply the patch <tt>gdkwindow-win32.c.diff</tt> to <tt>C:\gtksrc\gdk\win32\gdkwindow-win32.c</tt>.<br>
Apply the patch <tt>gtkicontheme.c.diff</tt> to <tt>C:\gtksrc\gtk\gtkicontheme.c</tt>.<br>
-Apply the patch <tt>gtkmain.c.diff</tt> to <tt>C:\gtksrc\gtk\gtkmain.c</tt>.</p>
+Apply the patch <tt>gtkmain.c.diff</tt> to <tt>C:\gtksrc\gtk\gtkmain.c</tt>.<br>
+Apply the recursive patch <tt>gtk-parentheses.diff</tt>.</p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/gtksrc<br>
@@ -273,8 +285,8 @@ for GNOME Icon Theme to install successfully.</i></p>
<h3>Install libxml</h3>
<p>Download and unzip to <tt>C:\libxml</tt>:<br>
-<a href="ftp://xmlsoft.org/libxml2/libxml2-2.9.4.tar.gz">
-<tt>ftp://xmlsoft.org/libxml2/libxml2-2.9.4.tar.gz</tt></a></p>
+<a href="ftp://xmlsoft.org/libxml2/libxml2-2.9.9.tar.gz">
+<tt>ftp://xmlsoft.org/libxml2/libxml2-2.9.9.tar.gz</tt></a></p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/libxml<br>
@@ -285,8 +297,8 @@ make install</tt></p></blockquote>
<h3>Install mpg123</h3>
<p>Download and unzip to <tt>C:\mpg123</tt>:<br>
-<a href="http://mpg123.de/download/mpg123-1.25.0.tar.bz2">
-<tt>http://mpg123.de/download/mpg123-1.25.0.tar.bz2</tt></a></p>
+<a href="http://mpg123.de/download/mpg123-1.25.13.tar.bz2">
+<tt>http://mpg123.de/download/mpg123-1.25.13.tar.bz2</tt></a></p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/mpg123<br>
@@ -297,16 +309,13 @@ make install</tt></p></blockquote>
<h3>Install libfaad</h3>
<p>Download and unzip to <tt>C:\libfaad</tt>:<br>
-<a href="http://sourceforge.net/projects/faac/files/faad2-src/faad2-2.7/faad2-2.7.tar.bz2/download">
-<tt>http://sourceforge.net/projects/faac/files/faad2-src/faad2-2.7/faad2-2.7.tar.bz2/download</tt></a></p>
+<a href="https://sourceforge.net/projects/faac/files/faad2-src/faad2-2.8.0/faad2-2.8.8.tar.gz/download">
+<tt>https://sourceforge.net/projects/faac/files/faad2-src/faad2-2.8.0/faad2-2.8.8.tar.gz/download</tt></a></p>
-<p>Apply the patch <tt>libfaad-makefile.am.diff</tt> to <tt>C:\libfaad\libfaad\Makefile.am</tt>.<br>
-Apply the patch <tt>libfaad-main.c.diff</tt> to <tt>C:\libfaad\frontend\main.c</tt>.</p>
+<p>Apply the patch <tt>libfaad-decoder.c.diff</tt> to <tt>C:\libfaad\decoder.c</tt>.</p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/libfaad<br>
-cp /C/msys32/usr/share/libtool/build-aux/ltmain.sh .<br>
-autoreconf<br>
./configure --prefix=/C/libs<br>
make<br>
make install</tt></p></blockquote>
@@ -329,12 +338,8 @@ make install</tt></p></blockquote>
<a href="http://sourceforge.net/projects/bs2b/files/libbs2b/3.1.0/libbs2b-3.1.0.tar.bz2/download">
<tt>http://sourceforge.net/projects/bs2b/files/libbs2b/3.1.0/libbs2b-3.1.0.tar.bz2/download</tt></a></p>
-<p>Apply the patch <tt>libbs2b-makefile.am.diff</tt> to <tt>C:\libs2b\src\Makefile.am</tt>.</p>
-
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/libbs2b<br>
-cp /C/msys32/usr/share/libtool/build-aux/ltmain.sh build-aux<br>
-autoreconf<br>
./configure --prefix=/C/libs<br>
make<br>
make install</tt></p></blockquote>
@@ -342,14 +347,20 @@ make install</tt></p></blockquote>
<h3>Install libcdio</h3>
<p>Download and unzip to <tt>C:\libcdio</tt>:<br>
-<a href="http://ftp.gnu.org/gnu/libcdio/libcdio-0.83.tar.gz">
-<tt>http://ftp.gnu.org/gnu/libcdio/libcdio-0.83.tar.gz</tt></a></p>
+<a href="http://ftp.gnu.org/gnu/libcdio/libcdio-2.1.0.tar.bz2">
+<tt>http://ftp.gnu.org/gnu/libcdio/libcdio-2.1.0.tar.bz2</tt></a></p>
-<p>Apply the recursive patch <tt>libcdio-0.83.diff</tt>.</p>
+<p>Download and unzip to <tt>C:\libcdio-paranoia</tt>:<br>
+<a href="http://ftp.gnu.org/gnu/libcdio/libcdio-paranoia-10.2+2.0.0.tar.bz2">
+<tt>http://ftp.gnu.org/gnu/libcdio/libcdio-paranoia-10.2+2.0.0.tar.bz2</tt></a></p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/libcdio<br>
-./configure --prefix=/C/libs --disable-rock<br>
+./configure --prefix=/C/libs<br>
+make<br>
+make install<br>
+cd /C/libcdio-paranoia<br>
+./configure --prefix=/C/libs<br>
make<br>
make install</tt></p></blockquote>
@@ -370,38 +381,34 @@ make install</tt></p></blockquote>
<h3>Install libcue</h3>
<p>Download and unzip to <tt>C:\libcue</tt>:<br>
-<a href="https://github.com/lipnitsk/libcue/archive/v2.1.0.tar.gz">
-<tt>https://github.com/lipnitsk/libcue/archive/v2.1.0.tar.gz</tt></a></p>
-
-<p>Apply the recursive patch <tt>libcue-install-dll.diff</tt>.</p>
+<a href="https://github.com/lipnitsk/libcue/archive/v2.2.1.tar.gz">
+<tt>https://github.com/lipnitsk/libcue/archive/v2.2.1.tar.gz</tt></a></p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/libcue<br>
-cmake -DCMAKE_INSTALL_PREFIX=/C/libs -G"MSYS Makefiles"<br>
+cmake -DCMAKE_INSTALL_PREFIX=/C/libs -DBUILD_SHARED_LIBS=1 -G"MSYS Makefiles"<br>
make<br>
make install</tt></p></blockquote>
<h3>Install LAME</h3>
<p>Download and unzip to <tt>C:\lame</tt>:<br>
-<a href="http://sourceforge.net/projects/lame/files/lame/3.99/lame-3.99.5.tar.gz/download">
-<tt>http://sourceforge.net/projects/lame/files/lame/3.99/lame-3.99.5.tar.gz/download</tt></a></p>
+<a href="https://sourceforge.net/projects/lame/files/lame/3.100/lame-3.100.tar.gz/download">
+<tt>https://sourceforge.net/projects/lame/files/lame/3.100/lame-3.100.tar.gz/download</tt></a></p>
-<p>Apply the recursive patch <tt>lame-3.99.diff</tt>.</p>
+<p>Apply the patch <tt>libmp3lame.sym.diff</tt> to <tt>C:\lame\include\libmp3lame.sym</tt>.</p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/lame<br>
-cp /C/msys32/usr/share/libtool/build-aux/ltmain.sh .<br>
-autoreconf<br>
-./configure --prefix=/C/libs<br>
+./configure --prefix=/C/libs --disable-frontend<br>
make<br>
make install</tt></p></blockquote>
<h3>Install libflac</h3>
<p>Download and unzip to <tt>C:\libflac</tt>:<br>
-<a href="http://downloads.xiph.org/releases/flac/flac-1.3.2.tar.xz">
-<tt>http://downloads.xiph.org/releases/flac/flac-1.3.2.tar.xzz</tt></a></p>
+<a href="https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.3.3.tar.xz">
+<tt>https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.3.3.tar.xz</tt></a></p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/libflac<br>
@@ -412,8 +419,8 @@ make install</tt></p></blockquote>
<h3>Install libogg</h3>
<p>Download and unzip to <tt>C:\libogg</tt>:<br>
-<a href="http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.xz">
-<tt>http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.xz</tt></a></p>
+<a href="https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-1.3.4.tar.xz">
+<tt>https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-1.3.4.tar.xz</tt></a></p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/libogg<br>
@@ -424,8 +431,8 @@ make install</tt></p></blockquote>
<h3>Install libvorbis</h3>
<p>Download and unzip to <tt>C:\libvorbis</tt>:<br>
-<a href="http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.5.tar.xz">
-<tt>http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.5.tar.xz</tt></a></p>
+<a href="https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-1.3.6.tar.xz">
+<tt>https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-1.3.6.tar.xz</tt></a></p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/libvorbis<br>
@@ -443,7 +450,7 @@ make install</tt></p></blockquote>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/libneon<br>
-./autogen.sh
+./autogen.sh<br>
./configure --prefix=/C/libs --enable-shared<br>
make<br>
make install</tt></p></blockquote>
@@ -479,8 +486,8 @@ make install</tt></p></blockquote>
<h3>Install FFmpeg</h3>
<p>Download and unzip to <tt>C:\ffmpeg</tt>:<br>
-<a href="http://ffmpeg.org/releases/ffmpeg-3.3.tar.xz">
-<tt>http://ffmpeg.org/releases/ffmpeg-3.3.tar.xz</tt></a></p>
+<a href="http://ffmpeg.org/releases/ffmpeg-4.2.1.tar.xz">
+<tt>http://ffmpeg.org/releases/ffmpeg-4.2.1.tar.xz</tt></a></p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/ffmpeg<br>
@@ -507,8 +514,8 @@ make install</tt></p></blockquote>
<h3>Install libbinio</h3>
<p>Download and unzip to <tt>C:\libbinio</tt>:<br>
-<a href="https://sourceforge.net/projects/libbinio/files/libbinio/1.4/libbinio-1.4.tar.bz2/download">
-<tt>https://sourceforge.net/projects/libbinio/files/libbinio/1.4/libbinio-1.4.tar.bz2/download</tt></a></p>
+<a href="https://github.com/adplug/libbinio/releases/download/libbinio-1.5/libbinio-1.5.tar.bz2">
+<tt>https://github.com/adplug/libbinio/releases/download/libbinio-1.5/libbinio-1.5.tar.bz2</tt></a></p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/libbinio<br>
@@ -519,8 +526,8 @@ make install</tt></p></blockquote>
<h3>Install adplug</h3>
<p>Download and unzip to <tt>C:\adplug</tt>:<br>
-<a href="https://github.com/adplug/adplug/releases/download/adplug-2.3/adplug-2.3.tar.bz2">
-<tt>https://github.com/adplug/adplug/releases/download/adplug-2.3/adplug-2.3.tar.bz2</tt></a></p>
+<a href="https://github.com/adplug/adplug/releases/download/adplug-2.3.1/adplug-2.3.1.tar.bz2">
+<tt>https://github.com/adplug/adplug/releases/download/adplug-2.3.1/adplug-2.3.1.tar.bz2</tt></a></p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/adplug<br>
@@ -543,8 +550,8 @@ make install</tt></p></blockquote>
<h3>Install libsidplayfp</h3>
<p>Download and unzip to <tt>C:\libsidplayfp</tt>:<br>
-<a href="https://sourceforge.net/projects/sidplay-residfp/files/libsidplayfp/1.8/libsidplayfp-1.8.7.tar.gz/download">
-<tt>https://sourceforge.net/projects/sidplay-residfp/files/libsidplayfp/1.8/libsidplayfp-1.8.7.tar.gz/download</tt></a></p>
+<a href="https://sourceforge.net/projects/sidplay-residfp/files/libsidplayfp/2.0/libsidplayfp-2.0.1.tar.gz/download">
+<tt>https://sourceforge.net/projects/sidplay-residfp/files/libsidplayfp/2.0/libsidplayfp-2.0.1.tar.gz/download</tt></a></p>
<p>In the MinGW shell:</p>
<blockquote><p><tt>cd /C/libsidplayfp<br>
diff --git a/win32/patches/gtk-parentheses.diff b/win32/patches/gtk-parentheses.diff
new file mode 100644
index 0000000..c473d7c
--- /dev/null
+++ b/win32/patches/gtk-parentheses.diff
@@ -0,0 +1,67 @@
+From 889a63dffc72c048502d0f7d2b26bfc8532462eb Mon Sep 17 00:00:00 2001
+From: John Lindgren <john@jlindgren.net>
+Date: Tue, 15 May 2018 21:47:12 -0400
+Subject: [PATCH] Fix compiler warnings with GCC 8.1.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+GCC 8.1 added some new warnings, including warning about parentheses
+with no effect in variable declarations. GTK2 headers have a few of
+these, which produce a lot of warnings in projects using GTK2.
+
+The warnings look like:
+/usr/include/gtk-2.0/gtk/gtkfilechooserbutton.h:59:8: warning:
+unnecessary parentheses in declaration of ‘__gtk_reserved1’ [-Wparentheses]
+ void (*__gtk_reserved1);
+ ^
+
+Removing the parentheses is harmless and fixes the warnings.
+---
+ gtk/gtkfilechooserbutton.h | 14 +++++++-------
+ gtk/gtkstatusicon.h | 4 ++--
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/gtk/gtkfilechooserbutton.h b/gtk/gtkfilechooserbutton.h
+index b3d9112cf9..fdacc4b6ec 100644
+--- a/gtk/gtkfilechooserbutton.h
++++ b/gtk/gtkfilechooserbutton.h
+@@ -56,13 +56,13 @@ struct _GtkFileChooserButtonClass
+
+ void (* file_set) (GtkFileChooserButton *fc);
+
+- void (*__gtk_reserved1);
+- void (*__gtk_reserved2);
+- void (*__gtk_reserved3);
+- void (*__gtk_reserved4);
+- void (*__gtk_reserved5);
+- void (*__gtk_reserved6);
+- void (*__gtk_reserved7);
++ void *__gtk_reserved1;
++ void *__gtk_reserved2;
++ void *__gtk_reserved3;
++ void *__gtk_reserved4;
++ void *__gtk_reserved5;
++ void *__gtk_reserved6;
++ void *__gtk_reserved7;
+ };
+
+
+diff --git a/gtk/gtkstatusicon.h b/gtk/gtkstatusicon.h
+index 19dbd1cdeb..c45caca5ae 100644
+--- a/gtk/gtkstatusicon.h
++++ b/gtk/gtkstatusicon.h
+@@ -73,8 +73,8 @@ struct _GtkStatusIconClass
+ gboolean keyboard_mode,
+ GtkTooltip *tooltip);
+
+- void (*__gtk_reserved1);
+- void (*__gtk_reserved2);
++ void *__gtk_reserved1;
++ void *__gtk_reserved2;
+ };
+
+ GType gtk_status_icon_get_type (void) G_GNUC_CONST;
+--
+2.22.0
+
diff --git a/win32/patches/lame-3.99.diff b/win32/patches/lame-3.99.diff
deleted file mode 100644
index fdb974c..0000000
--- a/win32/patches/lame-3.99.diff
+++ /dev/null
@@ -1,61 +0,0 @@
-diff --git a/configure.in b/configure.in
-index 2f8fa66..813d33d 100644
---- a/configure.in
-+++ b/configure.in
-@@ -96,7 +96,6 @@ AC_CHECK_HEADERS( \
- sys/soundcard.h \
- sys/time.h \
- unistd.h \
-- xmmintrin.h \
- linux/soundcard.h)
-
- dnl Checks for typedefs, structures, and compiler characteristics.
-@@ -393,8 +392,6 @@ CONFIG_MATH_LIB="${USE_LIBM}"
-
- dnl configure use of features
-
--AM_PATH_GTK(1.2.0, HAVE_GTK="yes", HAVE_GTK="no")
--
- dnl ElectricFence malloc debugging
- AC_MSG_CHECKING(use of ElectricFence malloc debugging)
- AC_ARG_ENABLE(efence,
-@@ -527,7 +524,7 @@ else
- AC_MSG_RESULT(no)
- fi
-
--if test "${HAVE_GTK}" = "no"; then
-+if false ; then
- if test "x${WITH_MP3X}" = "xmp3x"; then
- AC_MSG_WARN(can't build mp3x, no GTK installed)
- WITH_MP3X=
-@@ -635,7 +632,7 @@ WITH_VECTOR=no
- case $host_cpu in
- x86_64|amd64)
- CPUTYPE="no"
-- if test $ac_cv_header_xmmintrin_h = yes ; then
-+ if false ; then
- WITH_XMM=yes
- WITH_VECTOR=yes
- fi
-@@ -646,7 +643,7 @@ h precission)
- ;;
- *86)
- CPUTYPE="i386"
-- if test $ac_cv_header_xmmintrin_h = yes ; then
-+ if false ; then
- WITH_XMM=yes
- WITH_VECTOR=yes
- fi
-diff --git a/frontend/Makefile.am b/frontend/Makefile.am
-index a35cb17..3cf2d8f 100644
---- a/frontend/Makefile.am
-+++ b/frontend/Makefile.am
-@@ -35,7 +35,7 @@ lame_SOURCES = lame_main.c $(common_sources)
- mp3rtp_SOURCES = mp3rtp.c rtp.c $(common_sources)
- mp3x_SOURCES = mp3x.c gtkanal.c gpkplotting.c $(common_sources)
-
--CFLAGS = @CFLAGS@ @GTK_CFLAGS@ @FRONTEND_CFLAGS@ @SNDFILE_CFLAGS@
-+CFLAGS = @CFLAGS@ @FRONTEND_CFLAGS@ @SNDFILE_CFLAGS@
- LDFLAGS = @LDFLAGS@ @FRONTEND_LDFLAGS@ @SNDFILE_LIBS@
-
- INCLUDES = -I$(top_srcdir)/libmp3lame -I$(top_srcdir)/include -I$(top_builddir)
diff --git a/win32/patches/libbs2b-makefile.am.diff b/win32/patches/libbs2b-makefile.am.diff
deleted file mode 100644
index 8292c29..0000000
--- a/win32/patches/libbs2b-makefile.am.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- Makefile.am.0 2009-03-20 10:13:53 -0400
-+++ Makefile.am 2013-09-13 21:12:22 -0400
-@@ -18,7 +18,7 @@
- $(bs2b_HEADERS)
-
- libbs2b_la_LDFLAGS = \
-- -lm -version-info 0:0:0
-+ -lm -version-info 0:0:0 -no-undefined
-
- libbs2b_la_SOURCES = \
- bs2b.c \
diff --git a/win32/patches/libcdio-0.83.diff b/win32/patches/libcdio-0.83.diff
deleted file mode 100644
index 66516a6..0000000
--- a/win32/patches/libcdio-0.83.diff
+++ /dev/null
@@ -1,40 +0,0 @@
-diff --git a/lib/driver/MSWindows/win32_ioctl.c b/lib/driver/MSWindows/win32_ioctl.c
-index 02d1576..ca62915 100644
---- a/lib/driver/MSWindows/win32_ioctl.c
-+++ b/lib/driver/MSWindows/win32_ioctl.c
-@@ -30,9 +30,9 @@
- # include "NtScsi.h"
- # include "undocumented.h"
- #else
--# include <ddk/ntddcdrm.h>
--# include <ddk/ntddscsi.h>
--# include <ddk/scsi.h>
-+# include <windows.h>
-+# include <ntddcdrm.h>
-+# include <ntddscsi.h>
- #endif
-
- #ifdef WIN32
-diff --git a/src/util.c b/src/util.c
-index 21c83cc..efe9cdb 100644
---- a/src/util.c
-+++ b/src/util.c
-@@ -510,6 +510,7 @@ print_fs_attrs(iso9660_stat_t *p_statbuf, bool b_rock, bool b_xa,
- (unsigned int) p_statbuf->size );
- }
-
-+#ifdef HAVE_ROCK
- if (yep == p_statbuf->rr.b3_rock && b_rock) {
- struct tm tm;
-
-@@ -531,7 +532,9 @@ print_fs_attrs(iso9660_stat_t *p_statbuf, bool b_rock, bool b_xa,
- report(stdout, " -> %s", p_statbuf->rr.psz_symlink);
- }
-
-- } else {
-+ } else
-+#endif
-+ {
- strftime(date_str, sizeof(date_str), "%b %d %Y %H:%M:%S ", &p_statbuf->tm);
- report (stdout," %s %s", date_str, psz_name_translated);
- }
diff --git a/win32/patches/libcue-install-dll.diff b/win32/patches/libcue-install-dll.diff
deleted file mode 100644
index acf3079..0000000
--- a/win32/patches/libcue-install-dll.diff
+++ /dev/null
@@ -1,11 +0,0 @@
-diff -ur libcue-2.1.0-orig/CMakeLists.txt libcue-2.1.0-mod/CMakeLists.txt
---- libcue-2.1.0-orig/CMakeLists.txt 2016-04-15 01:31:27 -0400
-+++ libcue-2.1.0-mod/CMakeLists.txt 2016-07-31 15:28:48 -0400
-@@ -44,6 +44,7 @@
- C_VISIBILITY_PRESET hidden)
-
- INSTALL(TARGETS cue
-+ RUNTIME DESTINATION bin
- LIBRARY DESTINATION lib
- ARCHIVE DESTINATION lib)
- INSTALL(FILES ${CMAKE_SOURCE_DIR}/libcue.h DESTINATION include)
diff --git a/win32/patches/libfaad-decoder.c.diff b/win32/patches/libfaad-decoder.c.diff
new file mode 100644
index 0000000..5080a19
--- /dev/null
+++ b/win32/patches/libfaad-decoder.c.diff
@@ -0,0 +1,13 @@
+--- libfaad/decoder.c.0 2017-12-17 11:17:36.000000000 -0500
++++ libfaad/decoder.c 2019-10-28 15:29:26.058465600 -0400
+@@ -53,10 +53,6 @@
+ uint16_t dbg_count;
+ #endif
+
+-#if defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64
+-#include "win32_ver.h"
+-#endif
+-
+ /* static function declarations */
+ static void* aac_frame_decode(NeAACDecStruct *hDecoder,
+ NeAACDecFrameInfo *hInfo,
diff --git a/win32/patches/libfaad-main.c.diff b/win32/patches/libfaad-main.c.diff
deleted file mode 100644
index 1241e34..0000000
--- a/win32/patches/libfaad-main.c.diff
+++ /dev/null
@@ -1,10 +0,0 @@
---- main.c.0 2008-09-22 13:55:09 -0400
-+++ main.c 2011-04-01 19:00:33 -0500
-@@ -31,7 +31,6 @@
- #ifdef _WIN32
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
--#define off_t __int64
- #else
- #include <time.h>
- #endif
diff --git a/win32/patches/libfaad-makefile.am.diff b/win32/patches/libfaad-makefile.am.diff
deleted file mode 100644
index 8512846..0000000
--- a/win32/patches/libfaad-makefile.am.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- Makefile.am.0 2013-09-13 21:02:30 -0400
-+++ Makefile.am 2013-09-13 21:02:44 -0400
-@@ -4,7 +4,7 @@
- include_HEADERS = $(top_srcdir)/include/faad.h \
- $(top_srcdir)/include/neaacdec.h
-
--libfaad_la_LDFLAGS = -version-info 2:0:0
-+libfaad_la_LDFLAGS = -version-info 2:0:0 -no-undefined
- libfaad_la_LIBADD = -lm
-
- libfaad_la_SOURCES = bits.c cfft.c decoder.c drc.c \
diff --git a/win32/patches/libmp3lame.sym.diff b/win32/patches/libmp3lame.sym.diff
new file mode 100644
index 0000000..5c31040
--- /dev/null
+++ b/win32/patches/libmp3lame.sym.diff
@@ -0,0 +1,8 @@
+--- include/libmp3lame.sym.0 2017-09-06 15:33:35.000000000 -0400
++++ include/libmp3lame.sym 2019-10-28 16:18:05.949994000 -0400
+@@ -1,5 +1,4 @@
+ lame_init
+-lame_init_old
+ lame_set_num_samples
+ lame_get_num_samples
+ lame_set_in_samplerate