summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeruspe <Marc-Antoine@Perennou.com>2009-12-25 19:45:42 +0100
committerKeruspe <Marc-Antoine@Perennou.com>2009-12-25 19:45:42 +0100
commit38772ee6a2584cb681c5370983db840022e8806a (patch)
treecbf30cbaff75673613c48a5356e168e713ff7ac2
downloadkeruspe-38772ee6a2584cb681c5370983db840022e8806a.tar.gz
keruspe-38772ee6a2584cb681c5370983db840022e8806a.tar.bz2
keruspe-38772ee6a2584cb681c5370983db840022e8806a.zip
svn -> git + clean
-rw-r--r--app-admin/gnome-system-tools/gnome-system-tools-2.29.1.ebuild55
-rw-r--r--app-admin/paludis-scripts/paludis-scripts-scm.ebuild33
-rw-r--r--app-emulation/wine/files/wine-1.1.15-winegcc.patch55
-rw-r--r--app-emulation/wine/files/winepulse-0.32-configure.ac.patch58
-rw-r--r--app-emulation/wine/files/winepulse-0.33.patch2673
-rw-r--r--app-emulation/wine/files/winepulse-winecfg-0.6.patch313
-rw-r--r--app-emulation/wine/wine-1.1.34.ebuild177
-rw-r--r--app-misc/klavaro/klavaro-1.4.0.ebuild28
-rw-r--r--app-office/abiword/abiword-2.8.1.ebuild92
-rw-r--r--app-paludis/plop/Manifest8
-rw-r--r--app-paludis/plop/files/plop-0.2.3_0.30.8.patch312
-rw-r--r--app-paludis/plop/files/plop.bash-completion60
-rw-r--r--app-paludis/plop/plop-0.2.3.ebuild51
-rw-r--r--app-text/asciidoc/asciidoc-8.5.1.ebuild61
-rw-r--r--dev-libs/liboobs/liboobs-2.29.1.ebuild35
-rw-r--r--eclass/gnome2-la.eclass33
-rw-r--r--eclass/scm-git.eclass186
-rw-r--r--eclass/scm.eclass349
-rw-r--r--gnome-extra/gnome-globalmenu/gnome-globalmenu-9999.ebuild62
-rw-r--r--media-libs/libchamplain/libchamplain-0.4.2-r1.ebuild51
-rw-r--r--net-im/empathy/empathy-2.29.4.ebuild107
-rw-r--r--net-libs/gnutls/gnutls-2.8.5.ebuild98
-rw-r--r--net-libs/telepathy-glib/telepathy-glib-0.9.1.ebuild41
-rw-r--r--net-misc/networkmanager-openconnect/networkmanager-openconnect-0.7.2.ebuild50
-rw-r--r--net-voip/telepathy-salut/telepathy-salut-0.3.10.ebuild45
-rw-r--r--net-wireless/blueproximity/blueproximity-1.2.5.ebuild29
-rw-r--r--profiles/categories18
-rw-r--r--profiles/package.mask1
-rw-r--r--profiles/repo_name1
-rw-r--r--sys-boot/grub/files/grub-1.96-genkernel.patch11
-rw-r--r--sys-boot/grub/grub-1.97.1.ebuild104
-rw-r--r--x11-misc/notify-osd/notify-osd-0.9.24.ebuild33
-rw-r--r--x11-misc/rss-glx/rss-glx-0.9.0.ebuild120
-rw-r--r--x11-terms/terminator/terminator-0.14-r1.ebuild23
34 files changed, 5373 insertions, 0 deletions
diff --git a/app-admin/gnome-system-tools/gnome-system-tools-2.29.1.ebuild b/app-admin/gnome-system-tools/gnome-system-tools-2.29.1.ebuild
new file mode 100644
index 00000000..b06851d3
--- /dev/null
+++ b/app-admin/gnome-system-tools/gnome-system-tools-2.29.1.ebuild
@@ -0,0 +1,55 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+inherit autotools eutils gnome2
+
+DESCRIPTION="Tools aimed to make easy the administration of UNIX systems"
+HOMEPAGE="http://www.gnome.org/projects/gst/"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="nfs policykit samba"
+
+RDEPEND="
+ >=dev-libs/liboobs-2.29.1
+ >=x11-libs/gtk+-2.11.3
+ >=dev-libs/glib-2.15.2
+ >=gnome-base/gconf-2.2
+ dev-libs/dbus-glib
+ >=gnome-base/nautilus-2.9.90
+ sys-libs/cracklib
+ nfs? ( net-fs/nfs-utils )
+ samba? ( >=net-fs/samba-3 )
+ policykit? ( >=sys-auth/policykit-0.5 )"
+
+DEPEND="${RDEPEND}
+ >=app-admin/system-tools-backends-2.8.2
+ app-text/scrollkeeper
+ >=app-text/gnome-doc-utils-0.3.2
+ dev-util/pkgconfig
+ >=dev-util/intltool-0.35.0"
+
+DOCS="AUTHORS BUGS ChangeLog HACKING NEWS README TODO"
+
+pkg_setup() {
+ G2CONF="${G2CONF}
+ --disable-static
+ $(use_enable policykit polkit)"
+
+ if ! use nfs && ! use samba; then
+ G2CONF="${G2CONF} --disable-shares"
+ fi
+
+ if use policykit && ! built_with_use app-admin/system-tools-backends policykit; then
+ eerror "app-admin/system-tools-backends was not built with USE='policykit'"
+ die "Please rebuild app-admin/system-tools-backends with policykit support"
+ fi
+}
+
+src_unpack() {
+ gnome2_src_unpack
+ eautoreconf
+}
diff --git a/app-admin/paludis-scripts/paludis-scripts-scm.ebuild b/app-admin/paludis-scripts/paludis-scripts-scm.ebuild
new file mode 100644
index 00000000..fba8f4d4
--- /dev/null
+++ b/app-admin/paludis-scripts/paludis-scripts-scm.ebuild
@@ -0,0 +1,33 @@
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI="paludis-1"
+
+SCM_REPOSITORY="git://git.pioto.org/paludis-scripts.git"
+SCM_CHECKOUT_TO="${DISTDIR}/git-src/paludis-scripts"
+inherit scm-git
+
+DESCRIPTION="Scripts for paludis, the other package mangler"
+HOMEPAGE="http://paludis.pioto.org/"
+SRC_URI=""
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~alpha ~amd64 ~hppa ~ppc ~sparc ~x86"
+IUSE=""
+
+DEPEND=""
+RDEPEND="sys-apps/paludis[ruby-bindings]"
+
+src_unpack() {
+ scm_src_unpack
+}
+
+src_install() {
+ cd ${S}
+ insinto /usr/share/paludis/hooks/demos
+ doins *.hook
+ exeinto /opt/sbin
+ doexe `find . -maxdepth 1 -type f ! -name *.hook`
+}
diff --git a/app-emulation/wine/files/wine-1.1.15-winegcc.patch b/app-emulation/wine/files/wine-1.1.15-winegcc.patch
new file mode 100644
index 00000000..6e5bb22a
--- /dev/null
+++ b/app-emulation/wine/files/wine-1.1.15-winegcc.patch
@@ -0,0 +1,55 @@
+http://bugs.gentoo.org/260726
+
+--- wine-1.1.15/tools/winegcc/winegcc.c
++++ wine-1.1.15/tools/winegcc/winegcc.c
+@@ -215,10 +215,13 @@
+ strarray* files;
+ };
+
++#undef FORCE_POINTER_SIZE
+ #ifdef __i386__
+ static const enum target_cpu build_cpu = CPU_x86;
++#define FORCE_POINTER_SIZE
+ #elif defined(__x86_64__)
+ static const enum target_cpu build_cpu = CPU_x86_64;
++#define FORCE_POINTER_SIZE
+ #elif defined(__sparc__)
+ static const enum target_cpu build_cpu = CPU_SPARC;
+ #elif defined(__ALPHA__)
+@@ -968,6 +971,9 @@
+ opts.linker_args = strarray_alloc();
+ opts.compiler_args = strarray_alloc();
+ opts.winebuild_args = strarray_alloc();
++#ifdef FORCE_POINTER_SIZE
++ opts.force_pointer_size = sizeof(size_t);
++#endif
+
+ /* determine the processor type */
+ if (strendswith(argv[0], "winecpp")) opts.processor = proc_cpp;
+--- wine-1.1.15/tools/winebuild/main.c
++++ wine-1.1.15/tools/winebuild/main.c
+@@ -50,10 +50,13 @@
+ int link_ext_symbols = 0;
+ int force_pointer_size = 0;
+
++#undef FORCE_POINTER_SIZE
+ #ifdef __i386__
+ enum target_cpu target_cpu = CPU_x86;
++#define FORCE_POINTER_SIZE
+ #elif defined(__x86_64__)
+ enum target_cpu target_cpu = CPU_x86_64;
++#define FORCE_POINTER_SIZE
+ #elif defined(__sparc__)
+ enum target_cpu target_cpu = CPU_SPARC;
+ #elif defined(__ALPHA__)
+@@ -574,6 +577,10 @@
+ signal( SIGTERM, exit_on_signal );
+ signal( SIGINT, exit_on_signal );
+
++#ifdef FORCE_POINTER_SIZE
++ force_pointer_size = sizeof(size_t);
++#endif
++
+ output_file = stdout;
+ argv = parse_options( argc, argv, spec );
+
diff --git a/app-emulation/wine/files/winepulse-0.32-configure.ac.patch b/app-emulation/wine/files/winepulse-0.32-configure.ac.patch
new file mode 100644
index 00000000..1db339ef
--- /dev/null
+++ b/app-emulation/wine/files/winepulse-0.32-configure.ac.patch
@@ -0,0 +1,58 @@
+diff --git a/configure.ac b/configure.ac
+index 0cc339b..3f34f12 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -64,6 +64,7 @@ AC_ARG_WITH(png, AS_HELP_STRING([--without-png],[do not use PNG]),
+ [if test "x$withval" = "xno"; then ac_cv_header_png_h=no; fi])
+ AC_ARG_WITH(pthread, AS_HELP_STRING([--without-pthread],[do not use the pthread library]),
+ [if test "x$withval" = "xno"; then ac_cv_header_pthread_h=no; fi])
++AC_ARG_WITH(pulse, AC_HELP_STRING([--without-pulse],[do not use PulseAudio sound support]))
+ AC_ARG_WITH(sane, AS_HELP_STRING([--without-sane],[do not use SANE (scanner support)]))
+ AC_ARG_WITH(xcomposite,AS_HELP_STRING([--without-xcomposite],[do not use the Xcomposite extension]),
+ [if test "x$withval" = "xno"; then ac_cv_header_X11_extensions_Xcomposite_h=no; fi])
+@@ -1297,6 +1298,28 @@ then
+ CFLAGS="$save_CFLAGS"
+ fi
+
++dnl **** Check for PulseAudio ****
++if test "x$with_pulse" != "xno"; then
++ if test "$PKG_CONFIG" != "false"; then
++ AC_MSG_CHECKING([for pulseaudio >= 0.9.14])
++ if "$PKG_CONFIG" --atleast-version=0.9.14 libpulse; then
++ have_pulseaudio="yes"
++ else
++ have_pulseaudio="no"
++ fi
++ AC_MSG_RESULT([$have_pulseaudio])
++ if test x"$have_pulseaudio" = xyes; then
++ ac_pulse_libs=`$PKG_CONFIG --libs libpulse`
++ AC_DEFINE([HAVE_PULSEAUDIO], 1, [define this if you have pulseaudio])
++ AC_SUBST(PULSELIBS, "$ac_pulse_libs")
++ else
++ dnl This warning should be removed if ever commited.
++ dnl Only useful to show that the problem wasn't the patch.
++ WINE_WARNING([libpulse not found or too old. Pulseaudio support will NOT be built.])
++ fi
++ fi
++fi
++
+ dnl **** Check for ALSA 1.x ****
+ AC_SUBST(ALSALIBS,"")
+ if test "$ac_cv_header_sys_asoundlib_h" = "yes" -o "$ac_cv_header_alsa_asoundlib_h" = "yes"
+@@ -1449,7 +1472,7 @@ dnl **** Check for libodbc ****
+ WINE_CHECK_SONAME(odbc,SQLConnect,,[AC_DEFINE_UNQUOTED(SONAME_LIBODBC,["libodbc.$LIBEXT"])])
+
+ dnl **** Check for any sound system ****
+-if test "x$ALSALIBS$AUDIOIOLIBS$COREAUDIO$NASLIBS$ESDLIBS$ac_cv_lib_soname_jack" = "x" -a \
++if test "x$ALSALIBS$AUDIOIOLIBS$COREAUDIO$NASLIBS$ESDLIBS$PULSELIBS$ac_cv_lib_soname_jack" = "x" -a \
+ "$ac_cv_header_sys_soundcard_h" != "yes" -a \
+ "$ac_cv_header_machine_soundcard_h" != "yes" -a \
+ "$ac_cv_header_soundcard_h" != "yes" -a \
+@@ -2509,6 +2532,7 @@ WINE_CONFIG_MAKEFILE([dlls/winenas.drv/Makefile],[dlls/Makedll.rules],[dlls],[AL
+ WINE_CONFIG_MAKEFILE([dlls/wineoss.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
+ WINE_CONFIG_MAKEFILE([dlls/wineps.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
+ WINE_CONFIG_MAKEFILE([dlls/wineps16.drv16/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS],[enable_win16])
++WINE_CONFIG_MAKEFILE([dlls/winepulse.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
+ WINE_CONFIG_MAKEFILE([dlls/winequartz.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
+ WINE_CONFIG_MAKEFILE([dlls/winex11.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
+ WINE_CONFIG_MAKEFILE([dlls/wing.dll16/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS],[enable_win16])
diff --git a/app-emulation/wine/files/winepulse-0.33.patch b/app-emulation/wine/files/winepulse-0.33.patch
new file mode 100644
index 00000000..beee1061
--- /dev/null
+++ b/app-emulation/wine/files/winepulse-0.33.patch
@@ -0,0 +1,2673 @@
+diff --git a/dlls/winepulse.drv/Makefile.in b/dlls/winepulse.drv/Makefile.in
+new file mode 100644
+index 0000000..c99c1da
+--- /dev/null
++++ b/dlls/winepulse.drv/Makefile.in
+@@ -0,0 +1,15 @@
++TOPSRCDIR = @top_srcdir@
++TOPOBJDIR = ../..
++SRCDIR = @srcdir@
++VPATH = @srcdir@
++MODULE = winepulse.drv
++IMPORTS = winmm user32 kernel32
++EXTRALIBS = @PULSELIBS@
++
++C_SRCS = waveout.c \
++ wavein.c \
++ pulse.c
++
++@MAKE_DLL_RULES@
++
++@DEPENDENCIES@ # everything below this line is overwritten by make depend
+diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c
+new file mode 100644
+index 0000000..3dcb086
+--- /dev/null
++++ b/dlls/winepulse.drv/pulse.c
+@@ -0,0 +1,788 @@
++/*
++ * Wine Driver for PulseAudio
++ * http://pulseaudio.org/
++ *
++ * Copyright 2009 Arthur Taylor <theycallhimart@gmail.com>
++ *
++ * Contains code from other wine sound drivers.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
++ */
++
++#include "config.h"
++
++#include <stdarg.h>
++#include <stdio.h>
++
++#include "windef.h"
++#include "winbase.h"
++#include "wingdi.h"
++#include "winuser.h"
++#include "winreg.h"
++#include "mmddk.h"
++#include "ks.h"
++#include "ksguid.h"
++#include "ksmedia.h"
++
++#ifdef HAVE_UNISTD_H
++# include <unistd.h>
++#endif
++#include <poll.h>
++
++#ifdef HAVE_PULSEAUDIO
++
++#include "wine/unicode.h"
++#include "wine/debug.h"
++#include "wine/library.h"
++
++#include <winepulse.h>
++#include <pulse/pulseaudio.h>
++WINE_DEFAULT_DEBUG_CHANNEL(wave);
++
++/* These strings used only for tracing */
++const char * PULSE_getCmdString(enum win_wm_message msg) {
++ static char unknown[32];
++#define MSG_TO_STR(x) case x: return #x
++ switch(msg) {
++ MSG_TO_STR(WINE_WM_PAUSING);
++ MSG_TO_STR(WINE_WM_RESTARTING);
++ MSG_TO_STR(WINE_WM_RESETTING);
++ MSG_TO_STR(WINE_WM_HEADER);
++ MSG_TO_STR(WINE_WM_BREAKLOOP);
++ MSG_TO_STR(WINE_WM_CLOSING);
++ MSG_TO_STR(WINE_WM_STARTING);
++ MSG_TO_STR(WINE_WM_STOPPING);
++ MSG_TO_STR(WINE_WM_XRUN);
++ MSG_TO_STR(WINE_WM_FEED);
++ }
++#undef MSG_TO_STR
++ sprintf(unknown, "UNKNOWN(0x%08x)", msg);
++ return unknown;
++}
++
++/*======================================================================*
++ * Ring Buffer Functions - copied from winealsa.drv *
++ *======================================================================*/
++
++/* unless someone makes a wineserver kernel module, Unix pipes are faster than win32 events */
++#define USE_PIPE_SYNC
++
++#ifdef USE_PIPE_SYNC
++#define INIT_OMR(omr) do { if (pipe(omr->msg_pipe) < 0) { omr->msg_pipe[0] = omr->msg_pipe[1] = -1; } } while (0)
++#define CLOSE_OMR(omr) do { close(omr->msg_pipe[0]); close(omr->msg_pipe[1]); } while (0)
++#define SIGNAL_OMR(omr) do { int x = 0; write((omr)->msg_pipe[1], &x, sizeof(x)); } while (0)
++#define CLEAR_OMR(omr) do { int x = 0; read((omr)->msg_pipe[0], &x, sizeof(x)); } while (0)
++#define RESET_OMR(omr) do { } while (0)
++#define WAIT_OMR(omr, sleep) \
++ do { struct pollfd pfd; pfd.fd = (omr)->msg_pipe[0]; \
++ pfd.events = POLLIN; poll(&pfd, 1, sleep); } while (0)
++#else
++#define INIT_OMR(omr) do { omr->msg_event = CreateEventW(NULL, FALSE, FALSE, NULL); } while (0)
++#define CLOSE_OMR(omr) do { CloseHandle(omr->msg_event); } while (0)
++#define SIGNAL_OMR(omr) do { SetEvent((omr)->msg_event); } while (0)
++#define CLEAR_OMR(omr) do { } while (0)
++#define RESET_OMR(omr) do { ResetEvent((omr)->msg_event); } while (0)
++#define WAIT_OMR(omr, sleep) \
++ do { WaitForSingleObject((omr)->msg_event, sleep); } while (0)
++#endif
++
++#define PULSE_RING_BUFFER_INCREMENT 64
++
++/******************************************************************
++ * PULSE_InitRingMessage
++ *
++ * Initialize the ring of messages for passing between driver's caller
++ * and playback/record thread
++ */
++int PULSE_InitRingMessage(PULSE_MSG_RING* omr)
++{
++ omr->msg_toget = 0;
++ omr->msg_tosave = 0;
++ INIT_OMR(omr);
++ omr->ring_buffer_size = PULSE_RING_BUFFER_INCREMENT;
++ omr->messages = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,omr->ring_buffer_size * sizeof(PULSE_MSG));
++
++ InitializeCriticalSection(&omr->msg_crst);
++ omr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PULSE_MSG_RING.msg_crst");
++ return 0;
++}
++
++/******************************************************************
++ * PULSE_DestroyRingMessage
++ *
++ */
++int PULSE_DestroyRingMessage(PULSE_MSG_RING* omr)
++{
++ CLOSE_OMR(omr);
++ HeapFree(GetProcessHeap(),0,omr->messages);
++ omr->messages = NULL;
++ omr->ring_buffer_size = PULSE_RING_BUFFER_INCREMENT;
++ omr->msg_crst.DebugInfo->Spare[0] = 0;
++ DeleteCriticalSection(&omr->msg_crst);
++ return 0;
++}
++/******************************************************************
++ * PULSE_ResetRingMessage
++ *
++ */
++void PULSE_ResetRingMessage(PULSE_MSG_RING* omr)
++{
++ RESET_OMR(omr);
++}
++
++/******************************************************************
++ * PULSE_WaitRingMessage
++ *
++ */
++void PULSE_WaitRingMessage(PULSE_MSG_RING* omr, DWORD sleep)
++{
++ WAIT_OMR(omr, sleep);
++}
++
++/******************************************************************
++ * PULSE_AddRingMessage
++ *
++ * Inserts a new message into the ring (should be called from DriverProc derived routines)
++ */
++int PULSE_AddRingMessage(PULSE_MSG_RING* omr, enum win_wm_message msg, DWORD param, BOOL wait)
++{
++ HANDLE hEvent = INVALID_HANDLE_VALUE;
++
++ EnterCriticalSection(&omr->msg_crst);
++ if ((omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size)))
++ {
++ int old_ring_buffer_size = omr->ring_buffer_size;
++ omr->ring_buffer_size += PULSE_RING_BUFFER_INCREMENT;
++ omr->messages = HeapReAlloc(GetProcessHeap(),0,omr->messages, omr->ring_buffer_size * sizeof(PULSE_MSG));
++ /* Now we need to rearrange the ring buffer so that the new
++ buffers just allocated are in between omr->msg_tosave and
++ omr->msg_toget.
++ */
++ if (omr->msg_tosave < omr->msg_toget)
++ {
++ memmove(&(omr->messages[omr->msg_toget + PULSE_RING_BUFFER_INCREMENT]),
++ &(omr->messages[omr->msg_toget]),
++ sizeof(PULSE_MSG)*(old_ring_buffer_size - omr->msg_toget)
++ );
++ omr->msg_toget += PULSE_RING_BUFFER_INCREMENT;
++ }
++ }
++ if (wait)
++ {
++ hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
++ if (hEvent == INVALID_HANDLE_VALUE)
++ {
++ ERR("can't create event !?\n");
++ LeaveCriticalSection(&omr->msg_crst);
++ return 0;
++ }
++ /* fast messages have to be added at the start of the queue */
++ omr->msg_toget = (omr->msg_toget + omr->ring_buffer_size - 1) % omr->ring_buffer_size;
++
++ omr->messages[omr->msg_toget].msg = msg;
++ omr->messages[omr->msg_toget].param = param;
++ omr->messages[omr->msg_toget].hEvent = hEvent;
++ }
++ else
++ {
++ omr->messages[omr->msg_tosave].msg = msg;
++ omr->messages[omr->msg_tosave].param = param;
++ omr->messages[omr->msg_tosave].hEvent = INVALID_HANDLE_VALUE;
++ omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
++ }
++ LeaveCriticalSection(&omr->msg_crst);
++ /* signal a new message */
++ SIGNAL_OMR(omr);
++ if (wait)
++ {
++ /* wait for playback/record thread to have processed the message */
++ WaitForSingleObject(hEvent, INFINITE);
++ CloseHandle(hEvent);
++ }
++ return 1;
++}
++
++/******************************************************************
++ * PULSE_RetrieveRingMessage
++ *
++ * Get a message from the ring. Should be called by the playback/record thread.
++ */
++int PULSE_RetrieveRingMessage(PULSE_MSG_RING* omr,
++ enum win_wm_message *msg, DWORD *param, HANDLE *hEvent)
++{
++ EnterCriticalSection(&omr->msg_crst);
++
++ if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
++ {
++ LeaveCriticalSection(&omr->msg_crst);
++ return 0;
++ }
++
++ *msg = omr->messages[omr->msg_toget].msg;
++ omr->messages[omr->msg_toget].msg = 0;
++ *param = omr->messages[omr->msg_toget].param;
++ *hEvent = omr->messages[omr->msg_toget].hEvent;
++ omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
++ CLEAR_OMR(omr);
++ LeaveCriticalSection(&omr->msg_crst);
++ return 1;
++}
++
++/**************************************************************************
++ * Utility Functions
++ *************************************************************************/
++
++/******************************************************************
++ * PULSE_SetupFormat
++ *
++ * Checks to see if the audio format in wf is supported, and if so set up the
++ * pa_sample_spec at ss to that format.
++ */
++BOOL PULSE_SetupFormat(LPWAVEFORMATEX wf, pa_sample_spec *ss) {
++ WAVEFORMATEXTENSIBLE *wfex;
++
++ ss->channels = wf->nChannels;
++ ss->rate = wf->nSamplesPerSec;
++ ss->format = PA_SAMPLE_INVALID;
++
++ if (ss->rate < DSBFREQUENCY_MIN || ss->rate > DSBFREQUENCY_MAX) return FALSE;
++
++ switch (wf->wFormatTag) {
++ case WAVE_FORMAT_PCM:
++ /* MSDN says that for WAVE_FORMAT_PCM, nChannels must be 1 or 2 and
++ * wBitsPerSample must be 8 or 16, yet other values are used by some
++ * applications in the wild for surround. */
++ if (ss->channels > 6 || ss->channels < 1) return FALSE;
++ ss->format = wf->wBitsPerSample == 8 ? PA_SAMPLE_U8
++ : wf->wBitsPerSample == 16 ? PA_SAMPLE_S16NE
++ : wf->wBitsPerSample == 32 ? PA_SAMPLE_S32NE
++ : PA_SAMPLE_INVALID;
++ break;
++
++ case WAVE_FORMAT_MULAW:
++ if (wf->wBitsPerSample == 8) ss->format = PA_SAMPLE_ULAW;
++ break;
++
++ case WAVE_FORMAT_ALAW:
++ if (wf->wBitsPerSample == 8) ss->format = PA_SAMPLE_ALAW;
++ break;
++
++ case WAVE_FORMAT_EXTENSIBLE:
++ if (wf->cbSize > 22) return FALSE;
++ if (ss->channels < 1 || ss->channels > 6) return FALSE;
++ wfex = (WAVEFORMATEXTENSIBLE *)wf;
++ if (IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
++ if (wf->wBitsPerSample == wfex->Samples.wValidBitsPerSample) {
++ ss->format = wf->wBitsPerSample == 8 ? PA_SAMPLE_U8
++ : wf->wBitsPerSample == 16 ? PA_SAMPLE_S16NE
++ : wf->wBitsPerSample == 32 ? PA_SAMPLE_S32NE
++ : PA_SAMPLE_INVALID;
++ } else {
++ return FALSE;
++ }
++ } else if (wf->wBitsPerSample != wfex->Samples.wValidBitsPerSample) {
++ return FALSE;
++ } else if ((IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))) {
++ ss->format = PA_SAMPLE_FLOAT32NE;
++ } else {
++ WARN("only KSDATAFORMAT_SUBTYPE_PCM and KSDATAFORMAT_SUBTYPE_IEEE_FLOAT of WAVE_FORMAT_EXTENSIBLE supported\n");
++ return FALSE;
++ }
++ break;
++
++ default:
++ WARN("only WAVE_FORMAT_PCM, WAVE_FORMAT_MULAW, WAVE_FORMAT_ALAW and WAVE_FORMAT_EXTENSIBLE supported\n");
++ return FALSE;
++ }
++
++ if (!pa_sample_spec_valid(ss)) return FALSE;
++ if (wf->nBlockAlign != pa_frame_size(ss)) {
++ ERR("wf->nBlockAlign != the format frame size!\n");
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++/******************************************************************
++ * PULSE_SetupFormat
++ *
++ * Converts the current time to a MMTIME structure. lpTime shold be validated
++ * before calling.
++ */
++HRESULT PULSE_UsecToMMTime(pa_usec_t time, LPMMTIME lpTime, const pa_sample_spec *ss) {
++ pa_usec_t temp;
++ size_t bytes;
++
++ /* Convert to milliseconds */
++ time /= 1000;
++
++ bytes = time * pa_bytes_per_second(ss) / 1000;
++ /* Align to frame size */
++ bytes -= bytes % pa_frame_size(ss);
++
++ switch (lpTime->wType) {
++ case TIME_SAMPLES:
++ lpTime->u.sample = bytes / pa_frame_size(ss);
++ TRACE("TIME_SAMPLES=%u\n", lpTime->u.sample);
++ break;
++ case TIME_MS:
++ lpTime->u.ms = time;
++ TRACE("TIME_MS=%u\n", lpTime->u.ms);
++ break;
++ case TIME_SMPTE:
++ lpTime->u.smpte.fps = 30;
++ temp = bytes / pa_frame_size(ss);
++ temp += ss->rate / lpTime->u.smpte.fps - 1;
++ lpTime->u.smpte.sec = time/1000;
++ temp -= lpTime->u.smpte.sec * ss->rate;
++ lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
++ lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
++ lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
++ lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
++ lpTime->u.smpte.frame = temp * lpTime->u.smpte.fps / ss->rate;
++ TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
++ lpTime->u.smpte.hour, lpTime->u.smpte.min,
++ lpTime->u.smpte.sec, lpTime->u.smpte.frame);
++ break;
++ default:
++ WARN("Format %d not supported, using TIME_BYTES !\n", lpTime->wType);
++ lpTime->wType = TIME_BYTES;
++ /* fall through */
++ case TIME_BYTES:
++ lpTime->u.cb = bytes;
++ TRACE("TIME_BYTES=%u\n", lpTime->u.cb);
++ break;
++ }
++
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * PULSE_WaitForOperation
++ *
++ * Waits for pa operations to complete, and dereferences the operation.
++ */
++void PULSE_WaitForOperation(pa_operation *o) {
++ if (!o) return;
++
++ for (;;) {
++ if (pa_operation_get_state(o) != PA_OPERATION_RUNNING)
++ break;
++ pa_threaded_mainloop_wait(PULSE_ml);
++ }
++ pa_operation_unref(o);
++}
++
++/**************************************************************************
++ * Common Callbacks
++ */
++
++/**************************************************************************
++ * PULSE_StreamSuspendedCallback [internal]
++ *
++ * Called by the pulse mainloop any time stream playback is intentionally
++ * suspended or resumed from being suspended.
++ */
++void PULSE_StreamSuspendedCallback(pa_stream *s, void *userdata) {
++ WINE_WAVEINST *wwo = (WINE_WAVEINST*)userdata;
++ assert(s && wwo);
++
++ /* Currently we handle this kinda like an underrun. Perhaps we should
++ * tell the client somehow so it doesn't just hang? */
++
++ if (!pa_stream_is_suspended(s) && wwo->hThread != INVALID_HANDLE_VALUE && wwo->msgRing.ring_buffer_size > 0)
++ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_XRUN, 0, FALSE);
++}
++
++/**************************************************************************
++ * PULSE_StreamUnderflowCallback [internal]
++ *
++ * Called by the pulse mainloop when the prebuf runs out of data.
++ */
++void PULSE_StreamUnderflowCallback(pa_stream *s, void *userdata) {
++ WINE_WAVEINST *wwo = (WINE_WAVEINST*)userdata;
++ assert(s && wwo);
++
++ /* If we aren't playing, don't care ^_^ */
++ if (wwo->state != WINE_WS_PLAYING) return;
++
++ TRACE("Underrun occurred.\n");
++
++ if (wwo->hThread != INVALID_HANDLE_VALUE && wwo->msgRing.ring_buffer_size > 0);
++ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_XRUN, 0, FALSE);
++}
++
++/**************************************************************************
++ * PULSE_StreamMovedCallback [internal]
++ *
++ * Called by the pulse mainloop when the stream gets moved, resulting in
++ * possibly different metrics.
++ */
++void PULSE_StreamMovedCallback(pa_stream *s, void *userdata) {
++ FIXME("stub");
++}
++
++
++/******************************************************************
++ * PULSE_StreamStateCallback
++ *
++ * Called by pulse whenever the state of the stream changes.
++ */
++void PULSE_StreamStateCallback(pa_stream *s, void *userdata) {
++ assert(s);
++
++ switch (pa_stream_get_state(s)) {
++ case PA_STREAM_READY:
++ TRACE("Stream %p ready\n", userdata);
++ break;
++
++ case PA_STREAM_TERMINATED:
++ TRACE("Stream %p terminated\n", userdata);
++ break;
++
++ case PA_STREAM_FAILED:
++ ERR("Stream %p failed!\n", userdata);
++ break;
++
++ case PA_STREAM_UNCONNECTED:
++ case PA_STREAM_CREATING:
++ return;
++ }
++ pa_threaded_mainloop_signal(PULSE_ml, 0);
++}
++
++/**************************************************************************
++ * PULSE_StreamSucessCallback
++ */
++void PULSE_StreamSuccessCallback(pa_stream *s, int success, void *userdata) {
++ if (!success)
++ WARN("Stream %p operation failed: %s\n", userdata, pa_strerror(pa_context_errno(PULSE_context)));
++
++ pa_threaded_mainloop_signal(PULSE_ml, 0);
++}
++
++/**************************************************************************
++ * PULSE_ContextSuccessCallback
++ */
++void PULSE_ContextSuccessCallback(pa_context *c, int success, void *userdata) {
++ if (!success) ERR("Context operation failed: %s\n", pa_strerror(pa_context_errno(c)));
++ pa_threaded_mainloop_signal(PULSE_ml, 0);
++}
++
++/**************************************************************************
++ * Connection management and sink / source management.
++ */
++
++/**************************************************************************
++ * PULSE_ContextStateCallback [internal]
++ */
++static void PULSE_ContextStateCallback(pa_context *c, void *userdata) {
++ assert(c);
++
++ switch (pa_context_get_state(c)) {
++ case PA_CONTEXT_CONNECTING:
++ case PA_CONTEXT_UNCONNECTED:
++ case PA_CONTEXT_AUTHORIZING:
++ case PA_CONTEXT_SETTING_NAME:
++ break;
++
++ case PA_CONTEXT_READY:
++ case PA_CONTEXT_TERMINATED:
++ pa_threaded_mainloop_signal(PULSE_ml, 0);
++ break;
++
++ case PA_CONTEXT_FAILED:
++ ERR("Context failure: %s\n", pa_strerror(pa_context_errno(c)));
++ pa_threaded_mainloop_signal(PULSE_ml, 0);
++ break;
++ }
++}
++
++/**************************************************************************
++ * PULSE_AllocateWaveinDevice [internal]
++ *
++ * Creates or adds a device to WInDev based on the pa_source_info.
++ */
++static void PULSE_AllocateWaveinDevice(const char *name, const char *device, const char *description, const pa_cvolume *v) {
++ WINE_WAVEDEV *wdi;
++
++ if (WInDev)
++ wdi = HeapReAlloc(GetProcessHeap(), 0, WInDev, sizeof(WINE_WAVEDEV) * (PULSE_WidNumDevs + 1));
++ else
++ wdi = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_WAVEDEV));
++
++ if (!wdi) return;
++
++ WInDev = wdi;
++ wdi = &WInDev[PULSE_WidNumDevs++];
++ memset(wdi, 0, sizeof(WINE_WAVEDEV));
++ memset(&(wdi->caps.in), 0, sizeof(wdi->caps.in));
++ snprintf(wdi->interface_name, MAXPNAMELEN * 2, "winepulse: %s", name);
++ wdi->device_name = pa_xstrdup(device);
++ MultiByteToWideChar(CP_ACP, 0, description, -1, wdi->caps.in.szPname, sizeof(wdi->caps.in.szPname)/sizeof(WCHAR));
++ wdi->caps.in.szPname[sizeof(wdi->caps.in.szPname)/sizeof(WCHAR) - 1] = '\0';
++ wdi->caps.in.wMid = MM_CREATIVE;
++ wdi->caps.in.wPid = MM_CREATIVE_SBP16_WAVEOUT;
++ wdi->caps.in.vDriverVersion = 0x0100;
++ wdi->caps.in.wChannels = v->channels == 1 ? 1 : 2;
++ wdi->caps.in.dwFormats = PULSE_ALL_FORMATS;
++ memset(&wdi->ds_desc, 0, sizeof(DSDRIVERDESC));
++ memcpy(wdi->ds_desc.szDesc, description, min(sizeof(wdi->ds_desc.szDesc) - 1, strlen(description)));
++ memcpy(wdi->ds_desc.szDrvname, "winepulse.drv", 14);
++ wdi->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
++ wdi->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
++ wdi->ds_caps.dwPrimaryBuffers = 1;
++ wdi->ds_caps.dwFlags = \
++ DSCAPS_PRIMARYMONO |
++ DSCAPS_PRIMARYSTEREO |
++ DSCAPS_PRIMARY8BIT |
++ DSCAPS_PRIMARY16BIT |
++ DSCAPS_SECONDARYMONO |
++ DSCAPS_SECONDARYSTEREO |
++ DSCAPS_SECONDARY8BIT |
++ DSCAPS_SECONDARY16BIT |
++ DSCCAPS_MULTIPLECAPTURE;
++}
++
++/**************************************************************************
++ * PULSE_AllocateWaveoutDevice [internal]
++ *
++ * Creates or adds a sink to the WOutDev array.
++ */
++static void PULSE_AllocateWaveoutDevice(const char *name, const char *device, const char *description, const pa_cvolume *v) {
++ WINE_WAVEDEV *wdo;
++ int x;
++
++ if (WOutDev)
++ wdo = HeapReAlloc(GetProcessHeap(), 0, WOutDev, sizeof(WINE_WAVEDEV) * (PULSE_WodNumDevs + 1));
++ else
++ wdo = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_WAVEDEV));
++
++ if (!wdo) return;
++
++ WOutDev = wdo;
++ wdo = &WOutDev[PULSE_WodNumDevs++];
++ memset(wdo, 0, sizeof(WINE_WAVEDEV));
++
++ wdo->device_name = pa_xstrdup(device);
++ wdo->volume.channels = v->channels;
++ for (x = 0; x < v->channels; x++) wdo->volume.values[x] = v->values[x];
++ snprintf(wdo->interface_name, MAXPNAMELEN * 2, "winepulse: %s", name);
++ MultiByteToWideChar(CP_ACP, 0, description, -1, wdo->caps.out.szPname, sizeof(wdo->caps.out.szPname)/sizeof(WCHAR));
++ wdo->caps.out.szPname[sizeof(wdo->caps.out.szPname)/sizeof(WCHAR) - 1] = '\0';
++ wdo->caps.out.wMid = MM_CREATIVE;
++ wdo->caps.out.wPid = MM_CREATIVE_SBP16_WAVEOUT;
++ wdo->caps.out.vDriverVersion = 0x0100;
++ wdo->caps.out.dwSupport = WAVECAPS_VOLUME | WAVECAPS_SAMPLEACCURATE;// | WAVECAPS_DIRECTSOUND;
++ if (v->channels >= 2) {
++ wdo->caps.out.wChannels = 2;
++ wdo->caps.out.dwSupport |= WAVECAPS_LRVOLUME;
++ } else
++ wdo->caps.out.wChannels = 1;
++ wdo->caps.out.dwFormats = PULSE_ALL_FORMATS;
++ memset(&wdo->ds_desc, 0, sizeof(DSDRIVERDESC));
++ memcpy(wdo->ds_desc.szDesc, description, min(sizeof(wdo->ds_desc.szDesc) - 1, strlen(description)));
++ memcpy(wdo->ds_desc.szDrvname, "winepulse.drv", 14);
++ wdo->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
++ wdo->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
++ wdo->ds_caps.dwPrimaryBuffers = 1;
++ wdo->ds_caps.dwFlags = \
++ DSCAPS_PRIMARYMONO |
++ DSCAPS_PRIMARYSTEREO |
++ DSCAPS_PRIMARY8BIT |
++ DSCAPS_PRIMARY16BIT |
++ DSCAPS_SECONDARYMONO |
++ DSCAPS_SECONDARYSTEREO |
++ DSCAPS_SECONDARY8BIT |
++ DSCAPS_SECONDARY16BIT |
++ DSCAPS_CONTINUOUSRATE;
++}
++
++/**************************************************************************
++ * PULSE_SourceInfoCallback [internal]
++ */
++static void PULSE_SourceInfoCallback(pa_context *c, const pa_source_info *i, int eol, void *userdata) {
++
++ if (!eol && i)
++ PULSE_AllocateWaveinDevice(i->name, i->name, i->description, &i->volume);
++
++ pa_threaded_mainloop_signal(PULSE_ml, 0);
++}
++
++/**************************************************************************
++ * PULSE_SinkInfoCallback [internal]
++ */
++static void PULSE_SinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, void *userdata) {
++
++ if (!eol && i)
++ PULSE_AllocateWaveoutDevice(i->name, i->name, i->description, &i->volume);
++
++ pa_threaded_mainloop_signal(PULSE_ml, 0);
++}
++
++/**************************************************************************
++ * PULSE_ContextNotifyCallback [internal]
++ */
++static void PULSE_ContextNotifyCallback(pa_context *c, void *userdata) {
++ pa_threaded_mainloop_signal(PULSE_ml, 0);
++}
++
++/**************************************************************************
++ * PULSE_WaveClose [internal]
++ *
++ * Disconnect from the server, deallocated the WaveIn/WaveOut devices, stop and
++ * free the mainloop.
++ */
++static LONG PULSE_WaveClose(void) {
++ int x;
++ TRACE("()\n");
++ if (!PULSE_ml) return DRV_FAILURE;
++
++ pa_threaded_mainloop_lock(PULSE_ml);
++ /* device_name is allocated with pa_xstrdup, free with pa_xfree */
++ for (x = 0; x < PULSE_WodNumDevs; x++) pa_xfree(WOutDev[x].device_name);
++ for (x = 0; x < PULSE_WidNumDevs; x++) pa_xfree(WInDev[x].device_name);
++ HeapFree(GetProcessHeap(), 0, WOutDev);
++ HeapFree(GetProcessHeap(), 0, WInDev);
++ if (PULSE_context) {
++ PULSE_WaitForOperation(pa_context_drain(PULSE_context, PULSE_ContextNotifyCallback, NULL));
++ pa_context_disconnect(PULSE_context);
++ pa_context_unref(PULSE_context);
++ PULSE_context = NULL;
++ }
++
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ pa_threaded_mainloop_stop(PULSE_ml);
++ pa_threaded_mainloop_free(PULSE_ml);
++ PULSE_ml = NULL;
++
++ return DRV_SUCCESS;
++}
++
++/**************************************************************************
++ * PULSE_WaveInit [internal]
++ *
++ * Connects to the pulseaudio server, tries to discover sinks and sources and
++ * allocates the WaveIn/WaveOut devices.
++ */
++static LONG PULSE_WaveInit(void) {
++ char *app_name;
++ char path[PATH_MAX];
++ char *offset = NULL;
++ pa_cvolume fake_cvolume;
++
++ WOutDev = NULL;
++ WInDev = NULL;
++ PULSE_WodNumDevs = 0;
++ PULSE_WidNumDevs = 0;
++ PULSE_context = NULL;
++ PULSE_ml = NULL;
++
++ if (!(PULSE_ml = pa_threaded_mainloop_new())) {
++ WARN("Failed to create mainloop object.");
++ return DRV_FAILURE;
++ }
++
++ /* Application name giving to pulse should be unique to the binary so that
++ * pulse-*-restore can be useful */
++
++ /* Get binary path, and remove path a-la strrchr */
++ if (GetModuleFileNameA(NULL, path, PATH_MAX))
++ offset = strrchr(path, '\\');
++
++ if (offset && ++offset && offset < path + PATH_MAX) {
++ app_name = pa_xmalloc(strlen(offset) + 8);
++ snprintf(app_name, strlen(offset) + 8, "WINE [%s]", offset);
++ } else
++ app_name = pa_xstrdup("WINE Application");
++
++ TRACE("App name is \"%s\"\n", app_name);
++
++ pa_threaded_mainloop_start(PULSE_ml);
++ PULSE_context = pa_context_new(pa_threaded_mainloop_get_api(PULSE_ml), app_name);
++ assert(PULSE_context);
++ pa_xfree(app_name);
++
++ pa_context_set_state_callback(PULSE_context, PULSE_ContextStateCallback, NULL);
++
++ pa_threaded_mainloop_lock(PULSE_ml);
++
++ TRACE("libpulse protocol version: %u. API Version %u\n", pa_context_get_protocol_version(PULSE_context), PA_API_VERSION);
++ TRACE("Attempting to connect to pulseaudio server.\n");
++ if (pa_context_connect(PULSE_context, NULL, 0, NULL) < 0)
++ goto fail;
++
++ /* Wait for connection */
++ for (;;) {
++ pa_context_state_t state = pa_context_get_state(PULSE_context);
++
++ if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED)
++ goto fail;
++
++ if (state == PA_CONTEXT_READY)
++ break;
++
++ pa_threaded_mainloop_wait(PULSE_ml);
++ }
++
++ TRACE("Connected to server %s with protocol version: %i.\n",
++ pa_context_get_server(PULSE_context),
++ pa_context_get_server_protocol_version(PULSE_context));
++
++ fake_cvolume.channels = 2;
++ pa_cvolume_reset(&fake_cvolume, 2);
++ /* FIXME Translations? */
++ PULSE_AllocateWaveoutDevice("default", NULL, "Default", &fake_cvolume);
++ PULSE_AllocateWaveinDevice("default", NULL, "Default", &fake_cvolume);
++ PULSE_WaitForOperation(pa_context_get_sink_info_list(PULSE_context, PULSE_SinkInfoCallback, &PULSE_WodNumDevs));
++ PULSE_WaitForOperation(pa_context_get_source_info_list(PULSE_context, PULSE_SourceInfoCallback, &PULSE_WidNumDevs));
++ TRACE("Found %u output and %u input device(s).\n", PULSE_WodNumDevs - 1, PULSE_WidNumDevs - 1);
++
++ pa_threaded_mainloop_unlock(PULSE_ml);
++
++ return DRV_SUCCESS;
++
++fail:
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ ERR("Failed to connect to server\n");
++ return DRV_FAILURE;
++}
++
++#endif /* HAVE_PULSEAUDIO */
++
++/**************************************************************************
++ * DriverProc (WINEPULSE.@)
++ */
++LRESULT CALLBACK PULSE_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
++ LPARAM dwParam1, LPARAM dwParam2) {
++
++ switch(wMsg) {
++#ifdef HAVE_PULSEAUDIO
++ case DRV_LOAD: return PULSE_WaveInit();
++ case DRV_FREE: return PULSE_WaveClose();
++ case DRV_OPEN: return 1;
++ case DRV_CLOSE: return 1;
++ case DRV_ENABLE: return 1;
++ case DRV_DISABLE: return 1;
++ case DRV_QUERYCONFIGURE: return 1;
++ case DRV_CONFIGURE: MessageBoxA(0, "PulseAudio MultiMedia Driver !", "PulseAudio Driver", MB_OK); return 1;
++ case DRV_INSTALL: return DRVCNF_RESTART;
++ case DRV_REMOVE: return DRVCNF_RESTART;
++#endif
++ default:
++ return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
++ }
++}
+diff --git a/dlls/winepulse.drv/wavein.c b/dlls/winepulse.drv/wavein.c
+new file mode 100644
+index 0000000..7cbc781
+--- /dev/null
++++ b/dlls/winepulse.drv/wavein.c
+@@ -0,0 +1,595 @@
++/*
++ * Wine Driver for PulseAudio - WaveIn Functionality
++ * http://pulseaudio.org/
++ *
++ * Copyright 2009 Arthur Taylor <theycallhimart@gmail.com>
++ *
++ * Contains code from other wine multimedia drivers.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
++ */
++
++#include "config.h"
++
++#include <stdarg.h>
++
++#include "windef.h"
++#include "winbase.h"
++#include "wingdi.h"
++#include "winuser.h"
++#include "winnls.h"
++#include "mmddk.h"
++
++#include <winepulse.h>
++
++#include "wine/debug.h"
++
++WINE_DEFAULT_DEBUG_CHANNEL(wave);
++
++#if HAVE_PULSEAUDIO
++
++/*======================================================================*
++ * WAVE IN specific PulseAudio Callbacks *
++ *======================================================================*/
++
++/**************************************************************************
++ * widNotifyClient [internal]
++*/
++static DWORD widNotifyClient(WINE_WAVEINST* wwi, WORD wMsg, DWORD dwParam1, DWORD dwParam2) {
++ TRACE("wMsg = 0x%04x dwParm1 = %04X dwParam2 = %04X\n", wMsg, dwParam1, dwParam2);
++
++ switch (wMsg) {
++ case WIM_OPEN:
++ case WIM_CLOSE:
++ case WIM_DATA:
++ if (wwi->wFlags != DCB_NULL &&
++ !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags, (HDRVR)wwi->waveDesc.hWave,
++ wMsg, wwi->waveDesc.dwInstance, dwParam1, dwParam2)) {
++ WARN("can't notify client !\n");
++ return MMSYSERR_ERROR;
++ }
++ break;
++ default:
++ FIXME("Unknown callback message %u\n", wMsg);
++ return MMSYSERR_INVALPARAM;
++ }
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * widRecorder_NextFragment [internal]
++ *
++ * Gets the next fragment of data from the server.
++ */
++static size_t widRecorder_NextFragment(WINE_WAVEINST *wwi) {
++ size_t nbytes;
++
++ TRACE("()\n");
++
++ if (wwi->buffer)
++ pa_stream_drop(wwi->stream);
++
++ pa_stream_peek(wwi->stream, &wwi->buffer, &nbytes);
++ wwi->buffer_length = nbytes;
++ wwi->buffer_read_offset = 0;
++
++ return nbytes;
++}
++
++
++/**************************************************************************
++ * widRecorder_CopyData [internal]
++ *
++ * Copys data from the fragments pulse returns to queued buffers.
++ */
++static void widRecorder_CopyData(WINE_WAVEINST *wwi) {
++ LPWAVEHDR lpWaveHdr = wwi->lpQueuePtr;
++ size_t nbytes;
++
++ while (lpWaveHdr && wwi->state == WINE_WS_PLAYING) {
++
++ nbytes = min(wwi->buffer_length - wwi->buffer_read_offset, lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded);
++ if (nbytes == 0) break;
++
++ TRACE("%u bytes from %p to %p\n",
++ nbytes,
++ (PBYTE)wwi->buffer + wwi->buffer_read_offset,
++ lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded);
++
++ memcpy(lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded, (PBYTE)wwi->buffer + wwi->buffer_read_offset, nbytes);
++
++ lpWaveHdr->dwBytesRecorded += nbytes;
++ wwi->buffer_read_offset += nbytes;
++
++ if (wwi->buffer_read_offset == wwi->buffer_length) {
++ pa_threaded_mainloop_lock(PULSE_ml);
++ pa_stream_drop(wwi->stream);
++ if (pa_stream_readable_size(wwi->stream))
++ widRecorder_NextFragment(wwi);
++ else {
++ wwi->buffer = NULL;
++ wwi->buffer_length = 0;
++ wwi->buffer_read_offset = 0;
++ }
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ }
++
++ if (lpWaveHdr->dwBytesRecorded == lpWaveHdr->dwBufferLength) {
++ lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
++ lpWaveHdr->dwFlags |= WHDR_DONE;
++ wwi->lpQueuePtr = lpWaveHdr->lpNext;
++ widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
++ lpWaveHdr = wwi->lpQueuePtr;
++ }
++ }
++}
++
++/**************************************************************************
++ * widRecorder [internal]
++ */
++static DWORD CALLBACK widRecorder(LPVOID lpParam) {
++ WINE_WAVEINST *wwi = (WINE_WAVEINST*)lpParam;
++ LPWAVEHDR lpWaveHdr;
++ enum win_wm_message msg;
++ DWORD param;
++ HANDLE ev;
++ DWORD wait = INFINITE;
++
++ wwi->state = WINE_WS_STOPPED;
++ SetEvent(wwi->hStartUpEvent);
++
++ for (;;) {
++
++ if (wwi->state != WINE_WS_PLAYING) {
++ wait = INFINITE;
++ } else {
++ if (wwi->buffer == NULL && pa_stream_readable_size(wwi->stream)) {
++ pa_threaded_mainloop_lock(PULSE_ml);
++ wait = pa_bytes_to_usec(widRecorder_NextFragment(wwi), &wwi->sample_spec)/1000;
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ }
++ }
++
++ widRecorder_CopyData(wwi);
++
++ PULSE_WaitRingMessage(&wwi->msgRing, wait);
++
++ while (PULSE_RetrieveRingMessage(&wwi->msgRing, &msg, &param, &ev)) {
++ TRACE("Received %s %x\n", PULSE_getCmdString(msg), param);
++
++ switch (msg) {
++ case WINE_WM_FEED:
++ SetEvent(ev);
++ break;
++ case WINE_WM_STARTING:
++ wwi->state = WINE_WS_PLAYING;
++ if (wwi->lpQueuePtr)
++ wait = pa_bytes_to_usec(wwi->lpQueuePtr->dwBufferLength, &wwi->sample_spec)/1000;
++ else
++ wait = INFINITE;
++ wwi->dwLastReset = wwi->timing_info->read_index;
++ pa_threaded_mainloop_lock(PULSE_ml);
++ PULSE_WaitForOperation(pa_stream_cork(wwi->stream, 0, PULSE_StreamSuccessCallback, NULL));
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ SetEvent(ev);
++ break;
++ case WINE_WM_HEADER:
++ lpWaveHdr = (LPWAVEHDR)param;
++ lpWaveHdr->lpNext = 0;
++
++ /* insert buffer at the end of queue */
++ {
++ LPWAVEHDR *wh;
++ for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
++ *wh = lpWaveHdr;
++ }
++ break;
++ case WINE_WM_STOPPING:
++ if (wwi->state != WINE_WS_STOPPED) {
++ wwi->state = WINE_WS_STOPPED;
++ pa_threaded_mainloop_lock(PULSE_ml);
++ PULSE_WaitForOperation(pa_stream_cork(wwi->stream, 1, PULSE_StreamSuccessCallback, NULL));
++ pa_threaded_mainloop_unlock(PULSE_ml);
++
++ /* return current buffer to app */
++ lpWaveHdr = wwi->lpQueuePtr;
++ if (lpWaveHdr) {
++ LPWAVEHDR lpNext = lpWaveHdr->lpNext;
++ TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
++ lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
++ lpWaveHdr->dwFlags |= WHDR_DONE;
++ wwi->lpQueuePtr = lpNext;
++ widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
++ }
++ }
++ SetEvent(ev);
++ break;
++ case WINE_WM_RESETTING:
++ if (wwi->state != WINE_WS_STOPPED) {
++ wwi->state = WINE_WS_STOPPED;
++ pa_threaded_mainloop_lock(PULSE_ml);
++ PULSE_WaitForOperation(pa_stream_cork(wwi->stream, 1, PULSE_StreamSuccessCallback, NULL));
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ }
++
++ /* return all buffers to the app */
++ for (lpWaveHdr = wwi->lpPlayPtr ? wwi->lpPlayPtr : wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = wwi->lpQueuePtr) {
++ lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
++ lpWaveHdr->dwFlags |= WHDR_DONE;
++ wwi->lpQueuePtr = lpWaveHdr->lpNext;
++ widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
++ }
++
++ SetEvent(ev);
++ break;
++ case WINE_WM_CLOSING:
++ wwi->hThread = 0;
++ if ((DWORD)param == 1) {
++ /* If we are here, the stream failed */
++ wwi->state = WINE_WS_FAILED;
++ SetEvent(ev);
++ PULSE_DestroyRingMessage(&wwi->msgRing);
++ widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
++ wwi->lpPlayPtr = wwi->lpQueuePtr = NULL;
++ pa_threaded_mainloop_lock(PULSE_ml);
++ pa_stream_disconnect(wwi->stream);
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ TRACE("Thread exiting because of failure.\n");
++ ExitThread(1);
++ }
++ wwi->state = WINE_WS_CLOSED;
++ SetEvent(ev);
++ ExitThread(0);
++ /* shouldn't go here */
++ default:
++ FIXME("unknown message %d\n", msg);
++ break;
++ } /* switch(msg) */
++ } /* while(PULSE_RetrieveRingMessage()) */
++ } /* for (;;) */
++}
++
++/**************************************************************************
++ * widOpen [internal]
++ */
++static DWORD widOpen(WORD wDevID, DWORD_PTR *lpdwUser, LPWAVEOPENDESC lpDesc, DWORD dwFlags) {
++ WINE_WAVEDEV *wdi;
++ WINE_WAVEINST *wwi = NULL;
++ DWORD ret = MMSYSERR_NOERROR;
++
++ TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
++ if (lpDesc == NULL) {
++ WARN("Invalid Parameter !\n");
++ return MMSYSERR_INVALPARAM;
++ }
++
++ if (wDevID >= PULSE_WidNumDevs) {
++ TRACE("Asked for device %d, but only %d known!\n", wDevID, PULSE_WidNumDevs);
++ return MMSYSERR_BADDEVICEID;
++ }
++ wdi = &WInDev[wDevID];
++
++ wwi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_WAVEINST));
++ if (!wwi) return MMSYSERR_NOMEM;
++ *lpdwUser = (DWORD_PTR)wwi;
++
++ /* check to see if format is supported and make pa_sample_spec struct */
++ if (!PULSE_SetupFormat(lpDesc->lpFormat, &wwi->sample_spec)) {
++ WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
++ lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
++ lpDesc->lpFormat->nSamplesPerSec);
++ ret = WAVERR_BADFORMAT;
++ goto exit;
++ }
++
++ if (TRACE_ON(wave)) {
++ char t[PA_SAMPLE_SPEC_SNPRINT_MAX];
++ pa_sample_spec_snprint(t, sizeof(t), &wwi->sample_spec);
++ TRACE("Sample spec '%s'\n", t);
++ }
++
++ if (dwFlags & WAVE_FORMAT_QUERY) {
++ TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
++ lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
++ lpDesc->lpFormat->nSamplesPerSec);
++ ret = MMSYSERR_NOERROR;
++ goto exit;
++ }
++
++ wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
++ wwi->waveDesc = *lpDesc;
++ PULSE_InitRingMessage(&wwi->msgRing);
++
++ wwi->stream = pa_stream_new(PULSE_context, "WaveIn", &wwi->sample_spec, NULL);
++ if (!wwi->stream) {
++ ret = WAVERR_BADFORMAT;
++ goto exit;
++ }
++
++ pa_stream_set_state_callback(wwi->stream, PULSE_StreamStateCallback, wwi);
++
++ wwi->buffer_attr.maxlength = (uint32_t)-1;
++ wwi->buffer_attr.fragsize = pa_bytes_per_second(&wwi->sample_spec) / 100;
++
++ pa_threaded_mainloop_lock(PULSE_ml);
++ TRACE("Asking to open %s for recording.\n", wdi->device_name);
++ pa_stream_connect_record(wwi->stream, wdi->device_name, &wwi->buffer_attr,
++ PA_STREAM_START_CORKED |
++ PA_STREAM_AUTO_TIMING_UPDATE);
++
++ for (;;) {
++ pa_context_state_t cstate = pa_context_get_state(PULSE_context);
++ pa_stream_state_t sstate = pa_stream_get_state(wwi->stream);
++
++ if (cstate == PA_CONTEXT_FAILED || cstate == PA_CONTEXT_TERMINATED ||
++ sstate == PA_STREAM_FAILED || sstate == PA_STREAM_TERMINATED) {
++ ERR("Failed to connect context object: %s\n", pa_strerror(pa_context_errno(PULSE_context)));
++ ret = MMSYSERR_NODRIVER;
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ goto exit;
++ }
++
++ if (sstate == PA_STREAM_READY)
++ break;
++
++ pa_threaded_mainloop_wait(PULSE_ml);
++ }
++ TRACE("(%p)->stream connected for recording.\n", wwi);
++
++ PULSE_WaitForOperation(pa_stream_update_timing_info(wwi->stream, PULSE_StreamSuccessCallback, wwi));
++
++ wwi->timing_info = pa_stream_get_timing_info(wwi->stream);
++ assert(wwi->timing_info);
++ pa_threaded_mainloop_unlock(PULSE_ml);
++
++ wwi->hStartUpEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
++ wwi->hThread = CreateThread(NULL, 0, widRecorder, (LPVOID)wwi, 0, &(wwi->dwThreadID));
++ if (wwi->hThread)
++ SetThreadPriority(wwi->hThread, THREAD_PRIORITY_TIME_CRITICAL);
++ else {
++ ERR("Thread creation for the widRecorder failed!\n");
++ ret = MMSYSERR_NOMEM;
++ goto exit;
++ }
++ WaitForSingleObject(wwi->hStartUpEvent, INFINITE);
++ CloseHandle(wwi->hStartUpEvent);
++ wwi->hStartUpEvent = INVALID_HANDLE_VALUE;
++
++ return widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
++
++exit:
++ if (!wwi)
++ return ret;
++
++ if (wwi->hStartUpEvent != INVALID_HANDLE_VALUE)
++ CloseHandle(wwi->hStartUpEvent);
++
++ if (wwi->msgRing.ring_buffer_size > 0)
++ PULSE_DestroyRingMessage(&wwi->msgRing);
++
++ if (wwi->stream) {
++ if (pa_stream_get_state(wwi->stream) == PA_STREAM_READY)
++ pa_stream_disconnect(wwi->stream);
++ pa_stream_unref(wwi->stream);
++ }
++ HeapFree(GetProcessHeap(), 0, wwi);
++
++ return ret;
++}
++/**************************************************************************
++ * widClose [internal]
++ */
++static DWORD widClose(WORD wDevID, WINE_WAVEINST *wwi) {
++ DWORD ret;
++
++ TRACE("(%u, %p);\n", wDevID, wwi);
++ if (wDevID >= PULSE_WidNumDevs) {
++ WARN("Asked for device %d, but only %d known!\n", wDevID, PULSE_WodNumDevs);
++ return MMSYSERR_INVALHANDLE;
++ } else if (!wwi) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ if (wwi->state != WINE_WS_FAILED) {
++ if (wwi->lpQueuePtr) {
++ WARN("buffers recording recording !\n");
++ return WAVERR_STILLPLAYING;
++ }
++
++ pa_threaded_mainloop_lock(PULSE_ml);
++ if (pa_stream_get_state(wwi->stream) == PA_STREAM_READY)
++ pa_stream_drop(wwi->stream);
++ pa_stream_disconnect(wwi->stream);
++ pa_threaded_mainloop_unlock(PULSE_ml);
++
++ if (wwi->hThread != INVALID_HANDLE_VALUE)
++ PULSE_AddRingMessage(&wwi->msgRing, WINE_WM_CLOSING, 0, TRUE);
++
++ PULSE_DestroyRingMessage(&wwi->msgRing);
++ }
++ ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
++
++ pa_stream_unref(wwi->stream);
++ TRACE("Deallocating record instance.\n");
++ HeapFree(GetProcessHeap(), 0, wwi);
++ return ret;
++}
++
++/**************************************************************************
++ * widAddBuffer [internal]
++ *
++ */
++static DWORD widAddBuffer(WINE_WAVEINST* wwi, LPWAVEHDR lpWaveHdr, DWORD dwSize) {
++ TRACE("(%p, %p, %08X);\n", wwi, lpWaveHdr, dwSize);
++
++ if (!wwi || wwi->state == WINE_WS_FAILED) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
++ return WAVERR_UNPREPARED;
++
++ if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
++ return WAVERR_STILLPLAYING;
++
++ lpWaveHdr->dwFlags &= ~WHDR_DONE;
++ lpWaveHdr->dwFlags |= WHDR_INQUEUE;
++ lpWaveHdr->dwBytesRecorded = 0;
++ lpWaveHdr->lpNext = 0;
++
++ PULSE_AddRingMessage(&wwi->msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);
++
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * widRecorderMessage [internal]
++ */
++static DWORD widRecorderMessage(WINE_WAVEINST *wwi, enum win_wm_message message) {
++ if (!wwi || wwi->state == WINE_WS_FAILED) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ PULSE_AddRingMessage(&wwi->msgRing, message, 0, TRUE);
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * widGetPosition [internal]
++ */
++static DWORD widGetPosition(WINE_WAVEINST *wwi, LPMMTIME lpTime, DWORD uSize) {
++
++ if (!wwi || wwi->state == WINE_WS_FAILED) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ if (lpTime == NULL) return MMSYSERR_INVALPARAM;
++
++ return PULSE_UsecToMMTime(pa_bytes_to_usec(wwi->timing_info->read_index - wwi->dwLastReset, &wwi->sample_spec), lpTime, &wwi->sample_spec);
++}
++
++/**************************************************************************
++ * widGetDevCaps [internal]
++ */
++static DWORD widGetDevCaps(DWORD wDevID, LPWAVEINCAPSW lpCaps, DWORD dwSize) {
++ TRACE("(%u, %p, %u);\n", wDevID, lpCaps, dwSize);
++
++ if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
++
++ if (wDevID >= PULSE_WidNumDevs) {
++ TRACE("Asked for device %d, but only %d known!\n", wDevID, PULSE_WidNumDevs);
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ memcpy(lpCaps, &(WInDev[wDevID].caps.in), min(dwSize, sizeof(*lpCaps)));
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * widGetNumDevs [internal]
++ * Context-sanity check here, as if we respond with 0, WINE will move on
++ * to the next wavein driver.
++ */
++static DWORD widGetNumDevs() {
++ if (pa_context_get_state(PULSE_context) != PA_CONTEXT_READY)
++ return 0;
++
++ return PULSE_WidNumDevs;
++}
++
++/**************************************************************************
++ * widDevInterfaceSize [internal]
++ */
++static DWORD widDevInterfaceSize(UINT wDevID, LPDWORD dwParam1) {
++ TRACE("(%u, %p)\n", wDevID, dwParam1);
++
++ *dwParam1 = MultiByteToWideChar(CP_UNIXCP, 0, WInDev[wDevID].interface_name, -1,
++ NULL, 0 ) * sizeof(WCHAR);
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * widDevInterface [internal]
++ */
++static DWORD widDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2) {
++ if (dwParam2 >= MultiByteToWideChar(CP_UNIXCP, 0, WInDev[wDevID].interface_name, -1,
++ NULL, 0 ) * sizeof(WCHAR))
++ {
++ MultiByteToWideChar(CP_UNIXCP, 0, WInDev[wDevID].interface_name, -1,
++ dwParam1, dwParam2 / sizeof(WCHAR));
++ return MMSYSERR_NOERROR;
++ }
++ return MMSYSERR_INVALPARAM;
++}
++
++/**************************************************************************
++ * widDsDesc [internal]
++ */
++DWORD widDsDesc(UINT wDevID, PDSDRIVERDESC desc)
++{
++ *desc = WInDev[wDevID].ds_desc;
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * widMessage (WINEPULSE.@)
++ */
++DWORD WINAPI PULSE_widMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
++ DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
++
++ switch (wMsg) {
++ case DRVM_INIT:
++ case DRVM_EXIT:
++ case DRVM_ENABLE:
++ case DRVM_DISABLE:
++ /* FIXME: Pretend this is supported */
++ return 0;
++ case WIDM_OPEN: return widOpen (wDevID, (DWORD_PTR*)dwUser, (LPWAVEOPENDESC)dwParam1, dwParam2);
++ case WIDM_CLOSE: return widClose (wDevID, (WINE_WAVEINST*)dwUser);
++ case WIDM_ADDBUFFER: return widAddBuffer ((WINE_WAVEINST*)dwUser, (LPWAVEHDR)dwParam1, dwParam2);
++ case WIDM_PREPARE: return MMSYSERR_NOTSUPPORTED;
++ case WIDM_UNPREPARE: return MMSYSERR_NOTSUPPORTED;
++ case WIDM_GETDEVCAPS: return widGetDevCaps(wDevID, (LPWAVEINCAPSW)dwParam1, dwParam2);
++ case WIDM_GETNUMDEVS: return widGetNumDevs();
++ case WIDM_GETPOS: return widGetPosition ((WINE_WAVEINST*)dwUser, (LPMMTIME)dwParam1, dwParam2);
++ case WIDM_RESET: return widRecorderMessage((WINE_WAVEINST*)dwUser, WINE_WM_RESETTING);
++ case WIDM_START: return widRecorderMessage((WINE_WAVEINST*)dwUser, WINE_WM_STARTING);
++ case WIDM_STOP: return widRecorderMessage((WINE_WAVEINST*)dwUser, WINE_WM_STOPPING);
++ case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize(wDevID, (LPDWORD)dwParam1);
++ case DRV_QUERYDEVICEINTERFACE: return widDevInterface(wDevID, (PWCHAR)dwParam1, dwParam2);
++ case DRV_QUERYDSOUNDIFACE: return MMSYSERR_NOTSUPPORTED; /* Use emulation, as there is no advantage */
++ case DRV_QUERYDSOUNDDESC: return widDsDesc(wDevID, (PDSDRIVERDESC)dwParam1);
++ default:
++ FIXME("unknown message %d!\n", wMsg);
++ }
++ return MMSYSERR_NOTSUPPORTED;
++}
++
++#else /* HAVE_PULSEAUDIO */
++
++/**************************************************************************
++ * widMessage (WINEPULSE.@)
++ */
++DWORD WINAPI PULSE_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
++ DWORD dwParam1, DWORD dwParam2) {
++ FIXME("(%u, %04X, %08X, %08X, %08X):stub\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
++ return MMSYSERR_NOTENABLED;
++}
++
++#endif /* HAVE_PULSEAUDIO */
+diff --git a/dlls/winepulse.drv/waveout.c b/dlls/winepulse.drv/waveout.c
+new file mode 100644
+index 0000000..e7454fd
+--- /dev/null
++++ b/dlls/winepulse.drv/waveout.c
+@@ -0,0 +1,1040 @@
++/*
++ * Wine Driver for PulseAudio - WaveOut Functionality
++ * http://pulseaudio.org/
++ *
++ * Copyright 2009 Arthur Taylor <theycallhimart@gmail.com>
++ *
++ * Contains code from other wine multimedia drivers.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
++ */
++
++#include "config.h"
++
++#include <stdarg.h>
++
++#include "windef.h"
++#include "winbase.h"
++#include "wingdi.h"
++#include "winuser.h"
++#include "winnls.h"
++#include "winerror.h"
++#include "mmddk.h"
++
++#include <winepulse.h>
++
++#include "wine/debug.h"
++
++WINE_DEFAULT_DEBUG_CHANNEL(wave);
++
++#if HAVE_PULSEAUDIO
++
++/* state diagram for waveOut writing:
++ *
++ * +---------+-------------+---------------+---------------------------------+
++ * | state | function | event | new state |
++ * +---------+-------------+---------------+---------------------------------+
++ * | | open() | | STOPPED |
++ * | PAUSED | write() | | PAUSED |
++ * | STOPPED | write() | <thrd create> | PLAYING |
++ * | PLAYING | write() | HEADER | PLAYING |
++ * | (other) | write() | <error> | |
++ * | (any) | pause() | PAUSING | PAUSED |
++ * | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) |
++ * | PAUSED | reset() | RESETTING | PAUSED |
++ * | (other) | reset() | RESETTING | STOPPED |
++ * | (any) | close() | CLOSING | CLOSED |
++ * +---------+-------------+---------------+---------------------------------+
++ */
++
++/*
++ * - It is currently unknown if pausing in a loop works the same as expected.
++ */
++
++/*======================================================================*
++ * WAVE OUT specific PulseAudio Callbacks *
++ *======================================================================*/
++
++/**************************************************************************
++ * WAVEOUT_StreamRequestCallback
++ *
++ * Called by the pulse mainloop whenever it wants audio data.
++ */
++static void WAVEOUT_StreamRequestCallback(pa_stream *s, size_t nbytes, void *userdata) {
++ WINE_WAVEINST *ww = (WINE_WAVEINST*)userdata;
++
++ TRACE("Asking to be fed %u bytes\n", nbytes);
++
++ /* Make sure that the player/recorder is running */
++ if (ww->hThread != INVALID_HANDLE_VALUE && ww->msgRing.messages) {
++ PULSE_AddRingMessage(&ww->msgRing, WINE_WM_FEED, (DWORD)nbytes, FALSE);
++ }
++}
++
++/**************************************************************************
++ * WAVEOUT_SinkInputInfoCallback [internal]
++ *
++ * Called by the pulse thread. Used for wodGetVolume.
++ */
++static void WAVEOUT_SinkInputInfoCallback(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata) {
++ WINE_WAVEINST* wwo = (WINE_WAVEINST*)userdata;
++ if (!eol && i) {
++ for (wwo->volume.channels = 0; wwo->volume.channels != i->volume.channels; wwo->volume.channels++)
++ wwo->volume.values[wwo->volume.channels] = i->volume.values[wwo->volume.channels];
++ pa_threaded_mainloop_signal(PULSE_ml, 0);
++ }
++}
++
++/*======================================================================*
++ * "Low level" WAVE OUT implementation *
++ *======================================================================*/
++
++/**************************************************************************
++ * wodPlayer_NotifyClient [internal]
++ */
++static DWORD wodPlayer_NotifyClient(WINE_WAVEINST* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2) {
++ /* TRACE("wMsg = 0x%04x dwParm1 = %04X dwParam2 = %04X\n", wMsg, dwParam1, dwParam2); */
++
++ switch (wMsg) {
++ case WOM_OPEN:
++ case WOM_CLOSE:
++ case WOM_DONE:
++ if (wwo->wFlags != DCB_NULL &&
++ !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags, (HDRVR)wwo->waveDesc.hWave,
++ wMsg, wwo->waveDesc.dwInstance, dwParam1, dwParam2)) {
++ WARN("can't notify client !\n");
++ return MMSYSERR_ERROR;
++ }
++ break;
++ default:
++ FIXME("Unknown callback message %u\n", wMsg);
++ return MMSYSERR_INVALPARAM;
++ }
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * wodPlayer_BeginWaveHdr [internal]
++ *
++ * Makes the specified lpWaveHdr the currently playing wave header.
++ * If the specified wave header is a begin loop and we're not already in
++ * a loop, setup the loop.
++ */
++static void wodPlayer_BeginWaveHdr(WINE_WAVEINST* wwo, LPWAVEHDR lpWaveHdr) {
++ wwo->lpPlayPtr = lpWaveHdr;
++
++ if (!lpWaveHdr) return;
++
++ if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP) {
++ if (wwo->lpLoopPtr) {
++ WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
++ } else {
++ TRACE("Starting loop (%dx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
++ wwo->lpLoopPtr = lpWaveHdr;
++ /* Windows does not touch WAVEHDR.dwLoops,
++ * so we need to make an internal copy */
++ wwo->dwLoops = lpWaveHdr->dwLoops;
++ }
++ }
++ wwo->dwPartialOffset = 0;
++}
++
++/**************************************************************************
++ * wodPlayer_PlayPtrNext [internal]
++ *
++ * Advance the play pointer to the next waveheader, looping if required.
++ */
++static LPWAVEHDR wodPlayer_PlayPtrNext(WINE_WAVEINST* wwo) {
++ LPWAVEHDR lpWaveHdr = wwo->lpPlayPtr;
++
++ wwo->dwPartialOffset = 0;
++ if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr) {
++ /* We're at the end of a loop, loop if required */
++ if (--wwo->dwLoops > 0) {
++ wwo->lpPlayPtr = wwo->lpLoopPtr;
++ } else {
++ /* Handle overlapping loops correctly */
++ if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
++ FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
++ /* shall we consider the END flag for the closing loop or for
++ * the opening one or for both ???
++ * code assumes for closing loop only
++ */
++ } else {
++ lpWaveHdr = lpWaveHdr->lpNext;
++ }
++ wwo->lpLoopPtr = NULL;
++ wodPlayer_BeginWaveHdr(wwo, lpWaveHdr);
++ }
++ } else {
++ /* We're not in a loop. Advance to the next wave header */
++ wodPlayer_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
++ }
++
++ return lpWaveHdr;
++}
++
++/**************************************************************************
++ * wodPlayer_CheckReleasing [internal]
++ *
++ * Check to make sure that playback has not stalled. If stalled ask to reduce
++ * the size of the buffer on the pulse server side.
++ */
++static void wodPlayer_CheckReleasing(WINE_WAVEINST *wwo) {
++ LPWAVEHDR lpWaveHdr;
++
++ if (wwo->buffer_attr.tlength == -1) {
++ pa_threaded_mainloop_lock(PULSE_ml);
++ if (!wwo->timing_info->playing) {
++
++ /* Calculate how large a buffer the application has made so far */
++ wwo->buffer_attr.tlength = 0;
++ wwo->buffer_attr.minreq = wwo->lpQueuePtr->dwBufferLength;
++ for (lpWaveHdr = wwo->lpQueuePtr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext)
++ wwo->buffer_attr.tlength += lpWaveHdr->dwBufferLength;
++
++ WARN("Asking for new buffer target length of %llums (%u bytes)\n",
++ pa_bytes_to_usec(wwo->buffer_attr.tlength, &wwo->sample_spec) / 1000,
++ wwo->buffer_attr.tlength);
++
++ /* Try and adjust the buffer attributes so that playback can start.
++ * Because of bugs pa_stream_set_buffer_attr() does not work on started
++ * streams for server version 0.9.11 to 0.9.14 */
++ PULSE_WaitForOperation(pa_stream_set_buffer_attr(wwo->stream, &wwo->buffer_attr, PULSE_StreamSuccessCallback, wwo));
++ }
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ }
++}
++
++/**************************************************************************
++ * wodPlayer_NotifyCompletions [internal]
++ *
++ * Notifies the client of wavehdr completion starting from lpQueuePtr and
++ * stopping when hitting an unwritten wavehdr, the beginning of a loop or a
++ * wavehdr that has not been played, when referenced to the time parameter.
++ */
++static DWORD wodPlayer_NotifyCompletions(WINE_WAVEINST* wwo, BOOL force, pa_usec_t time) {
++ LPWAVEHDR lpWaveHdr = wwo->lpQueuePtr;
++ pa_usec_t wait;
++
++ while (lpWaveHdr) {
++ if (!force) {
++ /* Start from lpQueuePtr and keep notifying until:
++ * - we hit an unwritten wavehdr
++ * - we hit the beginning of a running loop
++ * - we hit a wavehdr which hasn't finished playing
++ */
++ if (lpWaveHdr == wwo->lpLoopPtr) { TRACE("loop %p\n", lpWaveHdr); return INFINITE; }
++ if (lpWaveHdr == wwo->lpPlayPtr) { TRACE("play %p\n", lpWaveHdr); return INFINITE; }
++
++ /* See if this data has been played, and if not, return when it will have been */
++ wait = pa_bytes_to_usec(lpWaveHdr->reserved + lpWaveHdr->dwBufferLength, &wwo->sample_spec);
++ if (wait >= time) {
++ wait = ((wait - time) + (pa_usec_t)999) / (pa_usec_t)1000;
++ return wait ?: 1;
++ }
++ }
++ TRACE("Returning %p.[%i]\n", lpWaveHdr, (DWORD)lpWaveHdr->reserved);
++
++ /* return the wavehdr */
++ wwo->lpQueuePtr = lpWaveHdr->lpNext;
++ lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
++ lpWaveHdr->dwFlags |= WHDR_DONE;
++
++ wodPlayer_NotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0);
++ lpWaveHdr = wwo->lpQueuePtr;
++ }
++ /* No more wavehdrs */
++ TRACE("Empty queue\n");
++ return INFINITE;
++}
++
++/**************************************************************************
++ * wodPlayer_WriteMax [internal]
++ *
++ * Write either how much free space or how much data we have, depending on
++ * which is less
++ */
++static DWORD wodPlayer_WriteMax(WINE_WAVEINST *wwo, size_t *space) {
++ LPWAVEHDR lpWaveHdr = wwo->lpPlayPtr;
++ size_t nbytes;
++
++ nbytes = min(lpWaveHdr->dwBufferLength - wwo->dwPartialOffset, *space);
++
++ TRACE("Writing wavehdr %p.%u[%u]\n", lpWaveHdr, wwo->dwPartialOffset, lpWaveHdr->dwBufferLength);
++ pa_stream_write(wwo->stream, lpWaveHdr->lpData + wwo->dwPartialOffset, nbytes, NULL, 0, PA_SEEK_RELATIVE);
++
++ /* Check to see if we wrote all of the wavehdr */
++ if ((wwo->dwPartialOffset += nbytes) >= lpWaveHdr->dwBufferLength)
++ wodPlayer_PlayPtrNext(wwo);
++
++ *space -= nbytes;
++
++ return nbytes;
++}
++
++/**************************************************************************
++ * wodPlayer_Feed [internal]
++ *
++ * Feed as much sound data as we can into pulse using wodPlayer_WriteMax.
++ * size_t space _must_ have come from either pa_stream_writable_size() or
++ * the value from a stream write callback, as if it isn't you run the risk
++ * of a buffer overflow in which audio data will be lost.
++ */
++static void wodPlayer_Feed(WINE_WAVEINST* wwo, size_t space) {
++
++ if (!space || !wwo->stream || !PULSE_context ||
++ pa_context_get_state(PULSE_context) != PA_CONTEXT_READY ||
++ pa_stream_get_state(wwo->stream) != PA_STREAM_READY)
++ return;
++
++ pa_threaded_mainloop_lock(PULSE_ml);
++ /* Feed from a partial wavehdr */
++ if (wwo->lpPlayPtr && wwo->dwPartialOffset != 0)
++ wodPlayer_WriteMax(wwo, &space);
++
++ /* Feed wavehdrs until we run out of wavehdrs or buffer space */
++ if (wwo->dwPartialOffset == 0 && wwo->lpPlayPtr) {
++ do {
++ wwo->lpPlayPtr->reserved = wwo->timing_info->write_index;
++ } while (wodPlayer_WriteMax(wwo, &space) && wwo->lpPlayPtr && space > 0);
++ }
++
++ pa_threaded_mainloop_unlock(PULSE_ml);
++}
++
++/**************************************************************************
++ * wodPlayer_Reset [internal]
++ *
++ * wodPlayer helper. Resets current output stream.
++ */
++static void wodPlayer_Reset(WINE_WAVEINST* wwo) {
++ enum win_wm_message msg;
++ DWORD param;
++ HANDLE ev;
++
++ TRACE("(%p)\n", wwo);
++
++ /* Remove any buffer */
++ wodPlayer_NotifyCompletions(wwo, TRUE, 0);
++
++ wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
++ if (wwo->state != WINE_WS_PAUSED)
++ wwo->state = WINE_WS_STOPPED;
++
++ wwo->dwPartialOffset = 0;
++
++ if (!wwo->stream ||
++ !PULSE_context ||
++ pa_context_get_state(PULSE_context) != PA_CONTEXT_READY ||
++ pa_stream_get_state(wwo->stream) != PA_STREAM_READY) {
++ return;
++ }
++
++ pa_threaded_mainloop_lock(PULSE_ml);
++
++ /* Flush the output buffer of written data*/
++ PULSE_WaitForOperation(pa_stream_flush(wwo->stream, PULSE_StreamSuccessCallback, NULL));
++
++ /* Reset the written byte count as some data may have been flushed */
++ if (wwo->timing_info->write_index_corrupt)
++ PULSE_WaitForOperation(pa_stream_update_timing_info(wwo->stream, PULSE_StreamSuccessCallback, wwo));
++
++ wwo->dwLastReset = wwo->timing_info->write_index;
++
++ /* Return all pending headers in queue */
++ EnterCriticalSection(&wwo->msgRing.msg_crst);
++ while (PULSE_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev)) {
++ if (msg != WINE_WM_HEADER) {
++ SetEvent(ev);
++ continue;
++ }
++ ((LPWAVEHDR)param)->dwFlags &= ~WHDR_INQUEUE;
++ ((LPWAVEHDR)param)->dwFlags |= WHDR_DONE;
++ wodPlayer_NotifyClient(wwo, WOM_DONE, param, 0);
++ }
++ PULSE_ResetRingMessage(&wwo->msgRing);
++ LeaveCriticalSection(&wwo->msgRing.msg_crst);
++
++ pa_threaded_mainloop_unlock(PULSE_ml);
++}
++
++/**************************************************************************
++ * wodPlayer_GetStreamTime [internal]
++ *
++ * Returns how many microseconds into the playback the audio stream is. Does
++ * not reset to 0 on Reset() calls. Better than pa_stream_get_time() as it is
++ * more constant.
++ */
++static pa_usec_t wodPlayer_GetStreamTime(WINE_WAVEINST *wwo) {
++ pa_usec_t time, temp;
++ const pa_timing_info *t;
++
++ t = wwo->timing_info;
++
++ pa_threaded_mainloop_lock(PULSE_ml);
++
++ time = pa_bytes_to_usec(t->read_index, &wwo->sample_spec);
++ if (t->read_index_corrupt) {
++ WARN("Read index corrupt?!\n");
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ return time;
++ }
++
++ if (t->playing) {
++ time += pa_timeval_age(&t->timestamp);
++ temp = t->transport_usec + t->configured_sink_usec;
++ if (temp > wwo->buffer_attr.tlength) temp = wwo->buffer_attr.tlength;
++ if (time > temp) time -= temp; else time = 0;
++ }
++
++ /* Make sure we haven't claimed to have played more than we have written */
++ temp = pa_bytes_to_usec(t->write_index, &wwo->sample_spec);
++ if (time > temp) time = temp;
++
++ /* No queued buffer shows an underrun, so we lie */
++ if (!wwo->lpQueuePtr) time = temp;
++
++ pa_threaded_mainloop_unlock(PULSE_ml);
++
++ return time;
++}
++
++/**************************************************************************
++ * wodPlayer_ProcessMessages [internal]
++ */
++static void wodPlayer_ProcessMessages(WINE_WAVEINST* wwo) {
++ LPWAVEHDR lpWaveHdr;
++ enum win_wm_message msg;
++ DWORD param;
++ HANDLE ev;
++
++ while (PULSE_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev)) {
++ TRACE("Received %s %x\n", PULSE_getCmdString(msg), param);
++
++ switch (msg) {
++ case WINE_WM_PAUSING:
++ wwo->state = WINE_WS_PAUSED;
++ pa_threaded_mainloop_lock(PULSE_ml);
++ PULSE_WaitForOperation(pa_stream_cork(wwo->stream, 1, PULSE_StreamSuccessCallback, wwo));
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ SetEvent(ev);
++ break;
++
++ case WINE_WM_RESTARTING:
++ if (wwo->state == WINE_WS_PAUSED) {
++ wwo->state = WINE_WS_PLAYING;
++ pa_threaded_mainloop_lock(PULSE_ml);
++ PULSE_WaitForOperation(pa_stream_cork(wwo->stream, 0, PULSE_StreamSuccessCallback, wwo));
++ /* If the serverside buffer was near full before pausing, we
++ * need to have space to write soon, so force playback start */
++ PULSE_WaitForOperation(pa_stream_trigger(wwo->stream, PULSE_StreamSuccessCallback, wwo));
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ }
++ SetEvent(ev);
++ break;
++
++ case WINE_WM_HEADER:
++ lpWaveHdr = (LPWAVEHDR)param;
++ /* insert buffer at the end of queue */
++ {
++ LPWAVEHDR *wh;
++ for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
++ *wh = lpWaveHdr;
++ }
++
++ if (!wwo->lpPlayPtr)
++ wodPlayer_BeginWaveHdr(wwo,lpWaveHdr);
++ if (wwo->state == WINE_WS_STOPPED)
++ wwo->state = WINE_WS_PLAYING;
++
++ wodPlayer_Feed(wwo, pa_stream_writable_size(wwo->stream));
++ SetEvent(ev);
++ break;
++
++ case WINE_WM_RESETTING:
++ wodPlayer_Reset(wwo);
++ SetEvent(ev);
++ break;
++
++ case WINE_WM_BREAKLOOP:
++ if (wwo->state == WINE_WS_PLAYING && wwo->lpLoopPtr != NULL)
++ /* ensure exit at end of current loop */
++ wwo->dwLoops = 1;
++ SetEvent(ev);
++ break;
++
++ case WINE_WM_FEED: /* Sent by the pulse thread */
++ wodPlayer_Feed(wwo, pa_stream_writable_size(wwo->stream));
++ SetEvent(ev);
++ break;
++
++ case WINE_WM_XRUN: /* Sent by the pulse thread */
++ WARN("Trying to recover from underrun.\n");
++ /* Return all the queued wavehdrs, so the app will send more data */
++ wodPlayer_NotifyCompletions(wwo, FALSE, (pa_usec_t)-1);
++
++ SetEvent(ev);
++ break;
++
++ case WINE_WM_CLOSING:
++ wwo->hThread = NULL;
++ wwo->state = WINE_WS_CLOSED;
++ /* sanity check: this should not happen since the device must have been reset before */
++ if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
++ SetEvent(ev);
++ TRACE("Thread exiting.\n");
++ ExitThread(0);
++ /* shouldn't go here */
++
++ default:
++ FIXME("unknown message %d\n", msg);
++ break;
++ }
++ }
++}
++
++/**************************************************************************
++ * wodPlayer [internal]
++ *
++ * The thread which is responsible for returning WaveHdrs via DriverCallback,
++ * the writing of queued WaveHdrs, and all pause / reset stream management.
++ */
++static DWORD CALLBACK wodPlayer(LPVOID lpParam) {
++ WINE_WAVEINST *wwo = (WINE_WAVEINST*)lpParam;
++ DWORD dwSleepTime = INFINITE;
++ int64_t delta_write;
++
++ wwo->state = WINE_WS_STOPPED;
++ SetEvent(wwo->hStartUpEvent);
++
++ /* Wait for the shortest time before an action is required. If there are
++ * no pending actions, wait forever for a command. */
++ for (;;) {
++ TRACE("Waiting %u ms\n", dwSleepTime);
++ PULSE_WaitRingMessage(&wwo->msgRing, dwSleepTime);
++
++ delta_write = wwo->timing_info->write_index;
++ wodPlayer_ProcessMessages(wwo);
++
++ /* Check for a stall situaiton */
++ if (delta_write == wwo->timing_info->write_index
++ && wwo->lpQueuePtr && !wwo->lpPlayPtr
++ && wwo->state != WINE_WS_STOPPED)
++ wodPlayer_CheckReleasing(wwo);
++
++ /* If there is audio playing, return headers and get next timeout */
++ if (wwo->state == WINE_WS_PLAYING) {
++ dwSleepTime = wodPlayer_NotifyCompletions(wwo, FALSE, wodPlayer_GetStreamTime(wwo));
++ } else
++ dwSleepTime = INFINITE;
++ }
++
++ return 0;
++}
++
++/**************************************************************************
++ * wodOpen [internal]
++ *
++ * Create a new pa_stream and connect it to a sink while creating a new
++ * WINE_WAVEINST to represent the device to the windows application.
++ */
++static DWORD wodOpen(WORD wDevID, DWORD_PTR lpdwUser, LPWAVEOPENDESC lpDesc, DWORD dwFlags) {
++ WINE_WAVEDEV *wdo;
++ WINE_WAVEINST *wwo = NULL;
++ DWORD ret = MMSYSERR_NOERROR;
++
++ TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
++ if (lpDesc == NULL) {
++ WARN("Invalid Parameter!\n");
++ return MMSYSERR_INVALPARAM;
++ }
++
++ if (wDevID >= PULSE_WodNumDevs) {
++ WARN("Asked for device %d, but only %d known!\n", wDevID, PULSE_WodNumDevs);
++ return MMSYSERR_BADDEVICEID;
++ }
++ wdo = &WOutDev[wDevID];
++
++ wwo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_WAVEINST));
++ if (!wwo) {
++ WARN("Out of memory?!\n");
++ return MMSYSERR_NOMEM;
++ }
++ *(WINE_WAVEINST**)lpdwUser = wwo;
++
++ /* check to see if format is supported and make pa_sample_spec struct */
++ if (!PULSE_SetupFormat(lpDesc->lpFormat, &wwo->sample_spec)) {
++ WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
++ lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
++ lpDesc->lpFormat->nSamplesPerSec);
++ ret = WAVERR_BADFORMAT;
++ goto exit;
++ }
++
++ /* Check to see if this was just a query */
++ if (dwFlags & WAVE_FORMAT_QUERY) {
++ TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
++ lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
++ lpDesc->lpFormat->nSamplesPerSec);
++ ret = MMSYSERR_NOERROR;
++ goto exit;
++ }
++
++ if (TRACE_ON(wave)) {
++ char t[PA_SAMPLE_SPEC_SNPRINT_MAX];
++ pa_sample_spec_snprint(t, sizeof(t), &wwo->sample_spec);
++ TRACE("Sample spec '%s'\n", t);
++ }
++
++ wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
++ wwo->waveDesc = *lpDesc;
++ PULSE_InitRingMessage(&wwo->msgRing);
++
++ wwo->stream = pa_stream_new(PULSE_context, "WaveOut", &wwo->sample_spec, NULL);
++ /* If server doesn't support sample_spec, it will error out here (re: 24bit) */
++ if (!wwo->stream) {
++ ret = WAVERR_BADFORMAT;
++ goto exit;
++ }
++
++ /* Setup callbacks */
++ pa_stream_set_write_callback (wwo->stream, WAVEOUT_StreamRequestCallback, wwo);
++ pa_stream_set_state_callback (wwo->stream, PULSE_StreamStateCallback, wwo);
++ pa_stream_set_underflow_callback (wwo->stream, PULSE_StreamUnderflowCallback, wwo);
++ pa_stream_set_moved_callback (wwo->stream, PULSE_StreamMovedCallback, wwo);
++ pa_stream_set_suspended_callback (wwo->stream, PULSE_StreamSuspendedCallback, wwo);
++
++ /* Blank Buffer Attributes */
++ wwo->buffer_attr.prebuf = (uint32_t)-1;
++ wwo->buffer_attr.tlength = (uint32_t)-1;
++ wwo->buffer_attr.minreq = (uint32_t)-1;
++ wwo->buffer_attr.maxlength = (uint32_t)-1;
++
++ /* Try and connect */
++ TRACE("Connecting stream for playback on %s.\n", wdo->device_name);
++ pa_threaded_mainloop_lock(PULSE_ml);
++ pa_stream_connect_playback(wwo->stream, wdo->device_name, NULL, PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY, NULL, NULL);
++
++ /* Wait for connection */
++ for (;;) {
++ pa_context_state_t cstate = pa_context_get_state(PULSE_context);
++ pa_stream_state_t sstate = pa_stream_get_state(wwo->stream);
++
++ if (cstate == PA_CONTEXT_FAILED || cstate == PA_CONTEXT_TERMINATED ||
++ sstate == PA_STREAM_FAILED || sstate == PA_STREAM_TERMINATED) {
++ ERR("Failed to connect stream context object: %s\n", pa_strerror(pa_context_errno(PULSE_context)));
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ ret = MMSYSERR_NODRIVER;
++ goto exit;
++ }
++
++ if (sstate == PA_STREAM_READY)
++ break;
++
++ pa_threaded_mainloop_wait(PULSE_ml);
++ }
++ TRACE("(%p)->stream connected for playback.\n", wwo);
++
++ /* Get the pa_timing_info structure */
++ PULSE_WaitForOperation(pa_stream_update_timing_info(wwo->stream, PULSE_StreamSuccessCallback, wwo));
++ wwo->timing_info = pa_stream_get_timing_info(wwo->stream);
++ assert(wwo->timing_info);
++ pa_threaded_mainloop_unlock(PULSE_ml);
++
++ /* Create and start the wodPlayer() thread to manage playback */
++ wwo->hStartUpEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
++ wwo->hThread = CreateThread(NULL, 0, wodPlayer, (LPVOID)wwo, 0, &(wwo->dwThreadID));
++ if (wwo->hThread)
++ SetThreadPriority(wwo->hThread, THREAD_PRIORITY_TIME_CRITICAL);
++ else {
++ ERR("Thread creation for the wodPlayer failed!\n");
++ ret = MMSYSERR_NOMEM;
++ goto exit;
++ }
++ WaitForSingleObject(wwo->hStartUpEvent, INFINITE);
++ CloseHandle(wwo->hStartUpEvent);
++ wwo->hStartUpEvent = INVALID_HANDLE_VALUE;
++
++ return wodPlayer_NotifyClient (wwo, WOM_OPEN, 0L, 0L);
++
++exit:
++ if (!wwo)
++ return ret;
++
++ if (wwo->hStartUpEvent != INVALID_HANDLE_VALUE)
++ CloseHandle(wwo->hStartUpEvent);
++
++ if (wwo->msgRing.ring_buffer_size > 0)
++ PULSE_DestroyRingMessage(&wwo->msgRing);
++
++ if (wwo->stream) {
++ if (pa_stream_get_state(wwo->stream) == PA_STREAM_READY)
++ pa_stream_disconnect(wwo->stream);
++ pa_stream_unref(wwo->stream);
++ wwo->stream = NULL;
++ }
++ HeapFree(GetProcessHeap(), 0, wwo);
++
++ return ret;
++}
++
++/**************************************************************************
++ * wodClose [internal]
++ */
++static DWORD wodClose(WINE_WAVEINST *wwo) {
++ DWORD ret;
++
++ TRACE("(%p);\n", wwo);
++ if (!wwo) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ if (wwo->state != WINE_WS_FAILED) {
++ if (wwo->lpQueuePtr && wwo->lpPlayPtr) {
++ WARN("buffers still playing !\n");
++ return WAVERR_STILLPLAYING;
++ }
++
++ pa_threaded_mainloop_lock(PULSE_ml);
++ PULSE_WaitForOperation(pa_stream_drain(wwo->stream, PULSE_StreamSuccessCallback, NULL));
++ pa_stream_disconnect(wwo->stream);
++ pa_threaded_mainloop_unlock(PULSE_ml);
++
++ if (wwo->hThread != INVALID_HANDLE_VALUE)
++ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_CLOSING, 0, TRUE);
++
++ PULSE_DestroyRingMessage(&wwo->msgRing);
++ }
++
++ if (wwo->stream)
++ pa_stream_unref(wwo->stream);
++ ret = wodPlayer_NotifyClient(wwo, WOM_CLOSE, 0L, 0L);
++
++ HeapFree(GetProcessHeap(), 0, wwo);
++
++ return ret;
++}
++
++/**************************************************************************
++ * wodWrite [internal]
++ */
++static DWORD wodWrite(WINE_WAVEINST *wwo, LPWAVEHDR lpWaveHdr, DWORD dwSize) {
++ if (!wwo || wwo->state == WINE_WS_FAILED) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
++ return WAVERR_UNPREPARED;
++
++ if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
++ return WAVERR_STILLPLAYING;
++
++ lpWaveHdr->dwFlags &= ~WHDR_DONE;
++ lpWaveHdr->dwFlags |= WHDR_INQUEUE;
++ lpWaveHdr->lpNext = 0;
++ lpWaveHdr->reserved = 0;
++
++ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * wodPause [internal]
++ */
++static DWORD wodPause(WINE_WAVEINST *wwo) {
++ if (!wwo || wwo->state == WINE_WS_FAILED) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_PAUSING, 0, TRUE);
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * wodGetPosition [internal]
++ */
++static DWORD wodGetPosition(WINE_WAVEINST *wwo, LPMMTIME lpTime, DWORD uSize) {
++ pa_usec_t time, temp;
++
++ if (!wwo || wwo->state == WINE_WS_FAILED) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ if (lpTime == NULL) return MMSYSERR_INVALPARAM;
++
++ time = wodPlayer_GetStreamTime(wwo);
++
++ temp = pa_bytes_to_usec(wwo->dwLastReset, &wwo->sample_spec);
++ if (time > temp) time -= temp; else time = 0;
++
++ return PULSE_UsecToMMTime(time, lpTime, &wwo->sample_spec);
++}
++/**************************************************************************
++ * wodBreakLoop [internal]
++ */
++static DWORD wodBreakLoop(WINE_WAVEINST *wwo) {
++ if (!wwo || wwo->state == WINE_WS_FAILED) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_BREAKLOOP, 0, TRUE);
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * wodGetDevCaps [internal]
++ */
++static DWORD wodGetDevCaps(DWORD wDevID, LPWAVEOUTCAPSW lpCaps, DWORD dwSize) {
++ TRACE("(%u, %p, %u);\n", wDevID, lpCaps, dwSize);
++
++ if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
++
++ if (wDevID >= PULSE_WodNumDevs) {
++ TRACE("Asked for device %d, but only %d known!\n", wDevID, PULSE_WodNumDevs);
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ memcpy(lpCaps, &(WOutDev[wDevID].caps.out), min(dwSize, sizeof(*lpCaps)));
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * wodGetNumDevs [internal]
++ * Context-sanity check here, as if we respond with 0, WINE will move on
++ * to the next waveout driver.
++ */
++static DWORD wodGetNumDevs(void) {
++ if (!PULSE_ml || !PULSE_context || pa_context_get_state(PULSE_context) != PA_CONTEXT_READY)
++ return 0;
++
++ return PULSE_WodNumDevs;
++}
++
++/**************************************************************************
++ * wodGetVolume [internal]
++ */
++static DWORD wodGetVolume(WINE_WAVEINST *wwo, LPDWORD lpdwVol) {
++ double value1, value2;
++ DWORD wleft, wright;
++
++ if (!wwo || wwo->state == WINE_WS_FAILED) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ TRACE("(%p, %p);\n", wwo, lpdwVol);
++
++ if (lpdwVol == NULL)
++ return MMSYSERR_NOTENABLED;
++
++ pa_threaded_mainloop_lock(PULSE_ml);
++ if (wwo->stream && PULSE_context && pa_context_get_state(PULSE_context) == PA_CONTEXT_READY &&
++ pa_stream_get_state(wwo->stream) == PA_STREAM_READY) {
++ PULSE_WaitForOperation(pa_context_get_sink_input_info(PULSE_context, pa_stream_get_index(wwo->stream), WAVEOUT_SinkInputInfoCallback, wwo));
++ }
++ pa_threaded_mainloop_unlock(PULSE_ml);
++
++
++ if (wwo->volume.channels == 2) {
++ value1 = pa_sw_volume_to_linear(wwo->volume.values[0]);
++ value2 = pa_sw_volume_to_linear(wwo->volume.values[1]);
++ } else {
++ value1 = pa_sw_volume_to_linear(pa_cvolume_avg(&wwo->volume));
++ value2 = value1;
++ }
++
++ wleft = 0xFFFFl * value1;
++ wright = 0xFFFFl * value2;
++
++ if (wleft > 0xFFFFl)
++ wleft = 0xFFFFl;
++ if (wright > 0xFFFFl)
++ wright = 0xFFFFl;
++
++ *lpdwVol = (WORD)wleft + (WORD)(wright << 16);
++
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * wodSetVolume [internal]
++ */
++static DWORD wodSetVolume(WINE_WAVEINST *wwo, DWORD dwParam1) {
++ double value1, value2;
++
++ TRACE("(%p, %08X);\n", wwo, dwParam1);
++ if (!wwo || wwo->state == WINE_WS_FAILED) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ value1 = (double)LOWORD(dwParam1)/(double)0xFFFFl;
++ value2 = (double)HIWORD(dwParam1)/(double)0xFFFFl;
++
++ if (wwo->sample_spec.channels == 2) {
++ wwo->volume.channels = 2;
++ wwo->volume.values[0] = pa_sw_volume_from_linear(value1);
++ wwo->volume.values[1] = pa_sw_volume_from_linear(value2);
++ } else {
++ if (value1 != value2) FIXME("Non-stereo streams can't pan!\n");
++ wwo->volume.channels = wwo->sample_spec.channels;
++ pa_cvolume_set(&wwo->volume, wwo->volume.channels, pa_sw_volume_from_linear(value1 > value2 ? value1 : value2));
++ }
++
++ if (TRACE_ON(wave)) {
++ char s[PA_CVOLUME_SNPRINT_MAX];
++ pa_cvolume_snprint(s, PA_CVOLUME_SNPRINT_MAX, &wwo->volume);
++ TRACE("%s\n", s);
++ }
++
++ pa_threaded_mainloop_lock(PULSE_ml);
++ if (!wwo->stream || !PULSE_context || pa_context_get_state(PULSE_context) != PA_CONTEXT_READY ||
++ pa_stream_get_state(wwo->stream) != PA_STREAM_READY || !pa_cvolume_valid(&wwo->volume)) {
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ return MMSYSERR_NOERROR;
++ }
++
++ PULSE_WaitForOperation(pa_context_set_sink_input_volume(PULSE_context,
++ pa_stream_get_index(wwo->stream), &wwo->volume,
++ PULSE_ContextSuccessCallback, wwo));
++ pa_threaded_mainloop_unlock(PULSE_ml);
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * wodRestart [internal]
++ */
++static DWORD wodRestart(WINE_WAVEINST *wwo) {
++ if (!wwo || wwo->state == WINE_WS_FAILED) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ if (wwo->state == WINE_WS_PAUSED)
++ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_RESTARTING, 0, TRUE);
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * wodReset [internal]
++ */
++static DWORD wodReset(WINE_WAVEINST *wwo) {
++ if (!wwo || wwo->state == WINE_WS_FAILED) {
++ WARN("Stream instance invalid.\n");
++ return MMSYSERR_INVALHANDLE;
++ }
++
++ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_RESETTING, 0, TRUE);
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * wodDevInterfaceSize [internal]
++ */
++static DWORD wodDevInterfaceSize(UINT wDevID, LPDWORD dwParam1) {
++
++ *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1, NULL, 0) * sizeof(WCHAR);
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * wodDevInterface [internal]
++ */
++static DWORD wodDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2) {
++ if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
++ NULL, 0 ) * sizeof(WCHAR))
++ {
++ MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
++ dwParam1, dwParam2 / sizeof(WCHAR));
++ return MMSYSERR_NOERROR;
++ }
++ return MMSYSERR_INVALPARAM;
++}
++
++DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc) {
++ TRACE("(%u, %p)\n", wDevID, desc);
++ *desc = WOutDev[wDevID].ds_desc;
++ return MMSYSERR_NOERROR;
++}
++
++/**************************************************************************
++ * wodMessage (WINEPULSE.@)
++ */
++DWORD WINAPI PULSE_wodMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
++
++ switch (wMsg) {
++
++ case DRVM_INIT:
++ case DRVM_EXIT:
++ case DRVM_ENABLE:
++ case DRVM_DISABLE:
++ return 0;
++
++ /* WaveOut Playback related functions */
++ case WODM_OPEN: return wodOpen (wDevID, dwUser, (LPWAVEOPENDESC)dwParam1, dwParam2);
++ case WODM_CLOSE: return wodClose ((WINE_WAVEINST*)dwUser);
++ case WODM_WRITE: return wodWrite ((WINE_WAVEINST*)dwUser, (LPWAVEHDR)dwParam1, dwParam2);
++ case WODM_PAUSE: return wodPause ((WINE_WAVEINST*)dwUser);
++ case WODM_GETPOS: return wodGetPosition ((WINE_WAVEINST*)dwUser, (LPMMTIME)dwParam1, dwParam2);
++ case WODM_BREAKLOOP: return wodBreakLoop ((WINE_WAVEINST*)dwUser);
++ case WODM_RESTART: return wodRestart ((WINE_WAVEINST*)dwUser);
++ case WODM_RESET: return wodReset ((WINE_WAVEINST*)dwUser);
++
++ case WODM_GETVOLUME: return wodGetVolume ((WINE_WAVEINST*)dwUser, (LPDWORD)dwParam1);
++ case WODM_SETVOLUME: return wodSetVolume ((WINE_WAVEINST*)dwUser, dwParam1);
++
++ case WODM_PREPARE:
++ case WODM_UNPREPARE:
++
++ case WODM_GETPITCH:
++ case WODM_SETPITCH:
++
++ case WODM_GETPLAYBACKRATE:
++ case WODM_SETPLAYBACKRATE:
++ return MMSYSERR_NOTSUPPORTED;
++
++ /* Device enumeration, directsound and capabilities */
++ case WODM_GETDEVCAPS: return wodGetDevCaps (wDevID, (LPWAVEOUTCAPSW)dwParam1, dwParam2);
++ case WODM_GETNUMDEVS: return wodGetNumDevs ();
++ case DRV_QUERYDEVICEINTERFACESIZE: return wodDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
++ case DRV_QUERYDEVICEINTERFACE: return wodDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
++ case DRV_QUERYDSOUNDIFACE: return MMSYSERR_NOTSUPPORTED;
++ case DRV_QUERYDSOUNDDESC: return wodDsDesc (wDevID, (PDSDRIVERDESC)dwParam1);
++
++ default:
++ FIXME("unknown message %d!\n", wMsg);
++ }
++ return MMSYSERR_NOTSUPPORTED;
++}
++
++#else /* !HAVE_PULSEAUDIO */
++
++/**************************************************************************
++ * wodMessage (WINEPULSE.@)
++ */
++DWORD WINAPI PULSE_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
++ DWORD dwParam1, DWORD dwParam2) {
++ FIXME("(%u, %04X, %08X, %08X, %08X):stub\n", wDevID, wMsg, dwUser,
++ dwParam1, dwParam2);
++ return MMSYSERR_NOTENABLED;
++}
++
++#endif /* HAVE_PULSEAUDIO */
+diff --git a/dlls/winepulse.drv/winepulse.drv.spec b/dlls/winepulse.drv/winepulse.drv.spec
+new file mode 100644
+index 0000000..1b49460
+--- /dev/null
++++ b/dlls/winepulse.drv/winepulse.drv.spec
+@@ -0,0 +1,3 @@
++@ stdcall -private DriverProc(long long long long long long) PULSE_DriverProc
++@ stdcall -private wodMessage(long long long long long long) PULSE_wodMessage
++@ stdcall -private widMessage(long long long long long long) PULSE_widMessage
+diff --git a/dlls/winepulse.drv/winepulse.h b/dlls/winepulse.drv/winepulse.h
+new file mode 100644
+index 0000000..0aa7e86
+--- /dev/null
++++ b/dlls/winepulse.drv/winepulse.h
+@@ -0,0 +1,196 @@
++/* Definitions for PulseAudio Wine Driver
++ *
++ * Copyright 2009 Arthur Taylor <theycallhimart@gmail.com>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
++ */
++
++#ifndef __WINE_CONFIG_H
++# error You must include config.h to use this header
++#endif
++
++#if defined(HAVE_PULSEAUDIO) && !defined(__WINEPULSE_H)
++#define __WINEPULSE_H
++
++#include "mmreg.h"
++#include "dsound.h"
++#include "dsdriver.h"
++
++#include "ks.h"
++#include "ksmedia.h"
++#include "ksguid.h"
++
++#include <pulse/pulseaudio.h>
++
++/* state diagram for waveOut writing:
++ *
++ * +---------+-------------+---------------+---------------------------------+
++ * | state | function | event | new state |
++ * +---------+-------------+---------------+---------------------------------+
++ * | | open() | | STOPPED |
++ * | PAUSED | write() | | PAUSED |
++ * | STOPPED | write() | <thrd create> | PLAYING |
++ * | PLAYING | write() | HEADER | PLAYING |
++ * | (other) | write() | <error> | |
++ * | (any) | pause() | PAUSING | PAUSED |
++ * | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) |
++ * | (any) | reset() | RESETTING | STOPPED |
++ * | (any) | close() | CLOSING | CLOSED |
++ * +---------+-------------+---------------+---------------------------------+
++ */
++
++/* states of the playing device */
++#define WINE_WS_PLAYING 1
++#define WINE_WS_PAUSED 2
++#define WINE_WS_STOPPED 3
++#define WINE_WS_CLOSED 4
++#define WINE_WS_FAILED 5
++
++#define PULSE_ALL_FORMATS \
++ WAVE_FORMAT_1M08 | /* Mono 11025Hz 8-bit */\
++ WAVE_FORMAT_1M16 | /* Mono 11025Hz 16-bit */\
++ WAVE_FORMAT_1S08 | /* Stereo 11025Hz 8-bit */\
++ WAVE_FORMAT_1S16 | /* Stereo 11025Hz 16-bit */\
++ WAVE_FORMAT_2M08 | /* Mono 22050Hz 8-bit */\
++ WAVE_FORMAT_2M16 | /* Mono 22050Hz 16-bit */\
++ WAVE_FORMAT_2S08 | /* Stereo 22050Hz 8-bit */\
++ WAVE_FORMAT_2S16 | /* Stereo 22050Hz 16-bit */\
++ WAVE_FORMAT_4M08 | /* Mono 44100Hz 8-bit */\
++ WAVE_FORMAT_4M16 | /* Mono 44100Hz 16-bit */\
++ WAVE_FORMAT_4S08 | /* Stereo 44100Hz 8-bit */\
++ WAVE_FORMAT_4S16 | /* Stereo 44100Hz 16-bit */\
++ WAVE_FORMAT_48M08 | /* Mono 48000Hz 8-bit */\
++ WAVE_FORMAT_48S08 | /* Stereo 48000Hz 8-bit */\
++ WAVE_FORMAT_48M16 | /* Mono 48000Hz 16-bit */\
++ WAVE_FORMAT_48S16 | /* Stereo 48000Hz 16-bit */\
++ WAVE_FORMAT_96M08 | /* Mono 96000Hz 8-bit */\
++ WAVE_FORMAT_96S08 | /* Stereo 96000Hz 8-bit */\
++ WAVE_FORMAT_96M16 | /* Mono 96000Hz 16-bit */\
++ WAVE_FORMAT_96S16 /* Stereo 96000Hz 16-bit */
++
++/* events to be sent to device */
++enum win_wm_message {
++ WINE_WM_PAUSING = WM_USER + 1, WINE_WM_RESTARTING, WINE_WM_RESETTING, WINE_WM_HEADER,
++ WINE_WM_BREAKLOOP, WINE_WM_CLOSING, WINE_WM_STARTING, WINE_WM_STOPPING, WINE_WM_XRUN, WINE_WM_FEED
++};
++
++typedef struct {
++ enum win_wm_message msg; /* message identifier */
++ DWORD param; /* parameter for this message */
++ HANDLE hEvent; /* if message is synchronous, handle of event for synchro */
++} PULSE_MSG;
++
++/* implement an in-process message ring for better performance
++ * (compared to passing thru the server)
++ * this ring will be used by the input (resp output) record (resp playback) routine
++ */
++typedef struct {
++ PULSE_MSG * messages;
++ int ring_buffer_size;
++ int msg_tosave;
++ int msg_toget;
++/* Either pipe or event is used, but that is defined in pulse.c,
++ * since this is a global header we define both here */
++ int msg_pipe[2];
++ HANDLE msg_event;
++ CRITICAL_SECTION msg_crst;
++} PULSE_MSG_RING;
++
++typedef struct WINE_WAVEDEV WINE_WAVEDEV;
++typedef struct WINE_WAVEINST WINE_WAVEINST;
++
++/* Per-playback/record device */
++struct WINE_WAVEDEV {
++ char interface_name[MAXPNAMELEN * 2];
++ char *device_name;
++ pa_cvolume volume;
++
++ union {
++ WAVEOUTCAPSW out;
++ WAVEINCAPSW in;
++ } caps;
++
++ /* DirectSound stuff */
++ DSDRIVERDESC ds_desc;
++ DSDRIVERCAPS ds_caps;
++};
++
++/* Per-playback/record instance */
++struct WINE_WAVEINST {
++ INT state; /* one of the WINE_WS_ manifest constants */
++ WAVEOPENDESC waveDesc;
++ WORD wFlags;
++
++ /* PulseAudio specific data */
++ pa_stream *stream; /* The PulseAudio stream */
++ const pa_timing_info *timing_info; /* The timing info structure for the stream */
++ pa_sample_spec sample_spec; /* Sample spec of this stream / device */
++ pa_cvolume volume; /* Software volume of the stream */
++ pa_buffer_attr buffer_attr; /* Buffer attribute, may not be used */
++
++ /* waveIn / waveOut wavaHdr */
++ LPWAVEHDR lpQueuePtr; /* Start of queued WAVEHDRs (waiting to be notified) */
++ LPWAVEHDR lpPlayPtr; /* Start of not yet fully written buffers */
++ DWORD dwPartialOffset; /* Offset of not yet written bytes in lpPlayPtr */
++ LPWAVEHDR lpLoopPtr; /* Pointer of first buffer in loop, if any */
++ DWORD dwLoops; /* Private copy of loop counter */
++ DWORD dwLastReset; /* When the last reset occured, as pa stream time doesn't reset */
++
++ /* waveIn specific */
++ const void *buffer; /* Pointer to the latest data fragment for recording streams */
++ DWORD buffer_length; /* How large the latest data fragment is */
++ DWORD buffer_read_offset; /* How far into latest data fragment we last read */
++
++ /* Thread communication and synchronization stuff */
++ HANDLE hStartUpEvent;
++ HANDLE hThread;
++ DWORD dwThreadID;
++ PULSE_MSG_RING msgRing;
++};
++
++/* We establish one context per instance, so make it global to the lib */
++pa_context *PULSE_context; /* Connection Context */
++pa_threaded_mainloop *PULSE_ml; /* PA Runtime information */
++
++/* WaveIn / WaveOut devices */
++WINE_WAVEDEV *WOutDev;
++WINE_WAVEDEV *WInDev;
++DWORD PULSE_WodNumDevs;
++DWORD PULSE_WidNumDevs;
++
++/* pulse.c: PulseAudio Async Callbacks */
++void PULSE_StreamSuccessCallback(pa_stream *s, int success, void *userdata);
++void PULSE_StreamStateCallback(pa_stream *s, void *userdata);
++void PULSE_StreamUnderflowCallback(pa_stream *s, void *userdata);
++void PULSE_StreamSuspendedCallback(pa_stream *s, void *userdata);
++void PULSE_StreamMovedCallback(pa_stream *s, void *userdata);
++void PULSE_ContextSuccessCallback(pa_context *c, int success, void *userdata);
++
++/* pulse.c: General Functions */
++void PULSE_WaitForOperation(pa_operation *o);
++BOOL PULSE_SetupFormat(LPWAVEFORMATEX wf, pa_sample_spec *ss);
++HRESULT PULSE_UsecToMMTime(pa_usec_t time, LPMMTIME lpTime, const pa_sample_spec *ss);
++
++/* pulse.c: Message Ring */
++int PULSE_InitRingMessage(PULSE_MSG_RING* omr);
++int PULSE_DestroyRingMessage(PULSE_MSG_RING* omr);
++void PULSE_ResetRingMessage(PULSE_MSG_RING* omr);
++void PULSE_WaitRingMessage(PULSE_MSG_RING* omr, DWORD sleep);
++int PULSE_AddRingMessage(PULSE_MSG_RING* omr, enum win_wm_message msg, DWORD param, BOOL wait);
++int PULSE_RetrieveRingMessage(PULSE_MSG_RING* omr, enum win_wm_message *msg, DWORD *param, HANDLE *hEvent);
++
++/* pulse.c: Tracing */
++const char * PULSE_getCmdString(enum win_wm_message msg);
++#endif
diff --git a/app-emulation/wine/files/winepulse-winecfg-0.6.patch b/app-emulation/wine/files/winepulse-winecfg-0.6.patch
new file mode 100644
index 00000000..9cbbf588
--- /dev/null
+++ b/app-emulation/wine/files/winepulse-winecfg-0.6.patch
@@ -0,0 +1,313 @@
+diff --git a/programs/winecfg/Bg.rc b/programs/winecfg/Bg.rc
+index fcdf895..ec24068 100644
+--- a/programs/winecfg/Bg.rc
++++ b/programs/winecfg/Bg.rc
+@@ -276,6 +276,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standard"
+ IDS_ACCEL_BASIC "Basic"
+ IDS_ACCEL_EMULATION "Emulation"
++ IDS_DRIVER_PULSE "PulseAudio Driver"
+ IDS_DRIVER_ALSA "ALSA Driver"
+ IDS_DRIVER_ESOUND "EsounD Driver"
+ IDS_DRIVER_OSS "OSS Driver"
+diff --git a/programs/winecfg/Cs.rc b/programs/winecfg/Cs.rc
+index d9c0b28..6171f1f 100644
+--- a/programs/winecfg/Cs.rc
++++ b/programs/winecfg/Cs.rc
+@@ -276,6 +276,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standardn"
+ IDS_ACCEL_BASIC "Zkladn"
+ IDS_ACCEL_EMULATION "Emulace"
++ IDS_DRIVER_PULSE "Ovlada PulseAudio"
+ IDS_DRIVER_ALSA "Ovlada ALSA"
+ IDS_DRIVER_ESOUND "Ovlada EsounD"
+ IDS_DRIVER_OSS "Ovlada OSS"
+diff --git a/programs/winecfg/Da.rc b/programs/winecfg/Da.rc
+index f53aead..e33bd78 100644
+--- a/programs/winecfg/Da.rc
++++ b/programs/winecfg/Da.rc
+@@ -270,6 +270,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standard"
+ IDS_ACCEL_BASIC "Grundlggende"
+ IDS_ACCEL_EMULATION "Emulring"
++ IDS_DRIVER_PULSE "PulseAudio-driver"
+ IDS_DRIVER_ALSA "ALSA-driver"
+ IDS_DRIVER_ESOUND "EsounD-driver"
+ IDS_DRIVER_OSS "OSS-driver"
+diff --git a/programs/winecfg/De.rc b/programs/winecfg/De.rc
+index aadd21e..f3016ab 100644
+--- a/programs/winecfg/De.rc
++++ b/programs/winecfg/De.rc
+@@ -282,6 +282,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standard"
+ IDS_ACCEL_BASIC "Einfach"
+ IDS_ACCEL_EMULATION "Emulation"
++ IDS_DRIVER_PULSE "PulseAudio-Treiber"
+ IDS_DRIVER_ALSA "ALSA-Treiber"
+ IDS_DRIVER_ESOUND "EsounD-Treiber"
+ IDS_DRIVER_OSS "OSS-Treiber"
+diff --git a/programs/winecfg/En.rc b/programs/winecfg/En.rc
+index 6aa5120..6f30805 100644
+--- a/programs/winecfg/En.rc
++++ b/programs/winecfg/En.rc
+@@ -282,6 +282,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standard"
+ IDS_ACCEL_BASIC "Basic"
+ IDS_ACCEL_EMULATION "Emulation"
++ IDS_DRIVER_PULSE "PulseAudio Driver"
+ IDS_DRIVER_ALSA "ALSA Driver"
+ IDS_DRIVER_ESOUND "EsounD Driver"
+ IDS_DRIVER_OSS "OSS Driver"
+diff --git a/programs/winecfg/Es.rc b/programs/winecfg/Es.rc
+index 1771b4e..aaacaa9 100644
+--- a/programs/winecfg/Es.rc
++++ b/programs/winecfg/Es.rc
+@@ -270,6 +270,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Estndar"
+ IDS_ACCEL_BASIC "Bsica"
+ IDS_ACCEL_EMULATION "Emulacin"
++ IDS_DRIVER_PULSE "Manejador PulseAudio"
+ IDS_DRIVER_ALSA "Manejador ALSA"
+ IDS_DRIVER_ESOUND "Manejador EsounD"
+ IDS_DRIVER_OSS "Manejador OSS"
+diff --git a/programs/winecfg/Fi.rc b/programs/winecfg/Fi.rc
+index 0dedf3a..5217482 100644
+--- a/programs/winecfg/Fi.rc
++++ b/programs/winecfg/Fi.rc
+@@ -270,6 +270,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standard"
+ IDS_ACCEL_BASIC "Basic"
+ IDS_ACCEL_EMULATION "Emulation"
++ IDS_DRIVER_PULSE "PulseAudio Driver"
+ IDS_DRIVER_ALSA "ALSA Driver"
+ IDS_DRIVER_ESOUND "EsounD Driver"
+ IDS_DRIVER_OSS "OSS Driver"
+diff --git a/programs/winecfg/Fr.rc b/programs/winecfg/Fr.rc
+index a9184f9..004ebb0 100644
+--- a/programs/winecfg/Fr.rc
++++ b/programs/winecfg/Fr.rc
+@@ -284,6 +284,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standard"
+ IDS_ACCEL_BASIC "Basique"
+ IDS_ACCEL_EMULATION "Émulation"
++ IDS_DRIVER_PULSE "Pilote PulseAudio"
+ IDS_DRIVER_ALSA "Pilote ALSA"
+ IDS_DRIVER_ESOUND "Pilote EsounD"
+ IDS_DRIVER_OSS "Pilote OSS"
+diff --git a/programs/winecfg/Hu.rc b/programs/winecfg/Hu.rc
+index dc887fe..9bd192e 100644
+--- a/programs/winecfg/Hu.rc
++++ b/programs/winecfg/Hu.rc
+@@ -270,6 +270,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standard"
+ IDS_ACCEL_BASIC "Basic"
+ IDS_ACCEL_EMULATION "Emulation"
++ IDS_DRIVER_PULSE "PulseAudio Driver"
+ IDS_DRIVER_ALSA "ALSA Driver"
+ IDS_DRIVER_ESOUND "EsounD Driver"
+ IDS_DRIVER_OSS "OSS Driver"
+diff --git a/programs/winecfg/It.rc b/programs/winecfg/It.rc
+index ddeda8c..1530b5f 100644
+--- a/programs/winecfg/It.rc
++++ b/programs/winecfg/It.rc
+@@ -284,6 +284,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standard"
+ IDS_ACCEL_BASIC "Base"
+ IDS_ACCEL_EMULATION "Emulazione"
++ IDS_DRIVER_PULSE "Driver PulseAudio"
+ IDS_DRIVER_ALSA "Driver ALSA"
+ IDS_DRIVER_ESOUND "Driver Esound"
+ IDS_DRIVER_OSS "Driver OSS"
+diff --git a/programs/winecfg/Ja.rc b/programs/winecfg/Ja.rc
+index 5b77da7..316d2e5 100644
+--- a/programs/winecfg/Ja.rc
++++ b/programs/winecfg/Ja.rc
+@@ -285,6 +285,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "標準"
+ IDS_ACCEL_BASIC "基本"
+ IDS_ACCEL_EMULATION "エミュレーション"
++ IDS_DRIVER_PULSE "PulseAudio ドライバ"
+ IDS_DRIVER_ALSA "ALSA ドライバ"
+ IDS_DRIVER_ESOUND "EsounD ドライバ"
+ IDS_DRIVER_OSS "OSS ドライバ"
+diff --git a/programs/winecfg/Ko.rc b/programs/winecfg/Ko.rc
+index bf06647..66f9803 100644
+--- a/programs/winecfg/Ko.rc
++++ b/programs/winecfg/Ko.rc
+@@ -285,6 +285,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "ǥ"
+ IDS_ACCEL_BASIC "⺻"
+ IDS_ACCEL_EMULATION "ֹķ̼"
++ IDS_DRIVER_PULSE "PulseAudio ̹"
+ IDS_DRIVER_ALSA "ALSA ̹"
+ IDS_DRIVER_ESOUND "EsounD ̹"
+ IDS_DRIVER_OSS "OSS ̹"
+diff --git a/programs/winecfg/Lt.rc b/programs/winecfg/Lt.rc
+index 7208cc6..5aa8fdb 100644
+--- a/programs/winecfg/Lt.rc
++++ b/programs/winecfg/Lt.rc
+@@ -283,6 +283,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standartinis"
+ IDS_ACCEL_BASIC "Bazinis"
+ IDS_ACCEL_EMULATION "Emuliacija"
++ IDS_DRIVER_PULSE "PulseAudio tvarkyklė"
+ IDS_DRIVER_ALSA "ALSA tvarkyklė"
+ IDS_DRIVER_ESOUND "EsounD tvarkyklė"
+ IDS_DRIVER_OSS "OSS tvarkyklė"
+diff --git a/programs/winecfg/Nl.rc b/programs/winecfg/Nl.rc
+index 2fbba6a..802abab 100644
+--- a/programs/winecfg/Nl.rc
++++ b/programs/winecfg/Nl.rc
+@@ -283,6 +283,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standaard"
+ IDS_ACCEL_BASIC "Eenvoudig"
+ IDS_ACCEL_EMULATION "Emulatie"
++ IDS_DRIVER_PULSE "PulseAudio Stuurprogramma"
+ IDS_DRIVER_ALSA "ALSA Stuurprogramma"
+ IDS_DRIVER_ESOUND "EsounD Stuurprogramma"
+ IDS_DRIVER_OSS "OSS Stuurprogramma"
+diff --git a/programs/winecfg/No.rc b/programs/winecfg/No.rc
+index cc34fad..0f0aea8 100644
+--- a/programs/winecfg/No.rc
++++ b/programs/winecfg/No.rc
+@@ -270,6 +270,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standard"
+ IDS_ACCEL_BASIC "Grunnleggende"
+ IDS_ACCEL_EMULATION "Emulering"
++ IDS_DRIVER_PULSE "PulseAudio-driver"
+ IDS_DRIVER_ALSA "ALSA-driver"
+ IDS_DRIVER_ESOUND "EsounD-driver"
+ IDS_DRIVER_OSS "OSS-driver"
+diff --git a/programs/winecfg/Pl.rc b/programs/winecfg/Pl.rc
+index d884881..bb97de5 100644
+--- a/programs/winecfg/Pl.rc
++++ b/programs/winecfg/Pl.rc
+@@ -273,6 +273,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standardowe"
+ IDS_ACCEL_BASIC "Podstawowe"
+ IDS_ACCEL_EMULATION "Emulacja"
++ IDS_DRIVER_PULSE "Sterownik PulseAudio"
+ IDS_DRIVER_ALSA "Sterownik ALSA"
+ IDS_DRIVER_ESOUND "Sterownik EsounD"
+ IDS_DRIVER_OSS "Sterownik OSS"
+diff --git a/programs/winecfg/Pt.rc b/programs/winecfg/Pt.rc
+index 683dc68..be92466 100644
+--- a/programs/winecfg/Pt.rc
++++ b/programs/winecfg/Pt.rc
+@@ -470,6 +470,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Padrão"
+ IDS_ACCEL_BASIC "Básico"
+ IDS_ACCEL_EMULATION "Emulação"
++ IDS_DRIVER_PULSE "Controlador PulseAudio"
+ IDS_DRIVER_ALSA "Controlador ALSA"
+ IDS_DRIVER_ESOUND "Controlador EsounD"
+ IDS_DRIVER_OSS "Controlador OSS"
+diff --git a/programs/winecfg/Ro.rc b/programs/winecfg/Ro.rc
+index 5626018..6c84511 100644
+--- a/programs/winecfg/Ro.rc
++++ b/programs/winecfg/Ro.rc
+@@ -282,6 +282,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standard"
+ IDS_ACCEL_BASIC "De bază"
+ IDS_ACCEL_EMULATION "Emulare"
++ IDS_DRIVER_PULSE "Driver PulseAudio"
+ IDS_DRIVER_ALSA "Driver ALSA"
+ IDS_DRIVER_ESOUND "Driver Esound"
+ IDS_DRIVER_OSS "Driver OSS"
+diff --git a/programs/winecfg/Ru.rc b/programs/winecfg/Ru.rc
+index 38b4546..73c0250 100644
+--- a/programs/winecfg/Ru.rc
++++ b/programs/winecfg/Ru.rc
+@@ -287,6 +287,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Стандартное"
+ IDS_ACCEL_BASIC "Минимальное"
+ IDS_ACCEL_EMULATION "Эмуляция"
++ IDS_DRIVER_PULSE "PulseAudio драйвер"
+ IDS_DRIVER_ALSA "ALSA драйвер"
+ IDS_DRIVER_ESOUND "EsounD драйвер"
+ IDS_DRIVER_OSS "OSS драйвер"
+diff --git a/programs/winecfg/Si.rc b/programs/winecfg/Si.rc
+index feaef36..1d10bae 100644
+--- a/programs/winecfg/Si.rc
++++ b/programs/winecfg/Si.rc
+@@ -272,6 +272,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standardno"
+ IDS_ACCEL_BASIC "Osnovno"
+ IDS_ACCEL_EMULATION "Emulacija"
++ IDS_DRIVER_PULSE "PulseAudio gonilnik"
+ IDS_DRIVER_ALSA "ALSA gonilnik"
+ IDS_DRIVER_ESOUND "EsounD gonilnik"
+ IDS_DRIVER_OSS "OSS gonilnik"
+diff --git a/programs/winecfg/Sv.rc b/programs/winecfg/Sv.rc
+index 7fea5aa..1979b5a 100644
+--- a/programs/winecfg/Sv.rc
++++ b/programs/winecfg/Sv.rc
+@@ -270,6 +270,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standard"
+ IDS_ACCEL_BASIC "Grundlggande"
+ IDS_ACCEL_EMULATION "Emulering"
++ IDS_DRIVER_PULSE "PulseAudio-drivrutin"
+ IDS_DRIVER_ALSA "ALSA-drivrutin"
+ IDS_DRIVER_ESOUND "EsounD-drivrutin"
+ IDS_DRIVER_OSS "OSS-drivrutin"
+diff --git a/programs/winecfg/Tr.rc b/programs/winecfg/Tr.rc
+index 0fa9778..5ea7da1 100644
+--- a/programs/winecfg/Tr.rc
++++ b/programs/winecfg/Tr.rc
+@@ -270,6 +270,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "Standart"
+ IDS_ACCEL_BASIC "Temel"
+ IDS_ACCEL_EMULATION "Taklit"
++ IDS_DRIVER_PULSE "PulseAudio Srcs"
+ IDS_DRIVER_ALSA "ALSA Srcs"
+ IDS_DRIVER_ESOUND "EsounD Srcs"
+ IDS_DRIVER_OSS "OSS Srcs"
+diff --git a/programs/winecfg/Zh.rc b/programs/winecfg/Zh.rc
+index 8c84061..3de1da8 100644
+--- a/programs/winecfg/Zh.rc
++++ b/programs/winecfg/Zh.rc
+@@ -275,6 +275,7 @@ BEGIN
+ IDS_ACCEL_STANDARD "标准"
+ IDS_ACCEL_BASIC "基本"
+ IDS_ACCEL_EMULATION "软件模拟"
++ IDS_DRIVER_PULSE "PulseAudio 驱动"
+ IDS_DRIVER_ALSA "ALSA 驱动"
+ IDS_DRIVER_ESOUND "EsounD 驱动"
+ IDS_DRIVER_OSS "OSS 驱动"
+diff --git a/programs/winecfg/audio.c b/programs/winecfg/audio.c
+index 9f8a0a2..59837ef 100644
+--- a/programs/winecfg/audio.c
++++ b/programs/winecfg/audio.c
+@@ -89,6 +89,7 @@ typedef struct
+ } AUDIO_DRIVER;
+
+ static const AUDIO_DRIVER sAudioDrivers[] = {
++ {IDS_DRIVER_PULSE, "pulse"},
+ {IDS_DRIVER_ALSA, "alsa"},
+ {IDS_DRIVER_OSS, "oss"},
+ {IDS_DRIVER_COREAUDIO, "coreaudio"},
+diff --git a/programs/winecfg/libraries.c b/programs/winecfg/libraries.c
+index 37cc12b..7c13fad 100644
+--- a/programs/winecfg/libraries.c
++++ b/programs/winecfg/libraries.c
+@@ -81,6 +81,7 @@ static const char * const builtin_only[] =
+ "wineoss.drv",
+ "wineps",
+ "wineps.drv",
++ "winepulse.drv",
+ "winex11.drv",
+ "winmm",
+ "wintab32",
+diff --git a/programs/winecfg/resource.h b/programs/winecfg/resource.h
+index f006861..57b2a15 100644
+--- a/programs/winecfg/resource.h
++++ b/programs/winecfg/resource.h
+@@ -187,7 +187,7 @@
+ #define IDS_ACCEL_BASIC 8302
+ #define IDS_ACCEL_EMULATION 8303
+ #define IDS_DRIVER_ALSA 8304
+-
++#define IDS_DRIVER_PULSE 8305
+ #define IDS_DRIVER_ESOUND 8306
+ #define IDS_DRIVER_OSS 8307
+ #define IDS_DRIVER_JACK 8308
diff --git a/app-emulation/wine/wine-1.1.34.ebuild b/app-emulation/wine/wine-1.1.34.ebuild
new file mode 100644
index 00000000..4c563486
--- /dev/null
+++ b/app-emulation/wine/wine-1.1.34.ebuild
@@ -0,0 +1,177 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI="2"
+
+inherit autotools eutils flag-o-matic multilib
+
+if [[ ${PV} == "9999" ]] ; then
+ EGIT_REPO_URI="git://source.winehq.org/git/wine.git"
+ inherit git
+ SRC_URI=""
+ #KEYWORDS=""
+else
+ MY_P="${PN}-${PV/_/-}"
+ SRC_URI="mirror://sourceforge/${PN}/${MY_P}.tar.bz2"
+ KEYWORDS="-* ~amd64 ~x86 ~x86-fbsd"
+ S=${WORKDIR}/${MY_P}
+fi
+
+GV="1.0.0-x86"
+DESCRIPTION="free implementation of Windows(tm) on Unix"
+HOMEPAGE="http://www.winehq.org/"
+SRC_URI="${SRC_URI}
+ gecko? ( mirror://sourceforge/wine/wine_gecko-${GV}.cab )"
+
+LICENSE="LGPL-2.1"
+SLOT="0"
+IUSE="alsa capi cups custom-cflags dbus esd fontconfig +gecko gnutls gphoto2 gsm hal jack jpeg lcms ldap mp3 nas ncurses openal +opengl oss +perl png pulseaudio samba scanner ssl test +threads +truetype win64 +X xcomposite xinerama xml"
+RESTRICT="test" #72375
+
+RDEPEND="truetype? ( >=media-libs/freetype-2.0.0 media-fonts/corefonts )
+ perl? ( dev-lang/perl dev-perl/XML-Simple )
+ capi? ( net-dialup/capi4k-utils )
+ ncurses? ( >=sys-libs/ncurses-5.2 )
+ fontconfig? ( media-libs/fontconfig )
+ gphoto2? ( media-libs/libgphoto2 )
+ jack? ( media-sound/jack-audio-connection-kit )
+ openal? ( media-libs/openal )
+ dbus? ( sys-apps/dbus )
+ gnutls? ( net-libs/gnutls )
+ hal? ( sys-apps/hal )
+ X? (
+ x11-libs/libXcursor
+ x11-libs/libXrandr
+ x11-libs/libXi
+ x11-libs/libXmu
+ x11-libs/libXxf86vm
+ x11-apps/xmessage
+ )
+ alsa? ( media-libs/alsa-lib )
+ esd? ( media-sound/esound )
+ nas? ( media-libs/nas )
+ cups? ( net-print/cups )
+ opengl? ( virtual/opengl )
+ gsm? ( media-sound/gsm )
+ jpeg? ( media-libs/jpeg )
+ ldap? ( net-nds/openldap )
+ lcms? ( media-libs/lcms )
+ mp3? ( media-sound/mpg123 )
+ samba? ( >=net-fs/samba-3.0.25 )
+ xml? ( dev-libs/libxml2 dev-libs/libxslt )
+ scanner? ( media-gfx/sane-backends )
+ ssl? ( dev-libs/openssl )
+ png? ( media-libs/libpng )
+ pulseaudio? ( >=media-sound/pulseaudio-0.9.15 )
+ !win64? ( amd64? (
+ truetype? ( >=app-emulation/emul-linux-x86-xlibs-2.1 )
+ X? (
+ >=app-emulation/emul-linux-x86-xlibs-2.1
+ >=app-emulation/emul-linux-x86-soundlibs-2.1
+ )
+ app-emulation/emul-linux-x86-baselibs
+ >=sys-kernel/linux-headers-2.6
+ ) )
+ xcomposite? ( x11-libs/libXcomposite ) "
+DEPEND="${RDEPEND}
+ X? (
+ x11-proto/inputproto
+ x11-proto/xextproto
+ x11-proto/xf86vidmodeproto
+ )
+ sys-devel/bison
+ sys-devel/flex"
+
+apply_winepulse() {
+ epatch "${FILESDIR}"/winepulse-0.33.patch
+ epatch "${FILESDIR}"/winepulse-0.32-configure.ac.patch
+ epatch "${FILESDIR}"/winepulse-winecfg-0.6.patch
+ eautoreconf
+}
+
+src_unpack() {
+ if [[ $(( $(gcc-major-version) * 100 + $(gcc-minor-version) )) -lt 404 ]] ; then
+ use win64 && die "you need gcc-4.4+ to build 64bit wine"
+ fi
+einfo "$(gcc-major-version) * 100 + $(gcc-minor-version)"
+
+ if [[ ${PV} == "9999" ]] ; then
+ git_src_unpack
+ else
+ unpack ${MY_P}.tar.bz2
+ fi
+}
+
+src_prepare() {
+ epatch "${FILESDIR}"/${PN}-1.1.15-winegcc.patch #260726
+ epatch_user #282735
+ sed -i '/^UPDATE_DESKTOP_DATABASE/s:=.*:=true:' tools/Makefile.in || die
+ sed -i '/^MimeType/d' tools/wine.desktop || die #117785
+ use pulseaudio && EPATCH_OPTS="-p1" apply_winepulse
+}
+
+src_configure() {
+ export LDCONFIG=/bin/true
+
+ use custom-cflags || strip-flags
+ use amd64 && ! use win64 && multilib_toolchain_setup x86
+
+ econf \
+ --sysconfdir=/etc/wine \
+ $(use_with alsa) \
+ $(use_with capi) \
+ $(use_with lcms cms) \
+ $(use_with cups) \
+ $(use_with ncurses curses) \
+ $(use_with esd) \
+ $(use_with fontconfig) \
+ $(use_with gnutls) \
+ $(use_with gphoto2 gphoto) \
+ $(use_with gsm) \
+ $(! use dbus && echo --without-hal || use_with hal) \
+ $(use_with jack) \
+ $(use_with jpeg) \
+ $(use_with ldap) \
+ $(use_with mp3 mpg123) \
+ $(use_with nas) \
+ $(use_with openal) \
+ $(use_with opengl) \
+ $(use_with ssl openssl) \
+ $(use_with oss) \
+ $(use_with png) \
+ $(use_with threads pthread) \
+ $(use_with scanner sane) \
+ $(use_enable test tests) \
+ $(use_with truetype freetype) \
+ $(use_enable win64) \
+ $(use_with X x) \
+ $(use_with xcomposite) \
+ $(use_with xinerama) \
+ $(use_with xml) \
+ $(use_with xml xslt) \
+ || die "configure failed"
+
+ emake -j1 depend || die "depend"
+}
+
+src_compile() {
+ emake all || die "all"
+}
+
+src_install() {
+ emake DESTDIR="${D}" install || die
+ dodoc ANNOUNCE AUTHORS README
+ if use gecko ; then
+ insinto /usr/share/wine/gecko
+ doins "${DISTDIR}"/wine_gecko-${GV}.cab || die
+ fi
+ if ! use perl ; then
+ rm "${D}"/usr/bin/{wine{dump,maker},function_grep.pl} "${D}"/usr/share/man/man1/wine{dump,maker}.1 || die
+ fi
+}
+
+pkg_postinst() {
+ paxctl -psmr "${ROOT}"/usr/bin/wine{,-preloader} 2>/dev/null #255055
+}
diff --git a/app-misc/klavaro/klavaro-1.4.0.ebuild b/app-misc/klavaro/klavaro-1.4.0.ebuild
new file mode 100644
index 00000000..ab421c56
--- /dev/null
+++ b/app-misc/klavaro/klavaro-1.4.0.ebuild
@@ -0,0 +1,28 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+inherit eutils
+
+DESCRIPTION="Another free touch typing tutor program"
+HOMEPAGE="http://klavaro.sourceforge.net/"
+SRC_URI="mirror://sourceforge/${PN}/${P}.tar.bz2"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE=""
+
+RDEPEND="net-misc/curl
+ x11-libs/gtkdatabox
+ x11-libs/libsexy"
+
+DEPEND="${RDEPEND}
+ sys-devel/gettext"
+
+src_install() {
+ emake DESTDIR="${D}" install || die "make install failed"
+ make_desktop_entry klavaro Klavaro "" Education
+ dodoc AUTHORS ChangeLog NEWS README TODO || die "dodoc failed"
+}
diff --git a/app-office/abiword/abiword-2.8.1.ebuild b/app-office/abiword/abiword-2.8.1.ebuild
new file mode 100644
index 00000000..b13764db
--- /dev/null
+++ b/app-office/abiword/abiword-2.8.1.ebuild
@@ -0,0 +1,92 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI="2"
+
+inherit alternatives eutils gnome2 versionator
+
+MY_MAJORV=$(get_version_component_range 1-2)
+
+DESCRIPTION="Fully featured yet light and fast cross platform word processor"
+HOMEPAGE="http://www.abisource.com/"
+SRC_URI="http://www.abisource.com/downloads/${PN}/${PV}/source/${P}.tar.gz"
+
+LICENSE="GPL-2"
+SLOT="2"
+KEYWORDS="~alpha ~amd64 ~hppa ~ia64 ~ppc ~ppc64 ~sparc ~x86"
+IUSE="debug gnome spell xml"
+
+# FIXME: gsf could probably be conditional
+
+# Pango version so it always has X use flag
+RDEPEND="dev-libs/popt
+ sys-libs/zlib
+ >=dev-libs/glib-2
+ >=x11-libs/gtk+-2.6
+ x11-libs/libXft
+ >=x11-libs/pango-1.24.2[X]
+ >=gnome-base/libglade-2
+ >=gnome-base/libgnomeprint-2.2
+ >=gnome-base/libgnomeprintui-2.2
+ >=x11-libs/goffice-0.6:0.6
+ >=media-libs/libpng-1.2
+ >=media-libs/fontconfig-2.1
+ >=media-libs/freetype-2.1
+ >=app-text/wv-1.2
+ >=dev-libs/fribidi-0.10.4
+ xml? ( >=dev-libs/libxml2-2.4.10 )
+ !xml? ( dev-libs/expat )
+ spell? ( >=app-text/enchant-1.2 )
+ gnome? (
+ >=gnome-base/libbonobo-2
+ >=gnome-base/libgnomeui-2.2
+ >=gnome-extra/gucharmap-1.4
+ >=gnome-base/gnome-vfs-2.2 )
+ >=gnome-extra/libgsf-1.12.0"
+
+DEPEND="${RDEPEND}
+ >=dev-util/pkgconfig-0.9"
+
+# FIXME: --enable-libabiword fails to compile
+
+pkg_setup() {
+ G2CONF="${G2CONF}
+ $(use_enable debug)
+ $(use_enable debug symbols)
+ $(use_enable gnome gnomeui)
+ $(use_enable gnome gucharmap)
+ $(use_enable gnome gnomevfs)
+ $(use_enable spell spellcheck)
+ $(use_with xml libxml2)
+ $(use_with !xml expat)
+ --enable-libabiword
+ --enable-printing"
+}
+
+src_install() {
+ # Install icon to pixmaps, bug #220097
+ sed 's:icondir = $(datadir)/icons:icondir = $(datadir)/pixmaps:' \
+ -i Makefile || die "sed 1 failed"
+
+ gnome2_src_install
+
+ sed "s:Exec=abiword:Exec=abiword-${MY_MAJORV}:" \
+ -i "${D}"/usr/share/applications/abiword.desktop || die "sed 2 failed"
+
+ mv "${D}/usr/bin/abiword" "${D}/usr/bin/AbiWord-${MY_MAJORV}"
+ dosym AbiWord-${MY_MAJORV} /usr/bin/abiword-${MY_MAJORV}
+
+ dodoc *.TXT user/wp/readme.txt
+}
+
+pkg_postinst() {
+ gnome2_pkg_postinst
+
+ alternatives_auto_makesym "/usr/bin/abiword" "/usr/bin/abiword-[0-9].[0-9]"
+
+ elog "As of version 2.4, all abiword plugins have been moved"
+ elog "into a seperate app-office/abiword-plugins package"
+ elog "You can install them by running emerge abiword-plugins"
+}
diff --git a/app-paludis/plop/Manifest b/app-paludis/plop/Manifest
new file mode 100644
index 00000000..9d6fd137
--- /dev/null
+++ b/app-paludis/plop/Manifest
@@ -0,0 +1,8 @@
+AUX plop-0.1_0.30.8.patch 11283 RMD160 83f81246c3cc0501e992dcef50e94455db8cd2fd SHA1 cc004895220c49fca44024f05aac671b01c47d2b SHA256 8aad9fed7a7bd8289ee0c8f55a9a5d9b14c03d80fac3bee7e47bd044bcf5ba6d
+AUX plop-0.2.1_0.30.8.patch 13347 RMD160 d7bc7af7f880014fed6c65f09874dfff1421a88b SHA1 1edb27977e404f3d73985161f6cc1a621a929d6c SHA256 2ae46a27cd12162a6350805eb68cb77607a5d5f4fd0da0367251aa0541c264c5
+AUX plop-0.2.2_0.30.8.patch 13905 RMD160 50584d3a3cfa1351e104fb7ed33932e4c447aa1e SHA1 b7f68ffbb037b12eb0c0ecc8ea4d9059e94fdd49 SHA256 239dd8134b0363fce6f4d7400f7ed7f1e394142561297276c7598b61512a8707
+AUX plop-0.2.3_0.30.8.patch 14202 RMD160 5b45265a49a9dfea6c316de38182a1cc660385b9 SHA1 15d40a3533eeb451f05551b20e4b454ca7df3f3b SHA256 9238e3f2a3508705df8a1689418eabfe5fd99eff4276947c6f6da957ef7dffab
+AUX plop-0.2_0.30.8.patch 13340 RMD160 eb21ef1e4e9872fd4609e07d184803a74a45a218 SHA1 c9572491dc9932b164362b29b5b94cece6dd5dc9 SHA256 04914d667a75d0bc0389a9b6b9cd73d49619bc14965be4f77e99585baa435bc2
+AUX plop.bash-completion 2255 RMD160 deb6e27bfb99fbca3cde5bd30b6d44567ac69a77 SHA1 fb7b9cddbe5b0358ed6cd4d9e5b0c269c1ed848a SHA256 08c96f4c2bc90bc40af08634d98fd5535986f5e935f90af9c252156906fcaeaf
+DIST plop-0.2.3.tar.gz 21315 RMD160 11a1590f91e49d985a5109fe8ca3421855cd4c9e SHA1 dafd5ec96c4ddd6d189feb104c9cb7811d143728 SHA256 944cdfcb9d633dacc4a196039d509e6dc9a22e4ec1715255733a75ca6a36a9e4
+EBUILD plop-0.2.3.ebuild 1648 RMD160 aed89c8bfbf1a0792ba4fb7a2333e2b077594768 SHA1 fb155c6f283805b0a49de8eb56c1f6993af683dc SHA256 9ebecf6b8d58ccf0a2c904f4786eb8f989ef9092c29e38b1ebba92ff85a995fe
diff --git a/app-paludis/plop/files/plop-0.2.3_0.30.8.patch b/app-paludis/plop/files/plop-0.2.3_0.30.8.patch
new file mode 100644
index 00000000..98b6b3f0
--- /dev/null
+++ b/app-paludis/plop/files/plop-0.2.3_0.30.8.patch
@@ -0,0 +1,312 @@
+--- genlop-0.30.8/genlop 2007-10-04 10:15:07.000000000 +0200
++++ plop-0.2.3/plop 2008-07-15 20:57:14.000000000 +0200
+@@ -17,16 +17,17 @@
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ #
+
+-use strict;
+-use warnings;
++#use strict;
++#use warnings;
++#use diagnostics;
+ use POSIX;
+ use Term::ANSIColor;
+ use Date::Manip;
+ use LWP::Simple;
+ use File::Basename;
+
+-my $version = "0.30.7";
+-my @logfiles = ("/var/log/emerge.log");
++my $version = "0.2.3";
++my @logfiles = ("/var/log/paludis.log");
+ my %COLORS = (
+ 'blue' => 'bold blue',
+ 'green' => 'bold green',
+@@ -109,9 +110,9 @@
+ sub open_file
+ {
+ my ($file, $fh) = @_;
+- if ($file eq "/var/log/emerge.log" && !-r $file)
++ if ($file eq "/var/log/paludis.log" && !-r $file)
+ {
+- print "$progname: cannot open " . $file . " for reading\n" . "maybe you are not a member of the portage group ?\n" . "try genlop -h for help\n";
++ print "$progname: cannot open " . $file . " for reading\n" . "maybe you are not a member of the portage group ?\n" . "try plop -h for help\n";
+ exit 1;
+ }
+ if (-T $file)
+@@ -334,24 +335,24 @@
+ # provides help information
+ sub help ()
+ {
+- print "Usage: ", colored("genlop ", $COLORS{'blue'}), "[", colored("options", $COLORS{'green'}), "] [", colored("-f ", $COLORS{'green'}), "logfile] [",
++ print "Usage: ", colored(basename($0)." ", $COLORS{'blue'}), "[", colored("options", $COLORS{'green'}), "] [", colored("-f ", $COLORS{'green'}), "logfile] [",
+ colored("category/package", $COLORS{'green'}), "]\n\n", colored("Options:\n", $COLORS{'green'}), colored(" -c ", $COLORS{'green'}),
+ "display the currently compiling packages (if any)\n", colored(" -e ", $COLORS{'green'}) . "display package history; default if any option is used.\n",
+- colored(" -f ", $COLORS{'green'}), "read emerge log information from \"logfile\" instead of ", $logfiles[0], "\n",
++ colored(" -f ", $COLORS{'green'}), "read paludis log information from \"logfile\" instead of ", $logfiles[0], "\n",
+ colored(" -h ", $COLORS{'green'}), "print this help\n", colored(" -i ", $COLORS{'green'}),
+ "extra infos for the selected package (build specific USE ", "and CFLAGS\n variables, average build time, etc)\n",
+ colored(" -g ", $COLORS{'green'}), "display GMT/UTC, not localized time.\n", colored(" -l ", $COLORS{'green'}), "show full merge history.\n",
+ colored(" -n ", $COLORS{'green'}), "no color in output\n", colored(" -p ", $COLORS{'green'}),
+- "estimate build time from a piped \"emerge -p\" output\n", colored(" -q ", $COLORS{'green'}),
++ "estimate build time from a piped \"paludis -p\" output\n", colored(" -q ", $COLORS{'green'}),
+ "query gentoo.linuxhowtos.org database if no local emerge was found\n", colored(" -r ", $COLORS{'green'}),
+ "search for portage tree sync/rsync history.\n", colored(" -s ", $COLORS{'green'}),
+ "use (case insensitive) regular expressions to match package names\n", colored(" -S ", $COLORS{'green'}),
+ "use case sensitive regular expressions to match package names\n", colored(" -t ", $COLORS{'green'}),
+ "calculate merge time for the specific package(s).\n", colored(" -u ", $COLORS{'green'}), "show when packages have been unmerged.\n",
+- colored(" -v ", $COLORS{'green'}), "display genlop version and exit.\n\n", colored(" --date datestring1", $COLORS{'green'}), " [",
++ colored(" -v ", $COLORS{'green'}), "display plop version and exit.\n\n", colored(" --date datestring1", $COLORS{'green'}), " [",
+ colored(" --date datestring2", $COLORS{'green'}), "] only shows results between datestring1\n",
+- " and datestring2. datestring2 dafaults to \"now\" if not", " explicitly set.\n", " (e.g. genlop --list --date 3 days ago)\n",
+- "\nThis program is licensed under the GPL v2. See COPYING.\n", "For further info about genlop please read the man page.\n";
++ " and datestring2. datestring2 dafaults to \"now\" if not", " explicitly set.\n", " (e.g. plop --list --date 3 days ago)\n",
++ "\nThis program is licensed under the GPL v2. See COPYING.\n", "For further info about plop please read the man page.\n";
+ exit 0;
+ }
+
+@@ -432,7 +433,7 @@
+ }
+ else
+ {
+- $regexp = qr/(.*)(-[0-9]{1,7}.*?)/i;
++ $regexp = qr/(.*)(-(?:[0-9]{1,7}|scm).*?)/i;
+ }
+ return "$regexp";
+ }
+@@ -452,8 +453,8 @@
+ {
+ $regexp =
+ $ssearch_found
+- ? qr/(.*$arg.*?)(-[0-9]{1,7}.*?)/
+- : qr/(.*$arg.*?)(-[0-9]{1,7}.*?)/i;
++ ? qr/(.*$arg.*?)(-(?:[0-9]{1,7}|scm).*?)/
++ : qr/(.*$arg.*?)(-(?:[0-9]{1,7}|scm).*?)/i;
+ }
+ return "$regexp";
+ }
+@@ -464,8 +465,8 @@
+ $category = $arg;
+ $regexp =
+ $ssearch_found
+- ? qr/($category.*?)(-[0-9]{1,7}.*?)/
+- : qr/($category.*?)(-[0-9]{1,7}.*?)/i;
++ ? qr/($category.*?)(-(?:[0-9]{1,7}|scm).*?)/
++ : qr/($category.*?)(-(?:[0-9]{1,7}|scm).*?)/i;
+ return "$regexp";
+ }
+ @list = split(/\//, $arg);
+@@ -475,7 +476,7 @@
+ $category = $list[0];
+ $ebuild = $list[1];
+ @list = ();
+- @list = split(/(-[0-9]{1,7})/, $ebuild);
++ @list = split(/(-(?:[0-9]{1,7}|scm))/, $ebuild);
+ if ($list[1])
+ {
+ $ebuild = $list[0];
+@@ -489,14 +490,14 @@
+ }
+ $regexp =
+ $ssearch_found
+- ? qr!($category\/$ebuild)(-[0-9]{1,7}.*?)!
+- : qr!($category\/$ebuild)(-[0-9]{1,7}.*?)!i;
++ ? qr!($category\/$ebuild)(-(?:[0-9]{1,7}|scm).*?)!
++ : qr!($category\/$ebuild)(-(?:[0-9]{1,7}|scm).*?)!i;
+ return "$regexp";
+ }
+ $regexp =
+ $ssearch_found
+- ? qr!(.*?/$ebuild)(-[0-9]{1,7}.*?)!
+- : qr!(.*?/$ebuild)(-[0-9]{1,7}.*?)!i;
++ ? qr!(.*?/$ebuild)(-(?:[0-9]{1,7}|scm).*?)!
++ : qr!(.*?/$ebuild)(-(?:[0-9]{1,7}|scm).*?)!i;
+ return "$regexp";
+ }
+
+@@ -558,10 +559,10 @@
+ print "These are the pretended packages:";
+ print " (this may take a while; wait...)\n\n";
+
+- # open STDIN; that's why emerge -p foo is piped to a genlop -p
++ # open STDIN; that's why emerge -p foo is piped to a plop -p
+ while (<STDIN>)
+ {
+- if ($_ =~ m/^\[e.*\] (.*?)\/(.*?)(\-[0-9])/)
++ if ($_ =~ m/^\* (.*?)\/(.*?)(\-(?:[0-9]|scm))/)
+ {
+ push @targets, $2;
+ print;
+@@ -580,11 +581,11 @@
+ open_file($logfile, \$handle);
+ foreach (<$handle>)
+ {
+- if (m/^(.*?)\: \>\>\> emerge.*?\/$ebuild_arg-[0-9].*/)
++ if (m/^(.*?)\: starting install of package .*?\/$ebuild_arg-(?:[0-9]|scm).*?::/)
+ {
+ $e_start = $1;
+ }
+- if (m/^(.*?)\: ::: completed .*?\) .*\/$ebuild_arg-[0-9].* to \//)
++ if (m/^(.*?)\: finished install of package .*?\/$ebuild_arg-(?:[0-9]|scm).*?::/)
+ {
+ $e_end = $1;
+ $tm_secondi += ($e_end - $e_start);
+@@ -666,11 +667,12 @@
+ # not check for sanity and have users check their FEATURES instead.
+ my @targets = ();
+ my @sandbox_pids = ();
+- my @sandbox_procs = qx{ps ax -o pid,args | tail -n +2 | sed -e's/^ *//' | grep ' sandbox ' | grep -v ' grep '};
+- my ($e_curmerge, $e_lastmerge);
++ my @sandbox_procs = qx{ps ax -w -o pid,args|grep '[s]andbox'}; # [s] so you don't need this ugly grep -v grep, also the use of tail and such are foobar
++ my $r_start = 0;
++ my ($r_curmerge, $r_lastmerge, $r_current);
+ foreach (@sandbox_procs)
+ {
+- if (m/^(.*?) \[(.*?)\-[0-9].*?\]/)
++ if (m/^(.*?) sandbox .*? .*\/(.*?)\-(?:[0-9]|scm).*?\.(ebuild|kdebuild-1) .*/)
+ {
+ push @sandbox_pids, $1;
+ push @targets, $2;
+@@ -692,7 +694,6 @@
+ }
+ foreach my $ebuild_arg (@targets)
+ {
+- my $e_current;
+ $ebuild_arg =~ s/(\+)/\\$1/g;
+ foreach my $logfile (@logfiles)
+ {
+@@ -700,14 +701,17 @@
+ open_file($logfile, \$handle);
+ foreach (<$handle>)
+ {
+- if (m/^(.*?)\: \>\>\> emerge \((.*?) of (.*?)\)(.*?\/$ebuild_arg-[0-9].*?)to \//)
++ if (m/^(.*?)\: starting install of package (.*?\/$ebuild_arg-(?:[0-9]|scm).*?::.*?) \((.*?) of (.*?)\)/)
+ {
++ if ($1 > $r_start) {
++ $r_start = $1;
++ $r_curmerge = $3;
++ $r_lastmerge = $4;
++ $r_current = $2;
++ }
+ $e_start = $1;
+- $e_curmerge = $2;
+- $e_lastmerge = $3;
+- $e_current = $4;
+ }
+- if (m/^(.*?)\: ::: completed .*?\) .*\/$ebuild_arg-[0-9].* to \//)
++ if (m/^(.*?)\: finished install of package .*\/$ebuild_arg-(?:[0-9]|scm).*::.* \(.*\)/)
+ {
+ $e_end = $1;
+ $e_count++;
+@@ -717,9 +721,9 @@
+ }
+ }
+ $e_end = CORE::time();
+- &gtime($e_end - $e_start);
+- print "\n Currently merging $e_curmerge out of $e_lastmerge\n";
+- print colored("\n \*$e_current\n\n", $COLORS{'blue'});
++ &gtime($e_end - $r_start);
++ print "\n Currently merging $r_curmerge out of $r_lastmerge\n";
++ print colored("\n \*$r_current\n\n", $COLORS{'blue'});
+ print " current merge time: ";
+ $current_found = undef;
+ &print_gtime();
+@@ -735,10 +739,10 @@
+ $e_count = 1;
+ }
+
+- if ($e_count && $e_start)
++ if ($e_count && $r_start)
+ {
+- &gtime(($tm_secondi / $e_count) - ($e_end - $e_start));
+- if (($e_end - $e_start) >= ($tm_secondi / $e_count))
++ &gtime(($tm_secondi / $e_count) - ($e_end - $r_start));
++ if (($e_end - $r_start) >= ($tm_secondi / $e_count))
+ {
+ print colored("any time now.\n", $COLORS{'green'});
+ }
+@@ -808,7 +812,7 @@
+ #$package =~ s/(\+)/\\$1/g;
+ my $tmp_package = $package;
+ $tmp_package =~ s/\+/\\+/g;
+- if ("$categoria/$package_dir" =~ m/$tmp_package\-[0-9].*/)
++ if ("$categoria/$package_dir" =~ m/$tmp_package\-(?:[0-9]|scm).*/)
+ {
+ $info_ok = 1;
+ print colored("\n * $categoria/$package_dir\n", $COLORS{'blue'});
+@@ -821,8 +825,8 @@
+ open_file($logfile, \$handle);
+ foreach (<$handle>)
+ {
+- my $pattern = gen_regexp("$categoria/$package_dir");
+- if (m/^([0-9]{10})\: ::: completed .*?\) $pattern to \//)
++ my $pattern = gen_regexp("$categoria/$package_dir");
++ if (m/^([0-9]{10})\: finished install of package ${pattern}:.*::/)
+ {
+ if ($gmt_found)
+ {
+@@ -851,13 +855,10 @@
+
+ # we search into the installed ebuild for USE flags available
+ # and store them in @potential_use.
+- open(pkg_ebuild, "$db_pkg_dir/$1.ebuild") || return;
++ open(pkg_ebuild, "$db_pkg_dir/IUSE") || return;
+ while (<pkg_ebuild>)
+ {
+- if ($_ =~ m/^IUSE=\"(\$\{IUSE\} )?(.*)"/g)
+- {
+- @potential_use = split(/\ /, $2);
+- }
++ @potential_use = split(/\ /, $_);
+ }
+ }
+
+@@ -917,7 +918,7 @@
+ my $handle;
+ open_file($_, \$handle);
+ while(<$handle>) {
+- if ($_ =~ m/^(.*?)\: \=\=\= Sync completed with/) {
++ if ($_ =~ m/^(.*?)\: finished sync of repository gentoo/) {
+ if ($date_found) {
+ if (datecompare($1) <= 0) {
+ next;
+@@ -952,7 +953,10 @@
+ help() if ($help_found);
+ if ($version_found)
+ {
+- print "genlop $version, maintained by Michael Cummings <mcummings\@gentoo.org>\n"
++ print "plop $version, patched genlop 0.30.8 for use with paludis\n"
++ . "patched by Tobias Hommel <software\@genoetigt.de>\n"
++ . "original genlop info:\n"
++ . "genlop, maintained by Michael Cummings <mcummings\@gentoo.org>\n"
+ . "original code by Giorgio Mandolfo and Antonio Dolcetta\n"
+ . "Please file any bugs found online at:\n"
+ . "https://bugs.gentoo.org\n"
+@@ -1015,15 +1019,15 @@
+ if ($current_found) { &current; }
+ if ($time_found or $info_found)
+ {
+- if ($_ =~ m/^([0-9]{10})\: \>\>\> emerge .*?\) $pattern/)
++ if ($_ =~ m/^([0-9]{10})\: starting install of package ${pattern}::/)
+ {
+ $e_start = $1;
+ $info_target = $2;
+ }
+ }
+- if ($_ =~ m/^([0-9]{10})\: ::: completed .*?\) $pattern to \//)
++ if ($_ =~ m/^([0-9]{10})\: finished install of package ${pattern}::/)
+ {
+- my $e_date;
++ my $e_date;
+ if ($gmt_found)
+ {
+ $e_date = scalar gmtime "$1";
+@@ -1093,7 +1097,7 @@
+ if ($unmerge_found or $info_found)
+ {
+ $pattern = gen_regexp($ebuild_arg);
+- if (m/^([0-9]{10})\: \>\>\> unmerge success: ($pattern.*)/g)
++ if (m/^([0-9]{10})\: finished uninstall of package ($pattern)::/g)
+ {
+ my $u_date = scalar localtime "$1";
+ if ($unmerge_found)
diff --git a/app-paludis/plop/files/plop.bash-completion b/app-paludis/plop/files/plop.bash-completion
new file mode 100644
index 00000000..ad03d86c
--- /dev/null
+++ b/app-paludis/plop/files/plop.bash-completion
@@ -0,0 +1,60 @@
+# -*- shell-script -*-
+# If you have bash completion installed and want plop to auto-complete
+# packages, save this file as /etc/bash_completion.d/plop
+#
+# Copyright 1999-2002 Gentoo Technologies, Inc.
+# Distributed under the terms of the GNU General Public License, v2 or later
+#
+# Author: Geert Bevin <gbevin@theleaf.be>
+# Author: Zach Forrest <zach@disinformation.ca>
+#
+# Adapted for genlop by Giorgio Mandolfo <giorgio@pollycoke.org>
+# Adapted for plop by Tobias Hommel <software@genoetigt.de>
+#
+_plop()
+{
+ local cur grepcmd sedcmd systemactions setsma setbig portagedir origdir
+
+ origdir="${PWD}"
+ COMPREPLY=()
+# whoa, what a funny construction
+ portagedir="$( echo `eval echo $(grep '^location' /etc/paludis/repositories/gentoo.conf|sed 's/^location = \(.*\)/\1/')` )"
+ if [ -z "${portagedir}" ]; then
+ portagedir=/usr/portage
+ fi
+ cur="${COMP_WORDS[COMP_CWORD]}"
+
+ cd "${portagedir}"
+ grepcmd="grep -E ^${cur}.*"
+ sedcmd="sed -e /^[^-]*$/d"
+ case "$cur" in
+ -*)
+ COMPREPLY=( $( compgen -W '--current --file --help \
+ --info --gmt --list --nocolor --pretend --rsync \
+ --search --time --unmerge --version' -- $cur ) )
+ ;;
+ *)
+ if [ "${cur}" ]; then
+ if [ $(echo "${cur}" | grep '/') ]; then
+ setbig=$(compgen -G "${cur}*" | ${sedcmd})"${systemactions}"
+ COMPREPLY=($(echo "${setbig}" | $grepcmd))
+ else
+ setsma=$(compgen -S '/' -G "${cur}*" | ${sedcmd})"${systemactions}"
+ if [ $(echo "${setsma}" | ${grepcmd} | grep '/' | wc -l) = 1 ]; then
+ setbig=$(compgen -G "*/*" | ${sedcmd})"${systemactions}"
+ COMPREPLY=($(echo "${setbig}" | ${grepcmd}))
+ else
+ COMPREPLY=($(echo "${setsma}" | ${grepcmd}))
+ fi
+ fi
+ else
+ setsma=$(compgen -S '/' -G "${cur}*" | ${sedcmd})"${systemactions}"
+ COMPREPLY=($(echo "${setsma}"))
+ fi
+ ;;
+ esac
+
+ cd "${origdir}"
+ return 0
+}
+complete -o default -F _plop plop
diff --git a/app-paludis/plop/plop-0.2.3.ebuild b/app-paludis/plop/plop-0.2.3.ebuild
new file mode 100644
index 00000000..a37e1dcb
--- /dev/null
+++ b/app-paludis/plop/plop-0.2.3.ebuild
@@ -0,0 +1,51 @@
+# Copyright 1999-2007 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+inherit eutils bash-completion
+
+DESCRIPTION="A nice paludis.log parser (patched genlop)"
+HOMEPAGE="http://www.genoetigt.de/site/projects/plop"
+# I copied the genlop-0.30.8.tar.gz and renamed it to plop-0.1.tar.gz
+SRC_URI="http://www.genoetigt.de/plop/${P}.tar.gz"
+RESTRICT="nomirror"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~alpha amd64 ~arm ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc x86 ~x86-fbsd"
+IUSE=""
+
+DEPEND=">=dev-lang/perl-5.8.0-r12
+ >=dev-perl/DateManip-5.40
+ dev-perl/libwww-perl"
+
+src_unpack() {
+ unpack ${A}
+ mv ${WORKDIR}/genlop-0.30.8/ ${S}
+ cd "${S}"
+ mv genlop plop
+ mv genlop.1 plop.1
+# mv genlop.bash-completion plop.bash-completion
+
+epatch "${FILESDIR}/plop-${PV}_0.30.8.patch"
+}
+
+src_install() {
+ dobin plop || die "failed to install plop (via dobin)"
+ dodoc README Changelog
+ doman plop.1
+ dobashcompletion ${FILESDIR}/plop.bash-completion plop
+}
+
+pkg_postinst() {
+ einfo "Note that plop is just a patched genlop-0.30.8. I only patched the"
+ einfo "main script. The manpage, README, etc. are all original genlop"
+ einfo "files, but since plop is expected to work like genlop this"
+ einfo "shouldn't be a problem. so if you find see genlop somewhere, simply"
+ einfo "substitute it with plop, as long as it hasn't to do anything with"
+ einfo "copyright or other credits"
+
+ einfo "to convert old emerge.logfiles I've written a small perlscript that"
+ einfo "you can download on the plop homepage"
+}
diff --git a/app-text/asciidoc/asciidoc-8.5.1.ebuild b/app-text/asciidoc/asciidoc-8.5.1.ebuild
new file mode 100644
index 00000000..f3fc7cab
--- /dev/null
+++ b/app-text/asciidoc/asciidoc-8.5.1.ebuild
@@ -0,0 +1,61 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI="2"
+
+DESCRIPTION="A text document format for writing short documents, articles, books and UNIX man pages"
+HOMEPAGE="http://www.methods.co.nz/asciidoc/"
+SRC_URI="mirror://sourceforge/${PN}/${P}.tar.gz"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~x86-fbsd"
+IUSE="examples vim-syntax"
+
+RDEPEND=">=virtual/python-2.4
+ >=app-text/docbook-xsl-stylesheets-1.75
+ dev-libs/libxslt
+ media-gfx/graphviz
+ app-text/docbook-xml-dtd:4.5
+ || ( www-client/links www-client/lynx www-client/w3m )"
+DEPEND=""
+
+src_prepare() {
+ if ! use vim-syntax; then
+ sed -i -e '/^install/s/install-vim//' Makefile.in
+ else
+ sed -i\
+ -e '/^vimdir/s/@sysconfdir@\/vim/\/usr\/share\/vim\/vimfiles/' \
+ -e 's/\/etc\/vim//' \
+ Makefile.in || die
+ fi
+}
+
+src_configure() {
+ econf --sysconfdir=/usr/share || die
+}
+
+src_install() {
+ dodir /usr/bin
+
+ use vim-syntax && dodir /usr/share/vim/vimfiles
+
+ emake DESTDIR="${D}" install || die "install failed"
+
+ if use examples; then
+ # This is a symlink to a directory
+ rm examples/website/images || die
+
+ insinto /usr/share/doc/${PF}
+ doins -r examples || die
+ dosym /usr/share/asciidoc/images /usr/share/doc/${PF}/examples || die
+ fi
+
+ dohtml doc/*.html || die
+ dosym /usr/share/asciidoc/images /usr/share/doc/${PF}/html || die
+ dosym /usr/share/asciidoc/stylesheets/docbook-xsl.css /usr/share/doc/${PF}/html || die
+
+ dodoc BUGS CHANGELOG README docbook-xsl/asciidoc-docbook-xsl.txt || die
+}
diff --git a/dev-libs/liboobs/liboobs-2.29.1.ebuild b/dev-libs/liboobs/liboobs-2.29.1.ebuild
new file mode 100644
index 00000000..eb5b890f
--- /dev/null
+++ b/dev-libs/liboobs/liboobs-2.29.1.ebuild
@@ -0,0 +1,35 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+GCONF_DEBUG="no"
+
+inherit gnome2
+
+DESCRIPTION="Liboobs is a wrapping library to the System Tools Backends."
+HOMEPAGE="http://www.gnome.org"
+
+LICENSE="LGPL-2"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="doc"
+
+# FIXME: according to the ChangLog hal is optional but it doesn't
+# have a configure switch
+# FIXME: check if policykit should be checked in configure ?
+
+RDEPEND=">=dev-libs/glib-2.14
+ >=dev-libs/dbus-glib-0.70
+ >=app-admin/system-tools-backends-2.5.4
+ >=sys-apps/hal-0.5.9"
+
+DEPEND="${RDEPEND}
+ >=dev-util/pkgconfig-0.9
+ doc? ( >=dev-util/gtk-doc-1.9 )"
+
+DOCS="AUTHORS ChangeLog NEWS README"
+
+pkg_setup() {
+ G2CONF="${G2CONF} --disable-static"
+}
diff --git a/eclass/gnome2-la.eclass b/eclass/gnome2-la.eclass
new file mode 100644
index 00000000..e9506c3d
--- /dev/null
+++ b/eclass/gnome2-la.eclass
@@ -0,0 +1,33 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+#
+# gnome2-la.eclass
+#
+# Original Author: Nirbheek Chauhan <nirbheek@gentoo.org>
+# Purpose: Temporary eclass for facilitating .la file removal
+#
+# Only for usage in the overlay. This eclass will be redundant once this feature
+# is reviewed and patched into gnome2.eclass (in-tree)
+#
+
+inherit gnome2
+
+EXPORT_FUNCTIONS src_install
+
+# Remove .la files in src_install?
+G2PUNT_LA=${G2PUNT_LA:-"no"}
+
+gnome2-la_src_install() {
+ gnome2_src_install
+
+ # Remove .la files if they're unneeded
+ # Be *absolutely* sure before doing this and read
+ # http://dev.gentoo.org/~nirbheek/gnome/gnome-policy.xml#doc_chap3
+ if [[ "${G2PUNT_LA}" = "yes" ]]; then
+ ebegin "Removing .la files"
+ find "${D}" -name '*.la' -delete
+ eend
+ fi
+}
diff --git a/eclass/scm-git.eclass b/eclass/scm-git.eclass
new file mode 100644
index 00000000..5c2fa206
--- /dev/null
+++ b/eclass/scm-git.eclass
@@ -0,0 +1,186 @@
+# Copyright 2008 David Leverton <dleverton@exherbo.org>
+# Distributed under the terms of the GNU General Public License v2
+# Based in part upon git.exlib, which is:
+# Copyright 2008 Fernando J. Pereda
+# Based upon 'git.eclass' which is:
+# Copyright 1999-2007 Gentoo Foundation
+
+if [[ -z ${SCM_TYPE} ]]; then
+ SCM_TYPE=git
+ inherit scm
+fi
+
+scm-git_do_dependencies() {
+ local git='>=dev-util/git-1.6.0'
+ if [[ $(scm_get_var REPOSITORY) == https://* ]]; then
+ echo "${git}$(scm_usedeps curl) net-misc/curl$(scm_usedeps ssl)"
+ elif [[ $(scm_get_var REPOSITORY) == http://* || $(scm_get_var REPOSITORY) == ftp://* ]]; then
+ echo "${git}$(scm_usedeps curl)"
+ elif [[ $(scm_get_var REPOSITORY) == rsync://* ]]; then
+ echo "${git} net-misc/rsync"
+ elif [[ $(scm_get_var REPOSITORY) == ssh://* ]] ||
+ [[ $(scm_get_var REPOSITORY) != *://* && $(scm_get_var REPOSITORY) == *:* ]]; then
+ echo "${git} net-misc/openssh"
+ else
+ echo "${git}"
+ fi
+
+ if [[ -n $(scm_get_var TAG) ]]; then
+ local keys
+ scm_get_array GIT_TAG_SIGNING_KEYS keys
+ [[ ${#keys[@]} -gt 0 ]] && echo app-crypt/gnupg
+ fi
+}
+
+scm-git_do_check_vars() {
+ [[ -n $(scm_get_var TAG) && -n $(scm_get_var REVISION) ]] \
+ && die "for git, $(scm_var_name TAG) must not be set at the same time as $(scm_var_name REVISION)"
+ [[ -z $(scm_get_var BRANCH) && -z $(scm_get_var REVISION) &&
+ -z $(scm_get_var TAG) ]] && scm_set_var BRANCH master
+ local rev=$(scm_get_var REVISION)
+ [[ -n ${rev} ]] && [[ ${rev} == *[^0123456789abcdef]* || ${#rev} -ne 40 ]] \
+ && die "for git, $(scm_var_name REVISION) must be a 40-character lowercase hexadecimal SHA-1 sum"
+ [[ -n $(scm_get_var SUBPATH) ]] && die "for git, $(scm_var_name SUBPATH) must not be set"
+
+ scm_modify_var REPOSITORY scm_trim_slashes -scheme -trailing
+}
+
+scm-git_git() {
+ local echo=echo
+ if [[ ${1} == -q ]]; then
+ shift
+ echo=:
+ fi
+
+ local need_git_dir=yes global=( )
+ while [[ ${#} -gt 0 && ${1} == -* ]]; do
+ global=( "${global[@]}" "${1}" )
+ [[ ${1} == --git-dir=* ]] && need_git_dir=
+ shift
+ done
+ [[ ${1} != clone && -n ${need_git_dir} ]] && global=( "${global[@]}" --git-dir="$(scm_get_var CHECKOUT_TO)" )
+
+ ${echo} git "${global[@]}" "${@}"
+ GIT_PAGER=cat git "${global[@]}" "${@}" || scm_die_unless_nonfatal "git ${1} failed"
+}
+
+scm-git_do_appraise() {
+ local dir=$(scm_get_var CHECKOUT_TO)
+
+ if ! scm_nonfatal scm-git_git -q rev-parse 2>/dev/null; then
+ echo "${dir} is not a git checkout"
+ return 3
+ fi
+
+ if [[ -n $(scm_get_var REVISION) ]]; then
+ if [[ -z $(scm_nonfatal scm-git_git -q cat-file -t $(scm_get_var REVISION) 2>/dev/null) ]]; then
+ echo "$(scm_get_var REVISION) is not present in ${dir}"
+ return 1
+ elif [[ $(scm-git_git -q cat-file -t $(scm_get_var REVISION)) == commit ]]; then
+ if [[ -n $(scm_get_var BRANCH) ]] && ! scm-git_git -q rev-list "refs/heads/$(scm_get_var BRANCH)" \
+ | grep -Fx $(scm_get_var REVISION) >/dev/null; then
+ echo "revision $(scm_get_var REVISION) is not part of branch $(scm_get_var BRANCH) of ${dir}"
+ return 1
+ fi
+ return 2
+ else
+ die "$(scm_get_var REVISION) is not a commit in ${dir}"
+ fi
+ fi
+
+ local origin=$(scm-git_git -q config remote.origin.url)
+ [[ -n ${origin} ]] || die "could not determine origin URL for ${dir}"
+ if [[ ${origin} != $(scm_get_var REPOSITORY) ]]; then
+ echo "${dir} is a clone of ${origin}, but wanted $(scm_get_var REPOSITORY)"
+ return 1
+ fi
+
+ if [[ -n $(scm_get_var TAG) ]]; then
+ if [[ -n $(scm-git_git -q for-each-ref "refs/tags/$(scm_get_var TAG)") ]]; then
+ if [[ -n $(scm_get_var BRANCH) ]] && ! scm-git_git -q rev-list "refs/heads/$(scm_get_var BRANCH)" \
+ | grep -Fx $(scm-git_git -q rev-parse "refs/tags/$(scm_get_var TAG)") >/dev/null; then
+ echo "tag $(scm_get_var TAG) is not part of branch $(scm_get_var BRANCH) of ${dir}"
+ return 1
+ fi
+
+ local keys
+ scm_get_array GIT_TAG_SIGNING_KEYS keys
+ if [[ ${#keys[@]} -gt 0 ]]; then
+ local gpghome=$(mktemp -d -p "${T}" gpg-XXXXXX)
+ [[ -n ${gpghome} ]] || die "mktemp failed"
+
+ cat >"${gpghome}/gpg" <<-EOF
+ #! /usr/bin/env bash
+ $(HOME=${gpghome} declare -p HOME)
+ $(gpg=$(type -P gpg); declare -p gpg)
+ errors=\$("\${gpg}" --keyserver-options no-auto-key-retrieve "\${@}" 2>&1 >/dev/null) && exit
+ status=\${?}
+ echo "\${errors}" >&2
+ exit \${status}
+ EOF
+ [[ ${?} -eq 0 ]] || die "create gpg wrapper failed"
+ chmod +x "${gpghome}/gpg" || die "chmod +x gpg wrapper failed"
+
+ PATH=${gpghome}:${PATH} gpg --import "${keys[@]}" || die "gpg --import ${keys[*]} failed"
+ PATH=${gpghome}:${PATH} scm-git_git -q verify-tag "$(scm_get_var TAG)" >/dev/null
+ fi
+
+ return 2
+ else
+ echo "${dir} does not contain the tag $(scm_get_var TAG)"
+ return 1
+ fi
+ fi
+
+ if [[ -n $(scm_get_var BRANCH) && -z $(scm-git_git -q for-each-ref "refs/heads/$(scm_get_var BRANCH)") ]]; then
+ echo "${dir} does not contain the branch $(scm_get_var BRANCH)"
+ return 1
+ fi
+
+ return 0
+}
+
+scm-git_do_checkout() {
+ scm-git_git clone --bare "$(scm_get_var REPOSITORY)" "$(scm_get_var CHECKOUT_TO)"
+ scm-git_git config remote.origin.url "$(scm_get_var REPOSITORY)"
+ scm-git_git gc --auto
+}
+
+scm-git_do_update() {
+ local old_origin=$(scm-git_git -q config remote.origin.url)
+ [[ -n ${old_origin} ]] || die "could not determine origin URL for $(scm_get_var CHECKOUT_TO)"
+ if [[ ${old_origin} != $(scm_get_var REPOSITORY) ]]; then
+ scm-git_git config remote.origin.url "$(scm_get_var REPOSITORY)"
+ eval "$(scm-git_git -q for-each-ref --shell --format "scm-git_git update-ref -d %(refname)" refs/{heads,tags}/\*)"
+ fi
+
+ local branch=$(scm_get_var BRANCH)
+ scm-git_git fetch -f -u origin "refs/heads/${branch:-*}:refs/heads/${branch:-*}"
+ scm-git_git gc --auto
+ [[ -n ${branch} ]] && scm_set_array FETCHED_BRANCHES "${branch}"
+}
+
+scm-git_do_revision() {
+ scm-git_git -q rev-parse $(
+ if [[ -n $(scm_get_var TAG) ]]; then
+ echo refs/tags/$(scm_get_var TAG)
+ elif [[ -n $(scm_get_var REVISION) ]]; then
+ scm_get_var REVISION
+ else
+ echo refs/heads/$(scm_get_var BRANCH)
+ fi)
+}
+
+scm-git_do_unpack() {
+ scm-git_git clone -s -n "$(scm_get_var CHECKOUT_TO)" "$(scm_get_var UNPACK_TO)"
+ scm-git_git --git-dir="$(scm_get_var UNPACK_TO)"/.git --work-tree="$(scm_get_var UNPACK_TO)" checkout -f $(
+ if [[ -n $(scm_get_var TAG) ]]; then
+ echo refs/tags/$(scm_get_var TAG)
+ elif [[ -n $(scm_get_var REVISION) ]]; then
+ scm_get_var REVISION
+ else
+ [[ -n $(scm-git_git -q --git-dir="$(scm_get_var UNPACK_TO)"/.git for-each-ref "refs/heads/$(scm_get_var BRANCH)") ]] \
+ || echo -b $(scm_get_var BRANCH) refs/remotes/origin/$(scm_get_var BRANCH)
+ fi) --
+}
+
diff --git a/eclass/scm.eclass b/eclass/scm.eclass
new file mode 100644
index 00000000..67d54985
--- /dev/null
+++ b/eclass/scm.eclass
@@ -0,0 +1,349 @@
+# Copyright 2008 David Leverton <dleverton@exherbo.org>
+# Distributed under the terms of the GNU General Public License v2
+# Based in part upon subversion.eclass, which is:
+# Copyright 1999-2008 Gentoo Foundation
+
+scm_need_extglob() {
+ [[ ${#} -eq 1 ]] || die "scm_need_extglob needs exactly one argument"
+ [[ -n $(declare -F ${1}) ]] || die "${1} is not a function"
+ eval "_scm_need_extglob_$(declare -f ${1})"
+ eval "${1}() {
+ local oldextglob=\$(shopt -p extglob)
+ shopt -s extglob
+ _scm_need_extglob_${1} \"\${@}\"
+ local status=\${?}
+ \${oldextglob}
+ return \${status}
+ }"
+}
+
+scm_usedeps() {
+ [[ ${#} -ge 1 ]] || die "scm_usedeps needs at least one argument"
+ local myeapi=$(echo ${EAPI/prefix})
+ has ${myeapi:-0} 0 1 && return
+ local IFS=,
+ local deps="[${*}]"
+ [[ ${myeapi:-0} == kdebuild-* ]] && deps=${deps//,/][}
+ echo "${deps}"
+}
+
+scm_nonfatal() {
+ SCM_NONFATAL=1 "${@}"
+}
+
+scm_die_unless_nonfatal() {
+ [[ -z ${SCM_NONFATAL} ]] && die "${@}"
+}
+
+scm_for_each() {
+ [[ ${#} -ge 1 ]] || die "scm_for_each needs at least one argument"
+ local SCM_THIS
+ for SCM_THIS in "" ${SCM_SECONDARY_REPOSITORIES}; do
+ "${@}"
+ done
+}
+
+scm_var_name() {
+ [[ ${#} -eq 1 ]] || die "scm_var_name needs exactly one argument"
+ echo SCM${SCM_THIS:+_${SCM_THIS}}_${1}
+}
+
+scm_get_var() {
+ [[ ${#} -eq 1 ]] || die "scm_get_var needs exactly one argument"
+ local var=$(scm_var_name ${1})
+ echo "${!var}"
+}
+
+scm_set_var() {
+ [[ ${#} -eq 2 ]] || die "scm_set_var needs exactly two arguments"
+ eval "$(scm_var_name ${1})=\${2}"
+}
+
+scm_modify_var() {
+ [[ ${#} -ge 2 ]] || die "scm_modify_var needs at least two arguments"
+ local var=${1}
+ shift
+ scm_set_var ${var} "$("${@}" "$(scm_get_var ${var})")"
+}
+
+scm_get_array() {
+ [[ ${#} -eq 2 ]] || die "scm_get_array needs exactly two arguments"
+ eval "${2}=( \"\${$(scm_var_name ${1})[@]}\" )"
+}
+
+scm_set_array() {
+ [[ ${#} -ge 1 ]] || die "scm_set_array needs at least one argument"
+ local name=${1}
+ shift
+ eval "$(scm_var_name ${name})=( \"\${@}\" )"
+}
+
+scm_call() {
+ [[ ${#} -ge 1 ]] || die "scm_call needs at least one argument"
+ local func=${1} type=$(scm_get_var TYPE)
+ shift
+ if [[ -n $(declare -F scm-${type}_do_${func}) ]]; then
+ scm-${type}_do_${func} "${@}"
+ elif [[ -n $(declare -F scm_do_${func}) ]]; then
+ scm_do_${func} "${@}"
+ else
+ die "bug in scm-${type}.eclass: scm-${type}_do_${func} not defined"
+ fi
+}
+
+scm_access_checkout() {
+ [[ ${#} -ge 1 ]] || die "scm_access_checkout needs at least one argument"
+ local dir=$(scm_get_var CHECKOUT_TO)
+ local lock=${dir%/*}/.lock-${dir##*/}
+
+ local dir_base=${dir%/*}
+ if [[ ! -d ${dir_base} ]]; then
+ local dir_addwrite=${dir_base}
+ local dir_search=${dir_addwrite%/*}
+ while [[ ! -d ${dir_search} ]]; do
+ dir_addwrite=${dir_search}
+ dir_search=${dir_search%/*}
+ done
+ (
+ addwrite "${dir_addwrite}"
+ mkdir -p "${dir_base}"
+ ) || die "mkdir failed"
+ fi
+
+ local SANDBOX_WRITE=${SANDBOX_WRITE}
+ addwrite "${dir}"
+ addwrite "${lock}"
+
+ local fd
+ for fd in {3..9}; do
+ [[ -e /dev/fd/${fd} ]] || break
+ done
+ [[ -e /dev/fd/${fd} ]] && die "can't find free file descriptor"
+
+ eval "
+ {
+ flock -x \${fd} || die \"flock failed\"
+ \"\${@}\"
+ local status=\${?}
+ :
+ } ${fd}>\"\${lock}\" || die \"opening lock file failed\"
+ "
+
+ return ${status}
+}
+
+scm_do_resolve_externals() {
+ :
+}
+
+scm_check_timestamp() {
+ [[ -e ${1}/${2} && -n $(find "${1}" -maxdepth 1 -name "${2}" \
+ -mmin -$((${SCM_MIN_UPDATE_DELAY} * 60)) -print) ]]
+}
+
+scm_perform_fetch() {
+ local dir=$(scm_get_var CHECKOUT_TO)
+
+ local whynot status
+ if [[ -d ${dir} ]]; then
+ whynot=$(scm_call appraise)
+ status=${?}
+ if [[ ${status} -eq 2 ]]; then
+ einfo "Not fetching ${SCM_THIS:-primary repository} because the existing checkout is perfect"
+ return
+ fi
+ else
+ whynot="${dir} does not exist"
+ status=1
+ fi
+
+ if [[ -n ${SCM_OFFLINE} ]]; then
+ [[ ${status} -ne 0 ]] && die "can't use SCM_OFFLINE for ${SCM_THIS:-primary repository} because ${whynot}"
+ einfo "Not fetching ${SCM_THIS:-primary repository} because SCM_OFFLINE is set"
+ return
+ fi
+
+ if [[ -n ${SCM_MIN_UPDATE_DELAY} ]]; then
+ [[ ${SCM_MIN_UPDATE_DELAY} == *[^0123456789]* || ${SCM_MIN_UPDATE_DELAY} -eq 0 ]] \
+ && die "SCM_MIN_UPDATE_DELAY must be a positive integer"
+ local branch=$(scm_get_var BRANCH)
+ if scm_check_timestamp "${dir}" .scm.eclass.timestamp ||
+ { [[ -n ${branch} ]] && scm_check_timestamp "${dir}" .scm.eclass.timestamp."${branch//\//--}"; }; then
+ if [[ ${status} -eq 0 ]]; then
+ einfo "Not fetching ${SCM_THIS:-primary repository} because SCM_MIN_UPDATE_DELAY (${SCM_MIN_UPDATE_DELAY}) hours have not passed"
+ return
+ else
+ einfo "Ignoring SCM_MIN_UPDATE_DELAY for ${SCM_THIS:-primary repository} because ${whynot}"
+ fi
+ fi
+ fi
+
+ if [[ ${status} -eq 3 ]]; then
+ echo rm -rf "${dir}"
+ rm -rf "${dir}"
+ [[ -d ${dir} ]] && die "rm failed"
+ fi
+
+ if [[ -d ${dir} ]]; then
+ scm_call update
+ else
+ scm_call checkout
+ fi
+
+ if [[ -d ${dir} ]]; then
+ whynot=$(scm_call appraise)
+ [[ ${?} -eq 1 || ${?} -eq 3 ]] && die "${whynot}"
+ else
+ die "${dir} does not exist"
+ fi
+
+ local fetched
+ scm_get_array FETCHED_BRANCHES fetched
+ if [[ ${#fetched[@]} -gt 0 ]]; then
+ fetched=( "${fetched[@]//\//--}" )
+ touch "${fetched[@]/#/${dir}/.scm.eclass.timestamp.}" || die "touch failed"
+ else
+ touch "${dir}/.scm.eclass.timestamp" || die "touch failed"
+ fi
+}
+
+scm_fetch_one() {
+ scm_perform_fetch
+ scm_call resolve_externals
+}
+
+scm_src_fetch_extra() {
+ scm_{for_each,access_checkout,fetch_one}
+}
+
+scm_scmrevision_one() {
+ local rev=$(scm_call revision)
+ [[ -n ${rev} ]] || die "could not determine revision for ${SCM_THIS:-primary repository}"
+ SCM_PKG_SCM_REVISION_RESULT=${SCM_PKG_SCM_REVISION_RESULT},${SCM_THIS}=${rev}
+}
+
+scm_pkg_scm_revision() {
+ local SCM_PKG_SCM_REVISION_RESULT=
+ scm_{for_each,access_checkout,scmrevision_one}
+ echo ${SCM_PKG_SCM_REVISION_RESULT#,=}
+}
+
+scm_do_unpack() {
+ echo cp -pPR "$(scm_get_var CHECKOUT_TO)" "$(scm_get_var UNPACK_TO)"
+ cp -pPR "$(scm_get_var CHECKOUT_TO)" "$(scm_get_var UNPACK_TO)" || die "cp failed"
+}
+
+scm_do_set_actual_vars() {
+ local rev=$(scm_call revision)
+ [[ -n ${rev} ]] || die "could not determine revision for ${SCM_THIS:-primary repository}"
+ scm_set_var ACTUAL_REVISION "${rev}"
+}
+
+scm_unpack_one() {
+ scm_call resolve_externals
+
+ local whynot
+ if [[ -d $(scm_get_var CHECKOUT_TO) ]]; then
+ whynot=$(scm_call appraise)
+ [[ ${?} -eq 1 || ${?} -eq 3 ]] && die "${whynot}"
+ else
+ die "$(scm_get_var CHECKOUT_TO) does not exist"
+ fi
+
+ local dir=$(scm_get_var UNPACK_TO)
+ if [[ -d ${dir} ]]; then
+ rmdir "${dir}" || die "rmdir failed"
+ else
+ mkdir -p "${dir%/*}" || die mkdir "failed"
+ fi
+
+ scm_call unpack
+ rm -f "${dir}/.scm.eclass.timestamp"{,.*}
+ scm_call set_actual_vars
+}
+
+scm_src_unpack() {
+ scm_src_fetch_extra
+
+ scm_{for_each,access_checkout,unpack_one}
+ SCM_IS_BUILT=1
+}
+
+scm_do_info() {
+ :
+}
+
+scm_pkg_info() {
+ [[ -n ${SCM_IS_BUILT} ]] && scm_{for_each,call} info
+}
+
+scm_trim_slashes() {
+ local scheme= leading= trailing=
+ while [[ ${#} -gt 0 && ${1} == -* ]]; do
+ case ${1} in
+ -scheme) scheme=1 ;;
+ -leading) leading=1 ;;
+ -trailing) trailing=1 ;;
+ *) die "scm_trim_slashes: unrecognised switch ${1}"
+ esac
+ shift
+ done
+
+ [[ ${#} -eq 1 ]] || die "scm_trim_slashes needs exactly one argument besides switches"
+ local value=${1}
+
+ local myscheme=
+ if [[ -n ${scheme} && ${value} == *://* ]]; then
+ myscheme=${value%%://*}://
+ value=${value#*://}
+ fi
+
+ value=${value//+(\/)/\/}
+ [[ -n ${leading} ]] && value=${value#/}
+ [[ -n ${trailing} ]] && value=${value%/}
+
+ echo "${myscheme}${value}"
+}
+scm_need_extglob scm_trim_slashes
+
+scm_do_check_vars() {
+ :
+}
+
+scm_global_stuff() {
+ if [[ -z $(scm_get_var TYPE) ]]; then
+ if [[ -n ${SCM_THIS} ]]; then
+ scm_set_var TYPE ${SCM_TYPE}
+ else
+ die "$(scm_var_name TYPE) must be set"
+ fi
+ fi
+ inherit scm-$(scm_get_var TYPE)
+
+ [[ -z $(scm_get_var REPOSITORY) ]] \
+ && die "$(scm_var_name REPOSITORY) must be set"
+
+ local checkout_to=$(scm_get_var CHECKOUT_TO)
+ [[ -z ${checkout_to} ]] && checkout_to=${SCM_THIS:-${PN}}
+ [[ ${checkout_to} == /* ]] || checkout_to=${SCM_HOME}/${checkout_to}
+ scm_set_var CHECKOUT_TO "$(scm_trim_slashes -trailing "${checkout_to}")"
+
+ local unpack_to=$(scm_get_var UNPACK_TO)
+ [[ -z ${unpack_to} ]] && unpack_to=${WORKDIR}/${SCM_THIS:-${P}}
+ scm_set_var UNPACK_TO "$(scm_trim_slashes -trailing "${unpack_to}")"
+
+ scm_call check_vars
+
+ DEPEND="${DEPEND} $(scm_call dependencies)"
+}
+
+SCM_HOME=${PORTAGE_ACTUAL_DISTDIR-${DISTDIR}}/scm
+scm_finalise() {
+ DEPEND="${DEPEND} >=sys-apps/util-linux-2.13_pre2"
+ scm_{for_each,global_stuff}
+}
+[[ -n ${SCM_REPOSITORY} ]] && scm_finalise
+
+#EXPORT_FUNCTIONS src_fetch_extra pkg_scm_revision src_unpack pkg_info
+EXPORT_FUNCTIONS src_unpack pkg_info
+
diff --git a/gnome-extra/gnome-globalmenu/gnome-globalmenu-9999.ebuild b/gnome-extra/gnome-globalmenu/gnome-globalmenu-9999.ebuild
new file mode 100644
index 00000000..2da0e997
--- /dev/null
+++ b/gnome-extra/gnome-globalmenu/gnome-globalmenu-9999.ebuild
@@ -0,0 +1,62 @@
+# Copyright 1999-2007 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI=1
+
+#inherit gnome2-utils subversion autotools
+inherit gnome2 subversion autotools
+
+ESVN_REPO_URI="http://gnome2-globalmenu.googlecode.com/svn/trunk/"
+
+DESCRIPTION="Global menubar applet for Gnome2."
+HOMEPAGE="http://code.google.com/p/gnome2-globalmenu/"
+SRC_URI=""
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~amd64"
+IUSE="gnome test xfce"
+
+RDEPEND="dev-libs/glib:2
+ gnome-base/gconf:2
+ gnome-base/gnome-menus
+ x11-libs/gtk+:2
+ x11-libs/libX11
+ x11-libs/libwnck
+ gnome? (
+ gnome-base/gnome-panel
+ x11-libs/libnotify )
+ xfce? (
+ xfce-base/xfce4-panel )"
+
+DEPEND="${RDEPEND}
+ dev-util/intltool
+ dev-util/pkgconfig
+ >=dev-lang/vala-0.7.3"
+
+pkg_setup() {
+ G2CONF="${G2CONF}
+ --without-gir
+ --docdir=/usr/share/doc/${PF}
+ $(use_enable test tests)
+ $(use_with gnome gnome-panel)
+ $(use_with xfce xfce4-panel)"
+}
+
+src_unpack() {
+ subversion_src_unpack || die "subversion_src_unpack failed"
+
+ ./autogen.sh --prefix=/usr || die "autogen failed"
+
+ gnome2_src_prepare || die "src_unpack failed"
+}
+
+pkg_postinst() {
+ gnome2_pkg_postinst || die "pkg_postinst failed"
+
+ ewarn "DO NOT report bugs to Gentoo's bugzilla"
+ einfo "Please report all bugs to http://gnome2-globalmenu.googlecode.com/issues"
+ einfo "Thank you"
+}
diff --git a/media-libs/libchamplain/libchamplain-0.4.2-r1.ebuild b/media-libs/libchamplain/libchamplain-0.4.2-r1.ebuild
new file mode 100644
index 00000000..553737d0
--- /dev/null
+++ b/media-libs/libchamplain/libchamplain-0.4.2-r1.ebuild
@@ -0,0 +1,51 @@
+# Copyrieht 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI="2"
+
+inherit gnome2 gnome2-la
+
+DESCRIPTION="Clutter based world map renderer"
+HOMEPAGE="http://blog.pierlux.com/projects/libchamplain/en/"
+
+LICENSE="LGPL-2"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="doc gtk introspection" # python mono (not ported to clutter 1.0)
+
+RDEPEND=">=dev-libs/glib-2.16
+ >=x11-libs/cairo-1.4
+ >=net-libs/libsoup-2.26[gnome]
+
+ media-libs/clutter:1.0
+ dev-db/sqlite:3
+
+ gtk? (
+ >=x11-libs/gtk+-2.10
+ >=media-libs/clutter-gtk-0.10:1.0 )"
+# FIXME: add pyclutter and pyclutter-gtk first
+# python? (
+# dev-python/pygtk
+# dev-python/pyclutter
+# >=gnome-base/gconf-2 )
+# FIXME: add clutter-sharp first
+# mono? (
+# >=dev-dotnet/gtk-sharp-2.12
+# >=dev-dotnet/gtk-sharp-gapi-2.12
+# )"
+DEPEND="${RDEPEND}
+ dev-util/pkgconfig
+ doc? ( >=dev-util/gtk-doc-1.9 )
+ introspection? ( >=dev-libs/gobject-introspection-0.6.3 )"
+
+pkg_setup() {
+ G2PUNT_LA="yes"
+ G2CONF="${G2CONF}
+ --disable-static
+ $(use_enable introspection)
+ $(use_enable gtk)"
+# $(use_enable python)
+# $(use_enable mono managed"
+}
diff --git a/net-im/empathy/empathy-2.29.4.ebuild b/net-im/empathy/empathy-2.29.4.ebuild
new file mode 100644
index 00000000..0d1df43a
--- /dev/null
+++ b/net-im/empathy/empathy-2.29.4.ebuild
@@ -0,0 +1,107 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI="2"
+
+inherit eutils gnome2 multilib
+
+DESCRIPTION="Telepathy client and library using GTK+"
+HOMEPAGE="http://live.gnome.org/Empathy"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+# FIXME: Add location support once geoclue stops being idiotic with automagic deps
+IUSE="applet map networkmanager python spell test webkit"
+
+# FIXME: libnotify & libcanberra hard deps
+RDEPEND=">=dev-libs/glib-2.16.0
+ >=x11-libs/gtk+-2.16.0
+ >=gnome-base/gconf-2
+ >=dev-libs/dbus-glib-0.51
+ >=gnome-extra/evolution-data-server-1.2
+ >=net-libs/telepathy-glib-0.9.0
+ >=media-libs/libcanberra-0.4[gtk]
+ >=x11-libs/libnotify-0.4.4
+ >=gnome-base/gnome-keyring-2.22
+
+ dev-libs/libunique
+ net-libs/farsight2
+ media-libs/gstreamer:0.10
+ media-libs/gst-plugins-base:0.10
+ net-libs/telepathy-farsight
+ dev-libs/libxml2
+ x11-libs/libX11
+ net-voip/telepathy-connection-managers
+
+ map? (
+ >=media-libs/libchamplain-0.4[gtk]
+ >=media-libs/clutter-gtk-0.10:1.0 )
+ networkmanager? ( >=net-misc/networkmanager-0.7 )
+ python? (
+ >=dev-lang/python-2.4.4-r5
+ >=dev-python/pygtk-2 )
+ spell? (
+ app-text/enchant
+ app-text/iso-codes )
+ webkit? ( >=net-libs/webkit-gtk-1.1.7 )
+"
+DEPEND="${RDEPEND}
+ app-text/scrollkeeper
+ >=app-text/gnome-doc-utils-0.17.3
+ >=dev-util/intltool-0.35.0
+ >=dev-util/pkgconfig-0.16
+ test? (
+ sys-apps/grep
+ >=dev-libs/check-0.9.4 )
+ dev-libs/libxslt
+ virtual/python
+"
+PDEPEND=">=net-im/telepathy-mission-control-5"
+
+DOCS="CONTRIBUTORS AUTHORS ChangeLog NEWS README"
+
+# FIXME: Highly broken with parallel make, mallard strike 2, see bug #286889
+MAKEOPTS="${MAKEOPTS} -j1"
+
+pkg_setup() {
+ G2CONF="${G2CONF}
+ --disable-maintainer-mode
+ --disable-static
+ --disable-location
+ --disable-gtk-doc
+ $(use_enable debug)
+ $(use_with networkmanager connectivity nm)
+ $(use_enable map)
+ $(use_enable python)
+ $(use_enable spell)
+ $(use_enable test coding-style-checks)
+ $(use_enable webkit)
+ "
+}
+
+src_prepare() {
+ gnome2_src_prepare
+
+ # Remove hard enabled -Werror (see AM_MAINTAINER_MODE), bug 218687
+ sed -i "s:-Werror::g" configure || die "sed 1 failed"
+}
+
+src_test() {
+ unset DBUS_SESSION_BUS_ADDRESS
+ emake check || die "emake check failed."
+}
+
+pkg_preinst() {
+ gnome2_pkg_preinst
+}
+
+pkg_postinst() {
+ gnome2_pkg_postinst
+ echo
+ elog "Empathy needs telepathy's connection managers to use any IM protocol."
+ elog "See the USE flags on net-voip/telepathy-connection-managers"
+ elog "to install them."
+}
diff --git a/net-libs/gnutls/gnutls-2.8.5.ebuild b/net-libs/gnutls/gnutls-2.8.5.ebuild
new file mode 100644
index 00000000..2bc85e64
--- /dev/null
+++ b/net-libs/gnutls/gnutls-2.8.5.ebuild
@@ -0,0 +1,98 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI="2"
+
+inherit autotools libtool
+
+DESCRIPTION="A TLS 1.0 and SSL 3.0 implementation for the GNU project"
+HOMEPAGE="http://www.gnutls.org/"
+
+if [[ "${PV}" == *pre* ]]; then
+ SRC_URI="http://daily.josefsson.org/${P%.*}/${P%.*}-${PV#*pre}.tar.gz"
+else
+ MINOR_VERSION="${PV#*.}"
+ MINOR_VERSION="${MINOR_VERSION%.*}"
+ if [[ $((MINOR_VERSION % 2)) == 0 ]]; then
+ #SRC_URI="ftp://ftp.gnu.org/pub/gnu/${PN}/${P}.tar.bz2"
+ SRC_URI="mirror://gnu/${PN}/${P}.tar.bz2"
+ else
+ SRC_URI="ftp://alpha.gnu.org/gnu/${PN}/${P}.tar.bz2"
+ fi
+ unset MINOR_VERSION
+fi
+
+# GPL-3 for the gnutls-extras library and LGPL for the gnutls library.
+LICENSE="LGPL-2.1 GPL-3"
+SLOT="0"
+KEYWORDS="~alpha ~amd64 ~arm hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~sparc-fbsd ~x86-fbsd"
+IUSE="bindist +cxx doc examples guile lzo nls zlib"
+
+RDEPEND="dev-libs/libgpg-error
+ >=dev-libs/libgcrypt-1.4.0
+ >=dev-libs/libtasn1-0.3.4
+ nls? ( virtual/libintl )
+ guile? ( >=dev-scheme/guile-1.8.4[networking] )
+ zlib? ( >=sys-libs/zlib-1.1 )
+ !bindist? ( lzo? ( >=dev-libs/lzo-2 ) )"
+DEPEND="${RDEPEND}
+ sys-devel/libtool
+ doc? ( dev-util/gtk-doc )
+ nls? ( sys-devel/gettext )"
+
+S="${WORKDIR}/${P%_pre*}"
+
+pkg_setup() {
+ if use lzo && use bindist; then
+ ewarn "lzo support was disabled for binary distribution of gnutls"
+ ewarn "due to licensing issues. See Bug 202381 for details."
+ epause 5
+ fi
+}
+
+src_prepare() {
+ sed -e 's/imagesdir = $(infodir)/imagesdir = $(htmldir)/' -i doc/Makefile.am
+
+ local dir
+ for dir in m4 lib/m4 libextra/m4; do
+ rm -f "${dir}/lt"* "${dir}/libtool.m4"
+ done
+ find . -name ltmain.sh -exec rm {} \;
+ for dir in . lib libextra; do
+ pushd "${dir}" > /dev/null
+ eautoreconf
+ popd > /dev/null
+ done
+
+ elibtoolize # for sane .so versioning on FreeBSD
+}
+
+src_configure() {
+ local myconf
+ use bindist && myconf="--without-lzo" || myconf="$(use_with lzo)"
+ econf --htmldir=/usr/share/doc/${P}/html \
+ $(use_enable cxx) \
+ $(use_enable doc gtk-doc) \
+ $(use_enable guile) \
+ $(use_enable nls) \
+ $(use_with zlib) \
+ ${myconf}
+}
+
+src_install() {
+ emake DESTDIR="${D}" install || die "emake install failed"
+
+ dodoc AUTHORS ChangeLog NEWS README THANKS doc/TODO
+
+ if use doc; then
+ dodoc doc/gnutls.{pdf,ps}
+ dohtml doc/gnutls.html
+ fi
+
+ if use examples; then
+ docinto examples
+ dodoc doc/examples/*.c
+ fi
+}
diff --git a/net-libs/telepathy-glib/telepathy-glib-0.9.1.ebuild b/net-libs/telepathy-glib/telepathy-glib-0.9.1.ebuild
new file mode 100644
index 00000000..ab292a4e
--- /dev/null
+++ b/net-libs/telepathy-glib/telepathy-glib-0.9.1.ebuild
@@ -0,0 +1,41 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI="2"
+
+DESCRIPTION="GLib bindings for the Telepathy D-Bus protocol."
+HOMEPAGE="http://telepathy.freedesktop.org"
+SRC_URI="http://telepathy.freedesktop.org/releases/${PN}/${P}.tar.gz"
+
+LICENSE="LGPL-2.1"
+SLOT="0"
+KEYWORDS="~alpha ~amd64 ~arm ~ia64 ~ppc ~ppc64 ~sparc ~x86 ~x86-fbsd"
+IUSE="debug"
+
+RDEPEND=">=dev-libs/glib-2.16
+ >=dev-libs/dbus-glib-0.73
+ >=dev-lang/python-2.3"
+
+DEPEND="${RDEPEND}
+ dev-libs/libxslt
+ >=dev-util/pkgconfig-0.21"
+
+src_configure() {
+ econf \
+ $(use_enable debug) \
+ $(use_enable debug backtrace) \
+ $(use_enable debug handle-leak-debug)
+}
+
+src_test() {
+ if ! dbus-launch emake -j1 check; then
+ die "Make check failed. See above for details."
+ fi
+}
+
+src_install() {
+ emake install DESTDIR="${D}" || die "emake install failed"
+ dodoc AUTHORS ChangeLog NEWS README || die "dodoc failed"
+}
diff --git a/net-misc/networkmanager-openconnect/networkmanager-openconnect-0.7.2.ebuild b/net-misc/networkmanager-openconnect/networkmanager-openconnect-0.7.2.ebuild
new file mode 100644
index 00000000..1dc2aef8
--- /dev/null
+++ b/net-misc/networkmanager-openconnect/networkmanager-openconnect-0.7.2.ebuild
@@ -0,0 +1,50 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI=2
+inherit eutils versionator
+
+# NetworkManager likes itself with capital letters
+MY_P=${P/networkmanager/NetworkManager}
+MYPV_MINOR=$(get_version_component_range 1-2)
+
+DESCRIPTION="NetworkManager openconnect plugin."
+HOMEPAGE="http://www.gnome.org/projects/NetworkManager/"
+SRC_URI="mirror://gnome/sources/NetworkManager-openconnect/0.7/${MY_P}.tar.bz2"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~arm ~amd64 ~ppc ~x86"
+IUSE="gnome"
+
+RDEPEND="
+ =net-misc/networkmanager-${MYPV_MINOR}*
+ net-dialup/pptpclient
+ gnome? (
+ >=gnome-base/gconf-2.20
+ >=gnome-base/gnome-keyring-2.20
+ >=gnome-base/libglade-2
+ >=gnome-base/libgnomeui-2.20
+ >=x11-libs/gtk+-2.10
+ )"
+
+DEPEND="${RDEPEND}
+ dev-util/intltool
+ dev-util/pkgconfig"
+
+S=${WORKDIR}/${MY_P}
+
+src_configure() {
+ ECONF="--disable-more-warnings \
+ $(use_with gnome)"
+
+ econf ${ECONF}
+}
+
+src_install() {
+ emake DESTDIR="${D}" install || die "emake install failed"
+
+ dodoc AUTHORS ChangeLog || die "dodoc failed"
+}
diff --git a/net-voip/telepathy-salut/telepathy-salut-0.3.10.ebuild b/net-voip/telepathy-salut/telepathy-salut-0.3.10.ebuild
new file mode 100644
index 00000000..9c3f9ab6
--- /dev/null
+++ b/net-voip/telepathy-salut/telepathy-salut-0.3.10.ebuild
@@ -0,0 +1,45 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI="2"
+
+inherit base
+
+DESCRIPTION="A link-local XMPP connection manager for Telepathy"
+HOMEPAGE="http://telepathy.freedesktop.org/wiki/Components"
+SRC_URI="http://telepathy.freedesktop.org/releases/${PN}/${P}.tar.gz"
+
+LICENSE="LGPL-2.1"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="ssl test"
+
+# FIXME: Automagic useless libasyncns check ?
+RDEPEND="dev-libs/libxml2
+ >=dev-libs/glib-2.16
+ >=sys-apps/dbus-1.1.0
+ >=dev-libs/dbus-glib-0.61
+ >=net-libs/telepathy-glib-0.7.36
+ >=net-dns/avahi-0.6.22
+ net-libs/libsoup:2.4
+ ssl? ( dev-libs/openssl )"
+DEPEND="${RDEPEND}
+ test? (
+ virtual/gsasl
+ app-text/xmldiff
+ >=dev-libs/check-0.9.4
+ dev-python/twisted-words )
+ dev-libs/libxslt
+ >=dev-lang/python-2.4"
+
+src_configure() {
+ econf $(use_enable ssl) --docdir=/usr/share/doc/${PF}
+ # too much changes required: $(use_enable test avahi-tests)
+}
+
+src_install() {
+ emake DESTDIR="${D}" install || die "emake install failed"
+ dodoc AUTHORS ChangeLog NEWS README || die "dodoc failed"
+}
diff --git a/net-wireless/blueproximity/blueproximity-1.2.5.ebuild b/net-wireless/blueproximity/blueproximity-1.2.5.ebuild
new file mode 100644
index 00000000..9654d3b6
--- /dev/null
+++ b/net-wireless/blueproximity/blueproximity-1.2.5.ebuild
@@ -0,0 +1,29 @@
+# Copyright 1999-2008 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+DESCRIPTION="Leave it - it's locked, come back - it's back too..."
+HOMEPAGE="http://blueproximity.sourceforge.net/"
+SRC_URI="mirror://sourceforge/${PN}/${P}.tar.gz"
+
+LICENSE=""
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE=""
+
+DEPEND=""
+RDEPEND="
+ dev-python/pybluez
+ dev-python/configobj
+ dev-python/pygtk
+ || ( net-wireless/bluez net-wireless/bluez-utils )
+ "
+
+src_install() {
+ insinto /opt/${PN}
+ sed "s:^cd.*:cd /opt/${PN}:" -i ${P}.orig/start_proximity.sh
+ doins ${P}.orig/*
+ newbin ${P}.orig/start_proximity.sh blueproximity
+}
+
diff --git a/profiles/categories b/profiles/categories
new file mode 100644
index 00000000..5b99a723
--- /dev/null
+++ b/profiles/categories
@@ -0,0 +1,18 @@
+app-admin
+app-emulation
+app-misc
+app-office
+app-paludis
+app-text
+dev-libs
+eclass
+gnome-extra
+media-libs
+net-im
+net-libs
+net-voip
+net-wireless
+profiles
+sys-boot
+x11-misc
+x11-terms
diff --git a/profiles/package.mask b/profiles/package.mask
new file mode 100644
index 00000000..3121ca99
--- /dev/null
+++ b/profiles/package.mask
@@ -0,0 +1 @@
+=sys-boot/grub-9999-r42
diff --git a/profiles/repo_name b/profiles/repo_name
new file mode 100644
index 00000000..ba9ed12b
--- /dev/null
+++ b/profiles/repo_name
@@ -0,0 +1 @@
+keruspe
diff --git a/sys-boot/grub/files/grub-1.96-genkernel.patch b/sys-boot/grub/files/grub-1.96-genkernel.patch
new file mode 100644
index 00000000..471fc66a
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.96-genkernel.patch
@@ -0,0 +1,11 @@
+--- util/grub.d/10_linux.in
++++ util/grub.d/10_linux.in
+@@ -93,7 +93,7 @@
+ echo "$a"
+ }
+
+-list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do
++list=`for i in /boot/kernel-* /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do
+ if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
+ done`
+
diff --git a/sys-boot/grub/grub-1.97.1.ebuild b/sys-boot/grub/grub-1.97.1.ebuild
new file mode 100644
index 00000000..dd8f166d
--- /dev/null
+++ b/sys-boot/grub/grub-1.97.1.ebuild
@@ -0,0 +1,104 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+# $Header: /var/cvsroot/gentoo-x86/sys-boot/grub/grub-1.97.ebuild,v 1.2 2009/11/01 19:51:01 vapier Exp $
+
+inherit autotools mount-boot eutils flag-o-matic toolchain-funcs
+
+if [[ ${PV} == "9999" ]] ; then
+ ESVN_REPO_URI="svn://svn.sv.gnu.org/grub/trunk/grub2"
+ inherit subversion
+ SRC_URI=""
+else
+ SRC_URI="ftp://alpha.gnu.org/gnu/${PN}/${P}.tar.gz
+ mirror://gentoo/${P}.tar.gz"
+fi
+
+DESCRIPTION="GNU GRUB 2 boot loader"
+HOMEPAGE="http://www.gnu.org/software/grub/"
+
+LICENSE="GPL-3"
+use multislot && SLOT="2" || SLOT="0"
+KEYWORDS="~amd64"
+IUSE="custom-cflags debug efi multislot static"
+
+RDEPEND=">=sys-libs/ncurses-5.2-r5
+ dev-libs/lzo"
+DEPEND="${RDEPEND}
+ dev-lang/ruby"
+PROVIDE="virtual/bootloader"
+
+export STRIP_MASK="*/grub/*/*.mod"
+QA_EXECSTACK="sbin/grub-probe sbin/grub-setup sbin/grub-mkdevicemap"
+
+src_unpack() {
+ if [[ ${PV} == "9999" ]] ; then
+ subversion_src_unpack
+ else
+ unpack ${A}
+ fi
+ cd "${S}"
+ epatch "${FILESDIR}"/${PN}-1.96-genkernel.patch #256335
+ epatch_user
+
+ # autogen.sh does more than just run autotools
+ sed -i -e 's:^auto:eauto:' autogen.sh
+ (. ./autogen.sh) || die
+}
+
+src_compile() {
+ use custom-cflags || unset CFLAGS CPPFLAGS LDFLAGS
+ use static && append-ldflags -static
+ use efi && efiopts="--with-platform=efi" || efiopts=""
+
+ econf \
+ ${efiopts} \
+ --disable-werror \
+ --sbindir=/sbin \
+ --bindir=/bin \
+ --libdir=/$(get_libdir) \
+ --disable-efiemu \
+ --enable-grub-mkfont \
+ $(use_enable debug mm-debug) \
+ $(use_enable debug grub-emu) \
+ $(use_enable debug grub-emu-usb) \
+ $(use_enable debug grub-fstest)
+ emake -j1 || die "making regular stuff"
+}
+
+src_install() {
+ emake DESTDIR="${D}" install || die
+ dodoc AUTHORS ChangeLog NEWS README THANKS TODO
+ cat <<-EOF >> "${D}"/lib*/grub/grub-mkconfig_lib
+ GRUB_DISTRIBUTOR="Gentoo"
+ EOF
+ if use multislot ; then
+ sed -i "s:grub-install:grub2-install:" "${D}"/sbin/grub-install || die
+ mv "${D}"/sbin/grub{,2}-install || die
+ mv "${D}"/usr/share/info/grub{,2}.info || die
+ fi
+}
+
+setup_boot_dir() {
+ local boot_dir=$1
+ local dir=${boot_dir}/grub
+
+ if [[ ! -e ${dir}/grub.cfg ]] ; then
+ einfo "Running: grub-mkconfig -o '${dir}/grub.cfg'"
+ grub-mkconfig -o "${dir}/grub.cfg"
+ fi
+
+ #local install=grub-install
+ #use multislot && install="grub2-install --grub-setup=/bin/true"
+ #einfo "Running: ${install} "
+ #${install}
+}
+
+pkg_postinst() {
+ if use multislot ; then
+ elog "You have installed grub2 with USE=multislot, so to coexist"
+ elog "with grub1, the grub2 install binary is named grub2-install."
+ fi
+ setup_boot_dir "${ROOT}"boot
+}
diff --git a/x11-misc/notify-osd/notify-osd-0.9.24.ebuild b/x11-misc/notify-osd/notify-osd-0.9.24.ebuild
new file mode 100644
index 00000000..54e8d048
--- /dev/null
+++ b/x11-misc/notify-osd/notify-osd-0.9.24.ebuild
@@ -0,0 +1,33 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI="2"
+
+inherit flag-o-matic versionator
+
+DESCRIPTION="Canonical's on-screen-display notification agent."
+HOMEPAGE="https://launchpad.net/notify-osd"
+SRC_URI="http://launchpad.net/notify-osd/trunk/ubuntu-9.10/+download/notify-osd-0.9.24.tar.gz"
+
+LICENSE="GPL-3"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE=""
+
+RDEPEND=">=dev-libs/dbus-glib-0.76
+ >=dev-libs/glib-2.16.0
+ gnome-base/gconf:2
+ >=x11-libs/gtk+-2.6
+ x11-libs/libwnck"
+DEPEND="${RDEPEND}"
+
+src_configure() {
+ append-flags -fno-strict-aliasing
+ default
+}
+
+src_install() {
+ emake DESTDIR="${D}" install || die "Install failed"
+}
diff --git a/x11-misc/rss-glx/rss-glx-0.9.0.ebuild b/x11-misc/rss-glx/rss-glx-0.9.0.ebuild
new file mode 100644
index 00000000..35f9fa1b
--- /dev/null
+++ b/x11-misc/rss-glx/rss-glx-0.9.0.ebuild
@@ -0,0 +1,120 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI=2
+inherit autotools multilib
+
+MY_P=${PN}_${PV}
+
+DESCRIPTION="Really Slick OpenGL Screensavers for XScreenSaver"
+HOMEPAGE="http://rss-glx.sourceforge.net"
+SRC_URI="mirror://sourceforge/${PN}/${MY_P}.tar.bz2"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~alpha amd64 ppc ~ppc64 sparc x86"
+IUSE="+bzip2 openal"
+
+RDEPEND="x11-libs/libX11
+ x11-libs/libXext
+ >=media-libs/glew-1.5.1
+ media-libs/mesa
+ || (
+ >=gnome-extra/gnome-screensaver-2.26.1
+ >=x11-misc/xscreensaver-5.10
+ )
+ >=media-gfx/imagemagick-6.2
+ bzip2? ( app-arch/bzip2 )
+ openal? ( >=media-libs/freealut-1.1.0-r1 )"
+DEPEND="${RDEPEND}
+ x11-proto/xextproto
+ dev-util/pkgconfig
+ sys-apps/sed"
+
+S=${WORKDIR}/${MY_P}
+
+src_prepare() {
+ sed -e '/CFLAGS=/s:-O2:${CFLAGS}:' \
+ -e '/CXXFLAGS=/s:-O2:${CXXFLAGS}:' \
+ -i configure.in || die "sed failed"
+ eautoreconf
+}
+
+src_configure() {
+ econf \
+ --bindir=/usr/$(get_libdir)/misc/xscreensaver \
+ --enable-shared \
+ --disable-dependency-tracking \
+ $(use_enable bzip2) \
+ $(use_enable openal sound) \
+ --with-configdir=/usr/share/xscreensaver/config
+}
+
+src_install() {
+ emake DESTDIR="${D}" install || die "emake install failed"
+ dodoc ChangeLog README*
+}
+
+pkg_postinst() {
+ local xssconf="${ROOT}usr/share/X11/app-defaults/XScreenSaver"
+
+ if [ -f ${xssconf} ]; then
+ sed -e '/*programs:/a\
+ GL: \"Cyclone\" cyclone --root \\n\\\
+ GL: \"Euphoria\" euphoria --root \\n\\\
+ GL: \"Fieldlines\" fieldlines --root \\n\\\
+ GL: \"Flocks\" flocks --root \\n\\\
+ GL: \"Flux\" flux --root \\n\\\
+ GL: \"Helios\" helios --root \\n\\\
+ GL: \"Hyperspace\" hyperspace --root \\n\\\
+ GL: \"Lattice\" lattice --root \\n\\\
+ GL: \"Plasma\" plasma --root \\n\\\
+ GL: \"Skyrocket\" skyrocket --root \\n\\\
+ GL: \"Solarwinds\" solarwinds --root \\n\\\
+ GL: \"Colorfire\" colorfire --root \\n\\\
+ GL: \"Hufos Smoke\" hufo_smoke --root \\n\\\
+ GL: \"Hufos Tunnel\" hufo_tunnel --root \\n\\\
+ GL: \"Sundancer2\" sundancer2 --root \\n\\\
+ GL: \"BioF\" biof --root \\n\\\
+ GL: \"BusySpheres\" busyspheres --root \\n\\\
+ GL: \"SpirographX\" spirographx --root \\n\\\
+ GL: \"MatrixView\" matrixview --root \\n\\\
+ GL: \"Lorenz\" lorenz --root \\n\\\
+ GL: \"Drempels\" drempels --root \\n\\\
+ GL: \"Feedback\" feedback --root \\n\\' \
+ -i ${xssconf} || die "sed failed"
+ fi
+}
+
+pkg_postrm() {
+ local xssconf="${ROOT}usr/share/X11/app-defaults/XScreenSaver"
+
+ if [ -f ${xssconf} ]; then
+ sed \
+ -e '/\"Cyclone\" cyclone/d' \
+ -e '/\"Euphoria\" euphoria/d' \
+ -e '/\"Fieldlines\" fieldlines/d' \
+ -e '/\"Flocks\" flocks/d' \
+ -e '/\"Flux\" flux/d' \
+ -e '/\"Helios\" helios/d' \
+ -e '/\"Hyperspace\" hyperspace/d' \
+ -e '/\"Lattice\" lattice/d' \
+ -e '/\"Plasma\" plasma/d' \
+ -e '/\"Skyrocket\" skyrocket/d' \
+ -e '/\"Solarwinds\" solarwinds/d' \
+ -e '/\"Colorfire\" colorfire/d' \
+ -e '/\"Hufos Smoke\" hufo_smoke/d' \
+ -e '/\"Hufos Tunnel\" hufo_tunnel/d' \
+ -e '/\"Sundancer2\" sundancer2/d' \
+ -e '/\"BioF\" biof/d' \
+ -e '/\"BusySpheres\" busyspheres/d' \
+ -e '/\"SpirographX\" spirographx/d' \
+ -e '/\"MatrixView\" matrixview/d' \
+ -e '/\"Lorenz\" lorenz/d' \
+ -e '/\"Drempels\" drempels/d' \
+ -e '/\"Feedback\" feedback/d' \
+ -i ${xssconf} || die "sed failed"
+ fi
+}
diff --git a/x11-terms/terminator/terminator-0.14-r1.ebuild b/x11-terms/terminator/terminator-0.14-r1.ebuild
new file mode 100644
index 00000000..5bee394c
--- /dev/null
+++ b/x11-terms/terminator/terminator-0.14-r1.ebuild
@@ -0,0 +1,23 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Copyright 2009 Marc-Antoine Perennou
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI="2"
+
+inherit distutils
+
+DESCRIPTION="Multiple GNOME terminals in one window"
+HOMEPAGE="http://www.tenshu.net/terminator/"
+SRC_URI="http://launchpad.net/${PN}/trunk/${PV}/+download/${PN}_${PV}.tar.gz"
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE=""
+
+RDEPEND="dev-python/notify-python
+ >=x11-libs/vte-0.16[python]"
+
+src_prepare() {
+ distutils_src_prepare
+}