From 355096acdce158cb68126ccadf12a767736a9029 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Fri, 4 Jan 2019 16:58:00 +1000
Subject: Add Haiku support


diff --git a/configure.ac b/configure.ac
index 9a0f5df..a4d8d0a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -603,6 +603,21 @@ if test "x$enable_filewriter" = "xyes" -a "x$enable_filewriter_mp3" != "xno"; th
     )
 fi
 
+dnl MediaKit
+dnl ==========
+
+AC_ARG_ENABLE(filewriter,
+    [AS_HELP_STRING([--disable-mediakit], [disable MediaKit output plugin (default=enabled)])],
+    [enable_mediakit=$enableval],
+    [enable_mediakit=yes]
+)
+
+have_mediakit=yes
+
+if test "x$enable_mediakit" != "xno"; then
+    OUTPUT_PLUGINS="$OUTPUT_PLUGINS mediakit"
+fi
+
 dnl Vorbis and FLAC support support reuse input plugin checks.
 
 if test "x$enable_filewriter" = "xyes" -a "x$have_vorbis" = "xyes"; then
@@ -633,7 +648,7 @@ fi
 
 dnl *** End of all plugin checks ***
 
-plugindir=`pkg-config audacious --variable=plugin_dir`
+plugindir="$libdir/audacious"
 AC_SUBST(plugindir)
 
 dnl XXX
@@ -745,6 +760,7 @@ echo "  Jack Audio Connection Kit:              $have_jack"
 echo "  Open Sound System:                      $have_oss4"
 echo "  PulseAudio:                             $have_pulse"
 echo "  Simple DirectMedia Layer:               $have_sdlout"
+echo "  MediaKit:                               $have_mediakit"
 echo "  Sndio:                                  $have_sndio"
 echo "  Win32 waveOut:                          $HAVE_MSWINDOWS"
 echo "  FileWriter:                             $enable_filewriter"
