Also uses the notification system to display tags.
---
 Makefile.am                              |   8 +
 configure.ac                             |  19 ++
 src/mixer/MixerList.hxx                  |   1 +
 src/mixer/plugins/HaikuMixerPlugin.cxx   |  73 +++++
 src/output/Registry.cxx                  |   4 +
 src/output/plugins/HaikuOutputPlugin.cxx | 532 +++++++++++++++++++++++++++++++
 src/output/plugins/HaikuOutputPlugin.hxx |  34 ++
 7 files changed, 671 insertions(+)
 create mode 100644 src/mixer/plugins/HaikuMixerPlugin.cxx
 create mode 100644 src/output/plugins/HaikuOutputPlugin.cxx
 create mode 100644 src/output/plugins/HaikuOutputPlugin.hxx

diff --git a/Makefile.am b/Makefile.am
index e4dc88a..155a6a7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1355,6 +1355,14 @@ liboutput_plugins_a_SOURCES += \
        src/output/plugins/FifoOutputPlugin.hxx
 endif
 
+if HAVE_HAIKU
+liboutput_plugins_a_SOURCES += \
+       src/output/plugins/HaikuOutputPlugin.cxx \
+       src/output/plugins/HaikuOutputPlugin.hxx
+libmixer_plugins_a_SOURCES += \
+       src/mixer/plugins/HaikuMixerPlugin.cxx 
src/mixer/plugins/HaikuMixerPlugin.hxx
+endif
+
 if ENABLE_PIPE_OUTPUT
 liboutput_plugins_a_SOURCES += \
        src/output/plugins/PipeOutputPlugin.cxx \
diff --git a/configure.ac b/configure.ac
index ba78814..5c06463 100644
--- a/configure.ac
+++ b/configure.ac
@@ -333,6 +333,11 @@ AC_ARG_ENABLE(fifo,
                [disable support for writing audio to a FIFO (default: 
enable)]),,
        enable_fifo=yes)
 
