mirror of
https://github.com/yann64/haikuports.git
synced 2026-04-15 00:00:07 +02:00
437 lines
12 KiB
Plaintext
437 lines
12 KiB
Plaintext
From e8e1c83dd8c8593921201152278fa7d9ab093ba4 Mon Sep 17 00:00:00 2001
|
|
From: Julian Harnath <julian.harnath@rwth-aachen.de>
|
|
Date: Mon, 24 Mar 2014 21:30:27 +0100
|
|
Subject: Add Haiku Media Kit audio output driver.
|
|
|
|
|
|
diff --git a/configure.ac b/configure.ac
|
|
index 67a06f8..8f2de8e 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -30,13 +30,15 @@ dnl Check for programs
|
|
dnl ====================================
|
|
|
|
cflags_save="$CFLAGS"
|
|
+cppflags_save="$CPPFLAGS"
|
|
AC_PROG_CC
|
|
+AC_PROG_CXX
|
|
AC_LIBTOOL_WIN32_DLL
|
|
AC_LIBTOOL_DLOPEN
|
|
AM_PROG_LIBTOOL
|
|
|
|
dnl ====================================
|
|
-dnl Check dlopen
|
|
+dnl Check dlopen
|
|
dnl ====================================
|
|
|
|
dnl Currently use this to disable plugin support dlfcn.h
|
|
@@ -68,6 +70,7 @@ if test -z "$GCC"; then
|
|
PLUGIN_LDFLAGS="-export-dynamic -avoid-version"
|
|
DEBUG="-g"
|
|
CFLAGS="-O"
|
|
+ CPPFLAGS="-O"
|
|
PROFILE="-g -p" ;;
|
|
esac
|
|
else
|
|
@@ -92,10 +95,12 @@ else
|
|
PLUGIN_LDFLAGS="-export-dynamic -avoid-version"
|
|
DEBUG="-g -Wall -D__NO_MATH_INLINES -fsigned-char"
|
|
CFLAGS="-O20 -D__NO_MATH_INLINES -fsigned-char"
|
|
+ CPPFLAGS="-O20 -D__NO_MATH_INLINES -fsigned-char"
|
|
PROFILE="-O20 -g -pg -D__NO_MATH_INLINES -fsigned-char" ;;
|
|
esac
|
|
fi
|
|
CFLAGS="$CFLAGS $cflags_save -DAO_BUILDING_LIBAO"
|
|
+CPPFLAGS="$CPPFLAGS $cppflags_save -DAO_BUILDING_LIBAO"
|
|
DEBUG="$DEBUG $cflags_save -DAO_BUILDING_LIBAO"
|
|
PROFILE="$PROFILE $cflags_save -DAO_BUILDING_LIBAO"
|
|
|
|
@@ -111,7 +116,7 @@ case $host in
|
|
*-mingw*|*-cygwin*)
|
|
LIBAO_LA_LDFLAGS="-no-undefined"
|
|
;;
|
|
- *)
|
|
+ *)
|
|
LIBAO_LA_LDFLAGS=""
|
|
;;
|
|
esac
|
|
@@ -151,7 +156,7 @@ case $host in
|
|
*hpux*)
|
|
DLOPEN_FLAG='(RTLD_LAZY)'
|
|
SHARED_LIB_EXT='.sl'
|
|
- ;;
|
|
+ ;;
|
|
*openbsd* | *netbsd* | *solaris2.7 | *darwin*)
|
|
DLOPEN_FLAG='(RTLD_LAZY)'
|
|
SHARED_LIB_EXT='.so'
|
|
@@ -194,7 +199,7 @@ AC_SUBST(SIZE16)
|
|
AC_SUBST(SIZE32)
|
|
|
|
dnl ======================================
|
|
-dnl Disable default use of SLP in roar
|
|
+dnl Disable default use of SLP in roar
|
|
dnl until such time as SLP doesn't block
|
|
dnl indefinitely
|
|
dnl ======================================
|
|
@@ -212,7 +217,7 @@ fi
|
|
AC_SUBST([SLP_DEF])
|
|
|
|
dnl ======================================
|
|
-dnl Detect possible output devices
|
|
+dnl Detect possible output devices
|
|
dnl ======================================
|
|
|
|
dnl Check for WMM
|
|
@@ -309,7 +314,7 @@ if test "x$enable_broken_oss" = "xyes"; then
|
|
AC_DEFINE(BROKEN_OSS)
|
|
AC_MSG_WARN(Broken OSS API workaround enabled. See README for details.)
|
|
fi
|
|
-
|
|
+
|
|
dnl Check for Sun audio
|
|
|
|
have_sun="no";
|
|
@@ -424,7 +429,7 @@ if test "$BUILD_NAS" = "yes"; then
|
|
AC_PATH_XTRA
|
|
AC_CHECK_LIB(Xau, XauFileName, have_nas=yes, have_nas=no, $X_LIBS)
|
|
AC_CHECK_LIB(audio, AuOpenServer, dummy="no-op", have_nas=no, -lXau $X_LIBS)
|
|
-
|
|
+
|
|
ac_save_CPPFLAGS="$CPPFLAGS"
|
|
CPPFLAGS="$CPPFLAGS $X_CFLAGS"
|
|
AC_CHECK_HEADER(audio/audiolib.h, dummy="no-op", have_nas=no)
|
|
@@ -457,6 +462,12 @@ AC_SUBST(PULSE_LIBS)
|
|
|
|
AM_CONDITIONAL(HAVE_PULSE,test "x$have_pulse" = xyes)
|
|
|
|
+dnl Check for Haiku audio
|
|
+
|
|
+have_haiku="no";
|
|
+AC_CHECK_HEADERS(MediaDefs.h, have_haiku=yes)
|
|
+AM_CONDITIONAL(HAVE_HAIKU,test "${have_haiku}" = yes)
|
|
+
|
|
dnl Orphaned driver. We'll probably dump it soon.
|
|
AM_CONDITIONAL(HAVE_SOLARIS,test "x$have_solaris" = xyes)
|
|
|
|
@@ -464,7 +475,7 @@ dnl Plugins get special LDFLAGS
|
|
AC_SUBST(PLUGIN_LDFLAGS)
|
|
|
|
|
|
-AC_OUTPUT([Makefile src/Makefile doc/Makefile include/Makefile include/ao/Makefile include/ao/os_types.h src/plugins/Makefile src/plugins/esd/Makefile src/plugins/oss/Makefile src/plugins/alsa/Makefile src/plugins/sun/Makefile src/plugins/irix/Makefile src/plugins/arts/Makefile src/plugins/macosx/Makefile src/plugins/nas/Makefile src/plugins/pulse/Makefile src/plugins/sndio/Makefile src/plugins/roar/Makefile ao.pc])
|
|
+AC_OUTPUT([Makefile src/Makefile doc/Makefile include/Makefile include/ao/Makefile include/ao/os_types.h src/plugins/Makefile src/plugins/esd/Makefile src/plugins/oss/Makefile src/plugins/alsa/Makefile src/plugins/sun/Makefile src/plugins/irix/Makefile src/plugins/arts/Makefile src/plugins/macosx/Makefile src/plugins/nas/Makefile src/plugins/pulse/Makefile src/plugins/sndio/Makefile src/plugins/roar/Makefile src/plugins/haiku/Makefile ao.pc])
|
|
|
|
AS_AC_EXPAND(LIBDIR, ${libdir})
|
|
AS_AC_EXPAND(INCLUDEDIR, ${includedir})
|
|
@@ -485,6 +496,7 @@ AC_MSG_RESULT([
|
|
ALSA live output: ............ ${have_alsa}
|
|
ARTS live output: ............ ${have_arts}
|
|
ESD live output: ............. ${have_esd}
|
|
+ HAIKU live output: ........... ${have_haiku}
|
|
IRIX live output: ............ ${have_irix}
|
|
MACOSX live output: .......... ${have_macosx}
|
|
NAS live output: ............. ${have_nas}
|
|
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
|
|
index 1af2303..1b417d4 100644
|
|
--- a/src/plugins/Makefile.am
|
|
+++ b/src/plugins/Makefile.am
|
|
@@ -1,4 +1,4 @@
|
|
## Process this file with automake to produce Makefile.in
|
|
|
|
AUTOMAKE_OPTIONS = foreign
|
|
-SUBDIRS = oss esd arts alsa sun irix macosx nas pulse sndio roar
|
|
+SUBDIRS = oss esd arts alsa sun irix macosx nas pulse sndio roar haiku
|
|
diff --git a/src/plugins/haiku/Makefile.am b/src/plugins/haiku/Makefile.am
|
|
new file mode 100644
|
|
index 0000000..596c664
|
|
--- /dev/null
|
|
+++ b/src/plugins/haiku/Makefile.am
|
|
@@ -0,0 +1,25 @@
|
|
+## Process this file with automake to produce Makefile.in
|
|
+
|
|
+AUTOMAKE_OPTIONS = foreign
|
|
+
|
|
+if HAVE_HAIKU
|
|
+
|
|
+haikultlibs = libhaiku.la
|
|
+haikusources = ao_haiku.cpp
|
|
+
|
|
+else
|
|
+
|
|
+haikultlibs =
|
|
+haikusources =
|
|
+
|
|
+endif
|
|
+
|
|
+INCLUDES = -I$(top_builddir)/include/ao -I$(top_srcdir)/include
|
|
+
|
|
+libdir = $(plugindir)
|
|
+lib_LTLIBRARIES = $(haikultlibs)
|
|
+
|
|
+libhaiku_la_LDFLAGS = @PLUGIN_LDFLAGS@ -lbe -lmedia
|
|
+libhaiku_la_SOURCES = $(haikusources)
|
|
+
|
|
+EXTRA_DIST = ao_haiku.cpp
|
|
diff --git a/src/plugins/haiku/ao_haiku.cpp b/src/plugins/haiku/ao_haiku.cpp
|
|
new file mode 100644
|
|
index 0000000..58d9dcb
|
|
--- /dev/null
|
|
+++ b/src/plugins/haiku/ao_haiku.cpp
|
|
@@ -0,0 +1,254 @@
|
|
+/*
|
|
+ * ao_haiku.cpp
|
|
+ *
|
|
+ * Copyright (C) Julian Harnath - March 2014
|
|
+ *
|
|
+ * This file is part of libao, a cross-platform audio output library. See
|
|
+ * README for a history of this source code.
|
|
+ *
|
|
+ * libao 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, or (at your option)
|
|
+ * any later version.
|
|
+ *
|
|
+ * libao 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 GNU Make; see the file COPYING. If not, write to
|
|
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+ *
|
|
+ ********************************************************************/
|
|
+
|
|
+#include <algorithm>
|
|
+#include <string.h>
|
|
+#include <stdio.h>
|
|
+
|
|
+#include <MediaDefs.h>
|
|
+#include <MediaRoster.h>
|
|
+#include <OS.h>
|
|
+#include <SoundPlayer.h>
|
|
+
|
|
+#include <ao/ao.h>
|
|
+#include <ao/plugin.h>
|
|
+
|
|
+
|
|
+static char* ao_haiku_options[] = {
|
|
+ "matrix"
|
|
+};
|
|
+
|
|
+
|
|
+struct ao_info ao_haiku_info = {
|
|
+ AO_TYPE_LIVE,
|
|
+ "Haiku Media Kit Output",
|
|
+ "haiku",
|
|
+ "Julian Harnath <julian.harnath@rwth-aachen.de>",
|
|
+ "Outputs to the Haiku Media Kit",
|
|
+ AO_FMT_NATIVE,
|
|
+ 30,
|
|
+ ao_haiku_options,
|
|
+ sizeof(ao_haiku_options) / sizeof(*ao_haiku_options)
|
|
+};
|
|
+
|
|
+
|
|
+typedef struct ao_haiku_internal {
|
|
+ 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;
|
|
+} ao_haiku_internal;
|
|
+
|
|
+
|
|
+int
|
|
+ao_plugin_test()
|
|
+{
|
|
+ BSoundPlayer testPlayer;
|
|
+ return testPlayer.InitCheck() == B_OK ? 1 :0;
|
|
+}
|
|
+
|
|
+
|
|
+ao_info*
|
|
+ao_plugin_driver_info()
|
|
+{
|
|
+ return &ao_haiku_info;
|
|
+}
|
|
+
|
|
+
|
|
+int
|
|
+ao_plugin_device_init(ao_device* device)
|
|
+{
|
|
+ ao_haiku_internal* const internal = (ao_haiku_internal*)calloc(1,
|
|
+ sizeof(ao_haiku_internal));
|
|
+ if (internal == NULL)
|
|
+ return 0;
|
|
+
|
|
+ internal->format = (media_raw_audio_format*)malloc(
|
|
+ sizeof(media_raw_audio_format));
|
|
+ if (internal->format == NULL) {
|
|
+ free(internal);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ internal->new_buffer = create_sem(0, "New buffer request");
|
|
+ internal->buffer_done = create_sem(1, "Buffer done");
|
|
+
|
|
+ device->output_matrix_order = AO_OUTPUT_MATRIX_FIXED;
|
|
+ device->internal = internal;
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+
|
|
+int
|
|
+ao_plugin_set_option(ao_device* device, const char* key, const char* value)
|
|
+{
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+fill_buffer(void* cookie, void* buffer, size_t size,
|
|
+ const media_raw_audio_format& format)
|
|
+{
|
|
+ ao_haiku_internal* const internal = (ao_haiku_internal*)cookie;
|
|
+
|
|
+ internal->buffer = (uint8*)buffer;
|
|
+ internal->buffer_size = size;
|
|
+ internal->buffer_filled = 0;
|
|
+ release_sem(internal->new_buffer);
|
|
+ acquire_sem(internal->buffer_done);
|
|
+}
|
|
+
|
|
+
|
|
+int
|
|
+ao_plugin_open(ao_device* device, ao_sample_format* format)
|
|
+{
|
|
+ ao_haiku_internal* const internal = (ao_haiku_internal*)device->internal;
|
|
+ media_raw_audio_format* const mediaRawFormat = internal->format;
|
|
+
|
|
+ mediaRawFormat->frame_rate = format->rate;
|
|
+ mediaRawFormat->channel_count = device->output_channels;
|
|
+
|
|
+ switch (format->bits) {
|
|
+ case 8:
|
|
+ mediaRawFormat->format = media_raw_audio_format::B_AUDIO_CHAR;
|
|
+ break;
|
|
+ case 16:
|
|
+ mediaRawFormat->format = media_raw_audio_format::B_AUDIO_SHORT;
|
|
+ break;
|
|
+ case 32:
|
|
+ mediaRawFormat->format = media_raw_audio_format::B_AUDIO_INT;
|
|
+ break;
|
|
+ default:
|
|
+ aerror("Unsupported sample bit depth");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ device->driver_byte_format = AO_FMT_NATIVE;
|
|
+ if (B_HOST_IS_LENDIAN)
|
|
+ mediaRawFormat->byte_order = B_MEDIA_LITTLE_ENDIAN;
|
|
+ else
|
|
+ mediaRawFormat->byte_order = B_MEDIA_BIG_ENDIAN;
|
|
+
|
|
+ mediaRawFormat->buffer_size = BMediaRoster::Roster()->AudioBufferSizeFor(
|
|
+ mediaRawFormat->channel_count, mediaRawFormat->format,
|
|
+ mediaRawFormat->frame_rate, B_UNKNOWN_BUS) * 2;
|
|
+
|
|
+ internal->sound_player = new BSoundPlayer(mediaRawFormat, "ao player",
|
|
+ fill_buffer, NULL, internal);
|
|
+
|
|
+ if (internal->sound_player->InitCheck() != B_OK) {
|
|
+ delete internal->sound_player;
|
|
+ internal->sound_player = NULL;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ internal->sound_player->SetVolume(1.0);
|
|
+ internal->sound_player->Start();
|
|
+ internal->sound_player->SetHasData(false);
|
|
+
|
|
+ if (device->inter_matrix == NULL) {
|
|
+ if (device->output_channels <= 2)
|
|
+ device->inter_matrix = strdup("L,R");
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+
|
|
+int
|
|
+ao_plugin_play(ao_device* device, const char* output_samples,
|
|
+ uint_32 num_bytes)
|
|
+{
|
|
+ ao_haiku_internal* const internal = (ao_haiku_internal*)device->internal;
|
|
+ BSoundPlayer* const soundPlayer = internal->sound_player;
|
|
+
|
|
+ if (num_bytes == 0) {
|
|
+ soundPlayer->SetHasData(false);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ soundPlayer->SetHasData(true);
|
|
+ acquire_sem(internal->new_buffer);
|
|
+
|
|
+ size_t bytesLeft = num_bytes;
|
|
+ while (bytesLeft > 0) {
|
|
+ if (internal->buffer_filled == internal->buffer_size) {
|
|
+ // Request another buffer from BSoundPlayer
|
|
+ release_sem(internal->buffer_done);
|
|
+ acquire_sem(internal->new_buffer);
|
|
+ }
|
|
+
|
|
+ const size_t copyBytes = std::min(bytesLeft, internal->buffer_size
|
|
+ - internal->buffer_filled);
|
|
+ memcpy(internal->buffer + internal->buffer_filled, output_samples,
|
|
+ copyBytes);
|
|
+ internal->buffer_filled += copyBytes;
|
|
+ output_samples += copyBytes;
|
|
+ bytesLeft -= copyBytes;
|
|
+ }
|
|
+
|
|
+ if (internal->buffer_filled < internal->buffer_size) {
|
|
+ // Continue filling this buffer the next time this function is called
|
|
+ release_sem(internal->new_buffer);
|
|
+ } else {
|
|
+ // Buffer is full
|
|
+ release_sem(internal->buffer_done);
|
|
+ soundPlayer->SetHasData(false);
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+
|
|
+int
|
|
+ao_plugin_close(ao_device* device)
|
|
+{
|
|
+ ao_haiku_internal* const internal = (ao_haiku_internal*)device->internal;
|
|
+
|
|
+ release_sem(internal->buffer_done);
|
|
+ internal->sound_player->SetHasData(false);
|
|
+ internal->sound_player->Stop();
|
|
+ delete internal->sound_player;
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+
|
|
+void
|
|
+ao_plugin_device_clear(ao_device* device)
|
|
+{
|
|
+ ao_haiku_internal* const internal = (ao_haiku_internal*)device->internal;
|
|
+
|
|
+ free(internal->format);
|
|
+ delete_sem(internal->new_buffer);
|
|
+ delete_sem(internal->buffer_done);
|
|
+ free(internal);
|
|
+}
|
|
--
|
|
1.8.3.4
|
|
|