diff --git a/src/mediakit/Makefile b/src/mediakit/Makefile
new file mode 100644
index 0000000..5d59cc1
--- /dev/null
+++ b/src/mediakit/Makefile
@@ -0,0 +1,13 @@
+PLUGIN = mediakit${PLUGIN_SUFFIX}
+
+SRCS = mediakit.cc ringbuffer.cc sndplayer.cc
+
+include ../../buildsys.mk
+include ../../extra.mk
+
+plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}
+
+LD = ${CXX}
+CPPFLAGS += -I../..
+CXXFLAGS += ${PLUGIN_CFLAGS}
+LIBS += -lbe -lmedia
diff --git a/src/mediakit/mediakit.cc b/src/mediakit/mediakit.cc
new file mode 100644
index 0000000..bc4d8a6
--- /dev/null
+++ b/src/mediakit/mediakit.cc
@@ -0,0 +1,175 @@
+/*
+ * Haiku MediaKit Output Plugin for Audacious
+ * Copyright 2018 Gerasim Troeglazov (3dEyes**)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions, and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions, and the following disclaimer in the documentation
+ *    provided with the distribution.
+ *
+ * This software is provided "as is" and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising from
+ * the use of this software.
+ */
+
+#include <math.h>
+#include <pthread.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/ringbuf.h>
+#include <libaudcore/runtime.h>
+
+#include "sndplayer.h"
+
+static SndPlayer player;
+
+class MediaKitOutput : public OutputPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+
+    static constexpr PluginInfo info = {
+        N_("MediaKit Output"),
+        PACKAGE,
+        about
+    };
+
+    constexpr MediaKitOutput () : OutputPlugin (info, 1) {}
+
+    bool init ();
+    void cleanup ();
+
+    StereoVolume get_volume ();
+    void set_volume (StereoVolume v);
+
+    bool open_audio (int aud_format, int rate, int chans, String & error);
+    void close_audio ();
+
+    void period_wait ();
+    int write_audio (const void * data, int size);
+    void drain ();
+
+    int get_delay ();
+
+    void pause (bool pause);
+    void flush ();
+};
+
+EXPORT MediaKitOutput aud_plugin_instance;
+
+const char MediaKitOutput::about[] =
+ N_("Haiku MediaKit Output Plugin for Audacious\n"
+    "Copyright 2018 Gerasim Troeglazov (3dEyes**)");
+
+const char * const MediaKitOutput::defaults[] = {
+ "vol_left", "100",
+ "vol_right", "100",
+ nullptr};
+
+static volatile int vol_left, vol_right;
+static bool paused_flag;
+
+bool MediaKitOutput::init ()
+{
+    aud_config_set_defaults ("sdlout", defaults);
+
+    vol_left = aud_get_int ("sdlout", "vol_left");
+    vol_right = aud_get_int ("sdlout", "vol_right");
+    
+    return true;
+}
+
+void MediaKitOutput::cleanup ()
+{
+}
+
+StereoVolume MediaKitOutput::get_volume ()
+{
+    return {vol_left, vol_right};
+}
+
+void MediaKitOutput::set_volume (StereoVolume v)
+{
+    vol_left = v.left;
+    vol_right = v.right;
+
+	if (player.isOK())
+		player.setVolume(vol_left, vol_right);
+
+    aud_set_int ("mediakit", "vol_left", v.left);
+    aud_set_int ("mediakit", "vol_right", v.right);
+}
+
+bool MediaKitOutput::open_audio (int format, int rate, int chan, String & error)
+{
+    if (format != FMT_S16_NE)
+    {
+        error = String ("MediaKit error: Only signed 16-bit, native endian audio is supported.");
+        return false;
+    }
+
+    player.channels = (float)chan;
+    player.sample_rate = (float)rate;
+
+	player.stop();
+	bool status = player.start();
+	if (!status) {
+		error = String ("MediaKit error: not started.");
+	} else {
+		player.setVolume(vol_left, vol_right);
+	}
+
+    paused_flag = !status;
+
+    return status;
+}
+
+void MediaKitOutput::close_audio ()
+{
+    player.stop();
+}
+
+void MediaKitOutput::period_wait ()
+{
+}
+
+int MediaKitOutput::write_audio (const void * data, int len)
+{
+	if (len <= 0 || !player.isOK())
+		return 0;
+
+	player.write( (unsigned char*)data, len );
+
+    return len;
+}
+
+void MediaKitOutput::drain ()
+{
+}
+
+int MediaKitOutput::get_delay ()
+{
+    return 0;
+}
+
+void MediaKitOutput::pause (bool pause)
+{
+    paused_flag = pause;
+}
+
+void MediaKitOutput::flush ()
+{
+	if (player.isOK())
+		player.flush();
+}
diff --git a/src/mediakit/ringbuffer.cc b/src/mediakit/ringbuffer.cc
new file mode 100644
index 0000000..ebd22f6
--- /dev/null
+++ b/src/mediakit/ringbuffer.cc
@@ -0,0 +1,129 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ringbuffer.h"
+
+RingBuffer::RingBuffer( int size )
+{
+	 initialized = false;
+     Buffer = new unsigned char[size];
+     if(Buffer!=NULL) {
+     	memset( Buffer, 0, size );
+	    BufferSize = size;     	
+     } else {
+     	BufferSize = 0;
+     }
+     reader = 0;
+     writer = 0;
+     writeBytesAvailable = size;
+     if((locker=create_sem(1,"locker")) >= B_OK) {
+     	initialized = true;
+     } else {
+     	if(Buffer!=NULL) {
+     		delete[] Buffer;     		
+     	}
+     }
+}
+
+RingBuffer::~RingBuffer( )
+{
+	 if(initialized) {
+     	delete[] Buffer;
+     	delete_sem(locker);
+	 }
+}
+
+bool 
+RingBuffer::Empty( void )
+{
+     memset( Buffer, 0, BufferSize );
+     reader = 0;
+     writer = 0;
+     writeBytesAvailable = BufferSize;
+     return true;
+}
+
+int 
+RingBuffer::Read( unsigned char *data, int size )
+{	
+	 acquire_sem(locker);
+	 
+     if( data == 0 || size <= 0 || writeBytesAvailable == BufferSize ) {
+     	 release_sem(locker);
+         return 0;
+     }
+
+     int readBytesAvailable = BufferSize - writeBytesAvailable;
+
+     if( size > readBytesAvailable ) {
+         size = readBytesAvailable;
+     }
+
+     if(size > BufferSize - reader) {
+         int len = BufferSize - reader;
+         memcpy(data, Buffer + reader, len);
+         memcpy(data + len, Buffer, size-len);
+     } else {
+         memcpy(data, Buffer + reader, size);
+     }
+
+     reader = (reader + size) % BufferSize;
+     writeBytesAvailable += size;
+	 
+	 release_sem(locker);
+     return size;
+}
+
+int 
+RingBuffer::Write( unsigned char *data, int size )
+{
+	 acquire_sem(locker);
+	 
+     if( data == 0 || size <= 0 || writeBytesAvailable == 0 ) {
+     	 release_sem(locker);
+         return 0;
+     }
+
+     if( size > writeBytesAvailable ) {
+         size = writeBytesAvailable;
+     }
+
+     if(size > BufferSize - writer) {
+         int len = BufferSize - writer;
+         memcpy(Buffer + writer, data, len);
+         memcpy(Buffer, data+len, size-len);
+     } else {
+         memcpy(Buffer + writer, data, size);
+     }
+
+     writer = (writer + size) % BufferSize;
+     writeBytesAvailable -= size;
+
+	 release_sem(locker);	 
+     return size;
+}
+
+int 
+RingBuffer::GetSize( void )
+{
+     return BufferSize;
+}
+
+int 
+RingBuffer::GetWriteAvailable( void )
+{
+     return writeBytesAvailable;
+}
+
+int 
+RingBuffer::GetReadAvailable( void )
+{
+     return BufferSize - writeBytesAvailable;
+}
+
+status_t 
+RingBuffer::InitCheck( void )
+{
+	return initialized?B_OK:B_ERROR;
+}
diff --git a/src/mediakit/ringbuffer.h b/src/mediakit/ringbuffer.h
new file mode 100644
index 0000000..4715632
--- /dev/null
+++ b/src/mediakit/ringbuffer.h
@@ -0,0 +1,31 @@
+#ifndef __RING_BUFFER_H__
+#define __RING_BUFFER_H__
+
+#include <OS.h>
+
+class RingBuffer {
+
+public:
+     RingBuffer(int size);
+     ~RingBuffer();
+     int Read( unsigned char* dataPtr, int numBytes );
+     int Write( unsigned char *dataPtr, int numBytes );
+     
+     bool Empty( void );
+     int GetSize( );
+     int GetWriteAvailable( );
+     int GetReadAvailable( );
+     status_t InitCheck( );
+private:
+     unsigned char *Buffer;
+     int BufferSize;
+     int reader;
+     int writer;
+     int writeBytesAvailable;
+     
+     sem_id locker;
+     
+     bool 	initialized;
+};
+
+#endif
diff --git a/src/mediakit/sndplayer.cc b/src/mediakit/sndplayer.cc
new file mode 100644
index 0000000..b796b24
--- /dev/null
+++ b/src/mediakit/sndplayer.cc
@@ -0,0 +1,113 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <SoundPlayer.h>
+
+#include "sndplayer.h"
+
+static void proc(void *cookie, void *buffer, size_t len, const media_raw_audio_format &format)
+{
+	RingBuffer *ring = (RingBuffer*)cookie;
+	unsigned char* ptr = (unsigned char*)buffer;
+
+	size_t readed = ring->Read(ptr,len);
+
+	if(readed < len)
+		memset(ptr+readed, 0, len - readed);
+}
+
+SndPlayer::SndPlayer()
+{	
+	channels = sample_rate = delay = 0;
+	player = NULL;
+	_isOK = true;
+}
+
+bool SndPlayer::start()
+{
+	size_t gSoundBufferSize = 8192 * sizeof(short);
+		
+	media_raw_audio_format form = {
+		sample_rate,
+		channels,
+		media_raw_audio_format::B_AUDIO_SHORT,
+		B_MEDIA_LITTLE_ENDIAN,
+		gSoundBufferSize
+	};
+	
+	ring = new RingBuffer(gSoundBufferSize * 3);
+	if(ring->InitCheck() != B_OK) {
+		delete ring; ring = 0;
+		return false;
+	}
+			
+	player = new BSoundPlayer(&form, "Audacious", proc, NULL, (void*)ring);
+	
+	if(player->InitCheck() != B_OK) {
+		delete player;
+		player = NULL;
+		return false;
+	}
+	
+	player->Start();
+	player->SetHasData(true);	
+
+	_isOK = true;
+
+	return player != NULL;
+}
+void SndPlayer::stop()
+{
+	if ( player )
+	{
+		if(player) {
+			player->Stop();
+			delete player;
+			delete ring;
+		}
+	
+		player = NULL;
+		ring = NULL;
+	}	
+}
+
+void SndPlayer::flush()
+{
+	ring->Empty();
+}
+
+void SndPlayer::setVolume(int left, int right)
+{
+	if (player!=NULL) {
+		float left_f = (float)left / 100.0;
+		float right_f = (float)right / 100.0;
+		player->SetVolume((left_f + right_f) / 2.0);
+	}
+}
+
+double SndPlayer::getLatency()
+{
+	double lat = player->Latency() / (ring->GetSize()*4.0);	
+
+	return lat;
+}
+
+bool SndPlayer::write( unsigned char *src_ptr, size_t size)
+{	
+	while ( size > 0 && size % 4 )
+		size--;
+	if ( size <= 0 )
+		return false;
+
+	size_t len = size;
+
+	for(;;) {
+			size_t len2 = ring->Write(src_ptr, len);
+			if (len2 == len)break;
+			len -= len2;
+			src_ptr += len2;
+			snooze(100);
+	}
+
+	return true;
+}
diff --git a/src/mediakit/sndplayer.h b/src/mediakit/sndplayer.h
new file mode 100644
index 0000000..bd042c3
--- /dev/null
+++ b/src/mediakit/sndplayer.h
@@ -0,0 +1,36 @@
+#ifndef SNDPLAY_H
+#define SNDPLAY_H
+
+#include <SoundPlayer.h>
+
+#include "ringbuffer.h"
+
+class SndPlayer
+{
+public:
+	SndPlayer();
+	inline ~SndPlayer() { stop();}
+	inline bool isOK() const {return _isOK;}
+	inline bool isOpen() const {return player!=NULL;}
+
+	bool start();
+	void stop();
+
+	double getLatency();
+
+	bool write( unsigned char *src_ptr, size_t size);
+	
+	void flush();
+	void setVolume(int left, int right);
+
+	double delay;
+	uchar channels;
+	float sample_rate;
+
+private:
+	bool _isOK;
+	BSoundPlayer *player;
+	RingBuffer *ring;
+};
+
+#endif
diff --git a/src/statusicon-qt/statusicon.cc b/src/statusicon-qt/statusicon.cc
index da5bdc1..17a46b1 100644
--- a/src/statusicon-qt/statusicon.cc
+++ b/src/statusicon-qt/statusicon.cc
@@ -182,8 +182,11 @@ bool StatusIcon::init ()
     aud_config_set_defaults ("statusicon", defaults);
 
     audqt::init ();