+AC_ARG_ENABLE(haiku,
+       AS_HELP_STRING([--enable-haiku],
+               [enable the Haiku output plugin (default: auto)]),,
+       enable_haiku=auto)
+
 AC_ARG_ENABLE(httpd-output,
        AS_HELP_STRING([--enable-httpd-output],
                [enables the HTTP server output]),,
@@ -1129,6 +1134,19 @@ fi
 MPD_DEFINE_CONDITIONAL(enable_fifo, HAVE_FIFO,
        [support for writing audio to a FIFO])
 
+dnl ----------------------------------- Haiku ---------------------------------
+if test x$enable_haiku = xauto; then
+       AC_CHECK_HEADER(media/MediaDefs.h,
+               [enable_haiku=yes],
+               [enable_haiku=no])
+fi
+if test x$enable_haiku = xyes; then
+       AC_DEFINE(HAVE_HAIKU,1,[Define for compiling Haiku support])
+       LIBS="$LIBS -lbe -lmedia"
+fi
+
+AM_CONDITIONAL(HAVE_HAIKU, test x$enable_haiku = xyes)
+
 dnl ------------------------------- HTTPD Output ------------------------------
 if test x$enable_httpd_output = xauto; then
        # handle HTTPD auto-detection: disable if no encoder is
@@ -1422,6 +1440,7 @@ printf '\nPlayback support:\n\t'
 results(alsa,ALSA)
 results(fifo,FIFO)
 results(recorder_output,[File Recorder])
+results(haiku,[Haiku])
 results(httpd_output,[HTTP Daemon])
 results(jack,[JACK])
 printf '\n\t'
diff --git a/src/mixer/MixerList.hxx b/src/mixer/MixerList.hxx
index 0700084..f2aa2e6 100644
--- a/src/mixer/MixerList.hxx
+++ b/src/mixer/MixerList.hxx
@@ -30,6 +30,7 @@ struct MixerPlugin;
 extern const MixerPlugin null_mixer_plugin;
 extern const MixerPlugin software_mixer_plugin;
 extern const MixerPlugin alsa_mixer_plugin;
+extern const MixerPlugin haiku_mixer_plugin;
 extern const MixerPlugin oss_mixer_plugin;
 extern const MixerPlugin roar_mixer_plugin;
 extern const MixerPlugin pulse_mixer_plugin;
diff --git a/src/mixer/plugins/HaikuMixerPlugin.cxx 
b/src/mixer/plugins/HaikuMixerPlugin.cxx
new file mode 100644
index 0000000..d6dfb66
--- /dev/null
+++ b/src/mixer/plugins/HaikuMixerPlugin.cxx
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * Copyright (C) 2010-2011 Philipp 'ph3-der-loewe' Schafft
+ * Copyright (C) 2010-2011 Hans-Kristian 'maister' Arntzen
+ * Copyright (C) 2014-2015 François 'mmu_man' Revol
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "config.h"
+#include "mixer/MixerInternal.hxx"
+#include "output/plugins/HaikuOutputPlugin.hxx"
+#include "Compiler.h"
+
+class HaikuMixer final : public Mixer {
+       /** the base mixer class */
+       HaikuOutput &self;
+
+public:
+       HaikuMixer(HaikuOutput &_output, MixerListener &_listener)
+               :Mixer(haiku_mixer_plugin, _listener),
+                self(_output) {}
+
+       /* virtual methods from class Mixer */
+       virtual bool Open(gcc_unused Error &error) override {
+               return true;
+       }
+
+       virtual void Close() override {
+       }
+
+       virtual int GetVolume(Error &error) override;
+       virtual bool SetVolume(unsigned volume, Error &error) override;
+};
+
+static Mixer *
+haiku_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
+               MixerListener &listener,
+               gcc_unused const ConfigBlock &block,
+               gcc_unused Error &error)
+{
+       return new HaikuMixer((HaikuOutput &)ao, listener);
+}
+
+int
+HaikuMixer::GetVolume(gcc_unused Error &error)
+{
+       return haiku_output_get_volume(self);
+}
+
+bool
+HaikuMixer::SetVolume(unsigned volume, gcc_unused Error &error)
+{
+       return haiku_output_set_volume(self, volume);
+}
+
+const MixerPlugin haiku_mixer_plugin = {
+       haiku_mixer_init,
+       false,
+};
diff --git a/src/output/Registry.cxx b/src/output/Registry.cxx
index 06928ce..b173498 100644
--- a/src/output/Registry.cxx
+++ b/src/output/Registry.cxx
@@ -24,6 +24,7 @@
 #include "plugins/AoOutputPlugin.hxx"
 #include "plugins/FifoOutputPlugin.hxx"
 #include "plugins/httpd/HttpdOutputPlugin.hxx"
+#include "plugins/HaikuOutputPlugin.hxx"
 #include "plugins/JackOutputPlugin.hxx"
 #include "plugins/NullOutputPlugin.hxx"
 #include "plugins/OpenALOutputPlugin.hxx"
