652 lines
14 KiB
Plaintext
652 lines
14 KiB
Plaintext
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
|
|
|