-
+#ifndef Q_OS_HAIKU
     tray = new SystemTrayIcon (qApp->windowIcon ());
+#else
+	tray = new SystemTrayIcon (QIcon::fromTheme ("music-note-16th"));
+#endif
     QObject::connect (tray, & QSystemTrayIcon::activated, activate);
     menu = audqt::menu_build (items);
     tray->setContextMenu (menu);
-- 
2.21.0


From 42ee265e732dc1d50de476865a36cd8e2f85ec94 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sun, 14 Apr 2019 17:58:31 +1000
Subject: Use system soundfont


diff --git a/src/amidiplug/backend-fluidsynth/b-fluidsynth.cc b/src/amidiplug/backend-fluidsynth/b-fluidsynth.cc
index 09d8c24..0d90608 100644
--- a/src/amidiplug/backend-fluidsynth/b-fluidsynth.cc
+++ b/src/amidiplug/backend-fluidsynth/b-fluidsynth.cc
@@ -32,6 +32,10 @@
 #include "../i_configure.h"
 #include "../i_midievent.h"
 
+#ifdef __HAIKU__
+#include <FindDirectory.h>
+#endif
+
 typedef struct
 {
     fluid_settings_t * settings;
@@ -208,6 +212,23 @@ static void i_soundfont_load ()
 {
     String soundfont_file = aud_get_str ("amidiplug", "fsyn_soundfont_file");
 
+#ifdef __HAIKU__
+	char midiSettings[PATH_MAX] = "";
+	if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, midiSettings, sizeof(midiSettings)) == B_OK) {
+		strcat(midiSettings, "/Media/midi_settings");
+		if( access( midiSettings, F_OK ) != -1 ) {
+			FILE *inFile = fopen(midiSettings, "rt");
+			if (inFile) {
+				char sf2file[PATH_MAX];
+				if (fscanf(inFile, "# Midi\n\tsoundfont \"%[^\"]\"", sf2file)) {
+					soundfont_file = String(sf2file);
+				}
+				fclose(inFile);
+			}
+		}
+	}
+#endif
+
     if (soundfont_file[0])
     {
         Index<String> sffiles = str_list_to_index (soundfont_file, ";");
-- 
2.21.0