@@ -51,6 +52,9 @@ const AudioOutputPlugin *const audio_output_plugins[] = {
 #ifdef HAVE_FIFO
        &fifo_output_plugin,
 #endif
+#ifdef HAVE_HAIKU
+       &haiku_output_plugin,
+#endif
 #ifdef ENABLE_PIPE_OUTPUT
        &pipe_output_plugin,
 #endif
diff --git a/src/output/plugins/HaikuOutputPlugin.cxx 
b/src/output/plugins/HaikuOutputPlugin.cxx
new file mode 100644
index 0000000..e235d59
--- /dev/null
+++ b/src/output/plugins/HaikuOutputPlugin.cxx
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ * Copyright (C) 2014-2015 François 'mmu_man' Revol
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "HaikuOutputPlugin.hxx"
+#include "../OutputAPI.hxx"
+#include "../Wrapper.hxx"
+#include "mixer/MixerList.hxx"
+#include "util/Error.hxx"
+#include "util/Domain.hxx"
+#include "Log.hxx"
+
+#include <AppFileInfo.h>
+#include <Application.h>
+#include <Bitmap.h>
+#include <IconUtils.h>
+#include <MediaDefs.h>
+#include <MediaRoster.h>
+#include <Notification.h>
+#include <OS.h>
+#include <Resources.h>
+#include <StringList.h>
+#include <SoundPlayer.h>
+
+#include <string.h>
+
+#define UTF8_PLAY "\xE2\x96\xB6"
+
+class HaikuOutput {
+       friend struct AudioOutputWrapper<HaikuOutput>;
+       friend int haiku_output_get_volume(HaikuOutput &haiku);
+       friend bool haiku_output_set_volume(HaikuOutput &haiku, unsigned 
volume);
+
+       AudioOutput base;
+
+       size_t write_size;
+
+       media_raw_audio_format* format;
+       BSoundPlayer* sound_player;
+
+       sem_id new_buffer;
+       sem_id buffer_done;
+
+       uint8* buffer;
+       size_t buffer_size;
+       size_t buffer_filled;
+
+       unsigned buffer_delay;
+
+public:
+       HaikuOutput()
+               :base(haiku_output_plugin) {}
+       ~HaikuOutput();
+
+       bool Initialize(const ConfigBlock &block, Error &error) {
+               return base.Configure(block, error);
+       }
+
+       static HaikuOutput *Create(const ConfigBlock &block, Error &error);
+
+       bool Open(AudioFormat &audio_format, Error &error);
+
+       void Close() {
+               DoClose();
+       }
+
+       size_t Play(const void *chunk, size_t size, Error &error);
+       void Cancel();
+
+       bool Configure(const ConfigBlock &block, Error &error);
+
+       size_t Delay();
+
+       void FillBuffer(void* _buffer, size_t size,
+               gcc_unused const media_raw_audio_format& _format);
+
+       void SendTag(const Tag &tag);
+
+private:
+
+       void DoClose();
+};
+
+static constexpr Domain haiku_output_domain("haiku_output");
+
+static void
+haiku_output_error(Error &error_r, status_t err)
+{
+       const char *error = strerror(err);
+       error_r.Set(haiku_output_domain, err, error);
+}
+
+static void
+initialize_application()
+{
+       // required to send the notification with a bitmap
+       // TODO: actually Run() it and handle B_QUIT_REQUESTED
+       // TODO: use some locking?
+       if (be_app == NULL) {
+               FormatDebug(haiku_output_domain, "creating be_app\n");
+               new BApplication("application/x-vnd.MusicPD");
+       }
+}
+
+static void
+finalize_application()
+{
+       // TODO: use some locking?
+       delete be_app;
+       be_app = NULL;
+       FormatDebug(haiku_output_domain, "deleting be_app\n");
+}
+
+inline bool
+HaikuOutput::Configure(const ConfigBlock &block, Error &error)
+{
+       /* XXX: by default we should let the MediaKit propose the buffer size */
+       write_size = block.GetBlockValue("write_size", 4096u);
+
+       format = (media_raw_audio_format*)malloc(
+               sizeof(media_raw_audio_format));
+       if (format == nullptr) {
+               haiku_output_error(error, B_NO_MEMORY);
+               return false;
+       }
+
+       return true;
+}
+
+static bool
+haiku_test_default_device(void)
+{
+       BSoundPlayer testPlayer;
+       return testPlayer.InitCheck() == B_OK;
+
+}
+
+inline HaikuOutput *
+HaikuOutput::Create(const ConfigBlock &block, Error &error)
+{
+       initialize_application();
+
+       HaikuOutput *ad = new HaikuOutput();
+
+       if (!ad->Initialize(block, error)) {
+               delete ad;
+               return nullptr;
+       }
+
+       if (!ad->Configure(block, error)) {
+               delete ad;
+               return nullptr;
+       }
+
+       return ad;
+}
+
+void
+HaikuOutput::DoClose()
+{
+       sound_player->SetHasData(false);
+       delete_sem(new_buffer);
+       delete_sem(buffer_done);
+       sound_player->Stop();
+       delete sound_player;
+       sound_player = nullptr;
+}
+
+
+
+HaikuOutput::~HaikuOutput()
+{
+       free(format);
+       delete_sem(new_buffer);
+       delete_sem(buffer_done);
+
+       finalize_application();
+}
+
+static void
+fill_buffer(void* cookie, void* buffer, size_t size,
+       const media_raw_audio_format& format)
+{
+       HaikuOutput *ad = (HaikuOutput *)cookie;
+       ad->FillBuffer(buffer, size, format);
+}
+
+
+void
+HaikuOutput::FillBuffer(void* _buffer, size_t size,
+       gcc_unused const media_raw_audio_format& _format)
+{
+
+       buffer = (uint8*)_buffer;
+       buffer_size = size;
+       buffer_filled = 0;
+       bigtime_t start = system_time();
+       release_sem(new_buffer);
+       acquire_sem(buffer_done);
+       bigtime_t w = system_time() - start;
+       
+       if (w > 5000LL) {
+               FormatDebug(haiku_output_domain,
+                       "haiku:fill_buffer waited %Ldus\n", w);
+       }
+       
+       if (buffer_filled < buffer_size) {
+               memset(buffer + buffer_filled, 0,
+                       buffer_size - buffer_filled);
+               FormatDebug(haiku_output_domain,
+                       "haiku:fill_buffer filled %d size %d clearing 
remainder\n",
+                       (int)buffer_filled, (int)buffer_size);
+
+       }
+}
+
+inline bool
+HaikuOutput::Open(AudioFormat &audio_format, Error &error)
+{
+       status_t err;
+       *format = media_multi_audio_format::wildcard;
+
+       switch (audio_format.format) {
+       case SampleFormat::S8:
+               format->format = media_raw_audio_format::B_AUDIO_CHAR;
+               break;
+
+       case SampleFormat::S16:
+               format->format = media_raw_audio_format::B_AUDIO_SHORT;
+               break;
+
+       case SampleFormat::S32:
+               format->format = media_raw_audio_format::B_AUDIO_INT;
+               break;
+
+       case SampleFormat::FLOAT:
+               format->format = media_raw_audio_format::B_AUDIO_FLOAT;
+               break;
+
+       default:
+               /* fall back to float */
+               audio_format.format = SampleFormat::FLOAT;
+               format->format = media_raw_audio_format::B_AUDIO_FLOAT;
+               break;
+       }
+
+       format->frame_rate = audio_format.sample_rate;
+       format->byte_order = B_MEDIA_HOST_ENDIAN;
+       format->channel_count = audio_format.channels;
+
+       buffer_size = 0;
+
+       if (write_size)
+               format->buffer_size = write_size;
+       else
+               format->buffer_size = 
BMediaRoster::Roster()->AudioBufferSizeFor(
+                       format->channel_count, format->format,
+                       format->frame_rate, B_UNKNOWN_BUS) * 2;
+
+       FormatDebug(haiku_output_domain,
+               "using haiku driver ad: bs: %d ws: %d "
+               "channels %d rate %f fmt %08lx bs %d\n",
+                       (int)buffer_size, (int)write_size,
+                       (int)format->channel_count, format->frame_rate,
+                       format->format, (int)format->buffer_size);
+
+       sound_player = new BSoundPlayer(format, "MPD Output",
+               fill_buffer, NULL, this);
+
+       err = sound_player->InitCheck();
+       if (err != B_OK) {
+               delete sound_player;
+               sound_player = NULL;
+               haiku_output_error(error, err);
+               return false;
+       }
+
+       // calculate the allowable delay for the buffer (ms)
+       buffer_delay = format->buffer_size;
+       buffer_delay /= (format->format &
+               media_raw_audio_format::B_AUDIO_SIZE_MASK);
+       buffer_delay /= format->channel_count;
+       buffer_delay *= 1000 / format->frame_rate;
+       // half of the total buffer play time
+       buffer_delay /= 2;
+       FormatDebug(haiku_output_domain,
+               "buffer delay: %d ms\n", buffer_delay);
+
+       new_buffer = create_sem(0, "New buffer request");
+       buffer_done = create_sem(0, "Buffer done");
+
+       sound_player->SetVolume(1.0);
+       sound_player->Start();
+       sound_player->SetHasData(false);
+
+       return true;
+}
+
+inline size_t
+HaikuOutput::Play(const void *chunk, size_t size, gcc_unused Error &error)
+{
+       BSoundPlayer* const soundPlayer = sound_player;
+       const uint8 *data = (const uint8 *)chunk;
+
+       if (size == 0) {
+               soundPlayer->SetHasData(false);
+               return 0;
+       }
+
+       if (!soundPlayer->HasData())
+               soundPlayer->SetHasData(true);
+       acquire_sem(new_buffer);
+
+       size_t bytesLeft = size;
+       while (bytesLeft > 0) {
+               if (buffer_filled == buffer_size) {
+                       // Request another buffer from BSoundPlayer
+                       release_sem(buffer_done);
+                       acquire_sem(new_buffer);
+               }
+
+               const size_t copyBytes = std::min(bytesLeft, buffer_size
+                       - buffer_filled);
+               memcpy(buffer + buffer_filled, data,
+                       copyBytes);
+               buffer_filled += copyBytes;
+               data += copyBytes;
+               bytesLeft -= copyBytes;
+       }
+
+
+       if (buffer_filled < buffer_size) {
+               // Continue filling this buffer the next time this function is 
called
+               release_sem(new_buffer);
+       } else {
+               // Buffer is full
+               release_sem(buffer_done);
+               //soundPlayer->SetHasData(false);
+       }
+
+       return size;
+}
+
+inline size_t
+HaikuOutput::Delay()
+{
+       unsigned delay = buffer_filled ? 0 : buffer_delay;
+
+       //FormatDebug(haiku_output_domain,
+       //              "delay=%d\n", delay / 2);
+       // XXX: doesn't work
+       //return (delay / 2) ? 1 : 0;
+       (void)delay;
+
+       return 0;
+}
+
+inline void
+HaikuOutput::SendTag(const Tag &tag)
+{
+       status_t err;
+
+       /* lazily initialized */
+       static BBitmap *icon = NULL;
+
+       if (icon == NULL) {
+               BAppFileInfo info;
+               BResources resources;
+               err = resources.SetToImage((const void *)&HaikuOutput::SendTag);
+               BFile file(resources.File());
+               err = info.SetTo(&file);
+               icon = new BBitmap(BRect(0, 0, (float)B_LARGE_ICON - 1,
+                       (float)B_LARGE_ICON - 1), B_BITMAP_NO_SERVER_LINK, 
B_RGBA32);
+               err = info.GetIcon(icon, B_LARGE_ICON);
+               if (err != B_OK) {
+                       delete icon;
+                       icon = NULL;
+               }
+       }
+
+       BNotification notification(B_INFORMATION_NOTIFICATION);
+
+       BString messageId("mpd_");
+       messageId << find_thread(NULL);
+       notification.SetMessageID(messageId);
+
+       notification.SetGroup("Music Player Daemon");
+
+       char timebuf[16];
+       unsigned seconds = 0;
+       if (!tag.duration.IsNegative()) {
+               seconds = tag.duration.ToS();
+               snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d",
+                        seconds / 3600, (seconds % 3600) / 60, seconds % 60);
+       }
+
+       BString artist;
+       BString album;
+       BString title;
+       BString track;
+       BString name;
+
+       for (const auto &item : tag)
+       {
+               switch (item.type) {
+               case TAG_ARTIST:
+               case TAG_ALBUM_ARTIST:
+                       if (artist.Length() == 0)
+                               artist << item.value;
+                       break;
+               case TAG_ALBUM:
+                       if (album.Length() == 0)
+                               album << item.value;
+                       break;
+               case TAG_TITLE:
+                       if (title.Length() == 0)
+                               title << item.value;
+                       break;
+               case TAG_TRACK:
+                       if (track.Length() == 0)
+                               track << item.value;
+                       break;
+               case TAG_NAME:
+                       if (name.Length() == 0)
+                               name << item.value;
+                       break;
+               case TAG_GENRE:
+               case TAG_DATE:
+               case TAG_PERFORMER:
+               case TAG_COMMENT:
+               case TAG_DISC:
+               case TAG_COMPOSER:
+               case TAG_MUSICBRAINZ_ARTISTID:
+               case TAG_MUSICBRAINZ_ALBUMID:
+               case TAG_MUSICBRAINZ_ALBUMARTISTID:
+               case TAG_MUSICBRAINZ_TRACKID:
+               default:
+                       FormatDebug(haiku_output_domain,
+                               "tag item: type %d value '%s'\n", item.type, 
item.value);
+                       break;
+               }
+       }
+
+       notification.SetTitle(UTF8_PLAY " Now Playing:");
+
+       BStringList content;
+       if (name.Length())
+               content.Add(name);
+       if (artist.Length())
+               content.Add(artist);
+       if (album.Length())
+               content.Add(album);
+       if (track.Length())
+               content.Add(track);
+       if (title.Length())
+               content.Add(title);
+
+       if (content.CountStrings() == 0)
+               content.Add("(Unknown)");
+
+       BString full = content.Join(" " B_UTF8_BULLET " ");
+
+       if (seconds > 0)
+               full << " (" << timebuf << ")";
+
+       notification.SetContent(full);
+
+       err = notification.SetIcon(icon);
+
+       notification.Send();
+}
+
+int
+haiku_output_get_volume(HaikuOutput &haiku)
+{
+       BSoundPlayer* const soundPlayer = haiku.sound_player;
+
+       if (soundPlayer == NULL || soundPlayer->InitCheck() != B_OK)
+               return 0;
+
+       return (int)(soundPlayer->Volume() * 100 + 0.5);
+}
+
+bool
+haiku_output_set_volume(HaikuOutput &haiku, unsigned volume)
+{
+       BSoundPlayer* const soundPlayer = haiku.sound_player;
+
+       if (soundPlayer == NULL || soundPlayer->InitCheck() != B_OK)
+               return false;
+
+       soundPlayer->SetVolume((float)volume / 100);
+       return true;
+}
+
+typedef AudioOutputWrapper<HaikuOutput> Wrapper;
+
+const struct AudioOutputPlugin haiku_output_plugin = {
+       "haiku",
+       haiku_test_default_device,
+       &Wrapper::Init,
+       &Wrapper::Finish,
+       nullptr,
+       nullptr,
+       &Wrapper::Open,
+       &Wrapper::Close,
+       &Wrapper::Delay,
+       &Wrapper::SendTag,
+       &Wrapper::Play,
+       nullptr,
+       nullptr,
+       nullptr,
+
+       &haiku_mixer_plugin,
+};
diff --git a/src/output/plugins/HaikuOutputPlugin.hxx 
b/src/output/plugins/HaikuOutputPlugin.hxx
new file mode 100644
index 0000000..fb85d4b
--- /dev/null
+++ b/src/output/plugins/HaikuOutputPlugin.hxx
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ * Copyright (C) 2014-2015 François 'mmu_man' Revol
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_HAIKU_OUTPUT_PLUGIN_HXX
+#define MPD_HAIKU_OUTPUT_PLUGIN_HXX
+
+class HaikuOutput;
+
+extern const struct AudioOutputPlugin haiku_output_plugin;
+
+int
+haiku_output_get_volume(HaikuOutput &haiku);
+
+bool
+haiku_output_set_volume(HaikuOutput &haiku, unsigned volume);
+
+#endif
-- 
2.2.2

_______________________________________________
mpd-devel mailing list
mpd-devel@musicpd.org
http://mailman.blarg.de/listinfo/mpd-devel

Reply via email to