aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--audio/herrie/README25
-rw-r--r--audio/herrie/README.SBo121
-rw-r--r--audio/herrie/herrie.SlackBuild (renamed from multimedia/herrie/herrie.SlackBuild)53
-rw-r--r--audio/herrie/herrie.info8
-rw-r--r--audio/herrie/herriectl61
-rw-r--r--audio/herrie/patches/herrie-2.1-filters-orig.diff221
-rw-r--r--audio/herrie/patches/herrie-2.1-filters.diff263
-rw-r--r--audio/herrie/patches/herrie-2.1-signals.diff67
-rw-r--r--audio/herrie/patches/herrie-autoquit.diff187
-rw-r--r--audio/herrie/slack-desc (renamed from multimedia/herrie/slack-desc)0
-rw-r--r--multimedia/herrie/README20
-rw-r--r--multimedia/herrie/README.SBo48
-rw-r--r--multimedia/herrie/herrie.info8
13 files changed, 998 insertions, 84 deletions
diff --git a/audio/herrie/README b/audio/herrie/README
new file mode 100644
index 0000000000000..cbe587856733a
--- /dev/null
+++ b/audio/herrie/README
@@ -0,0 +1,25 @@
+Herrie is a minimalistic music player that uses the command line. It is written
+to support a variety of audio subsystems and file formats, including playlists.
+
+Herrie has a split-screen user interface, with a playlist at the top of the
+screen and a file browser at the bottom. Herrie supports XMMS shortcuts for
+playback control and can play in XMMS mode or "party" mode (which acts as a
+song queue). Herrie also has some more exotic features, including support for
+AudioScrobbler and the ability to chroot() itself into a directory.
+
+The default options for this Slackbuild are set for no scrobbler, modplugin, wave,
+or XSPF support. ALSA is the chosen sound output. This makes it so the program
+can be built with the least amount of dependencies (with these options all of them
+should be included in Slackware 12.1). See the README in the herrie source for
+the dependencies needed if you enable other options.
+
+This SlackBuild also includes some experimental patches to add functionality to
+herrie. These include adding more signals and remote control, file filtering, and
+autoquit upon playlist completion.
+
+These patches are not used by default in this slackBuild, so you either need to
+set their corresponding option in the build script or run the script with the
+respective variable set. For example, this would choose to use all three patches:
+ AUTOQUIT=YES SIGNALS=YES FILTER=YES herrie.SlackBuild
+
+Please see README.SBo for usage and configuration help for this and other options.
diff --git a/audio/herrie/README.SBo b/audio/herrie/README.SBo
new file mode 100644
index 0000000000000..2ae094a6ecc1f
--- /dev/null
+++ b/audio/herrie/README.SBo
@@ -0,0 +1,121 @@
+** Auto-saved playlist file **
+By default, when you exit herrie your current playlist is saved to
+~/.herrie/autosave.pls. This list is automatically loaded at the next startup of
+herrie.
+
+*NOTE* The file will not be created unless the full path to it exists (it is not
+created by herrie). Therefore, by default you will need to create your ~/.herrie
+folder. The config option, playq.dumpfile, can be used to change the default
+location of the autosave.pls file.
+
+
+** The Config file **
+The global config file is by default at /etc/herrie.conf.
+User-specific settings can be set by creating a config file at ~/.herrie/config.
+The '-c' argument allows you to specify a different config file other than
+these defaults. Please note that config settings are overidden on a per setting
+basis. For instance, if gui.browser.defaultpath is specified in /etc/herrie.conf,
+but it is not specified in ~/.herrie/config then the setting in /etc/herrie.conf
+will be used. The other settings that are in ~/.herrie/config would still be used.
+
+
+** AutoPlay **
+Herrie can be configured to begin playback at startup by setting
+
+playq.autoplay=yes
+
+in the config file. Alternatively, you can run herrie with the '-p' switch.
+
+
+** AutoQuit **
+Herrie can be configured to automatically exit after playing the last song in the
+playlist by setting
+
+playq.autoquit=yes
+
+in the config file. Alternatively, you can run herrie with the '-q' switch.
+Do note that, by definition, using autoquit ignores 'repeat' since you will want
+herrie to quit after the playlist finishes.
+
+
+** Skip Command Confirmation **
+If you would like to skip the Yes/No confirmation dialog when quitting herrie,
+removing all files from the playlist queue, and other commands then set
+
+gui.input.confirm=no
+
+in the config file.
+
+
+** File Filtering **
+Herrie can be configured to perform file filtering in two different ways:
+
+1) Filter only when adding whole folders to the playlist
+ vfs.ext.whitelist is used as the config option and its default is currently
+ "mp3 wav ogg". If it is set to "" (blank) then filtering is turned off.
+ Each file extension whitelisted must have *one* space in between them.
+ No '.'s are needed and the extensions are case insensitive.
+
+2) Filter files always (including in file browser)
+ To make non-whitelisted file types essentially invisible (works the same as
+ vfs.dir.hide_dotfiles) simply set
+
+ vfs.dir.hide_extfiles=yes
+
+ in the config file. Note, vfs.ext.whitelist is used to specify which file
+ extensions are whitelisted. Also, like vfs.dir.hide_dotfiles, this setting
+ does not hide files within playlist files.
+
+
+** Remote Control of Herrie **
+Sending signals to herrie will cause it to perform certain actions.
+
+SIGUSR1 PAUSE
+SIGUSR2 NEXT
+SIGRTMIN+1 PLAY
+SIGRTMIN+2 STOP
+SIGRTMIN+3 PREVIOUS
+
+An included script, herriectl, sends these signals to all running instances of
+herrie with the same effective uid as the process running the script. The
+signal sent is based upon the input argument. The short args correspond to the
+keyboard shortcuts for controlling herrie (XMMS style play control). Please run
+herriectl with "-h" or "--help" to see the full usage.
+
+
+** Chroot Mode **
+Be sure that the user you use for vfs.lockup.user is the OWNER of the folder used
+for vfs.lockup.chroot. For some reason it is not enough to have read permissions
+through a group. Also, note that other settings that use paths, such as
+gui.browser.defaultpath and playq.dumpfile will use the chrooted path. You might
+need to create a .herrie folder under your chrooted folder in order to be able to
+automatically save your playlists.
+
+Also, herrie will not work properly when using AO in chroot mode!
+ALSA is now the default sound system used because of this.
+
+Here is an example config file for using herrie in chroot mode:
+# Herrie Config file for chrooted herrie
+gui.browser.defaultpath=/
+vfs.lockup.chroot=/mnt/MEDIA/MyMusic
+vfs.lockup.user=USERNAME
+playq.dumpfile=/.herrie/autosave.pls
+
+
+** Using AO **
+If AO is chosen as the sound output an option can be specified in the
+config file.
+
+Config Examples of Using AO:
+# Useful for KDE users
+audio.output.ao.driver=arts
+
+# For sending sound output to a remote SSH session
+audio.output.ao.driver=esd
+audio.output.ao.host=env_ssh
+
+
+** For More Information... **
+Please refer to the man page for the keyboard control bindings
+and for more config options. An online version of the man page
+can be found at http://herrie.info/herrie.1
diff --git a/multimedia/herrie/herrie.SlackBuild b/audio/herrie/herrie.SlackBuild
index d6fa0ebd9229c..00adeafb19534 100644
--- a/multimedia/herrie/herrie.SlackBuild
+++ b/audio/herrie/herrie.SlackBuild
@@ -1,10 +1,10 @@
#!/bin/sh
# Slackware build script for herrie
-# Written by Phil Warner <pc_warner@yahoo.com>
+# Written by Phillip Warner <pc_warner@yahoo.com>
PRGNAM=herrie
-VERSION=2.0
+VERSION=${VERSION:-2.2}
ARCH=${ARCH:-i486}
BUILD=${BUILD:-1}
TAG=${TAG:-_SBo}
@@ -14,22 +14,58 @@ TMP=${TMP:-/tmp/SBo}
PKG=$TMP/package-$PRGNAM
OUTPUT=${OUTPUT:-/tmp}
+########################
+# Experimental Patches #
+#
+# I have found these to be stable on my systems,
+# and they might be included in future upstream
+# sources, but for now you use these at your own risk.
+#
+# Please read README.SBo for more information on the
+# functionality that these patches add.
+AUTOQUIT=${AUTOQUIT:-NO}
+SIGNALS=${SIGNALS:-NO}
+FILTER=${FILTER:-NO}
+########################
+
if [ "$ARCH" = "i486" ]; then
SLKCFLAGS="-O2 -march=i486 -mtune=i686"
elif [ "$ARCH" = "i686" ]; then
SLKCFLAGS="-O2 -march=i686 -mtune=i686"
+elif [ "$ARCH" = "x86_64" ]; then
+ SLKCFLAGS="-O2 -fPIC"
fi
set -e
-rm -rf $PKG
+rm -rf $PKG
mkdir -p $TMP $PKG/usr $OUTPUT
cd $TMP
rm -rf $PRGNAM-$VERSION
tar xvf $CWD/$PRGNAM-$VERSION.tar.bz2
cd $PRGNAM-$VERSION
chown -R root:root .
-chmod -R a-s,u+rw,go-w .
+find . \
+ \( -perm 777 -o -perm 775 -o -perm 711 -o -perm 555 -o -perm 511 \) \
+ -exec chmod 755 {} \; -o \
+ \( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \
+ -exec chmod 644 {} \;
+
+if [ "$AUTOQUIT" == "YES" ]; then
+ patch -p2 < $CWD/patches/herrie-autoquit.diff
+fi
+
+if [ "$SIGNALS" == "YES" ]; then
+ patch -p2 < $CWD/patches/herrie-2.1-signals.diff
+fi
+
+if [ "$FILTER" == "YES" ]; then
+ if [ "$AUTOQUIT" == "YES" ]; then
+ patch -p2 < $CWD/patches/herrie-2.1-filters.diff
+ else
+ patch -p2 < $CWD/patches/herrie-2.1-filters-orig.diff
+ fi
+fi
####################CONFIG OPTIONS###########################
#no_http Disable support for HTTP audio streams
@@ -63,17 +99,18 @@ CONFDIR="/etc" \
MANDIR="/usr/man" \
./configure \
no_sndfile \
- no_http \
no_modplug \
- no_nls \
no_scrobbler \
no_xspf \
- alsa \
- ncurses
+ alsa
CFLAGS="$SLKCFLAGS" CXXFLAGS="$SLKCFLAGS" force_arch="$ARCH" make
make install DESTDIR=$PKG
+if [ "$SIGNALS" == "YES" ]; then
+ install -m 0755 $CWD/herriectl $PKG/usr/bin/herriectl
+fi
+
( cd $PKG
find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true
find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
diff --git a/audio/herrie/herrie.info b/audio/herrie/herrie.info
new file mode 100644
index 0000000000000..8d37654987825
--- /dev/null
+++ b/audio/herrie/herrie.info
@@ -0,0 +1,8 @@
+PRGNAM="herrie"
+VERSION="2.2"
+HOMEPAGE="http://herrie.info/"
+DOWNLOAD="http://herrie.info/distfiles/herrie-2.2.tar.bz2"
+MD5SUM="88832b10298ab89473730eb0c93b6ddf"
+MAINTAINER="Phillip Warner"
+EMAIL="pc_warner@yahoo.com"
+APPROVED="rworkman"
diff --git a/audio/herrie/herriectl b/audio/herrie/herriectl
new file mode 100644
index 0000000000000..259e777d80ead
--- /dev/null
+++ b/audio/herrie/herriectl
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+# herriectl
+# This script sends varying signals to all running instances of herrie
+# with the same effective uid as the process running this script
+# The signal sent is based upon the input argument
+# Written by Phillip Warner
+
+VERSION=0.1
+
+# Signales that correspond to functions
+SPLAY="SIGRTMIN+1"
+SSTOP="SIGRTMIN+2"
+SPAUSE="SIGUSR1"
+SNEXT="SIGUSR2"
+SPREV="SIGRTMIN+3"
+
+usage() {
+ echo "$(basename $0) $VERSION - by Phillip Warner"
+ echo "Usage:"
+ echo " $0 [OPTION]"
+ echo "Only one parameter can be used at a time."
+ echo "The script's parameters are:"
+ echo " -h, --help Help"
+ echo " -b, --next Play Next"
+ echo " -c, --pause Pause"
+ echo " -v, --stop Stop"
+ echo " -x, --play Play Selected"
+ echo " -z, --previous Play Previous"
+ echo
+ echo "Current herrie PIDs (euid=$(id -u)):"
+ pgrep -u $(id -u) herrie$
+}
+
+# Make sure there is no more than one arg
+if [ $2 ]
+then
+ usage
+elif [ $1 ]
+then
+ case $1 in
+ -h|--help ) usage
+ ;;
+ -b|--next ) pkill -$SNEXT -u $(id -u) herrie$
+ ;;
+ -c|--pause ) pkill -$SPAUSE -u $(id -u) herrie$
+ ;;
+ -v|--stop ) pkill -$SSTOP -u $(id -u) herrie$
+ ;;
+ -x|--play ) pkill -$SPLAY -u $(id -u) herrie$
+ ;;
+ -z|--previous ) pkill -$SPREV -u $(id -u) herrie$
+ ;;
+ * ) usage
+ ;;
+ esac
+else
+ usage
+fi
+
+exit
diff --git a/audio/herrie/patches/herrie-2.1-filters-orig.diff b/audio/herrie/patches/herrie-2.1-filters-orig.diff
new file mode 100644
index 0000000000000..c5aba0e08690b
--- /dev/null
+++ b/audio/herrie/patches/herrie-2.1-filters-orig.diff
@@ -0,0 +1,221 @@
+diff -ru herrie-2.1-orig/herrie-2.1/src/config.c herrie-2.1-filters-orig/herrie-2.1/src/config.c
+--- herrie-2.1-orig/herrie-2.1/src/config.c 2008-07-15 10:59:07.000000000 -0500
++++ herrie-2.1-filters-orig/herrie-2.1/src/config.c 2008-07-18 09:51:35.000000000 -0500
+@@ -171,6 +171,8 @@
+ { "scrobbler.username", "", NULL, NULL },
+ #endif /* BUILD_SCROBBLER */
+ { "vfs.dir.hide_dotfiles", "yes", valid_bool, NULL },
++ { "vfs.dir.hide_extfiles", "no", valid_bool, NULL },
++ { "vfs.ext.whitelist", "mp3 wav ogg", NULL, NULL },
+ #ifdef G_OS_UNIX
+ { "vfs.lockup.chroot", "", NULL, NULL },
+ { "vfs.lockup.user", "", NULL, NULL },
+diff -ru herrie-2.1-orig/herrie-2.1/src/playq.c herrie-2.1-filters-orig/herrie-2.1/src/playq.c
+--- herrie-2.1-orig/herrie-2.1/src/playq.c 2008-07-15 10:59:07.000000000 -0500
++++ herrie-2.1-filters-orig/herrie-2.1/src/playq.c 2008-07-18 10:16:04.000000000 -0500
+@@ -259,12 +259,20 @@
+ playq_repeat = 1;
+ }
+
++ /* Create and compile Whitelist regex */
++ vfs_create_whitelist(config_getopt("vfs.ext.whitelist"));
++
+ filename = config_getopt("playq.dumpfile");
+ if (load_dumpfile && filename[0] != '\0') {
+ /* Autoload playlist */
+ vr = vfs_lookup(filename, NULL, NULL, 0);
+ if (vr != NULL) {
+- vfs_unfold(&playq_list, vr);
++ if (config_getopt_bool("vfs.dir.hide_extfiles"))
++ vfs_unfold(&playq_list, vr, 1);
++ else {
++ /* Don't filter out files at this time */
++ vfs_unfold(&playq_list, vr, 0);
++ }
+ vfs_close(vr);
+ }
+ }
+@@ -313,7 +321,7 @@
+ struct vfslist newlist = VFSLIST_INITIALIZER;
+
+ /* Recursively expand the item */
+- vfs_unfold(&newlist, vr);
++ vfs_unfold(&newlist, vr, 1);
+ if (vfs_list_empty(&newlist))
+ return;
+
+@@ -336,7 +344,7 @@
+ struct vfslist newlist = VFSLIST_INITIALIZER;
+
+ /* Recursively expand the item */
+- vfs_unfold(&newlist, vr);
++ vfs_unfold(&newlist, vr, 1);
+ if (vfs_list_empty(&newlist))
+ return;
+
+@@ -446,7 +454,7 @@
+ struct vfslist newlist = VFSLIST_INITIALIZER;
+
+ /* Recursively expand the item */
+- vfs_unfold(&newlist, nvr);
++ vfs_unfold(&newlist, nvr, 1);
+ if (vfs_list_empty(&newlist))
+ return;
+
+@@ -468,7 +476,7 @@
+ struct vfslist newlist = VFSLIST_INITIALIZER;
+
+ /* Recursively expand the item */
+- vfs_unfold(&newlist, nvr);
++ vfs_unfold(&newlist, nvr, 1);
+ if (vfs_list_empty(&newlist))
+ return;
+
+diff -ru herrie-2.1-orig/herrie-2.1/src/vfs.c herrie-2.1-filters-orig/herrie-2.1/src/vfs.c
+--- herrie-2.1-orig/herrie-2.1/src/vfs.c 2008-07-15 10:59:07.000000000 -0500
++++ herrie-2.1-filters-orig/herrie-2.1/src/vfs.c 2008-07-18 10:10:18.000000000 -0500
+@@ -185,6 +185,11 @@
+ return g_string_free(npath, FALSE);
+ }
+
++struct vfsmatch * vfs_get_vm_whitelist()
++{
++ return vm_whitelist;
++}
++
+ const char *
+ vfs_lockup(void)
+ {
+@@ -245,6 +250,27 @@
+ g_slice_free(struct vfsent, ve);
+ }
+
++void
++vfs_create_whitelist(const char* whitelist)
++{
++ char res[128] = "";
++ char *expr = "|[.]";
++ strcat(res, "[.]");
++
++ int i,j;
++ for (i=0,j=strlen(res); i < strlen(whitelist); i++) {
++ if (whitelist[i] == ' ') {
++ strcat(res, expr);
++ j+=strlen(expr);
++ }
++ else
++ res[j++] = whitelist[i];
++ }
++ res[j] = '\0';
++
++ vm_whitelist = vfs_match_new(res);
++}
++
+ struct vfsref *
+ vfs_lookup(const char *filename, const char *name, const char *basepath,
+ int strict)
+@@ -363,7 +389,7 @@
+ }
+
+ void
+-vfs_unfold(struct vfslist *vl, const struct vfsref *vr)
++vfs_unfold(struct vfslist *vl, const struct vfsref *vr, int useWhiteList)
+ {
+ struct vfsref *cvr;
+
+@@ -374,8 +400,14 @@
+ /* See if we can recurse it */
+ vfs_populate(vr);
+ VFS_LIST_FOREACH(&vr->ent->population, cvr) {
+- if (cvr->ent->recurse)
+- vfs_unfold(vl, cvr);
++ if (cvr->ent->recurse) {
++ /* Ignore Whitelist if it is not valid
++ * Make sure directories aren't filtered
++ */
++ if (!useWhiteList || vm_whitelist == NULL || !vfs_playable(cvr) ||
++ vfs_match_compare(vm_whitelist, vfs_filename(cvr)))
++ vfs_unfold(vl, cvr, useWhiteList);
++ }
+ }
+ }
+ }
+diff -ru herrie-2.1-orig/herrie-2.1/src/vfs.h herrie-2.1-filters-orig/herrie-2.1/src/vfs.h
+--- herrie-2.1-orig/herrie-2.1/src/vfs.h 2008-07-15 10:59:07.000000000 -0500
++++ herrie-2.1-filters-orig/herrie-2.1/src/vfs.h 2008-07-18 09:59:21.000000000 -0500
+@@ -164,11 +164,21 @@
+ };
+
+ /**
++ * @brief The compiled regex for the whitelist
++ */
++static struct vfsmatch *vm_whitelist;
++
++/**
+ * @brief Contents of an empty VFS list structure.
+ */
+ #define VFSLIST_INITIALIZER { NULL, NULL, 0 }
+
+ /**
++ * @brief Returns the whitelist
++ */
++struct vfsmatch * vfs_get_vm_whitelist();
++
++/**
+ * @brief Run-time initialize a VFS list structure.
+ */
+ static inline void
+@@ -362,6 +372,14 @@
+ const char *vfs_lockup(void);
+
+ /**
++ * @brief Create the compiled regex for the whitelist.
++ * The input string should be formatted similar to
++ * "ext1 ext2 ext3" and this will be converted into a
++ * Regular Expr like "[.]ext1|[.]ext2|[.]ext3".
++ */
++void vfs_create_whitelist(const char* whitelist);
++
++/**
+ * @brief Create a VFS reference from a filename. The name argument is
+ * optional. It only allows you to display entities with a
+ * different name (inside playlists). When setting the basepath
+@@ -390,7 +408,7 @@
+ * @brief Recursively expand a VFS reference to all their usable
+ * children and append them to the specified list.
+ */
+-void vfs_unfold(struct vfslist *vl, const struct vfsref *vr);
++void vfs_unfold(struct vfslist *vl, const struct vfsref *vr, int useWhiteList);
+ /**
+ * @brief Recursively search through a VFS reference and add all
+ * matching objects to a list. The VFS reference itself will be
+diff -ru herrie-2.1-orig/herrie-2.1/src/vfs_regular.c herrie-2.1-filters-orig/herrie-2.1/src/vfs_regular.c
+--- herrie-2.1-orig/herrie-2.1/src/vfs_regular.c 2008-07-15 10:59:07.000000000 -0500
++++ herrie-2.1-filters-orig/herrie-2.1/src/vfs_regular.c 2008-07-18 10:03:06.000000000 -0500
+@@ -73,9 +73,13 @@
+ GDir *dir;
+ const char *sfn;
+ struct vfsref *nvr, *svr;
+- int hide_dotfiles;
++ struct vfsmatch *whitelist;
++ int hide_dotfiles, hide_extfiles;
+
+ hide_dotfiles = config_getopt_bool("vfs.dir.hide_dotfiles");
++ hide_extfiles = config_getopt_bool("vfs.dir.hide_extfiles");
++
++ whitelist = vfs_get_vm_whitelist();
+
+ if ((dir = g_dir_open(ve->filename, 0, NULL)) == NULL)
+ return (-1);
+@@ -88,6 +92,11 @@
+ if ((nvr = vfs_lookup(sfn, NULL, ve->filename, 1)) == NULL)
+ continue;
+
++ /* Hide files (not directories) that are not whitelisted */
++ if (hide_extfiles && whitelist != NULL && vfs_playable(nvr) &&
++ !vfs_match_compare(whitelist, vfs_filename(nvr)))
++ continue;
++
+ /*
+ * Add the items to the tailq in a sorted manner.
+ */
diff --git a/audio/herrie/patches/herrie-2.1-filters.diff b/audio/herrie/patches/herrie-2.1-filters.diff
new file mode 100644
index 0000000000000..36ef1fcc806f6
--- /dev/null
+++ b/audio/herrie/patches/herrie-2.1-filters.diff
@@ -0,0 +1,263 @@
+diff -ru herrie-2.1-autoquit/herrie-2.1/src/config.c herrie-2.1-filters/herrie-2.1/src/config.c
+--- herrie-2.1-autoquit/herrie-2.1/src/config.c 2008-07-18 10:40:34.000000000 -0500
++++ herrie-2.1-filters/herrie-2.1/src/config.c 2008-07-18 10:27:31.000000000 -0500
+@@ -172,6 +172,8 @@
+ { "scrobbler.username", "", NULL, NULL },
+ #endif /* BUILD_SCROBBLER */
+ { "vfs.dir.hide_dotfiles", "yes", valid_bool, NULL },
++ { "vfs.dir.hide_extfiles", "no", valid_bool, NULL },
++ { "vfs.ext.whitelist", "mp3 wav ogg", NULL, NULL },
+ #ifdef G_OS_UNIX
+ { "vfs.lockup.chroot", "", NULL, NULL },
+ { "vfs.lockup.user", "", NULL, NULL },
+diff -ru herrie-2.1-autoquit/herrie-2.1/src/playq.c herrie-2.1-filters/herrie-2.1/src/playq.c
+--- herrie-2.1-autoquit/herrie-2.1/src/playq.c 2008-07-18 10:40:34.000000000 -0500
++++ herrie-2.1-filters/herrie-2.1/src/playq.c 2008-07-18 10:53:53.000000000 -0500
+@@ -153,7 +153,7 @@
+ /**
+ * @brief If true, quit when end of list reached
+ */
+-int playq_autoquit = 0;
++int playq_autoquit = 0;
+
+ /**
+ * @brief Infinitely play music in the playlist, honouring the
+@@ -182,19 +182,19 @@
+
+ /* Try to start a new song when we're not stopped */
+ if (!(playq_flags & PF_STOP)) {
+- if ((nvr = funcs->give()) != NULL) {
+- /* We've got work to do */
+- break;
+- }
+- else {
+- if (playq_autoquit_ready && playq_autoquit) {
+- /* Time to quit - Send ourself the SIGTERM */
+- int res = getpid();
+- if (res !=0){
+- kill(res,SIGTERM);
+- }
+- }
+- }
++ if ((nvr = funcs->give()) != NULL) {
++ /* We've got work to do */
++ break;
++ }
++ else {
++ if (playq_autoquit_ready && playq_autoquit) {
++ /* Time to quit - Send ourself the SIGTERM */
++ int res = getpid();
++ if (res !=0){
++ kill(res,SIGTERM);
++ }
++ }
++ }
+ }
+
+ /* Wait for new events to occur */
+@@ -282,12 +282,20 @@
+ if (autoquit || config_getopt_bool("playq.autoquit"))
+ playq_autoquit = 1;
+
++ /* Create and compile Whitelist regex */
++ vfs_create_whitelist(config_getopt("vfs.ext.whitelist"));
++
+ filename = config_getopt("playq.dumpfile");
+ if (load_dumpfile && filename[0] != '\0') {
+ /* Autoload playlist */
+ vr = vfs_lookup(filename, NULL, NULL, 0);
+ if (vr != NULL) {
+- vfs_unfold(&playq_list, vr);
++ if (config_getopt_bool("vfs.dir.hide_extfiles"))
++ vfs_unfold(&playq_list, vr, 1);
++ else {
++ /* Don't filter out files at this time */
++ vfs_unfold(&playq_list, vr, 0);
++ }
+ vfs_close(vr);
+ }
+ }
+@@ -336,7 +344,7 @@
+ struct vfslist newlist = VFSLIST_INITIALIZER;
+
+ /* Recursively expand the item */
+- vfs_unfold(&newlist, vr);
++ vfs_unfold(&newlist, vr, 1);
+ if (vfs_list_empty(&newlist))
+ return;
+
+@@ -359,7 +367,7 @@
+ struct vfslist newlist = VFSLIST_INITIALIZER;
+
+ /* Recursively expand the item */
+- vfs_unfold(&newlist, vr);
++ vfs_unfold(&newlist, vr, 1);
+ if (vfs_list_empty(&newlist))
+ return;
+
+@@ -469,7 +477,7 @@
+ struct vfslist newlist = VFSLIST_INITIALIZER;
+
+ /* Recursively expand the item */
+- vfs_unfold(&newlist, nvr);
++ vfs_unfold(&newlist, nvr, 1);
+ if (vfs_list_empty(&newlist))
+ return;
+
+@@ -491,7 +499,7 @@
+ struct vfslist newlist = VFSLIST_INITIALIZER;
+
+ /* Recursively expand the item */
+- vfs_unfold(&newlist, nvr);
++ vfs_unfold(&newlist, nvr, 1);
+ if (vfs_list_empty(&newlist))
+ return;
+
+diff -ru herrie-2.1-autoquit/herrie-2.1/src/vfs.c herrie-2.1-filters/herrie-2.1/src/vfs.c
+--- herrie-2.1-autoquit/herrie-2.1/src/vfs.c 2008-07-15 10:59:07.000000000 -0500
++++ herrie-2.1-filters/herrie-2.1/src/vfs.c 2008-07-18 10:27:31.000000000 -0500
+@@ -185,6 +185,11 @@
+ return g_string_free(npath, FALSE);
+ }
+
++struct vfsmatch * vfs_get_vm_whitelist()
++{
++ return vm_whitelist;
++}
++
+ const char *
+ vfs_lockup(void)
+ {
+@@ -245,6 +250,27 @@
+ g_slice_free(struct vfsent, ve);
+ }
+
++void
++vfs_create_whitelist(const char* whitelist)
++{
++ char res[128] = "";
++ char *expr = "|[.]";
++ strcat(res, "[.]");
++
++ int i,j;
++ for (i=0,j=strlen(res); i < strlen(whitelist); i++) {
++ if (whitelist[i] == ' ') {
++ strcat(res, expr);
++ j+=strlen(expr);
++ }
++ else
++ res[j++] = whitelist[i];
++ }
++ res[j] = '\0';
++
++ vm_whitelist = vfs_match_new(res);
++}
++
+ struct vfsref *
+ vfs_lookup(const char *filename, const char *name, const char *basepath,
+ int strict)
+@@ -363,7 +389,7 @@
+ }
+
+ void
+-vfs_unfold(struct vfslist *vl, const struct vfsref *vr)
++vfs_unfold(struct vfslist *vl, const struct vfsref *vr, int useWhiteList)
+ {
+ struct vfsref *cvr;
+
+@@ -374,8 +400,14 @@
+ /* See if we can recurse it */
+ vfs_populate(vr);
+ VFS_LIST_FOREACH(&vr->ent->population, cvr) {
+- if (cvr->ent->recurse)
+- vfs_unfold(vl, cvr);
++ if (cvr->ent->recurse) {
++ /* Ignore Whitelist if it is not valid
++ * Make sure directories aren't filtered
++ */
++ if (!useWhiteList || vm_whitelist == NULL || !vfs_playable(cvr) ||
++ vfs_match_compare(vm_whitelist, vfs_filename(cvr)))
++ vfs_unfold(vl, cvr, useWhiteList);
++ }
+ }
+ }
+ }
+diff -ru herrie-2.1-autoquit/herrie-2.1/src/vfs.h herrie-2.1-filters/herrie-2.1/src/vfs.h
+--- herrie-2.1-autoquit/herrie-2.1/src/vfs.h 2008-07-15 10:59:07.000000000 -0500
++++ herrie-2.1-filters/herrie-2.1/src/vfs.h 2008-07-18 10:27:31.000000000 -0500
+@@ -164,11 +164,21 @@
+ };
+
+ /**
++ * @brief The compiled regex for the whitelist
++ */
++static struct vfsmatch *vm_whitelist;
++
++/**
+ * @brief Contents of an empty VFS list structure.
+ */
+ #define VFSLIST_INITIALIZER { NULL, NULL, 0 }
+
+ /**
++ * @brief Returns the whitelist
++ */
++struct vfsmatch * vfs_get_vm_whitelist();
++
++/**
+ * @brief Run-time initialize a VFS list structure.
+ */
+ static inline void
+@@ -362,6 +372,14 @@
+ const char *vfs_lockup(void);
+
+ /**
++ * @brief Create the compiled regex for the whitelist.
++ * The input string should be formatted similar to
++ * "ext1 ext2 ext3" and this will be converted into a
++ * Regular Expr like "[.]ext1|[.]ext2|[.]ext3".
++ */
++void vfs_create_whitelist(const char* whitelist);
++
++/**
+ * @brief Create a VFS reference from a filename. The name argument is
+ * optional. It only allows you to display entities with a
+ * different name (inside playlists). When setting the basepath
+@@ -390,7 +408,7 @@
+ * @brief Recursively expand a VFS reference to all their usable
+ * children and append them to the specified list.
+ */
+-void vfs_unfold(struct vfslist *vl, const struct vfsref *vr);
++void vfs_unfold(struct vfslist *vl, const struct vfsref *vr, int useWhiteList);
+ /**
+ * @brief Recursively search through a VFS reference and add all
+ * matching objects to a list. The VFS reference itself will be
+diff -ru herrie-2.1-autoquit/herrie-2.1/src/vfs_regular.c herrie-2.1-filters/herrie-2.1/src/vfs_regular.c
+--- herrie-2.1-autoquit/herrie-2.1/src/vfs_regular.c 2008-07-15 10:59:07.000000000 -0500
++++ herrie-2.1-filters/herrie-2.1/src/vfs_regular.c 2008-07-18 10:27:31.000000000 -0500
+@@ -73,9 +73,13 @@
+ GDir *dir;
+ const char *sfn;
+ struct vfsref *nvr, *svr;
+- int hide_dotfiles;
++ struct vfsmatch *whitelist;
++ int hide_dotfiles, hide_extfiles;
+
+ hide_dotfiles = config_getopt_bool("vfs.dir.hide_dotfiles");
++ hide_extfiles = config_getopt_bool("vfs.dir.hide_extfiles");
++
++ whitelist = vfs_get_vm_whitelist();
+
+ if ((dir = g_dir_open(ve->filename, 0, NULL)) == NULL)
+ return (-1);
+@@ -88,6 +92,11 @@
+ if ((nvr = vfs_lookup(sfn, NULL, ve->filename, 1)) == NULL)
+ continue;
+
++ /* Hide files (not directories) that are not whitelisted */
++ if (hide_extfiles && whitelist != NULL && vfs_playable(nvr) &&
++ !vfs_match_compare(whitelist, vfs_filename(nvr)))
++ continue;
++
+ /*
+ * Add the items to the tailq in a sorted manner.
+ */
diff --git a/audio/herrie/patches/herrie-2.1-signals.diff b/audio/herrie/patches/herrie-2.1-signals.diff
new file mode 100644
index 0000000000000..b1a39bea1d716
--- /dev/null
+++ b/audio/herrie/patches/herrie-2.1-signals.diff
@@ -0,0 +1,67 @@
+diff -ru herrie-2.1-orig/herrie-2.1/src/gui_input.c herrie-2.1-signals/herrie-2.1/src/gui_input.c
+--- herrie-2.1-orig/herrie-2.1/src/gui_input.c 2008-07-15 10:59:07.000000000 -0500
++++ herrie-2.1-signals/herrie-2.1/src/gui_input.c 2008-07-18 09:44:41.000000000 -0500
+@@ -521,6 +521,9 @@
+ sigset_t sset;
+
+ sigemptyset(&sset);
++ sigaddset(&sset, SIGRTMIN+1);
++ sigaddset(&sset, SIGRTMIN+2);
++ sigaddset(&sset, SIGRTMIN+3);
+ sigaddset(&sset, SIGUSR1);
+ sigaddset(&sset, SIGUSR2);
+ sigaddset(&sset, SIGHUP);
+@@ -545,20 +548,29 @@
+ if (shutting_down)
+ return;
+
+- switch (signal) {
+- case SIGUSR1:
+- playq_cursong_pause();
+- break;
+- case SIGUSR2:
+- playq_cursong_next();
+- break;
+- case SIGHUP:
+- case SIGINT:
+- case SIGPIPE:
+- case SIGQUIT:
+- case SIGTERM:
+- gui_input_quit();
+- g_assert_not_reached();
++ if (signal == (SIGRTMIN+1)) { gui_playq_song_select(); }
++ else {
++ if (signal == (SIGRTMIN+2)) { playq_cursong_stop(); }
++ else {
++ if (signal == (SIGRTMIN+3)) { playq_cursong_prev(); }
++ else {
++ switch (signal) {
++ case SIGUSR1:
++ playq_cursong_pause();
++ break;
++ case SIGUSR2:
++ playq_cursong_next();
++ break;
++ case SIGHUP:
++ case SIGINT:
++ case SIGPIPE:
++ case SIGQUIT:
++ case SIGTERM:
++ gui_input_quit();
++ g_assert_not_reached();
++ }
++ }
++ }
+ }
+ }
+ #endif /* G_OS_UNIX */
+@@ -570,6 +582,9 @@
+ unsigned int i;
+
+ #ifdef G_OS_UNIX
++ signal(SIGRTMIN+1, gui_input_sighandler);
++ signal(SIGRTMIN+2, gui_input_sighandler);
++ signal(SIGRTMIN+3, gui_input_sighandler);
+ signal(SIGUSR1, gui_input_sighandler);
+ signal(SIGUSR2, gui_input_sighandler);
+ signal(SIGHUP, gui_input_sighandler);
diff --git a/audio/herrie/patches/herrie-autoquit.diff b/audio/herrie/patches/herrie-autoquit.diff
new file mode 100644
index 0000000000000..d2f01b60dbe22
--- /dev/null
+++ b/audio/herrie/patches/herrie-autoquit.diff
@@ -0,0 +1,187 @@
+diff -ru herrie-autoplay/herrie-2.0.2/src/config.c herrie-autoquit/herrie-2.0.2/src/config.c
+--- herrie-autoplay/herrie-2.0.2/src/config.c 2008-05-16 20:49:55.000000000 -0500
++++ herrie-autoquit/herrie-2.0.2/src/config.c 2008-05-16 02:31:56.000000000 -0500
+@@ -163,6 +163,7 @@
+ { "gui.input.may_quit", "yes", valid_bool, NULL },
+ { "gui.vfslist.scrollpages", "no", valid_bool, NULL },
+ { "playq.autoplay", "no", valid_bool, NULL },
++ { "playq.autoquit", "no", valid_bool, NULL },
+ { "playq.dumpfile", CONFHOMEDIR PLAYQ_DUMPFILE, NULL, NULL },
+ { "playq.xmms", "no", valid_bool, NULL },
+ #ifdef BUILD_SCROBBLER
+diff -ru herrie-autoplay/herrie-2.0.2/src/main.c herrie-autoquit/herrie-2.0.2/src/main.c
+--- herrie-autoplay/herrie-2.0.2/src/main.c 2008-05-16 20:49:55.000000000 -0500
++++ herrie-autoquit/herrie-2.0.2/src/main.c 2008-05-16 02:33:37.000000000 -0500
+@@ -99,7 +99,7 @@
+ static void
+ usage(void)
+ {
+- g_printerr("%s: " APP_NAME " [-pvx] [-c configfile] "
++ g_printerr("%s: " APP_NAME " [-pqvx] [-c configfile] "
+ "[file ...]\n", _("usage"));
+ exit(1);
+ }
+@@ -110,7 +110,7 @@
+ int
+ main(int argc, char *argv[])
+ {
+- int ch, i, show_version = 0, autoplay = 0, xmms = 0;
++ int ch, i, show_version = 0, autoplay = 0, autoquit = 0, xmms = 0;
+ char *cwd;
+ const char *errmsg;
+ struct vfsref *vr;
+@@ -128,7 +128,7 @@
+ config_load(CONFFILE, 1);
+ config_load(CONFHOMEDIR "config", 1);
+
+- while ((ch = getopt(argc, argv, "c:pvx")) != -1) {
++ while ((ch = getopt(argc, argv, "c:pqvx")) != -1) {
+ switch (ch) {
+ case 'c':
+ config_load(optarg, 0);
+@@ -136,6 +136,9 @@
+ case 'p':
+ autoplay = 1;
+ break;
++ case 'q':
++ autoquit = 1;
++ break;
+ case 'v':
+ show_version = 1;
+ break;
+@@ -173,7 +176,7 @@
+ #ifdef BUILD_SCROBBLER
+ scrobbler_init();
+ #endif /* BUILD_SCROBBLER */
+- playq_init(autoplay, xmms, (argc == 0));
++ playq_init(autoplay, autoquit, xmms, (argc == 0));
+
+ /* Draw all the windows */
+ gui_draw_init_post();
+diff -ru herrie-autoplay/herrie-2.0.2/src/playq.c herrie-autoquit/herrie-2.0.2/src/playq.c
+--- herrie-autoplay/herrie-2.0.2/src/playq.c 2008-05-16 20:49:55.000000000 -0500
++++ herrie-autoquit/herrie-2.0.2/src/playq.c 2008-05-25 00:25:02.000000000 -0500
+@@ -151,6 +151,11 @@
+ static volatile int playq_seek_time;
+
+ /**
++ * @brief If true, quit when end of list reached
++ */
++int playq_autoquit = 0;
++
++/**
+ * @brief Infinitely play music in the playlist, honouring the
+ * playq_flags.
+ */
+@@ -163,6 +168,8 @@
+
+ gui_input_sigmask();
+
++ /* Used to prevent autoquit occuring at startup when autoplay is enabled on an empty list */
++ int playq_autoquit_ready = 0;
+ do {
+ /* Wait until there's a song available */
+ playq_lock();
+@@ -174,10 +181,20 @@
+ }
+
+ /* Try to start a new song when we're not stopped */
+- if (!(playq_flags & PF_STOP) &&
+- (nvr = funcs->give()) != NULL) {
++ if (!(playq_flags & PF_STOP)) {
++ if ((nvr = funcs->give()) != NULL) {
+ /* We've got work to do */
+ break;
++ }
++ else {
++ if (playq_autoquit_ready && playq_autoquit) {
++ /* Time to quit - Send ourself the SIGTERM */
++ int res = getpid();
++ if (res !=0){
++ kill(res,SIGTERM);
++ }
++ }
++ }
+ }
+
+ /* Wait for new events to occur */
+@@ -188,6 +205,9 @@
+ }
+ playq_unlock();
+
++ /* Safe to autoquit now */
++ playq_autoquit_ready = 1;
++
+ cur = audio_file_open(nvr);
+ if (cur == NULL) {
+ /* Skip broken songs */
+@@ -242,7 +262,7 @@
+ }
+
+ void
+-playq_init(int autoplay, int xmms, int load_dumpfile)
++playq_init(int autoplay, int autoquit, int xmms, int load_dumpfile)
+ {
+ const char *filename;
+ struct vfsref *vr;
+@@ -259,6 +279,9 @@
+ playq_repeat = 1;
+ }
+
++ if (autoquit || config_getopt_bool("playq.autoquit"))
++ playq_autoquit = 1;
++
+ filename = config_getopt("playq.dumpfile");
+ if (load_dumpfile && filename[0] != '\0') {
+ /* Autoload playlist */
+diff -ru herrie-autoplay/herrie-2.0.2/src/playq.h herrie-autoquit/herrie-2.0.2/src/playq.h
+--- herrie-autoplay/herrie-2.0.2/src/playq.h 2008-05-16 20:49:55.000000000 -0500
++++ herrie-autoquit/herrie-2.0.2/src/playq.h 2008-05-16 02:38:12.000000000 -0500
+@@ -33,7 +33,7 @@
+ /**
+ * @brief Initialize the playlist locking.
+ */
+-void playq_init(int autoplay, int xmms, int load_dumpfile);
++void playq_init(int autoplay, int autoquit, int xmms, int load_dumpfile);
+ /**
+ * @brief Spawn the playback thread.
+ */
+diff -ru herrie-autoplay/herrie-2.0.2/src/playq_modules.h herrie-autoquit/herrie-2.0.2/src/playq_modules.h
+--- herrie-autoplay/herrie-2.0.2/src/playq_modules.h 2008-04-23 14:29:24.000000000 -0500
++++ herrie-autoquit/herrie-2.0.2/src/playq_modules.h 2008-05-16 03:01:29.000000000 -0500
+@@ -36,6 +36,11 @@
+ extern int playq_repeat;
+
+ /**
++ * @brief Flag whether autoquit is turned on by the user.
++ */
++extern int playq_autoquit;
++
++/**
+ * @brief Herrie's routine to fetch the next song from the playlist
+ * (always the first song).
+ */
+diff -ru herrie-autoplay/herrie-2.0.2/src/playq_party.c herrie-autoquit/herrie-2.0.2/src/playq_party.c
+--- herrie-autoplay/herrie-2.0.2/src/playq_party.c 2008-04-23 14:29:24.000000000 -0500
++++ herrie-autoquit/herrie-2.0.2/src/playq_party.c 2008-05-16 03:57:41.000000000 -0500
+@@ -49,7 +49,7 @@
+ nvr = vfs_dup(vr);
+ gui_playq_notify_pre_removal(1);
+ vfs_list_remove(&playq_list, vr);
+- if (playq_repeat) {
++ if (playq_repeat && !playq_autoquit) {
+ /* Add it back to the tail */
+ vfs_list_insert_tail(&playq_list, vr);
+ gui_playq_notify_post_insertion(vfs_list_items(&playq_list));
+diff -ru herrie-autoplay/herrie-2.0.2/src/playq_xmms.c herrie-autoquit/herrie-2.0.2/src/playq_xmms.c
+--- herrie-autoplay/herrie-2.0.2/src/playq_xmms.c 2008-05-16 20:49:55.000000000 -0500
++++ herrie-autoquit/herrie-2.0.2/src/playq_xmms.c 2008-05-16 02:50:17.000000000 -0500
+@@ -61,7 +61,7 @@
+ /* Song after current song */
+ cursong = vfs_list_next(cursong);
+ /* We've reached the end */
+- if (cursong == NULL && playq_repeat)
++ if (cursong == NULL && playq_repeat && !playq_autoquit)
+ cursong = vfs_list_first(&playq_list);
+ } else {
+ cursong = vfs_list_first(&playq_list);
diff --git a/multimedia/herrie/slack-desc b/audio/herrie/slack-desc
index 5d1bcbcc7968a..5d1bcbcc7968a 100644
--- a/multimedia/herrie/slack-desc
+++ b/audio/herrie/slack-desc
diff --git a/multimedia/herrie/README b/multimedia/herrie/README
deleted file mode 100644
index cddfa88e5fe0d..0000000000000
--- a/multimedia/herrie/README
+++ /dev/null
@@ -1,20 +0,0 @@
-Herrie - interactive music playlist player
-
-Herrie is a minimalistic music player that uses the command line. It is written
-to support a variety of audio subsystems and file formats, including playlists.
-
-Herrie has a split-screen user interface, with a playlist at the top of the
-screen and a file browser at the bottom. Herrie supports XMMS shortcuts for
-playback control and can play in XMMS mode or "party" mode (which acts as a
-song queue).
-
-Herrie also has some more exotic features, including support for AudioScrobbler
-and the ability to chroot() itself into a directory. The default options for
-this Slackbuild are set for no scrobbler, http, nls, modplugin, wave, or XSPF
-support. ALSA is the chosen sound output and Ncurses (NOT Ncursesw) is the chosen
-'gui'. This makes it so the program can be built with the least amount of
-dependencies (with these options all of them should be included in
-Slackware 12). See the README in the herrie source for the dependencies
-needed if you enable these other options.
-
-Also see README.SBo for useage and configuration help. \ No newline at end of file
diff --git a/multimedia/herrie/README.SBo b/multimedia/herrie/README.SBo
deleted file mode 100644
index c5a9bca7a47c9..0000000000000
--- a/multimedia/herrie/README.SBo
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-** The Config file **
-The global config file is by default at /etc/herrie.conf.
-User-specific settings can be set by creating a config file at ~/.herrie/config.
-The '-c' argument allows you to specify a different config file other than
-these defaults. Please note that config settings are overidden on a per setting
-basis. For instance, if gui.browser.defaultpath is specified in /etc/herrie.conf,
-but it is not specified in ~/.herrie/config then the setting in /etc/herrie.conf
-will be used. The other settings that are in ~/.herrie/config would still be used.
-
-
-** Chroot Mode **
-Be sure that the user you use for vfs.lockup.user is the OWNER of the folder used
-for vfs.lockup.chroot. For some reason it is not enough to have read permissions
-through a group. Also, note that other settings that use paths, such as
-gui.browser.defaultpath and playq.dumpfile will use the chrooted path. You might
-need to create a .herrie folder under your chrooted folder in order to be able to
-automatically save your playlists.
-
-Also, herrie will not work properly when using AO in chroot mode!
-ALSA is now the default sound system used because of this.
-
-Here is an example config file for using herrie in chroot mode:
-# Herrie Config file for chrooted herrie
-gui.browser.defaultpath=/
-vfs.lockup.chroot=/mnt/MEDIA/MyMusic
-vfs.lockup.user=USERNAME
-playq.dumpfile=/.herrie/autosave.pls
-
-
-** Using AO **
-If AO is chosen as the sound output an option can be specified in the
-config file.
-
-Config Examples of Using AO:
-# Useful for KDE users
-audio.output.ao.driver=arts
-
-# For sending sound output to a remote SSH session
-audio.output.ao.driver=esd
-audio.output.ao.host=env_ssh
-
-
-** For More Information... **
-Please refer to the man page for the keyboard control bindings
-and for more config options. An online version of the man page
-can be found at http://herrie.info/herrie.1
diff --git a/multimedia/herrie/herrie.info b/multimedia/herrie/herrie.info
deleted file mode 100644
index 3c043fde1014a..0000000000000
--- a/multimedia/herrie/herrie.info
+++ /dev/null
@@ -1,8 +0,0 @@
-PRGNAM="herrie"
-VERSION="2.0"
-HOMEPAGE="http://herrie.info/"
-DOWNLOAD="http://herrie.info/distfiles/herrie-2.0.tar.bz2"
-MD5SUM="22bf3bf61f651956efc25ecceb761e70"
-MAINTAINER="Phil Warner"
-EMAIL="pc_warner@yahoo.com"
-APPROVED="David Somero"