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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 +#include +#include + +#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 + +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 +#include +#include +#include + +#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 + +#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 +#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 sffiles = str_list_to_index (soundfont_file, ";"); -- 2.21.0