diff options
50 files changed, 6989 insertions, 17 deletions
diff --git a/android/Android.mk b/android/Android.mk new file mode 100644 index 00000000..464ca244 --- /dev/null +++ b/android/Android.mk @@ -0,0 +1,1241 @@ +# +# jack-1.9.9.5 +# + +LOCAL_PATH := $(call my-dir) +JACK_ROOT := $(call my-dir)/.. +SUPPORT_ALSA_IN_JACK := true +ALSA_INCLUDES := vendor/samsung/common/external/alsa-lib/include +JACK_STL_LDFLAGS := -Lprebuilts/ndk/current/sources/cxx-stl/gnu-libstdc++/libs/$(TARGET_CPU_ABI) -lgnustl_static +JACK_STL_INCLUDES := $(JACK_ROOT)/android/cxx-stl/gnu-libstdc++/libs/$(TARGET_CPU_ABI)/include \ + prebuilts/ndk/current/sources/cxx-stl/gnu-libstdc++/libs/$(TARGET_CPU_ABI)/include \ + prebuilts/ndk/current/sources/cxx-stl/gnu-libstdc++/include + +########################################################## +# common +########################################################## + +common_cflags := -O0 -g -Wall -fexceptions -fvisibility=hidden -DHAVE_CONFIG_H +common_cflags += -Wno-unused -Wno-sign-compare -Wno-deprecated-declarations -Wno-cpp +common_cppflags := -frtti -Wno-sign-promo -fcheck-new +common_shm_cflags := -O0 -g -Wall -fexceptions -DHAVE_CONFIG_H -Wno-unused +common_c_includes := \ + $(JACK_ROOT) \ + $(JACK_ROOT)/common \ + $(JACK_ROOT)/common/jack \ + $(JACK_ROOT)/android \ + $(JACK_ROOT)/linux \ + $(JACK_ROOT)/linux/alsa \ + $(JACK_ROOT)/posix \ + $(JACK_STL_INCLUDES) + +# copy common source file +common_libsource_server_dir = .server +common_libsource_client_dir = .client + +$(shell rm -rf $(LOCAL_PATH)/$(common_libsource_server_dir)) +$(shell rm -rf $(LOCAL_PATH)/$(common_libsource_client_dir)) +$(shell mkdir $(LOCAL_PATH)/$(common_libsource_server_dir)) +$(shell mkdir $(LOCAL_PATH)/$(common_libsource_client_dir)) + +$(shell cp -rf $(LOCAL_PATH)/../common/JackActivationCount.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackActivationCount.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackAPI.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackAPI.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackClient.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackClient.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackConnectionManager.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackConnectionManager.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/ringbuffer.c $(LOCAL_PATH)/$(common_libsource_server_dir)/ringbuffer.c) +$(shell cp -rf $(LOCAL_PATH)/JackError.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackError.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackException.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackException.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackFrameTimer.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackFrameTimer.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackGraphManager.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackGraphManager.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackPort.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackPort.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackPortType.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackPortType.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackAudioPort.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackAudioPort.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackMidiPort.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackMidiPort.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackMidiAPI.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackMidiAPI.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackEngineControl.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackEngineControl.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackShmMem.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackShmMem.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackGenericClientChannel.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackGenericClientChannel.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackGlobals.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackGlobals.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackDebugClient.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackDebugClient.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackTransportEngine.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackTransportEngine.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/timestamps.c $(LOCAL_PATH)/$(common_libsource_server_dir)/timestamps.c) +$(shell cp -rf $(LOCAL_PATH)/../common/JackTools.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackTools.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackMessageBuffer.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackMessageBuffer.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackEngineProfiling.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackEngineProfiling.cpp) +$(shell cp -rf $(LOCAL_PATH)/JackAndroidThread.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackAndroidThread.cpp) +$(shell cp -rf $(LOCAL_PATH)/JackAndroidSemaphore.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackAndroidSemaphore.cpp) +$(shell cp -rf $(LOCAL_PATH)/../posix/JackPosixProcessSync.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackPosixProcessSync.cpp) +$(shell cp -rf $(LOCAL_PATH)/../posix/JackPosixMutex.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackPosixMutex.cpp) +$(shell cp -rf $(LOCAL_PATH)/../posix/JackSocket.cpp $(LOCAL_PATH)/$(common_libsource_server_dir)/JackSocket.cpp) +$(shell cp -rf $(LOCAL_PATH)/../linux/JackLinuxTime.c $(LOCAL_PATH)/$(common_libsource_server_dir)/JackLinuxTime.c) + +$(shell cp -rf $(LOCAL_PATH)/../common/JackActivationCount.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackActivationCount.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackAPI.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackAPI.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackClient.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackClient.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackConnectionManager.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackConnectionManager.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/ringbuffer.c $(LOCAL_PATH)/$(common_libsource_client_dir)/ringbuffer.c) +$(shell cp -rf $(LOCAL_PATH)/JackError.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackError.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackException.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackException.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackFrameTimer.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackFrameTimer.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackGraphManager.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackGraphManager.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackPort.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackPort.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackPortType.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackPortType.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackAudioPort.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackAudioPort.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackMidiPort.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackMidiPort.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackMidiAPI.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackMidiAPI.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackEngineControl.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackEngineControl.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackShmMem.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackShmMem.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackGenericClientChannel.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackGenericClientChannel.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackGlobals.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackGlobals.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackDebugClient.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackDebugClient.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackTransportEngine.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackTransportEngine.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/timestamps.c $(LOCAL_PATH)/$(common_libsource_client_dir)/timestamps.c) +$(shell cp -rf $(LOCAL_PATH)/../common/JackTools.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackTools.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackMessageBuffer.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackMessageBuffer.cpp) +$(shell cp -rf $(LOCAL_PATH)/../common/JackEngineProfiling.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackEngineProfiling.cpp) +$(shell cp -rf $(LOCAL_PATH)/JackAndroidThread.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackAndroidThread.cpp) +$(shell cp -rf $(LOCAL_PATH)/JackAndroidSemaphore.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackAndroidSemaphore.cpp) +$(shell cp -rf $(LOCAL_PATH)/../posix/JackPosixProcessSync.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackPosixProcessSync.cpp) +$(shell cp -rf $(LOCAL_PATH)/../posix/JackPosixMutex.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackPosixMutex.cpp) +$(shell cp -rf $(LOCAL_PATH)/../posix/JackSocket.cpp $(LOCAL_PATH)/$(common_libsource_client_dir)/JackSocket.cpp) +$(shell cp -rf $(LOCAL_PATH)/../linux/JackLinuxTime.c $(LOCAL_PATH)/$(common_libsource_client_dir)/JackLinuxTime.c) + +common_libsource_server := \ + $(common_libsource_server_dir)/JackActivationCount.cpp \ + $(common_libsource_server_dir)/JackAPI.cpp \ + $(common_libsource_server_dir)/JackClient.cpp \ + $(common_libsource_server_dir)/JackConnectionManager.cpp \ + $(common_libsource_server_dir)/ringbuffer.c \ + $(common_libsource_server_dir)/JackError.cpp \ + $(common_libsource_server_dir)/JackException.cpp \ + $(common_libsource_server_dir)/JackFrameTimer.cpp \ + $(common_libsource_server_dir)/JackGraphManager.cpp \ + $(common_libsource_server_dir)/JackPort.cpp \ + $(common_libsource_server_dir)/JackPortType.cpp \ + $(common_libsource_server_dir)/JackAudioPort.cpp \ + $(common_libsource_server_dir)/JackMidiPort.cpp \ + $(common_libsource_server_dir)/JackMidiAPI.cpp \ + $(common_libsource_server_dir)/JackEngineControl.cpp \ + $(common_libsource_server_dir)/JackShmMem.cpp \ + $(common_libsource_server_dir)/JackGenericClientChannel.cpp \ + $(common_libsource_server_dir)/JackGlobals.cpp \ + $(common_libsource_server_dir)/JackDebugClient.cpp \ + $(common_libsource_server_dir)/JackTransportEngine.cpp \ + $(common_libsource_server_dir)/timestamps.c \ + $(common_libsource_server_dir)/JackTools.cpp \ + $(common_libsource_server_dir)/JackMessageBuffer.cpp \ + $(common_libsource_server_dir)/JackEngineProfiling.cpp \ + $(common_libsource_server_dir)/JackAndroidThread.cpp \ + $(common_libsource_server_dir)/JackAndroidSemaphore.cpp \ + $(common_libsource_server_dir)/JackPosixProcessSync.cpp \ + $(common_libsource_server_dir)/JackPosixMutex.cpp \ + $(common_libsource_server_dir)/JackSocket.cpp \ + $(common_libsource_server_dir)/JackLinuxTime.c + +common_libsource_client := \ + $(common_libsource_client_dir)/JackActivationCount.cpp \ + $(common_libsource_client_dir)/JackAPI.cpp \ + $(common_libsource_client_dir)/JackClient.cpp \ + $(common_libsource_client_dir)/JackConnectionManager.cpp \ + $(common_libsource_client_dir)/ringbuffer.c \ + $(common_libsource_client_dir)/JackError.cpp \ + $(common_libsource_client_dir)/JackException.cpp \ + $(common_libsource_client_dir)/JackFrameTimer.cpp \ + $(common_libsource_client_dir)/JackGraphManager.cpp \ + $(common_libsource_client_dir)/JackPort.cpp \ + $(common_libsource_client_dir)/JackPortType.cpp \ + $(common_libsource_client_dir)/JackAudioPort.cpp \ + $(common_libsource_client_dir)/JackMidiPort.cpp \ + $(common_libsource_client_dir)/JackMidiAPI.cpp \ + $(common_libsource_client_dir)/JackEngineControl.cpp \ + $(common_libsource_client_dir)/JackShmMem.cpp \ + $(common_libsource_client_dir)/JackGenericClientChannel.cpp \ + $(common_libsource_client_dir)/JackGlobals.cpp \ + $(common_libsource_client_dir)/JackDebugClient.cpp \ + $(common_libsource_client_dir)/JackTransportEngine.cpp \ + $(common_libsource_client_dir)/timestamps.c \ + $(common_libsource_client_dir)/JackTools.cpp \ + $(common_libsource_client_dir)/JackMessageBuffer.cpp \ + $(common_libsource_client_dir)/JackEngineProfiling.cpp \ + $(common_libsource_client_dir)/JackAndroidThread.cpp \ + $(common_libsource_client_dir)/JackAndroidSemaphore.cpp \ + $(common_libsource_client_dir)/JackPosixProcessSync.cpp \ + $(common_libsource_client_dir)/JackPosixMutex.cpp \ + $(common_libsource_client_dir)/JackSocket.cpp \ + $(common_libsource_client_dir)/JackLinuxTime.c + +server_libsource := \ + ../common/JackAudioDriver.cpp \ + ../common/JackTimedDriver.cpp \ + ../common/JackMidiDriver.cpp \ + ../common/JackDriver.cpp \ + ../common/JackEngine.cpp \ + ../common/JackExternalClient.cpp \ + ../common/JackFreewheelDriver.cpp \ + ../common/JackInternalClient.cpp \ + ../common/JackServer.cpp \ + ../common/JackThreadedDriver.cpp \ + ../common/JackRestartThreadedDriver.cpp \ + ../common/JackWaitThreadedDriver.cpp \ + ../common/JackServerAPI.cpp \ + ../common/JackDriverLoader.cpp \ + ../common/JackServerGlobals.cpp \ + ../common/JackControlAPI.cpp \ + JackControlAPIAndroid.cpp \ + ../common/JackNetTool.cpp \ + ../common/JackNetInterface.cpp \ + ../common/JackArgParser.cpp \ + ../common/JackRequestDecoder.cpp \ + ../common/JackMidiAsyncQueue.cpp \ + ../common/JackMidiAsyncWaitQueue.cpp \ + ../common/JackMidiBufferReadQueue.cpp \ + ../common/JackMidiBufferWriteQueue.cpp \ + ../common/JackMidiRawInputWriteQueue.cpp \ + ../common/JackMidiRawOutputWriteQueue.cpp \ + ../common/JackMidiReadQueue.cpp \ + ../common/JackMidiReceiveQueue.cpp \ + ../common/JackMidiSendQueue.cpp \ + ../common/JackMidiUtil.cpp \ + ../common/JackMidiWriteQueue.cpp \ + ../posix/JackSocketServerChannel.cpp \ + ../posix/JackSocketNotifyChannel.cpp \ + ../posix/JackSocketServerNotifyChannel.cpp \ + ../posix/JackNetUnixSocket.cpp + +net_libsource := \ + ../common/JackNetAPI.cpp \ + ../common/JackNetInterface.cpp \ + ../common/JackNetTool.cpp \ + ../common/JackException.cpp \ + ../common/JackAudioAdapterInterface.cpp \ + ../common/JackLibSampleRateResampler.cpp \ + ../common/JackResampler.cpp \ + ../common/JackGlobals.cpp \ + ../posix/JackPosixMutex.cpp \ + ../common/ringbuffer.c \ + ../posix/JackNetUnixSocket.cpp \ + ../posix/JackPosixThread.cpp \ + ../linux/JackLinuxTime.c + +client_libsource := \ + ../common/JackLibClient.cpp \ + ../common/JackLibAPI.cpp \ + ../posix/JackSocketClientChannel.cpp \ + ../posix/JackPosixServerLaunch.cpp + +netadapter_libsource := \ + ../common/JackResampler.cpp \ + ../common/JackLibSampleRateResampler.cpp \ + ../common/JackAudioAdapter.cpp \ + ../common/JackAudioAdapterInterface.cpp \ + ../common/JackNetAdapter.cpp + +audioadapter_libsource := \ + ../common/JackResampler.cpp \ + ../common/JackLibSampleRateResampler.cpp \ + ../common/JackAudioAdapter.cpp \ + ../common/JackAudioAdapterInterface.cpp \ + ../common/JackAudioAdapterFactory.cpp \ + ../linux/alsa/JackAlsaAdapter.cpp + +# ======================================================== +# libjackserver.so +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(common_libsource_server) $(server_libsource) +LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +LOCAL_CPPFLAGS := $(common_cppflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libjackshm +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := libjackserver + +include $(BUILD_SHARED_LIBRARY) + +## ======================================================== +## libjacknet.so +## ======================================================== +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := $(net_libsource) +#LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +#LOCAL_CPPFLAGS := $(common_cppflags) +#LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +#LOCAL_C_INCLUDES := $(common_c_includes) $(JACK_ROOT)/../libsamplerate/include +#LOCAL_SHARED_LIBRARIES := libc libdl libcutils libsamplerate +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := libjacknet +# +#include $(BUILD_SHARED_LIBRARY) + +# ======================================================== +# libjack.so +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(common_libsource_client) $(client_libsource) +LOCAL_CFLAGS := $(common_cflags) +LOCAL_CPPFLAGS := $(common_cppflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libjackshm +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := libjack + +include $(BUILD_SHARED_LIBRARY) + +# ======================================================== +# netmanager.so +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../common/JackNetManager.cpp +LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +LOCAL_CPPFLAGS := $(common_cppflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libjackserver +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := netmanager + +include $(BUILD_SHARED_LIBRARY) + +# ======================================================== +# profiler.so +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../common/JackProfiler.cpp +LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +LOCAL_CPPFLAGS := $(common_cppflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libjackserver +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := profiler + +include $(BUILD_SHARED_LIBRARY) + +## ======================================================== +## netadapter.so +## ======================================================== +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := $(netadapter_libsource) +#LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +#LOCAL_CPPFLAGS := $(common_cppflags) +#LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +#LOCAL_C_INCLUDES := $(common_c_includes) $(JACK_ROOT)/../libsamplerate/include +#LOCAL_SHARED_LIBRARIES := libc libdl libcutils libsamplerate libjackserver +#LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := netadapter +# +#include $(BUILD_SHARED_LIBRARY) + +## ======================================================== +## audioadapter.so +## ======================================================== +#ifeq ($(SUPPORT_ALSA_IN_JACK),true) +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := $(audioadapter_libsource) +#LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE -D_POSIX_SOURCE +#LOCAL_CPPFLAGS := $(common_cppflags) +#LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +#LOCAL_C_INCLUDES := $(common_c_includes) $(JACK_ROOT)/../libsamplerate/include $(ALSA_INCLUDES) +#LOCAL_SHARED_LIBRARIES := libc libdl libcutils libasound libsamplerate libjackserver +#LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := audioadapter +# +#include $(BUILD_SHARED_LIBRARY) +##endif + +########################################################## +# linux +########################################################## + +# ======================================================== +# jackd +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + ../common/Jackdmp.cpp +# ../dbus/reserve.c +# ../dbus/audio_reserve.c +LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +LOCAL_CPPFLAGS := $(common_cppflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) -ldl -Wl,--no-fatal-warnings +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libc libutils libjackserver +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jackd + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# driver - dummy +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../common/JackDummyDriver.cpp +#'HAVE_CONFIG_H','SERVER_SIDE', 'HAVE_PPOLL', 'HAVE_TIMERFD +LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +LOCAL_CPPFLAGS := $(common_cppflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libjackserver +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_dummy + +include $(BUILD_SHARED_LIBRARY) + +# ======================================================== +# driver - alsa +# ======================================================== +ifeq ($(SUPPORT_ALSA_IN_JACK),true) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + ../linux/alsa/JackAlsaDriver.cpp \ + ../linux/alsa/alsa_rawmidi.c \ + ../linux/alsa/alsa_seqmidi.c \ + ../linux/alsa/alsa_midi_jackmp.cpp \ + ../common/memops.c \ + ../linux/alsa/generic_hw.c \ + ../linux/alsa/hdsp.c \ + ../linux/alsa/alsa_driver.c \ + ../linux/alsa/hammerfall.c \ + ../linux/alsa/ice1712.c +#'HAVE_CONFIG_H','SERVER_SIDE', 'HAVE_PPOLL', 'HAVE_TIMERFD +LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE -D_POSIX_SOURCE -D_XOPEN_SOURCE=600 +LOCAL_CPPFLAGS := $(common_cppflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) $(ALSA_INCLUDES) +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libjackserver libasound +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_alsa + +include $(BUILD_SHARED_LIBRARY) +endif + +## ======================================================== +## driver - alsarawmidi +## ======================================================== +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := \ +# ../linux/alsarawmidi/JackALSARawMidiDriver.cpp \ +# ../linux/alsarawmidi/JackALSARawMidiInputPort.cpp \ +# ../linux/alsarawmidi/JackALSARawMidiOutputPort.cpp \ +# ../linux/alsarawmidi/JackALSARawMidiPort.cpp \ +# ../linux/alsarawmidi/JackALSARawMidiReceiveQueue.cpp \ +# ../linux/alsarawmidi/JackALSARawMidiSendQueue.cpp \ +# ../linux/alsarawmidi/JackALSARawMidiUtil.cpp +##'HAVE_CONFIG_H','SERVER_SIDE', 'HAVE_PPOLL', 'HAVE_TIMERFD +#LOCAL_CFLAGS := $(common_cflags) -D_POSIX_SOURCE -D__ALSA_RAWMIDI_H +#LOCAL_CPPFLAGS := $(common_cppflags) +#LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +#LOCAL_C_INCLUDES := $(common_c_includes) $(ALSA_INCLUDES) +#LOCAL_SHARED_LIBRARIES := libc libdl libcutils libjackserver libasound +#LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := jack_alsarawmidi +# +#include $(BUILD_SHARED_LIBRARY) + +## LIBFREEBOB required +## ======================================================== +## driver - freebob +## ======================================================== +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := ../linux/freebob/JackFreebobDriver.cpp +##'HAVE_CONFIG_H','SERVER_SIDE', 'HAVE_PPOLL', 'HAVE_TIMERFD +#LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +#LOCAL_CPPFLAGS := $(common_cppflags) +#LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +#LOCAL_C_INCLUDES := $(common_c_includes) +#LOCAL_SHARED_LIBRARIES := libc libdl libcutils libjackserver +#LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := jack_freebob +# +#include $(BUILD_SHARED_LIBRARY) + +## LIBFFADO required +## ======================================================== +## driver - firewire +## ======================================================== +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := \ +# ../linux/firewire/JackFFADODriver.cpp \ +# ../linux/firewire/JackFFADOMidiInputPort.cpp \ +# ../linux/firewire/JackFFADOMidiOutputPort.cpp \ +# ../linux/firewire/JackFFADOMidiReceiveQueue.cpp \ +# ../linux/firewire/JackFFADOMidiSendQueue.cpp +##'HAVE_CONFIG_H','SERVER_SIDE', 'HAVE_PPOLL', 'HAVE_TIMERFD +#LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +#LOCAL_CPPFLAGS := $(common_cppflags) +#LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +#LOCAL_C_INCLUDES := $(common_c_includes) +#LOCAL_SHARED_LIBRARIES := libc libdl libcutils libjackserver +#LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := jack_firewire +# +#include $(BUILD_SHARED_LIBRARY) + +# ======================================================== +# driver - net +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../common/JackNetDriver.cpp +#'HAVE_CONFIG_H','SERVER_SIDE', 'HAVE_PPOLL', 'HAVE_TIMERFD +LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +LOCAL_CPPFLAGS := $(common_cppflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libjackserver +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_net + +include $(BUILD_SHARED_LIBRARY) + +# ======================================================== +# driver - loopback +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../common/JackLoopbackDriver.cpp +#'HAVE_CONFIG_H','SERVER_SIDE', 'HAVE_PPOLL', 'HAVE_TIMERFD +LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +LOCAL_CPPFLAGS := $(common_cppflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libjackserver +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_loopback + +include $(BUILD_SHARED_LIBRARY) + +##HAVE_SAMPLERATE, HAVE_CELT required +## ======================================================== +## driver - netone +## ======================================================== +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := \ +# ../common/JackNetOneDriver.cpp \ +# ../common/netjack.c \ +# ../common/netjack_packet.c +##'HAVE_CONFIG_H','SERVER_SIDE', 'HAVE_PPOLL', 'HAVE_TIMERFD +#LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +#LOCAL_CPPFLAGS := $(common_cppflags) +#LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +#LOCAL_C_INCLUDES := $(common_c_includes) $(JACK_ROOT)/../libsamplerate/include +#LOCAL_SHARED_LIBRARIES := libc libdl libcutils libsamplerate libjackserver +#LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := jack_netone +# +#include $(BUILD_SHARED_LIBRARY) + +########################################################## +# android +########################################################## + +# ======================================================== +# libjackshm.so +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := BnAndroidShm.cpp BpAndroidShm.cpp IAndroidShm.cpp AndroidShm.cpp Shm.cpp +LOCAL_CFLAGS := $(common_shm_cflags) -DSERVER_SIDE +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libbinder +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := libjackshm + +include $(BUILD_SHARED_LIBRARY) + +# ======================================================== +# jack_goldfish.so - Goldfish driver for emulator +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := JackGoldfishDriver.cpp +LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +LOCAL_CPPFLAGS := $(common_cppflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libjackserver +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_goldfish + +include $(BUILD_SHARED_LIBRARY) + +# ======================================================== +# jack_opensles.so - OpenSL ES driver +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := JackOpenSLESDriver.cpp opensl_io.c +LOCAL_CFLAGS := $(common_cflags) -DSERVER_SIDE +LOCAL_CPPFLAGS := $(common_cppflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) frameworks/wilhelm/include +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libjackserver libOpenSLES +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/jack +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_opensles + +include $(BUILD_SHARED_LIBRARY) + +########################################################## +# android/AndroidShmServer +########################################################## + +# ======================================================== +# androidshmservice +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ./AndroidShmServer/main_androidshmservice.cpp +LOCAL_CFLAGS := $(common_cflags) +LOCAL_CPPFLAGS := $(common_cppflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libcutils libutils libbinder libjackshm +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE:= androidshmservice + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# shmservicetest +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ./AndroidShmServer/test/shmservicetest.cpp +LOCAL_SHARED_LIBRARIES := libcutils libutils libjackshm libbinder +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := shmservicetest +LOCAL_CFLAGS += -DLOG_TAG=\"ShmServiceTest\" + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# shmservicedump +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ./AndroidShmServer/test/shmservicedump.cpp +LOCAL_SHARED_LIBRARIES := libcutils libutils libjackshm libbinder +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := shmservicedump +LOCAL_CFLAGS += $(common_cflags) -DLOG_TAG=\"ShmServiceDump\" +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) + +include $(BUILD_EXECUTABLE) + +########################################################## +# example-clients +########################################################## + +# ======================================================== +# jack_freewheel +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/freewheel.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_freewheel + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_connect +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/connect.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_connect + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_disconnect +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/connect.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_disconnect + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_lsp +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/lsp.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_lsp + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_metro +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/metro.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_metro + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_midiseq +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/midiseq.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_midiseq + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_midisine +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/midisine.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_midisine + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_showtime +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/showtime.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_showtime + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_simple_client +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/simple_client.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_simple_client + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_zombie +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/zombie.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_zombie + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_load +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/ipload.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_load + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_unload +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/ipunload.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_unload + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_alias +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/alias.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_alias + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_bufsize +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/bufsize.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_bufsize + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_wait +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/wait.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_wait + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_samplerate +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/samplerate.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_samplerate + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_evmon +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/evmon.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_evmon + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_monitor_client +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/monitor_client.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_monitor_client + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_thru +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/thru_client.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_thru + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_cpu_load +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/cpu_load.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_cpu_load + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_simple_session_client +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/simple_session_client.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_simple_session_client + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_session_notify +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/session_notify.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_session_notify + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_server_control +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/server_control.cpp +LOCAL_CFLAGS := $(common_cflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjackserver +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_server_control + +include $(BUILD_EXECUTABLE) + +## ======================================================== +## jack_net_slave +## ======================================================== +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := ../example-clients/netslave.c +#LOCAL_CFLAGS := $(common_cflags) +#LOCAL_C_INCLUDES := $(common_c_includes) +#LOCAL_SHARED_LIBRARIES := libjacknet +#LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := jack_net_slave +# +#include $(BUILD_EXECUTABLE) + +## ======================================================== +## jack_net_master +## ======================================================== +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := ../example-clients/netmaster.c +#LOCAL_CFLAGS := $(common_cflags) +#LOCAL_C_INCLUDES := $(common_c_includes) +#LOCAL_SHARED_LIBRARIES := libjacknet +#LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := jack_net_master +# +#include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_latent_client +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/latent_client.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_latent_client + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_midi_dump +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/midi_dump.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_midi_dump + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_midi_latency_test +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/midi_latency_test.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_midi_latency_test + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_transport +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/transport.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_transport + +include $(BUILD_EXECUTABLE) + +## ======================================================== +## jack_rec +## ======================================================== +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := ../example-clients/capture_client.c +#LOCAL_CFLAGS := $(common_cflags) +#LOCAL_C_INCLUDES := $(common_c_includes) $(JACK_ROOT)/../libsndfile/src +#LOCAL_SHARED_LIBRARIES := libjack libsndfile +#LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := jack_rec +# +#include $(BUILD_EXECUTABLE) + +## ======================================================== +## jack_netsource +## ======================================================== +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := ../example-clients/netsource.c ../common/netjack_packet.c +#LOCAL_CFLAGS := $(common_cflags) -DNO_JACK_ERROR +#LOCAL_C_INCLUDES := $(common_c_includes) $(JACK_ROOT)/../libsamplerate/include +#LOCAL_SHARED_LIBRARIES := libsamplerate libjack +#LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := jack_netsource +# +#include $(BUILD_EXECUTABLE) + +## ======================================================== +## alsa_in +## ======================================================== +#ifeq ($(SUPPORT_ALSA_IN_JACK),true) +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := ../example-clients/alsa_in.c ../common/memops.c +#LOCAL_CFLAGS := $(common_cflags) -DNO_JACK_ERROR -D_POSIX_SOURCE -D_XOPEN_SOURCE=600 +#LOCAL_C_INCLUDES := $(common_c_includes) $(JACK_ROOT)/../libsamplerate/include $(ALSA_INCLUDES) +#LOCAL_SHARED_LIBRARIES := libasound libsamplerate libjack +#LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := alsa_in +# +#include $(BUILD_EXECUTABLE) +#endif + +## ======================================================== +## alsa_out +## ======================================================== +#ifeq ($(SUPPORT_ALSA_IN_JACK),true) +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := ../example-clients/alsa_out.c ../common/memops.c +#LOCAL_CFLAGS := $(common_cflags) -DNO_JACK_ERROR -D_POSIX_SOURCE -D_XOPEN_SOURCE=600 +#LOCAL_C_INCLUDES := $(common_c_includes) $(JACK_ROOT)/../libsamplerate/include $(ALSA_INCLUDES) +#LOCAL_SHARED_LIBRARIES := libasound libsamplerate libjack +#LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +#LOCAL_MODULE_TAGS := eng optional +#LOCAL_MODULE := alsa_out +# +#include $(BUILD_EXECUTABLE) +#endif + +# ======================================================== +# inprocess +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../example-clients/inprocess.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjackserver +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := example_lib + +include $(BUILD_SHARED_LIBRARY) + +########################################################## +# tests +########################################################## + +# ======================================================== +# jack_test +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../tests/test.cpp +LOCAL_CFLAGS := $(common_cflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack libjackshm +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_test + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_cpu +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../tests/cpu.c +LOCAL_CFLAGS := $(common_cflags) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack libjackshm +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_cpu + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_iodelay +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../tests/iodelay.cpp +LOCAL_CFLAGS := $(common_cflags) +LOCAL_CFLAGS += -Wno-narrowing +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack libjackshm +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_iodelay + +include $(BUILD_EXECUTABLE) + +# ======================================================== +# jack_multiple_metro +# ======================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../tests/external_metro.cpp +LOCAL_CFLAGS := $(common_cflags) +LOCAL_LDFLAGS := $(JACK_STL_LDFLAGS) +LOCAL_C_INCLUDES := $(common_c_includes) +LOCAL_SHARED_LIBRARIES := libjack libjackshm +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng optional +LOCAL_MODULE := jack_multiple_metro + +include $(BUILD_EXECUTABLE) diff --git a/android/AndroidShm.cpp b/android/AndroidShm.cpp new file mode 100644 index 00000000..ff9847c3 --- /dev/null +++ b/android/AndroidShm.cpp @@ -0,0 +1,251 @@ +#define LOG_TAG "JAMSHMSERVICE" + +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <binder/MemoryHeapBase.h> +#include <binder/IServiceManager.h> +#include <binder/IPCThreadState.h> +#include <utils/Log.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/un.h> +#include <sys/wait.h> +#include "BnAndroidShm.h" +#include "AndroidShm.h" + + +#include "JackConstants.h" + + +#include <fcntl.h> +#include <signal.h> +#include <limits.h> +#include <errno.h> +#include <dirent.h> +#include <sys/mman.h> +#include <linux/ashmem.h> +#include <cutils/ashmem.h> + +#include "JackError.h" + +#include <semaphore.h> + + +#define MEMORY_SIZE 10*1024 + +#define SEMAPHORE_NULL_CHAR '\0' + +// remove ALOGI log +#undef ALOGI +#define ALOGI + +namespace android { + + + int AndroidShm::instantiate() { + defaultServiceManager()->addService(String16("com.samsung.android.jam.IAndroidShm"), new AndroidShm); // SINGLETON WITH SAME NAME + return 0; + } + + int AndroidShm::sendCommand(const char* command) { + ALOGI("I(pid:%d) send command is %s\n", getpid(), command); + if(strcmp(command, "semaphore") == 0) { + // print debug message about semaphore simulation + for(int i = MAX_SEMAPHORE_MEMORY_COUNT -1 ; i >= 0; i--) { + printf("index[%3d] = ptr[%p] name[%s]\n", i, (mSemaphore[i] != NULL)?mSemaphore[i]->getBase():0, mSemaphoreName[i]); + ALOGI("index[%3d] = ptr[%p] name[%s]\n", i, (mSemaphore[i] != NULL)?mSemaphore[i]->getBase():0, mSemaphoreName[i]); + } + } + return NO_ERROR; + } + + int AndroidShm::testGetBufferByNewProcess() { + ALOGI("testGetBufferByNewProcess..."); + int status; + int childPid = fork(); + + if(childPid > 0) { + ALOGI("I(pid%d) made a child process(pid:%d)", getpid(), childPid); + ALOGI("I(pid%d) wait until child(%d) was finish", getpid(), childPid); + wait(&status); + // wait ÇÏÁö ¾ÊÀ¸¸é child process°¡ ³²¾Æ ÀÖÀ½. + ALOGI("child(%d) was finished. ", childPid); + } else if(childPid == 0) { + ALOGI("im a new child process(pid:%d) ", getpid()); + if(-1 == execlp("/system/bin/getbufferclient","getbufferclient",NULL)) { + ALOGE("failed to execute getbufferclient"); + } + exit(0); + } else { + ALOGI("failed creating child process"); + } + return 0; + } + + int AndroidShm::testGetBuffer() { + ALOGI("I(pid:%d) trying to test get buffer...", getpid()); + sp<IServiceManager> sm = defaultServiceManager(); + ALOGI("get default ServiceManager is done"); + sp<IBinder> b; + //String16* serviceName = new String16("com.samsung.android.jam.IAndroidShm"); + do { + //ALOGI("here"); + b = sm->getService(String16("com.samsung.android.jam.IAndroidShm")); + //ALOGI("getservice is done"); + + if(b != 0) + break; + //ALOGI("AndroidShm is not working, waiting..."); + usleep(500000); + + } while(true); + + sp<IAndroidShm> service = interface_cast<IAndroidShm>(b); + + //shared buffer. + sp<IMemoryHeap> receiverMemBase = service->getBuffer(0); + + unsigned int *base = (unsigned int *) receiverMemBase->getBase(); + int ret = 0; + if(base != (unsigned int *) -1) { + ALOGD("AndroidShm::testGetBuffer base=%p Data=0x%x\n",base, *base); + *base = (*base)+1; + ret = (unsigned int)(*base); + ALOGI("AndroidShm::testGetBuffer base=%p Data=0x%x CHANGED\n",base, *base); + receiverMemBase = 0; + } else { + ALOGE("Error shared memory not available\n"); + } + return 0; + } + + sp<IMemoryHeap> AndroidShm::getBuffer(int index) { + ALOGI("I(pid:%d) getBuffer index:%d", getpid(), index); + if(index < 0 || index >= MAX_SHARED_MEMORY_COUNT) { + ALOGE("error : out of index [%d]", index); + return NULL; + } + return mMemHeap[index]; + } + + int AndroidShm::MemAlloc(unsigned int size) { + ALOGI("try to allocate memory size[%d]", size); + for(int i = 0; i < MAX_SHARED_MEMORY_COUNT; i++) { + if(mMemHeap[i] == NULL) { + mMemHeap[i] = new MemoryHeapBase(size); + if(mMemHeap[i] == NULL){ + ALOGI("fail to alloc, try one more..."); + continue; // try one more. + } + return i; + } + } + ALOGE("fail to MemAlloc"); + return -1; // fail to alloc + } + + AndroidShm::AndroidShm() { + ALOGI("AndroidShm is created"); + for(int i = 0; i < MAX_SHARED_MEMORY_COUNT; i++) { + mMemHeap[i] = NULL; + } + mRegistryIndex = 10000; + //mMemHeap = new MemoryHeapBase(MEMORY_SIZE); + //unsigned int *base = (unsigned int*) mMemHeap->getBase(); + //*base = 0xdeadcafe;// + + for(int j = 0; j < MAX_SEMAPHORE_MEMORY_COUNT; j++) { + mSemaphore[j] = NULL; + memset(mSemaphoreName[j], SEMAPHORE_NULL_CHAR, MAX_SEMAPHORE_NAME_LENGTH); + } + } + + AndroidShm::~AndroidShm() { + ALOGI("AndroidShm is destroyed"); + for(int i = 0; i < MAX_SHARED_MEMORY_COUNT; i++) { + (mMemHeap[i]).clear(); + } + for(int j = 0; j < MAX_SEMAPHORE_MEMORY_COUNT; j++) { + (mSemaphore[j]).clear(); + } + } + + //status_t AndroidShm::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { + // return BnAndroidShm::onTransact(code, data, reply, flags); + //} + + int AndroidShm::allocShm(const int size) { // if negative return value is error + ALOGI("try to alloc shared memory size[%d]", size); + return MemAlloc(size); + } + + int AndroidShm::removeShm(const unsigned int index) { // shared memory Á¦°Å + ALOGI("try to remove shared memory index[%d]", index); + if(index >= MAX_SHARED_MEMORY_COUNT) { + ALOGE("remove shared memory: out of index"); + return -1; + } + (mMemHeap[index]).clear(); + return 1; + } + + int AndroidShm::isAllocated(const unsigned int index) { // allocated ¿©ºÎ È®ÀÎ + ALOGI("try to check the memory allocation index[%d]", index); + if(index >= MAX_SHARED_MEMORY_COUNT) { + ALOGE("shared memory: out of index"); + return 0; + } + if(mMemHeap[index] == NULL) + return 0; + else + return 1; + } + + int AndroidShm::setRegistryIndex(const unsigned int index) { + ALOGI("set registry index %d", index); + mRegistryIndex = index; + return 1; + } + + int AndroidShm::getRegistryIndex() { + return mRegistryIndex; + } + + sp<IMemoryHeap> AndroidShm::InitSemaphore(const char* name) { + ALOGI("init semaphore [%s]", name); + for(int i = 0; i < MAX_SEMAPHORE_MEMORY_COUNT; i++) { + if(mSemaphoreName[i][0] == SEMAPHORE_NULL_CHAR) { + mSemaphore[i] = new MemoryHeapBase(sizeof(sem_t)); + if(mSemaphore[i] == NULL){ + ALOGI("fail to alloc, try one more..."); + continue; + } + if(sem_init((sem_t*)(mSemaphore[i]->getBase()), 1, 0) == 0) { + strncpy(mSemaphoreName[i], name, MAX_SEMAPHORE_NAME_LENGTH - 1); + mSemaphoreName[i][MAX_SEMAPHORE_NAME_LENGTH - 1] = '\0'; + ALOGI("sem_init success"); + return mSemaphore[i]; + } else { + (mSemaphore[i]).clear(); + ALOGE("sem_init failed null returned"); + return NULL; + } + } else { + // find already exist name + if(strcmp(mSemaphoreName[i], name) == 0) { // found + ALOGI("found - return alread allocated semaphore"); + return mSemaphore[i]; + } + } + } + ALOGE("sem_init failed null returned 2"); + return NULL; + } + +}; + diff --git a/android/AndroidShm.h b/android/AndroidShm.h new file mode 100644 index 00000000..b868827a --- /dev/null +++ b/android/AndroidShm.h @@ -0,0 +1,51 @@ +#ifndef ANDROIDSHM +#define ANDROIDSHM + +#include <binder/Parcel.h> +#include "BnAndroidShm.h" +#include <utils/Log.h> +#include <binder/MemoryHeapBase.h> +#include "shm.h" +#include "android/Shm.h" //android extension of shm.h + +namespace android { + + class AndroidShm : public BnAndroidShm + { +#define MAX_SHARED_MEMORY_COUNT 257 + private: + int MemAlloc(unsigned int size); + + public: + virtual ~AndroidShm(); + static int instantiate(); + virtual int sendCommand(const char* command); + virtual int allocShm(const int size); // if negative return value is error + virtual int removeShm(const unsigned int index); // shared memory Á¦°Å + virtual int isAllocated(const unsigned int index); // allocated ¿©ºÎ È®ÀÎ + virtual int setRegistryIndex(const unsigned int index); + virtual int getRegistryIndex(); + virtual sp<IMemoryHeap> InitSemaphore(const char* name); + virtual sp<IMemoryHeap> getBuffer(int index); + //virtual status_t onTransact( + // uint32_t code, + // const Parcel& data, + // Parcel* reply, + // uint32_t flags); + private: + int testGetBuffer(); + int testGetBufferByNewProcess(); + AndroidShm(); + + sp<MemoryHeapBase> mMemHeap[MAX_SHARED_MEMORY_COUNT]; + unsigned int mRegistryIndex; + + // for named semaphore simulation + #define MAX_SEMAPHORE_MEMORY_COUNT 300 + #define MAX_SEMAPHORE_NAME_LENGTH 300 + sp<MemoryHeapBase> mSemaphore[MAX_SEMAPHORE_MEMORY_COUNT]; + char mSemaphoreName[MAX_SEMAPHORE_MEMORY_COUNT][MAX_SEMAPHORE_NAME_LENGTH]; + }; +}; + +#endif diff --git a/android/AndroidShmServer/main_androidshmservice.cpp b/android/AndroidShmServer/main_androidshmservice.cpp new file mode 100644 index 00000000..1c6dde8f --- /dev/null +++ b/android/AndroidShmServer/main_androidshmservice.cpp @@ -0,0 +1,19 @@ +#define LOG_TAG "main_androidshmservice" + +#include <binder/IPCThreadState.h> +#include <binder/ProcessState.h> +#include <binder/IServiceManager.h> +#include <utils/Log.h> + +#include "../../common/shm.h" +#include "../Shm.h" //android extension of shm.h + +using namespace android; + +int main(int argc, char *argv[]) { + jack_instantiate(); + ProcessState::self()->startThreadPool(); + ALOGI("AndroidShmService is starting now"); + IPCThreadState::self()->joinThreadPool(); + return 0; +} diff --git a/android/AndroidShmServer/readme.txt b/android/AndroidShmServer/readme.txt new file mode 100644 index 00000000..9b475beb --- /dev/null +++ b/android/AndroidShmServer/readme.txt @@ -0,0 +1,23 @@ +IAndroidShmÀÇ ±â´ÉÀ» Å×½ºÆ® Çϱâ À§ÇÑ ¿ëµµ·Î »ç¿ëµÇ´Â ÇÁ·Î±×·¥ÀÔ´Ï´Ù. + +AndroidShmÀº service manager¿¡ shared memory¸¦ ÇÒ´çÇØÁÖ´Â ¼ºñ½ºÀÔ´Ï´Ù. + +service name: com.sec.apa.IAndroidShm + +½ÇÇà ÆÄÀÏ: +/system/bin/androidshmservice + +------------------------------------------- +./test + +AndroidShmService¸¦ Å×½ºÆ®ÇÏ´Â ÇÁ·Î±×·¥ + +/system/bin/shmservicetest + +AndroidShmService¿¡¼ Á¦°øÇÏ´Â ±â´ÉÀ» UnitTestÇÕ´Ï´Ù. + +µ¿ÀÛ È®ÀÎ ¹æ¹ý: +adb logcat À¸·Î ·Î±×·Î ¼º°ø/½ÇÆÐ È®ÀÎÇÔ. + +ÀüÁ¦ Á¶°Ç: +/system/bin/androidshmservice¸¦ ½ÇÇàÁßÀÎ »óÅÂÀ̾î¾ß ÇÕ´Ï´Ù.
\ No newline at end of file diff --git a/android/AndroidShmServer/test/shmservicedump.cpp b/android/AndroidShmServer/test/shmservicedump.cpp new file mode 100644 index 00000000..d7413f74 --- /dev/null +++ b/android/AndroidShmServer/test/shmservicedump.cpp @@ -0,0 +1,177 @@ +#include "../../IAndroidShm.h" +#include <binder/MemoryHeapBase.h> +#include <binder/IServiceManager.h> +#include "../../../common/shm.h" + +namespace android { + +static sp<IMemoryHeap> receiverMemBase; +#define MAX_SHARED_MEMORY_COUNT 257 + +sp<IAndroidShm> getAndroidShmService() { + sp<IAndroidShm> shm = 0; + + /* Get the buffer service */ + if (shm == NULL) { + sp<IServiceManager> sm = defaultServiceManager(); + sp<IBinder> binder; + binder = sm->getService(String16("com.samsung.android.jam.IAndroidShm")); + if (binder != 0) { + shm = IAndroidShm::asInterface(binder); + //shm = interface_cast<IAndroidShm>(binder); + } + } + return shm; +} + +unsigned int * getBufferMemPointer(int index) +{ + sp<IAndroidShm> shm = getAndroidShmService(); + if (shm == NULL) { + printf("The EneaBufferServer is not published\n"); + return (unsigned int *)-1; /* return an errorcode... */ + } else { + receiverMemBase = shm->getBuffer(index); + if(receiverMemBase != NULL) + return (unsigned int *) receiverMemBase->getBase(); + else + return (unsigned int*)-1; + } +} + +} + +using namespace android; + +void showStatus() { + sp<IAndroidShm> shm = getAndroidShmService(); + if(shm == NULL) { + printf("shm service is not available\n"); + return; + } + + printf("<<<<<<<<<<< dump memory allocation status >>>>>>>>>>\n"); + for(int i = 256; i >= 0; i--) { + if(shm->isAllocated(i) == 1) { + printf("Mem[%3d] == 0x%x\n", i, (unsigned int)getBufferMemPointer(i)); + } else { + printf("Mem[%3d] == NULL\n", i); + } + } +} + +void showRegistryIndex() { + sp<IAndroidShm> shm = getAndroidShmService(); + + if(shm == NULL) { + printf("shm service is not available\n"); + return; + } + + printf("<<<<<<<<<<< show registry index >>>>>>>>>>\n"); + + printf("index [%3d]\n",shm->getRegistryIndex()); +} + +void showHeader() { + sp<IAndroidShm> shm = getAndroidShmService(); + + if(shm == NULL) { + printf("shm service is not available\n"); + return; + } + + if(shm->getRegistryIndex() > 256) { + printf("don't have a registry header\n"); + return; + } + + unsigned int* buffer = getBufferMemPointer(shm->getRegistryIndex()); + if(buffer) { + jack_shm_header_t * header = (jack_shm_header_t*)buffer; + printf("<<<<<<<<<< register header value >>>>>>>>>>\n"); + printf("memory address 0x%x 0x%x\n", (unsigned int)(header), (unsigned int)buffer); + printf("magic = %d\n", header->magic); + printf("protocol = %d\n", header->protocol); + printf("type = %d\n", header->type); + printf("size = %d\n", header->size); + printf("hdr_len = %d\n", header->hdr_len); + printf("entry_len = %d\n", header->entry_len); + for(int j = 0; j < MAX_SERVERS; j++) { + //char name[256]; + //memset(name, '\0', 256); + //strncpy(name, header->server[j].name, 10); + printf("server[%d] pid = %d, name = %s\n", j, header->server[j].pid, header->server[j].name); + } + } +} + +void showBody() { + sp<IAndroidShm> shm = getAndroidShmService(); + + if(shm == NULL) { + printf("shm service is not available\n"); + return; + } + + if(shm->getRegistryIndex() > 256) { + printf("don't have a registry body\n"); + return; + } + unsigned int* buffer = getBufferMemPointer(shm->getRegistryIndex()); + if(buffer) { + jack_shm_header_t * header = (jack_shm_header_t*)buffer; + printf("<<<<<<<<<< registry body value >>>>>>>>>>\n"); + jack_shm_registry_t * registry = (jack_shm_registry_t *) (header + 1); + for(int k = 255; k >= 0; k--) { + printf("registry[%3d] index[%3d],allocator[%3d],size[%6d],id[%10s],fd[%3d]\n", k, + registry[k].index, registry[k].allocator, registry[k].size, + registry[k].id, + registry[k].fd); + } + } +} + +void showSemaphore() { + sp<IAndroidShm> shm = getAndroidShmService(); + + if(shm == NULL) { + printf("shm service is not available\n"); + return; + } + + shm->sendCommand("semaphore"); + printf("log will be shown in the logcat log\n"); +} + +int main(int argc, char** argv) { + // base could be on same address as Servers base but this + // is purely by luck do NEVER rely on this. Linux memory + // management may put it wherever it likes. + + if(argc < 2) { + printf("usage\n shmservicedump [status|header|body|index|semaphore]\n"); + printf(" status: show the shared memory allocation status\n"); + printf(" header: show the registry header infomations if the registry exist\n"); + printf(" body: show the registry body infomations if the registry exist\n"); + printf(" index: show the index of array that is allocated registry shared memory\n"); + printf(" semaphore: show the memory array about semaphore simulation\n"); + return 0; + } + + if(strcmp(argv[1], "semaphore") == 0) { + showSemaphore(); + } else if(strcmp(argv[1], "index") == 0) { + showRegistryIndex(); + } else if(strcmp(argv[1], "status") == 0) { + showStatus(); + } else if(strcmp(argv[1], "header") == 0) { + showHeader(); + } else if(strcmp(argv[1], "body") == 0) { + showBody(); + } else { + printf("%s is invalid parameter\n", argv[1]); + } + + return 0; +} diff --git a/android/AndroidShmServer/test/shmservicetest.cpp b/android/AndroidShmServer/test/shmservicetest.cpp new file mode 100644 index 00000000..d91670cc --- /dev/null +++ b/android/AndroidShmServer/test/shmservicetest.cpp @@ -0,0 +1,189 @@ +#include "../../IAndroidShm.h" +#include <binder/MemoryHeapBase.h> +#include <binder/IServiceManager.h> + +namespace android { + +static sp<IMemoryHeap> receiverMemBase; +#define MAX_SHARED_MEMORY_COUNT 257 + +sp<IAndroidShm> getAndroidShmService() { + sp<IAndroidShm> shm = 0; + + /* Get the buffer service */ + if (shm == NULL) { + sp<IServiceManager> sm = defaultServiceManager(); + sp<IBinder> binder; + binder = sm->getService(String16("com.samsung.android.jam.IAndroidShm")); + if (binder != 0) { + shm = IAndroidShm::asInterface(binder); + //shm = interface_cast<IAndroidShm>(binder); + } + } + return shm; +} + +unsigned int * getBufferMemPointer(int index) { + sp<IAndroidShm> shm = getAndroidShmService(); + if (shm == NULL) { + ALOGE("The EneaBufferServer is not published"); + return (unsigned int *)-1; /* return an errorcode... */ + } else { + receiverMemBase = shm->getBuffer(index); + if(receiverMemBase != NULL) + return (unsigned int *) receiverMemBase->getBase(); + else + return (unsigned int*)-1; + } +} + +} + +using namespace android; + +void setup_test() { + sp<IAndroidShm> shm = getAndroidShmService(); + if(shm == NULL) return; + for(int i = 0; i < MAX_SHARED_MEMORY_COUNT; i++) { + shm->removeShm(i); + } +} + +void teardown_test() { +} + +void increase_value_once() { + ALOGD("*****test: increase_value_once*****\n"); + sp<IAndroidShm> shm = getAndroidShmService(); + if(shm == NULL) return; + + int slot = shm->allocShm(10000); + unsigned int *base = getBufferMemPointer(slot); + if(base != (unsigned int *)-1) { + ALOGD("ShmServiceTest base=%p Data=0x%x\n",base, *base); + *base = (*base)+1; + ALOGD("ShmServiceTest base=%p Data=0x%x CHANGED\n",base, *base); + //receiverMemBase = 0; + } else { + ALOGE("Error shared memory not available\n"); + } +} + +void increase_value_10times() { + ALOGD("*****test: increase_value_10times*****\n"); + sp<IAndroidShm> shm = getAndroidShmService(); + if(shm == NULL) return; + + int slot = shm->allocShm(10000); + + for(int i = 0; i < 10; i++) { + unsigned int *base = getBufferMemPointer(slot); + if(base != (unsigned int *)-1) { + ALOGD("ShmServiceTest base=%p Data=0x%x\n",base, *base); + *base = (*base)+1; + ALOGD("ShmServiceTest base=%p Data=0x%x CHANGED\n",base, *base); + //receiverMemBase = 0; + } else { + ALOGE("Error shared memory not available\n"); + } + } +} + +void check_allocated() { + ALOGD("*****test: check_allocated*****\n"); + sp<IAndroidShm> shm = getAndroidShmService(); + if(shm == NULL) return; + + int slot = shm->allocShm(10000); + int i = 0; + for(; i < MAX_SHARED_MEMORY_COUNT; i++) { + if(slot == i) { + if(shm->isAllocated(i) == 1) { + //ALOGD("pass\n"); + } else { + ALOGD("failed\n"); + } + } else { + if(shm->isAllocated(i) == 0) { + //ALOGD("pass\n"); + } else { + ALOGD("failed\n"); + } + } + } + + if(i == MAX_SHARED_MEMORY_COUNT) { + ALOGD("pass\n"); + } +} + +void test_set_get_registry_index() { + ALOGD("*****test: test_set_get_registry_index*****\n"); + sp<IAndroidShm> shm = getAndroidShmService(); + if(shm == NULL) return; + + int registry = 1; + shm->setRegistryIndex(registry); + if(registry == shm->getRegistryIndex()) { + ALOGD("pass\n"); + } else { + ALOGD("fail\n"); + } + + registry = 0; + shm->setRegistryIndex(registry); + if(registry == shm->getRegistryIndex()) { + ALOGD("pass\n"); + } else { + ALOGD("fail\n"); + } +} + +void test_memset() { + ALOGD("*****test: test_memset*****\n"); + sp<IAndroidShm> shm = getAndroidShmService(); + if(shm == NULL) return; + + int slot = shm->allocShm(10000); + + unsigned int * pnt = getBufferMemPointer(slot); + + memset (pnt, 0, 10000); + + ALOGD("result : 0 0 0 0\n"); + ALOGD("memory dump : %d %d %d %d\n", pnt[0], pnt[1], pnt[2], pnt[3]); + + memset (pnt, 0xffffffff, 10000); + + ALOGD("result : -1 -1 -1 -1\n"); + ALOGD("memory dump : %d %d %d %d", pnt[0], pnt[1], pnt[2], pnt[3]); +} + +int main(int argc, char** argv) { + // base could be on same address as Servers base but this + // is purely by luck do NEVER rely on this. Linux memory + // management may put it wherever it likes. + + setup_test(); + increase_value_once(); + teardown_test(); + + setup_test(); + increase_value_10times(); + teardown_test(); + + setup_test(); + check_allocated(); + teardown_test(); + + setup_test(); + test_set_get_registry_index(); + teardown_test(); + + setup_test(); + test_memset(); + teardown_test(); + + return 0; +} + diff --git a/android/BnAndroidShm.cpp b/android/BnAndroidShm.cpp new file mode 100644 index 00000000..6ea0afcc --- /dev/null +++ b/android/BnAndroidShm.cpp @@ -0,0 +1,83 @@ +#include "BnAndroidShm.h" +#include <binder/Parcel.h> + +namespace android { + status_t BnAndroidShm::onTransact( uint32_t code, + const Parcel &data, + Parcel *reply, + uint32_t flags) + { + switch(code) { + case HW_SENDCOMMAND:{ + CHECK_INTERFACE(IAndroidShm, data, reply); + const char *str; + str = data.readCString(); + reply->writeInt32(sendCommand(str)); + return NO_ERROR; + }break; + + case HW_GETBUFFER:{ + CHECK_INTERFACE(IAndroidShm, data, reply); + int32_t index; + data.readInt32(&index); + sp<IMemoryHeap> Data = getBuffer(index); + if(Data != NULL){ + reply->writeStrongBinder(Data->asBinder()); + } + return NO_ERROR; + }break; + + case HW_ALLOC_SHM:{ + CHECK_INTERFACE(IAndroidShm, data, reply); + int32_t size; + data.readInt32(&size); + reply->writeInt32(allocShm(size)); + return NO_ERROR; + }break; + + case HW_REMOVE_SHM:{ + CHECK_INTERFACE(IAndroidShm, data, reply); + int32_t index; + data.readInt32(&index); + reply->writeInt32(removeShm(index)); + return NO_ERROR; + }break; + + case HW_IS_ALLOCATED:{ + CHECK_INTERFACE(IAndroidShm, data, reply); + int32_t index; + data.readInt32(&index); + reply->writeInt32(isAllocated(index)); + return NO_ERROR; + }break; + + case HW_SET_REGISTRY_INDEX:{ + CHECK_INTERFACE(IAndroidShm, data, reply); + int32_t index; + data.readInt32(&index); + reply->writeInt32(setRegistryIndex(index)); + return NO_ERROR; + }break; + + case HW_GET_REGISTRY_INDEX:{ + CHECK_INTERFACE(IAndroidShm, data, reply); + reply->writeInt32(getRegistryIndex()); + return NO_ERROR; + }break; + + case HW_INIT_SEMAPHORE:{ + CHECK_INTERFACE(IAndroidShm, data, reply); + const char *name; + name = data.readCString(); + sp<IMemoryHeap> Data = InitSemaphore(name); + if(Data != NULL){ + reply->writeStrongBinder(Data->asBinder()); + } + return NO_ERROR; + }break; + + default: + return BBinder::onTransact(code, data, reply, flags); + } + } +}; diff --git a/android/BnAndroidShm.h b/android/BnAndroidShm.h new file mode 100644 index 00000000..9b3a46af --- /dev/null +++ b/android/BnAndroidShm.h @@ -0,0 +1,16 @@ +#ifndef BNANDROIDSHM +#define BNANDROIDSHM + +#include <binder/Parcel.h> +#include "IAndroidShm.h" + +namespace android { + class BnAndroidShm : public BnInterface<IAndroidShm> { + public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); + }; +}; +#endif diff --git a/android/BpAndroidShm.cpp b/android/BpAndroidShm.cpp new file mode 100644 index 00000000..49dc8c47 --- /dev/null +++ b/android/BpAndroidShm.cpp @@ -0,0 +1,111 @@ +#include <binder/Parcel.h> +#include <utils/Log.h> +#include "BpAndroidShm.h" + +namespace android{ + + int BpAndroidShm::sendCommand(const char*command) { + Parcel data, reply; + data.writeInterfaceToken( + IAndroidShm::getInterfaceDescriptor()); + data.writeCString(command); + status_t status = remote()->transact(HW_SENDCOMMAND, data, &reply); + if(status != NO_ERROR) { + ALOGE("print sendCommand error: %s", strerror(-status)); + } else { + status= reply.readInt32(); + } + return status; + } + + sp<IMemoryHeap> BpAndroidShm::getBuffer(int index) { + Parcel data, reply; + sp<IMemoryHeap> memHeap = NULL; + data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); + data.writeInt32(index); + remote()->transact(HW_GETBUFFER, data, &reply); + memHeap = interface_cast<IMemoryHeap> (reply.readStrongBinder()); + return memHeap; + } + + BpAndroidShm::BpAndroidShm( const sp<IBinder>& impl) + : BpInterface<IAndroidShm>(impl) + {} + + BpAndroidShm::~BpAndroidShm() + {} + + int BpAndroidShm::allocShm(const int size) { // if negative return value is error + Parcel data, reply; + data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); + data.writeInt32(size); + status_t status = remote()->transact(HW_ALLOC_SHM, data, &reply); + if(status != NO_ERROR) { + ALOGE("print allocShm error: %s", strerror(-status)); + } else { + status= reply.readInt32(); + } + return status; + } + + int BpAndroidShm::removeShm(const unsigned int index) { // shared memory Á¦°Å + Parcel data, reply; + data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); + data.writeInt32(index); + status_t status = remote()->transact(HW_REMOVE_SHM, data, &reply); + if(status != NO_ERROR) { + ALOGE("print removeShm error: %s", strerror(-status)); + } else { + status= reply.readInt32(); + } + return status; + } + + int BpAndroidShm::isAllocated(const unsigned int index) { // allocated ¿©ºÎ È®ÀÎ + Parcel data, reply; + data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); + data.writeInt32(index); + status_t status = remote()->transact(HW_IS_ALLOCATED, data, &reply); + if(status != NO_ERROR) { + ALOGE("print isAllocated error: %s", strerror(-status)); + } else { + status= reply.readInt32(); + } + return status; + } + + int BpAndroidShm::setRegistryIndex(const unsigned int index) { + Parcel data, reply; + data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); + data.writeInt32(index); + status_t status = remote()->transact(HW_SET_REGISTRY_INDEX, data, &reply); + if(status != NO_ERROR) { + ALOGE("print setRegistryIndex error: %s", strerror(-status)); + } else { + status= reply.readInt32(); + } + return status; + } + + int BpAndroidShm::getRegistryIndex() { + Parcel data, reply; + data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); + status_t status = remote()->transact(HW_GET_REGISTRY_INDEX, data, &reply); + if(status != NO_ERROR) { + ALOGE("print getRegistryIndex error: %s", strerror(-status)); + } else { + status= reply.readInt32(); + } + return status; + } + + sp<IMemoryHeap> BpAndroidShm::InitSemaphore(const char* name) { + Parcel data, reply; + sp<IMemoryHeap> memHeap = NULL; + data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); + data.writeCString(name); + status_t status = remote()->transact(HW_INIT_SEMAPHORE, data, &reply); + memHeap = interface_cast<IMemoryHeap> (reply.readStrongBinder()); + return memHeap; + } +}; diff --git a/android/BpAndroidShm.h b/android/BpAndroidShm.h new file mode 100644 index 00000000..e079cc49 --- /dev/null +++ b/android/BpAndroidShm.h @@ -0,0 +1,25 @@ +#ifndef BPANDROIDSHM +#define BPANDROIDSHM + +#include <binder/Parcel.h> +#include "IAndroidShm.h" +#include <binder/IMemory.h> + +namespace android { + class BpAndroidShm: public BpInterface<IAndroidShm> { + public: + BpAndroidShm( const sp<IBinder> & impl); + virtual ~BpAndroidShm(); + virtual sp<IMemoryHeap> getBuffer(int index); + virtual int sendCommand(const char *command); + virtual int allocShm(const int size); // if negative return value is error + virtual int removeShm(const unsigned int index); // shared memory Á¦°Å + virtual int isAllocated(const unsigned int index); // allocated ¿©ºÎ È®ÀÎ + virtual int setRegistryIndex(const unsigned int index); + virtual int getRegistryIndex(); + + virtual sp<IMemoryHeap> InitSemaphore(const char* name); + }; +}; + +#endif diff --git a/android/CleanSpec.mk b/android/CleanSpec.mk new file mode 100644 index 00000000..cdcf505e --- /dev/null +++ b/android/CleanSpec.mk @@ -0,0 +1,66 @@ + +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/common) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/alsa_in_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/alsa_out_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/androidshmservice_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/shmservicetest_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/shmservicedump_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_samplerate_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_freewheel_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_connect_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_disconnect_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_latent_client_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_midiseq_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_zombie_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_lsp_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_load_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jackd_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_monitor_client_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_looper_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_client_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_cpu_load_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_iodelay_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_midisine_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_cpu_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_keyboard_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_unload_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_wait_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_alias_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_metro_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_bufsize_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_thru_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_session_notify_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_midi_latency_test_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_rec_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_netsource_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_net_master_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_net_slave_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_showtime_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_server_control_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_evmon_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_test_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_transport_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_session_client_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_effect_intermediates) +$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_multiple_metro_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_midi_dump_intermediates) + +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/common) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/posix) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjack_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjacknet_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjackserver_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjackshm_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_alsa_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_dummy_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_net_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_loopback_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_netone_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/audioadapter_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/example_lib_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/netadapter_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/netmanager_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/profiler_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_goldfish_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_opensles_intermediates) + diff --git a/android/IAndroidShm.cpp b/android/IAndroidShm.cpp new file mode 100644 index 00000000..95f5924b --- /dev/null +++ b/android/IAndroidShm.cpp @@ -0,0 +1,6 @@ +#include "IAndroidShm.h" +#include "BpAndroidShm.h" + +namespace android{ + IMPLEMENT_META_INTERFACE(AndroidShm, "com.samsung.android.jam.IAndroidShm"); +}; diff --git a/android/IAndroidShm.h b/android/IAndroidShm.h new file mode 100644 index 00000000..a890162c --- /dev/null +++ b/android/IAndroidShm.h @@ -0,0 +1,41 @@ +#ifndef IANDROIDSHM +#define IANDROIDSHM + +#include <binder/IInterface.h> +#include <binder/IMemory.h> + + namespace android { + + enum { + HW_GETBUFFER = IBinder::FIRST_CALL_TRANSACTION, + HW_MULTIPLY, + HW_STARTSERVER, + HW_MAKECLIENT, + HW_SENDCOMMAND, + HW_LOADSO, + HW_ALLOC_SHM, + HW_REMOVE_SHM, + HW_IS_ALLOCATED, + HW_SET_REGISTRY_INDEX, + HW_GET_REGISTRY_INDEX, + HW_INIT_SEMAPHORE + }; + + class IAndroidShm: public IInterface { + public: + DECLARE_META_INTERFACE(AndroidShm); + + virtual sp<IMemoryHeap> getBuffer(int index) = 0; + virtual int sendCommand(const char *command) = 0; + virtual int allocShm(const int size) = 0; // if negative return value is error + virtual int removeShm(const unsigned int index) = 0; // shared memory Á¦°Å + virtual int isAllocated(const unsigned int index) = 0; // allocated ¿©ºÎ È®ÀÎ + virtual int setRegistryIndex(const unsigned int index) = 0; + virtual int getRegistryIndex() = 0; + + // for named semaphore simulation + virtual sp<IMemoryHeap> InitSemaphore(const char* name) = 0; + }; +}; + +#endif diff --git a/android/JackAndroidSemaphore.cpp b/android/JackAndroidSemaphore.cpp new file mode 100644 index 00000000..703e289c --- /dev/null +++ b/android/JackAndroidSemaphore.cpp @@ -0,0 +1,262 @@ +/* +Copyright (C) 2004-2008 Grame +Copyright (C) 2013 Samsung Electronics + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "JackAndroidSemaphore.h" +#include "JackTools.h" +#include "JackConstants.h" +#include "JackError.h" +#include <fcntl.h> +#include <stdio.h> +#include <sys/time.h> +#include "IAndroidShm.h" +#include "shm.h" +#include "android/Shm.h" //android extension of shm.h + +namespace Jack +{ + +pthread_mutex_t JackAndroidSemaphore::mutex = PTHREAD_MUTEX_INITIALIZER; + +void JackAndroidSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size) +{ + char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; + JackTools::RewriteName(client_name, ext_client_name); + if (getenv("JACK_PROMISCUOUS_SERVER")) { + snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name); + } else { + snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); + } +} + +bool JackAndroidSemaphore::Signal() +{ + int res; + + if (!fSemaphore) { + jack_error("JackAndroidSemaphore::Signal name = %s already deallocated!!", fName); + return false; + } + + if (fFlush) + return true; + + if ((res = sem_post(fSemaphore)) != 0) { + jack_error("JackAndroidSemaphore::Signal name = %s err = %s", fName, strerror(errno)); + } + return (res == 0); +} + +bool JackAndroidSemaphore::SignalAll() +{ + int res; + + if (!fSemaphore) { + jack_error("JackAndroidSemaphore::SignalAll name = %s already deallocated!!", fName); + return false; + } + + if (fFlush) + return true; + + if ((res = sem_post(fSemaphore)) != 0) { + jack_error("JackAndroidSemaphore::SignalAll name = %s err = %s", fName, strerror(errno)); + } + return (res == 0); +} + +/* +bool JackAndroidSemaphore::Wait() +{ + int res; + + if (!fSemaphore) { + jack_error("JackAndroidSemaphore::Wait name = %s already deallocated!!", fName); + return false; + } + + if ((res = sem_wait(fSemaphore)) != 0) { + jack_error("JackAndroidSemaphore::Wait name = %s err = %s", fName, strerror(errno)); + } + return (res == 0); +} +*/ + +bool JackAndroidSemaphore::Wait() +{ + int res; + + while ((res = sem_wait(fSemaphore) < 0)) { + jack_error("JackAndroidSemaphore::Wait name = %s err = %s", fName, strerror(errno)); + if (errno != EINTR) { + break; + } + } + return (res == 0); +} + +bool JackAndroidSemaphore::TimedWait(long usec) +{ + int res; + struct timeval now; + timespec time; + + if (!fSemaphore) { + jack_error("JackAndroidSemaphore::TimedWait name = %s already deallocated!!", fName); + return false; + } + gettimeofday(&now, 0); + time.tv_sec = now.tv_sec + usec / 1000000; + long tv_usec = (now.tv_usec + (usec % 1000000)); + time.tv_sec += tv_usec / 1000000; + time.tv_nsec = (tv_usec % 1000000) * 1000; + + while ((res = sem_timedwait(fSemaphore, &time)) < 0) { + jack_error("JackAndroidSemaphore::TimedWait err = %s", strerror(errno)); + jack_log("JackAndroidSemaphore::TimedWait now : %ld %ld ", now.tv_sec, now.tv_usec); + jack_log("JackAndroidSemaphore::TimedWait next : %ld %ld ", time.tv_sec, time.tv_nsec/1000); + if (errno == ETIMEDOUT) { + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec = time.tv_sec - ts.tv_sec; + ts.tv_nsec = time.tv_nsec - ts.tv_nsec; + if (ts.tv_nsec < 0) { + ts.tv_nsec += 1000000000; + ts.tv_sec -= 1; + } + if (ts.tv_sec < 0 || ts.tv_nsec < 0) { + jack_error("JackAndroidSemaphore::TimedWait time may changed or client killed already! wait again!"); + gettimeofday(&now, 0); + time.tv_sec = now.tv_sec + usec / 1000000; + long tv_usec = (now.tv_usec + (usec % 1000000)); + time.tv_sec += tv_usec / 1000000; + time.tv_nsec = (tv_usec % 1000000) * 1000; + if ((res = sem_timedwait(fSemaphore, &time)) < 0) { + jack_error("JackAndroidSemaphore::TimedWait err = %s", strerror(errno)); + jack_log("JackAndroidSemaphore::TimedWait now : %ld %ld ", now.tv_sec, now.tv_usec); + jack_log("JackAndroidSemaphore::TimedWait next : %ld %ld ", time.tv_sec, time.tv_nsec/1000); + } + } + } + if (errno != EINTR) { + break; + } + } + return (res == 0); +} + +// Server side : publish the semaphore in the global namespace +bool JackAndroidSemaphore::Allocate(const char* name, const char* server_name, int value) +{ + pthread_mutex_lock (&mutex); + BuildName(name, server_name, fName, sizeof(fName)); + jack_log("JackAndroidSemaphore::Allocate name = %s val = %ld", fName, value); + + android::sp<android::IAndroidShm> service = android::Shm::getShmService(); + if(service == NULL){ + jack_error("shm service is null"); + return false; + } + fSemaphoreMemory = service->InitSemaphore(fName); + if(fSemaphoreMemory != NULL){ + fSemaphore = (sem_t*)(fSemaphoreMemory->getBase()); + } + + if(fSemaphore == NULL) { + jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno)); + pthread_mutex_unlock (&mutex); + return false; + } else { + sem_init(fSemaphore, 1, 0); + jack_log("sem_init()"); + pthread_mutex_unlock (&mutex); + return true; + } +} + +// Client side : get the published semaphore from server +bool JackAndroidSemaphore::ConnectInput(const char* name, const char* server_name) +{ + pthread_mutex_lock (&mutex); + BuildName(name, server_name, fName, sizeof(fName)); + jack_log("JackAndroidSemaphore::Connect name = %s", fName); + + // Temporary... + if (fSemaphore) { + jack_log("Already connected name = %s", name); + pthread_mutex_unlock (&mutex); + return true; + } + + android::sp<android::IAndroidShm> service = android::Shm::getShmService(); + if(service == NULL){ + jack_error("shm service is null"); + return false; + } + + fSemaphoreMemory = service->InitSemaphore(fName); + if(fSemaphoreMemory != NULL){ + fSemaphore = (sem_t*)(fSemaphoreMemory->getBase()); + } + + if(fSemaphore == NULL) { + jack_error("Connect: can't connect named semaphore name = %s err = %s", fName, strerror(errno)); + pthread_mutex_unlock (&mutex); + return false; + } else { + int val = 0; + sem_getvalue(fSemaphore, &val); + jack_log("JackAndroidSemaphore::Connect sem_getvalue %ld", val); + pthread_mutex_unlock (&mutex); + return true; + } +} + +bool JackAndroidSemaphore::Connect(const char* name, const char* server_name) +{ + return ConnectInput(name, server_name); +} + +bool JackAndroidSemaphore::ConnectOutput(const char* name, const char* server_name) +{ + return ConnectInput(name, server_name); +} + +bool JackAndroidSemaphore::Disconnect() +{ + if (fSemaphore) { + jack_log("JackAndroidSemaphore::Disconnect name = %s", fName); + fSemaphore = NULL; + } + return true; +} + +// Server side : destroy the semaphore +void JackAndroidSemaphore::Destroy() +{ + if (fSemaphore != NULL) { + jack_log("JackAndroidSemaphore::Disconnect name = %s", fName); + fSemaphore = NULL; + } else { + jack_error("JackAndroidSemaphore::Destroy semaphore == NULL"); + } +} + +} // end of namespace + diff --git a/android/JackAndroidSemaphore.h b/android/JackAndroidSemaphore.h new file mode 100644 index 00000000..dd8afdb9 --- /dev/null +++ b/android/JackAndroidSemaphore.h @@ -0,0 +1,76 @@ +/* +Copyright (C) 2004-2008 Grame +Copyright (C) 2013 Samsung Electronics + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __JackAndroidSemaphore__ +#define __JackAndroidSemaphore__ + +#include "JackSynchro.h" +#include "JackCompilerDeps.h" +#include <semaphore.h> +#include <time.h> +#include <assert.h> + +#include <binder/IMemory.h> +#include <binder/MemoryHeapBase.h> +#include <utils/RefBase.h> + +namespace Jack +{ + +/*! +\brief Inter process synchronization using POSIX semaphore. +*/ + +class SERVER_EXPORT JackAndroidSemaphore : public detail::JackSynchro +{ + + private: + + sem_t* fSemaphore; + android::sp<android::IMemoryHeap> fSemaphoreMemory; + static pthread_mutex_t mutex; + + protected: + + void BuildName(const char* name, const char* server_name, char* res, int size); + + public: + + JackAndroidSemaphore():JackSynchro(), fSemaphore(NULL) + {} + + bool Signal(); + bool SignalAll(); + bool Wait(); + bool TimedWait(long usec); + + bool Allocate(const char* name, const char* server_name, int value); + bool Connect(const char* name, const char* server_name); + bool ConnectInput(const char* name, const char* server_name); + bool ConnectOutput(const char* name, const char* server_name); + bool Disconnect(); + void Destroy(); +}; + +} // end of namespace + + +#endif + diff --git a/android/JackAndroidThread.cpp b/android/JackAndroidThread.cpp new file mode 100644 index 00000000..6c9e135d --- /dev/null +++ b/android/JackAndroidThread.cpp @@ -0,0 +1,374 @@ +/* +Copyright (C) 2001 Paul Davis +Copyright (C) 2004-2008 Grame +Copyright (C) 2013 Samsung Electronics + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "JackAndroidThread.h" +#include "JackError.h" +#include "JackTime.h" +#include "JackGlobals.h" +#include <string.h> // for memset +#include <unistd.h> // for _POSIX_PRIORITY_SCHEDULING check +#include <signal.h> + +//#define JACK_SCHED_POLICY SCHED_RR +#define JACK_SCHED_POLICY SCHED_FIFO + +namespace Jack +{ + +void JackAndroidThread::thread_exit_handler(int sig) +{ + printf("this signal is %d \n", sig); + pthread_exit(0); +} + +void* JackAndroidThread::ThreadHandler(void* arg) +{ + JackAndroidThread* obj = (JackAndroidThread*)arg; + JackRunnableInterface* runnable = obj->fRunnable; + int err; + + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = thread_exit_handler; + sigaction(SIGUSR1,&actions,NULL); + + // Signal creation thread when started with StartSync + jack_log("JackAndroidThread::ThreadHandler : start"); + obj->fStatus = kIniting; + + // Call Init method + if (!runnable->Init()) { + jack_error("Thread init fails: thread quits"); + return 0; + } + + obj->fStatus = kRunning; + + // If Init succeed, start the thread loop + bool res = true; + while (obj->fStatus == kRunning && res) { + res = runnable->Execute(); + } + + jack_log("JackAndroidThread::ThreadHandler : exit"); + pthread_exit(0); + return 0; // never reached +} + +int JackAndroidThread::Start() +{ + fStatus = kStarting; + + // Check if the thread was correctly started + if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { + fStatus = kIdle; + return -1; + } else { + return 0; + } +} + +int JackAndroidThread::StartSync() +{ + fStatus = kStarting; + + if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { + fStatus = kIdle; + return -1; + } else { + int count = 0; + while (fStatus == kStarting && ++count < 1000) { + JackSleep(1000); + } + return (count == 1000) ? -1 : 0; + } +} + +int JackAndroidThread::StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg) +{ + pthread_attr_t attributes; + struct sched_param rt_param; + pthread_attr_init(&attributes); + int res; + + if ((res = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE))) { + jack_error("Cannot request joinable thread creation for thread res = %d", res); + return -1; + } + + if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) { + jack_error("Cannot set scheduling scope for thread res = %d", res); + return -1; + } + + if (realtime) { + + jack_log("JackAndroidThread::StartImp : create RT thread"); + + if ((res = pthread_attr_setschedpolicy(&attributes, JACK_SCHED_POLICY))) { + jack_error("Cannot set RR scheduling class for RT thread res = %d", res); + return -1; + } + + memset(&rt_param, 0, sizeof(rt_param)); + rt_param.sched_priority = priority; + + if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) { + jack_error("Cannot set scheduling priority for RT thread res = %d", res); + return -1; + } + + } else { + jack_log("JackAndroidThread::StartImp : create non RT thread"); + } + + if ((res = pthread_attr_setstacksize(&attributes, THREAD_STACK))) { + jack_error("Cannot set thread stack size res = %d", res); + return -1; + } + + if ((res = JackGlobals::fJackThreadCreator(thread, &attributes, start_routine, arg))) { + jack_error("Cannot create thread res = %d", res); + return -1; + } + + pthread_attr_destroy(&attributes); + return 0; +} + +int JackAndroidThread::Kill() +{ + if (fThread != (jack_native_thread_t)NULL) { // If thread has been started + jack_log("JackAndroidThread::Kill"); + void* status; + + pthread_kill(fThread, SIGUSR1); + pthread_join(fThread, &status); + fStatus = kIdle; + fThread = (jack_native_thread_t)NULL; + return 0; + } else { + return -1; + } +} + +int JackAndroidThread::Stop() +{ + if (fThread != (jack_native_thread_t)NULL) { // If thread has been started + jack_log("JackAndroidThread::Stop"); + void* status; + fStatus = kIdle; // Request for the thread to stop + pthread_join(fThread, &status); + fThread = (jack_native_thread_t)NULL; + return 0; + } else { + return -1; + } +} + +int JackAndroidThread::KillImp(jack_native_thread_t thread) +{ + if (thread != (jack_native_thread_t)NULL) { // If thread has been started + jack_log("JackAndroidThread::Kill"); + void* status; + pthread_kill(thread, SIGUSR1); + pthread_join(thread, &status); + return 0; + } else { + return -1; + } +} + +int JackAndroidThread::StopImp(jack_native_thread_t thread) +{ + if (thread != (jack_native_thread_t)NULL) { // If thread has been started + jack_log("JackAndroidThread::Stop"); + void* status; + pthread_join(thread, &status); + return 0; + } else { + return -1; + } +} + +int JackAndroidThread::AcquireRealTime() +{ + return (fThread != (jack_native_thread_t)NULL) ? AcquireRealTimeImp(fThread, fPriority) : -1; +} + +int JackAndroidThread::AcquireSelfRealTime() +{ + return AcquireRealTimeImp(pthread_self(), fPriority); +} + +int JackAndroidThread::AcquireRealTime(int priority) +{ + fPriority = priority; + return AcquireRealTime(); +} + +int JackAndroidThread::AcquireSelfRealTime(int priority) +{ + fPriority = priority; + return AcquireSelfRealTime(); +} +int JackAndroidThread::AcquireRealTimeImp(jack_native_thread_t thread, int priority) +{ + struct sched_param rtparam; + int res; + memset(&rtparam, 0, sizeof(rtparam)); + rtparam.sched_priority = priority; + + jack_log("JackAndroidThread::AcquireRealTimeImp priority = %d", priority); + + if ((res = pthread_setschedparam(thread, JACK_SCHED_POLICY, &rtparam)) != 0) { + jack_error("Cannot use real-time scheduling (RR/%d)" + "(%d: %s)", rtparam.sched_priority, res, + strerror(res)); + return -1; + } + return 0; +} + +int JackAndroidThread::DropRealTime() +{ + return (fThread != (jack_native_thread_t)NULL) ? DropRealTimeImp(fThread) : -1; +} + +int JackAndroidThread::DropSelfRealTime() +{ + return DropRealTimeImp(pthread_self()); +} + +int JackAndroidThread::DropRealTimeImp(jack_native_thread_t thread) +{ + struct sched_param rtparam; + int res; + memset(&rtparam, 0, sizeof(rtparam)); + rtparam.sched_priority = 0; + + if ((res = pthread_setschedparam(thread, SCHED_OTHER, &rtparam)) != 0) { + jack_error("Cannot switch to normal scheduling priority(%s)", strerror(errno)); + return -1; + } + return 0; +} + +jack_native_thread_t JackAndroidThread::GetThreadID() +{ + return fThread; +} + +bool JackAndroidThread::IsThread() +{ + return pthread_self() == fThread; +} + +void JackAndroidThread::Terminate() +{ + jack_log("JackAndroidThread::Terminate"); + pthread_exit(0); +} + +SERVER_EXPORT void ThreadExit() +{ + jack_log("ThreadExit"); + pthread_exit(0); +} + +} // end of namespace + +bool jack_get_thread_realtime_priority_range(int * min_ptr, int * max_ptr) +{ +#if defined(_POSIX_PRIORITY_SCHEDULING) && !defined(__APPLE__) + int min, max; + + min = sched_get_priority_min(JACK_SCHED_POLICY); + if (min == -1) + { + jack_error("sched_get_priority_min() failed."); + return false; + } + + max = sched_get_priority_max(JACK_SCHED_POLICY); + if (max == -1) + { + jack_error("sched_get_priority_max() failed."); + return false; + } + + *min_ptr = min; + *max_ptr = max; + + return true; +#else + return false; +#endif +} + +bool jack_tls_allocate_key(jack_tls_key *key_ptr) +{ + int ret; + + ret = pthread_key_create(key_ptr, NULL); + if (ret != 0) + { + jack_error("pthread_key_create() failed with error %d", ret); + return false; + } + + return true; +} + +bool jack_tls_free_key(jack_tls_key key) +{ + int ret; + + ret = pthread_key_delete(key); + if (ret != 0) + { + jack_error("pthread_key_delete() failed with error %d", ret); + return false; + } + + return true; +} + +bool jack_tls_set(jack_tls_key key, void *data_ptr) +{ + int ret; + + ret = pthread_setspecific(key, (const void *)data_ptr); + if (ret != 0) + { + jack_error("pthread_setspecific() failed with error %d", ret); + return false; + } + + return true; +} + +void *jack_tls_get(jack_tls_key key) +{ + return pthread_getspecific(key); +} diff --git a/android/JackAndroidThread.h b/android/JackAndroidThread.h new file mode 100644 index 00000000..d6ec66d8 --- /dev/null +++ b/android/JackAndroidThread.h @@ -0,0 +1,97 @@ +/* +Copyright (C) 2001 Paul Davis +Copyright (C) 2004-2008 Grame +Copyright (C) 2013 Samsung Electronics + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __JackAndroidThread__ +#define __JackAndroidThread__ + +#include "JackThread.h" +#include <pthread.h> + +namespace Jack +{ + +/* use 512KB stack per thread - the default is way too high to be feasible + * with mlockall() on many systems */ +#define THREAD_STACK 524288 + +enum +{ + PTHREAD_CANCEL_DEFERRED, + PTHREAD_CANCEL_ASYNCHRONOUS +}; + +/*! +\brief The POSIX thread base class. +*/ + +class SERVER_EXPORT JackAndroidThread : public detail::JackThreadInterface +{ + + protected: + + jack_native_thread_t fThread; + static void* ThreadHandler(void* arg); + static void thread_exit_handler(int sig); + + public: + + JackAndroidThread(JackRunnableInterface* runnable, bool real_time, int priority, int cancellation) + : JackThreadInterface(runnable, priority, real_time, cancellation), fThread((jack_native_thread_t)NULL) + {} + JackAndroidThread(JackRunnableInterface* runnable, int cancellation = PTHREAD_CANCEL_ASYNCHRONOUS) + : JackThreadInterface(runnable, 0, false, cancellation), fThread((jack_native_thread_t)NULL) + {} + + int Start(); + int StartSync(); + int Kill(); + int Stop(); + void Terminate(); + + int AcquireRealTime(); // Used when called from another thread + int AcquireSelfRealTime(); // Used when called from thread itself + + int AcquireRealTime(int priority); // Used when called from another thread + int AcquireSelfRealTime(int priority); // Used when called from thread itself + + int DropRealTime(); // Used when called from another thread + int DropSelfRealTime(); // Used when called from thread itself + + jack_native_thread_t GetThreadID(); + bool IsThread(); + + static int AcquireRealTimeImp(jack_native_thread_t thread, int priority); + static int AcquireRealTimeImp(jack_native_thread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraint) + { + return JackAndroidThread::AcquireRealTimeImp(thread, priority); + } + static int DropRealTimeImp(jack_native_thread_t thread); + static int StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg); + static int StopImp(jack_native_thread_t thread); + static int KillImp(jack_native_thread_t thread); +}; + +SERVER_EXPORT void ThreadExit(); + +} // end of namespace + + +#endif diff --git a/android/JackAtomic_os.h b/android/JackAtomic_os.h new file mode 100644 index 00000000..8b0ba2c6 --- /dev/null +++ b/android/JackAtomic_os.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2004-2008 Grame + Copyright (C) 2013 Samsung Electronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#ifndef __JackAtomic_android__ +#define __JackAtomic_android__ + +#include "JackTypes.h" + +#include <sys/atomics.h> +static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr) +{ +#if 1 + return !__atomic_cmpxchg(value, newvalue, (volatile int *)addr); +#else + //slow compare_and_swap_32 + if (*(UInt32*)addr == value) { + *(UInt32*)addr = newvalue; + return true; + } + return false; +#endif +} + +#endif + diff --git a/android/JackCompilerDeps_os.h b/android/JackCompilerDeps_os.h new file mode 100644 index 00000000..8e6e5ff5 --- /dev/null +++ b/android/JackCompilerDeps_os.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2004-2008 Grame + Copyright (C) 2013 Samsung Electronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#ifndef __JackCompilerDeps_android__ +#define __JackCompilerDeps_android__ + +#include "JackConstants.h" + +#if __GNUC__ + + #define MEM_ALIGN(x,y) x __attribute__((aligned(y))) + #define LIB_EXPORT __attribute__((visibility("default"))) + #ifdef SERVER_SIDE + #if (__GNUC__< 4) + #define SERVER_EXPORT + #else + #define SERVER_EXPORT __attribute__((visibility("default"))) + #endif + #else + #define SERVER_EXPORT __attribute__((visibility("hidden"))) + #endif + +#else + #define MEM_ALIGN(x,y) x + #define LIB_EXPORT + #define SERVER_EXPORT + + /* Add other things here for non-gcc platforms */ +#endif + +#endif /* __JackCompilerDeps_android__ */ diff --git a/android/JackControlAPIAndroid.cpp b/android/JackControlAPIAndroid.cpp new file mode 100644 index 00000000..a915b4dd --- /dev/null +++ b/android/JackControlAPIAndroid.cpp @@ -0,0 +1,89 @@ +// u/* -*- Mode: C++ ; c-basic-offset: 4 -*- */ +/* + JACK control API implementation + + Copyright (C) 2008 Nedko Arnaudov + Copyright (C) 2008 Grame + Copyright (C) 2013 Samsung Electronics + + 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; version 2 of the License. + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef WIN32 +#include <stdint.h> +#include <dirent.h> +#include <pthread.h> +#endif + +#include "types.h" +#include <string.h> +#include <errno.h> +#include <stdio.h> +#include <assert.h> +#include <signal.h> + +#include "JackControlAPIAndroid.h" +#include "JackConstants.h" +#include "JackServerGlobals.h" + +using namespace Jack; + +struct jackctl_sigmask +{ + sigset_t signals; +}; + +static jackctl_sigmask sigmask; + +SERVER_EXPORT int +jackctl_wait_signals_and_return(jackctl_sigmask_t * sigmask) +{ + int sig; + bool waiting = true; + + while (waiting) { + #if defined(sun) && !defined(__sun__) // SUN compiler only, to check + sigwait(&sigmask->signals); + #else + sigwait(&sigmask->signals, &sig); + #endif + fprintf(stderr, "Jack main caught signal %d\n", sig); + + switch (sig) { + case SIGUSR1: + //jack_dump_configuration(engine, 1); + break; + case SIGUSR2: + // driver exit + waiting = false; + break; + case SIGTTOU: + break; + default: + waiting = false; + break; + } + } + + if (sig != SIGSEGV) { + // unblock signals so we can see them during shutdown. + // this will help prod developers not to lose sight of + // bugs that cause segfaults etc. during shutdown. + sigprocmask(SIG_UNBLOCK, &sigmask->signals, 0); + } + + return sig; +} + diff --git a/android/JackControlAPIAndroid.h b/android/JackControlAPIAndroid.h new file mode 100644 index 00000000..92694113 --- /dev/null +++ b/android/JackControlAPIAndroid.h @@ -0,0 +1,44 @@ +/* + JACK control API + + Copyright (C) 2008 Nedko Arnaudov + Copyright (C) 2008 Grame + Copyright (C) 2013 Samsung Electronics + + 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; version 2 of the License. + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __JackControlAPIAndroid__ +#define __JackControlAPIAndroid__ + +#include "JackCompilerDeps.h" + +/** opaque type for sigmask object */ +typedef struct jackctl_sigmask jackctl_sigmask_t; + +#ifdef __cplusplus +extern "C" { +#endif + +SERVER_EXPORT int +jackctl_wait_signals_and_return( + jackctl_sigmask_t * signals); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/android/JackError.cpp b/android/JackError.cpp new file mode 100644 index 00000000..af9b08b5 --- /dev/null +++ b/android/JackError.cpp @@ -0,0 +1,153 @@ +/* + Copyright (C) 2001 Paul Davis + Copyright (C) 2004-2008 Grame + Copyright (C) 2008 Nedko Arnaudov + Copyright (C) 2013 Samsung Electronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#include <stdarg.h> +#include <stdio.h> +#include "JackError.h" +#include "JackGlobals.h" +#include "JackMessageBuffer.h" + +#define LOG_BUF_SIZE 1024 +#undef LOG_TAG +#ifdef SERVER_SIDE +#define LOG_TAG "JackAudioServer" +#else +#define LOG_TAG "JackAudioClient" +#endif +#include <utils/Log.h> + +using namespace Jack; + +static bool change_thread_log_function(jack_log_function_t log_function) +{ + return (jack_tls_get(JackGlobals::fKeyLogFunction) == NULL + && jack_tls_set(JackGlobals::fKeyLogFunction, (void*)log_function)); +} + +SERVER_EXPORT int set_threaded_log_function() +{ + return change_thread_log_function(JackMessageBufferAdd); +} + +void jack_log_function(int level, const char *message) +{ + void (* log_callback)(const char *); + + switch (level) + { + case LOG_LEVEL_INFO: + log_callback = jack_info_callback; + break; + case LOG_LEVEL_ERROR: + log_callback = jack_error_callback; + break; + default: + return; + } + + log_callback(message); +} + +static void jack_format_and_log(int level, const char *prefix, const char *fmt, va_list ap) +{ + char buffer[256]; + size_t len; + jack_log_function_t log_function; + + if (prefix != NULL) { + len = strlen(prefix); + assert(len < 256); + memcpy(buffer, prefix, len); + } else { + len = 0; + } + + vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap); + + log_function = (jack_log_function_t)jack_tls_get(JackGlobals::fKeyLogFunction); + + /* if log function is not overriden for thread, use default one */ + if (log_function == NULL) + { + log_function = jack_log_function; + //log_function(LOG_LEVEL_INFO, "------ Using default log function"); + } + else + { + //log_function(LOG_LEVEL_INFO, "++++++ Using thread-specific log function"); + } + + log_function(level, buffer); +} + +SERVER_EXPORT void jack_error(const char *fmt, ...) +{ + va_list ap; + char buf[LOG_BUF_SIZE]; + va_start(ap, fmt); + vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); + va_end(ap); + __android_log_write(ANDROID_LOG_ERROR, LOG_TAG, buf); +} + +SERVER_EXPORT void jack_info(const char *fmt, ...) +{ + va_list ap; + char buf[LOG_BUF_SIZE]; + va_start(ap, fmt); + vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); + va_end(ap); + __android_log_write(ANDROID_LOG_INFO, LOG_TAG, buf); +} + +SERVER_EXPORT void jack_log(const char *fmt,...) +{ + va_list ap; + char buf[LOG_BUF_SIZE]; + if (JackGlobals::fVerbose) { + va_start(ap, fmt); + vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); + va_end(ap); + __android_log_write(ANDROID_LOG_VERBOSE, LOG_TAG, buf); + } +} + +SERVER_EXPORT void default_jack_error_callback(const char *desc) +{ + fprintf(stderr, "%s\n", desc); + fflush(stderr); +} + +SERVER_EXPORT void default_jack_info_callback(const char *desc) +{ + fprintf(stdout, "%s\n", desc); + fflush(stdout); +} + +SERVER_EXPORT void silent_jack_error_callback(const char *desc) +{} + +SERVER_EXPORT void silent_jack_info_callback(const char *desc) +{} + +SERVER_EXPORT void (*jack_error_callback)(const char *desc) = &default_jack_error_callback; +SERVER_EXPORT void (*jack_info_callback)(const char *desc) = &default_jack_info_callback; diff --git a/android/JackGoldfishDriver.cpp b/android/JackGoldfishDriver.cpp new file mode 100644 index 00000000..0765d8b3 --- /dev/null +++ b/android/JackGoldfishDriver.cpp @@ -0,0 +1,212 @@ +/* +Copyright (C) 2001 Paul Davis +Copyright (C) 2004-2008 Grame +Copyright (C) 2013 Samsung Electronics + +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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "JackGoldfishDriver.h" +#include "JackDriverLoader.h" +#include "JackThreadedDriver.h" +#include "JackEngineControl.h" +#include "JackGraphManager.h" +#include "JackCompilerDeps.h" +#include <iostream> +#include <unistd.h> +#include <fcntl.h> +#include <math.h> + +#define JACK_GOLDFISH_BUFFER_SIZE 4096 + +namespace Jack +{ + +static char const * const kAudioDeviceName = "/dev/eac"; + +int JackGoldfishDriver::Open(jack_nframes_t buffer_size, + jack_nframes_t samplerate, + bool capturing, + bool playing, + int inchannels, + int outchannels, + bool monitor, + const char* capture_driver_uid, + const char* playback_driver_uid, + jack_nframes_t capture_latency, + jack_nframes_t playback_latency) { + jack_log("JackGoldfishDriver::Open"); + + // Generic JackAudioDriver Open + if (JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, + capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) { + return -1; + } + + mFd = ::open(kAudioDeviceName, O_RDWR); + jack_log("JackGoldfishDriver::Open(mFd=%d)", mFd); + + if (!mBuffer) + mBuffer = (short *) malloc(sizeof(short) * JACK_GOLDFISH_BUFFER_SIZE * 2); + + //JackAudioDriver::SetBufferSize(buffer_size); + //JackAudioDriver::SetSampleRate(samplerate); + + return 0; +} + +int JackGoldfishDriver::Close() { + jack_log("JackGoldfishDriver::Close"); + + // Generic audio driver close + int res = JackAudioDriver::Close(); + + if (mFd >= 0) ::close(mFd); + + if (mBuffer) { + free(mBuffer); + mBuffer = NULL; + } + + return res; +} + +int JackGoldfishDriver::Read() { + jack_log("JackGoldfishDriver::Read"); + for (int i = 0; i < fCaptureChannels; i++) { + //silence + memset(GetInputBuffer(i), 0, sizeof(jack_default_audio_sample_t) * JACK_GOLDFISH_BUFFER_SIZE /* fEngineControl->fBufferSize */); + } + return 0; +} + +int JackGoldfishDriver::Write() { + jack_log("JackGoldfishDriver::Write"); + //write(mFd, GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); + + jack_default_audio_sample_t* outputBuffer_1 = GetOutputBuffer(0); + jack_default_audio_sample_t* outputBuffer_2 = GetOutputBuffer(1); + + for(int i=0, j=0; i<JACK_GOLDFISH_BUFFER_SIZE /* fEngineControl->fBufferSize */; i++) { + //convert float to short + *(mBuffer + j) = (short) (*(outputBuffer_1 + i) * 32640); j++; + *(mBuffer + j) = (short) (*(outputBuffer_2 + i) * 32640); j++; + } + write(mFd, mBuffer, sizeof(short) * JACK_GOLDFISH_BUFFER_SIZE * 2); + return 0; +} + +int JackGoldfishDriver::SetBufferSize(jack_nframes_t buffer_size) { + jack_log("JackGoldfishDriver::SetBufferSize"); + JackAudioDriver::SetBufferSize(buffer_size); + return 0; +} + +} // end of namespace + + +#ifdef __cplusplus +extern "C" +{ +#endif + + SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor () { + jack_driver_desc_t * desc; + jack_driver_desc_filler_t filler; + jack_driver_param_value_t value; + + desc = jack_driver_descriptor_construct("goldfish", JackDriverMaster, "Timer based backend", &filler); + + value.ui = 2U; + jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamUInt, &value, NULL, "Number of capture ports", NULL); + jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamUInt, &value, NULL, "Number of playback ports", NULL); + + value.ui = 44100U; + jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL); + + value.i = 0; + jack_driver_descriptor_add_parameter(desc, &filler, "monitor", 'm', JackDriverParamBool, &value, NULL, "Provide monitor ports for the output", NULL); + + value.ui = JACK_GOLDFISH_BUFFER_SIZE; + jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL); + + value.ui = 21333U; + jack_driver_descriptor_add_parameter(desc, &filler, "wait", 'w', JackDriverParamUInt, &value, NULL, "Number of usecs to wait between engine processes", NULL); + + return desc; + } + + SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) { + jack_nframes_t sample_rate = 44100; + jack_nframes_t buffer_size = JACK_GOLDFISH_BUFFER_SIZE; + unsigned int capture_ports = 2; + unsigned int playback_ports = 2; + int wait_time = 0; + const JSList * node; + const jack_driver_param_t * param; + bool monitor = false; + + for (node = params; node; node = jack_slist_next (node)) { + param = (const jack_driver_param_t *) node->data; + + switch (param->character) { + + case 'C': + capture_ports = param->value.ui; + break; + + case 'P': + playback_ports = param->value.ui; + break; + + case 'r': + sample_rate = param->value.ui; + break; + + case 'p': + buffer_size = param->value.ui; + break; + + case 'w': + wait_time = param->value.ui; + break; + + case 'm': + monitor = param->value.i; + break; + } + } + + if (wait_time > 0) { + buffer_size = lroundf((wait_time * sample_rate) / 1000000.0f); + if (buffer_size > BUFFER_SIZE_MAX) { + buffer_size = BUFFER_SIZE_MAX; + jack_error("Buffer size set to %d", BUFFER_SIZE_MAX); + } + } + + Jack::JackDriverClientInterface* driver = new Jack::JackThreadedDriver(new Jack::JackGoldfishDriver("system", "goldfish_pcm", engine, table)); + if (driver->Open(buffer_size, sample_rate, 1, 1, capture_ports, playback_ports, monitor, "goldfish", "goldfish", 0, 0) == 0) { + return driver; + } else { + delete driver; + return NULL; + } + } + +#ifdef __cplusplus +} +#endif diff --git a/android/JackGoldfishDriver.h b/android/JackGoldfishDriver.h new file mode 100644 index 00000000..c30aec5c --- /dev/null +++ b/android/JackGoldfishDriver.h @@ -0,0 +1,70 @@ +/* +Copyright (C) 2001 Paul Davis +Copyright (C) 2004-2008 Grame +Copyright (C) 2013 Samsung Electronics + +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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __JackGoldfishDriver__ +#define __JackGoldfishDriver__ + +#include "JackAudioDriver.h" + +namespace Jack +{ + +/*! +\brief The goldfish driver. +*/ + +class JackGoldfishDriver : public JackAudioDriver +{ + + public: + + JackGoldfishDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) + : JackAudioDriver(name, alias, engine, table), mFd(-1), mBuffer(NULL) + {} + virtual ~JackGoldfishDriver() + {} + + int Open(jack_nframes_t buffe_size, + jack_nframes_t samplerate, + bool capturing, + bool playing, + int chan_in, + int chan_out, + bool monitor, + const char* capture_driver_name, + const char* playback_driver_name, + jack_nframes_t capture_latency, + jack_nframes_t playback_latency); + int Close(); + int Read(); + int Write(); + int SetBufferSize(jack_nframes_t buffer_size); + +private: + + int mFd; + short *mBuffer; + +}; + +} // end of namespace + +#endif diff --git a/android/JackOpenSLESDriver.cpp b/android/JackOpenSLESDriver.cpp new file mode 100644 index 00000000..61a07da1 --- /dev/null +++ b/android/JackOpenSLESDriver.cpp @@ -0,0 +1,236 @@ +/* +Copyright (C) 2001 Paul Davis +Copyright (C) 2004-2008 Grame +Copyright (C) 2013 Samsung Electronics + +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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "JackOpenSLESDriver.h" +#include "JackDriverLoader.h" +#include "JackThreadedDriver.h" +#include "JackEngineControl.h" +#include "JackGraphManager.h" +#include "JackCompilerDeps.h" +#include <iostream> +#include <unistd.h> +#include <fcntl.h> +#include <math.h> + +#include <android/log.h> +#include "opensl_io.h" + +#define JACK_OPENSLES_DEFAULT_SAMPLERATE 48000 +#define JACK_OPENSLES_DEFAULT_BUFFER_SIZE 1024 + +namespace Jack +{ + +static OPENSL_STREAM *pOpenSL_stream; + +int JackOpenSLESDriver::Open(jack_nframes_t buffer_size, + jack_nframes_t samplerate, + bool capturing, + bool playing, + int inchannels, + int outchannels, + bool monitor, + const char* capture_driver_uid, + const char* playback_driver_uid, + jack_nframes_t capture_latency, + jack_nframes_t playback_latency) { + jack_log("JackOpenSLESDriver::Open"); + + // Generic JackAudioDriver Open + if (JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, + capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) { + return -1; + } + //JackAudioDriver::SetBufferSize(buffer_size); + //JackAudioDriver::SetSampleRate(samplerate); + + if (capturing) { + inbuffer = (float *) malloc(sizeof(float) * buffer_size); //mono input + memset(inbuffer, 0, sizeof(float) * buffer_size); + } + if (playing) { + outbuffer = (float *) malloc(sizeof(float) * buffer_size * 2); //stereo output + memset(outbuffer, 0, sizeof(float) * buffer_size * 2); + } + pOpenSL_stream = android_OpenAudioDevice(samplerate, capturing ? 1 : 0, playing ? 2 : 0, buffer_size); + if (pOpenSL_stream == NULL) return -1; + + return 0; +} + +int JackOpenSLESDriver::Close() { + jack_log("JackOpenSLESDriver::Close"); + + // Generic audio driver close + int res = JackAudioDriver::Close(); + + android_CloseAudioDevice(pOpenSL_stream); + + if (inbuffer) { + free(inbuffer); + inbuffer = NULL; + } + if (outbuffer) { + free(outbuffer); + outbuffer = NULL; + } + return res; +} + +int JackOpenSLESDriver::Read() { + //jack_log("JackOpenSLESDriver::Read"); + jack_default_audio_sample_t* inputBuffer_1 = GetInputBuffer(0); + jack_default_audio_sample_t* inputBuffer_2 = GetInputBuffer(1); + + if (inbuffer) { + int samps = android_AudioIn(pOpenSL_stream,inbuffer,fEngineControl->fBufferSize); + //jack_log("JackOpenSLESDriver::Read(%d)", samps); //for debug + for (int i = 0; i < samps; i++) { + *(inputBuffer_1 + i) = *(inbuffer + i); + *(inputBuffer_2 + i) = *(inbuffer + i); + } + } else { + for (int i = 0; i < fCaptureChannels; i++) { + memset(GetInputBuffer(i), 0, sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); //silence + } + } + + return 0; +} + +int JackOpenSLESDriver::Write() { + //jack_log("JackOpenSLESDriver::Write"); + jack_default_audio_sample_t* outputBuffer_1 = GetOutputBuffer(0); + jack_default_audio_sample_t* outputBuffer_2 = GetOutputBuffer(1); + + if (outbuffer) { + android_AudioOut(pOpenSL_stream, outbuffer, fEngineControl->fBufferSize * 2); //stereo output + for (unsigned int i = 0, j = 0; i < fEngineControl->fBufferSize; i++) { + *(outbuffer + j) = *(outputBuffer_1 + i); j++; + *(outbuffer + j) = *(outputBuffer_2 + i); j++; + } + } + + return 0; +} + +int JackOpenSLESDriver::SetBufferSize(jack_nframes_t buffer_size) { + jack_log("JackOpenSLESDriver::SetBufferSize"); + JackAudioDriver::SetBufferSize(buffer_size); + return 0; +} + +} // end of namespace + + +#ifdef __cplusplus +extern "C" +{ +#endif + + SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor () { + jack_driver_desc_t * desc; + jack_driver_desc_filler_t filler; + jack_driver_param_value_t value; + + desc = jack_driver_descriptor_construct("opensles", JackDriverMaster, "Timer based backend", &filler); + + value.ui = 2U; + jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamUInt, &value, NULL, "Number of capture ports", NULL); + jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamUInt, &value, NULL, "Number of playback ports", NULL); + + value.ui = 48000U; + jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL); + + value.i = 0; + jack_driver_descriptor_add_parameter(desc, &filler, "monitor", 'm', JackDriverParamBool, &value, NULL, "Provide monitor ports for the output", NULL); + + value.ui = JACK_OPENSLES_DEFAULT_BUFFER_SIZE; + jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL); + + value.ui = 21333U; + jack_driver_descriptor_add_parameter(desc, &filler, "wait", 'w', JackDriverParamUInt, &value, NULL, "Number of usecs to wait between engine processes", NULL); + + return desc; + } + + SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) { + jack_nframes_t sample_rate = JACK_OPENSLES_DEFAULT_SAMPLERATE; + jack_nframes_t buffer_size = JACK_OPENSLES_DEFAULT_BUFFER_SIZE; + unsigned int capture_ports = 2; + unsigned int playback_ports = 2; + int wait_time = 0; + const JSList * node; + const jack_driver_param_t * param; + bool monitor = false; + + for (node = params; node; node = jack_slist_next (node)) { + param = (const jack_driver_param_t *) node->data; + + switch (param->character) { + + case 'C': + capture_ports = param->value.ui; + break; + + case 'P': + playback_ports = param->value.ui; + break; + + case 'r': + sample_rate = param->value.ui; + break; + + case 'p': + buffer_size = param->value.ui; + break; + + case 'w': + wait_time = param->value.ui; + break; + + case 'm': + monitor = param->value.i; + break; + } + } + + if (wait_time > 0) { + buffer_size = lroundf((wait_time * sample_rate) / 1000000.0f); + if (buffer_size > BUFFER_SIZE_MAX) { + buffer_size = BUFFER_SIZE_MAX; + jack_error("Buffer size set to %d", BUFFER_SIZE_MAX); + } + } + + Jack::JackDriverClientInterface* driver = new Jack::JackThreadedDriver(new Jack::JackOpenSLESDriver("system", "opensles_pcm", engine, table)); + if (driver->Open(buffer_size, sample_rate, capture_ports? 1 : 0, playback_ports? 1 : 0, capture_ports, playback_ports, monitor, "opensles", "opensles", 0, 0) == 0) { + return driver; + } else { + delete driver; + return NULL; + } + } + +#ifdef __cplusplus +} +#endif + diff --git a/android/JackOpenSLESDriver.h b/android/JackOpenSLESDriver.h new file mode 100644 index 00000000..04ddf6a1 --- /dev/null +++ b/android/JackOpenSLESDriver.h @@ -0,0 +1,70 @@ +/* +Copyright (C) 2001 Paul Davis +Copyright (C) 2004-2008 Grame +Copyright (C) 2013 Samsung Electronics + +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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __JackOpenSLESDriver__ +#define __JackOpenSLESDriver__ + +#include "JackAudioDriver.h" + +namespace Jack +{ + +/*! +\brief The OpenSLES driver. +*/ + +class JackOpenSLESDriver : public JackAudioDriver +{ + + public: + + JackOpenSLESDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) + : JackAudioDriver(name, alias, engine, table), inbuffer(NULL), outbuffer(NULL) + {} + virtual ~JackOpenSLESDriver() + {} + + int Open(jack_nframes_t buffe_size, + jack_nframes_t samplerate, + bool capturing, + bool playing, + int chan_in, + int chan_out, + bool monitor, + const char* capture_driver_name, + const char* playback_driver_name, + jack_nframes_t capture_latency, + jack_nframes_t playback_latency); + int Close(); + int Read(); + int Write(); + int SetBufferSize(jack_nframes_t buffer_size); + + private: + + float *inbuffer; + float *outbuffer; + +}; + +} // end of namespace + +#endif diff --git a/android/JackPlatformPlug_os.h b/android/JackPlatformPlug_os.h new file mode 100644 index 00000000..cc35d478 --- /dev/null +++ b/android/JackPlatformPlug_os.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2004-2008 Grame + Copyright (C) 2013 Samsung Electronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#ifndef __JackPlatformPlug_android__ +#define __JackPlatformPlug_android__ + +#define jack_server_dir "/data/misc/jack" +#define jack_client_dir "/data/misc/jack" +#define JACK_DEFAULT_DRIVER "alsa" + +namespace Jack +{ + struct JackRequest; + struct JackResult; + + class JackPosixMutex; + class JackAndroidThread; + class JackFifo; + class JackSocketServerChannel; + class JackSocketClientChannel; + class JackSocketServerNotifyChannel; + class JackSocketNotifyChannel; + class JackClientSocket; + class JackNetUnixSocket; +} + +/* __JackPlatformMutex__ */ +#include "JackPosixMutex.h" +namespace Jack {typedef JackPosixMutex JackMutex; } + +/* __JackPlatformThread__ */ +#include "JackAndroidThread.h" +namespace Jack { typedef JackAndroidThread JackThread; } + +/* __JackPlatformSynchro__ client activation */ +/* +#include "JackFifo.h" +namespace Jack { typedef JackFifo JackSynchro; } +*/ + +#include "JackAndroidSemaphore.h" +namespace Jack { typedef JackAndroidSemaphore JackSynchro; } + +/* __JackPlatformChannelTransaction__ */ +/* +#include "JackSocket.h" +namespace Jack { typedef JackClientSocket JackChannelTransaction; } +*/ + +/* __JackPlatformProcessSync__ */ +#include "JackPosixProcessSync.h" +namespace Jack { typedef JackPosixProcessSync JackProcessSync; } + +/* __JackPlatformServerChannel__ */ +#include "JackSocketServerChannel.h" +namespace Jack { typedef JackSocketServerChannel JackServerChannel; } + +/* __JackPlatformClientChannel__ */ +#include "JackSocketClientChannel.h" +namespace Jack { typedef JackSocketClientChannel JackClientChannel; } + +/* __JackPlatformServerNotifyChannel__ */ +#include "JackSocketServerNotifyChannel.h" +namespace Jack { typedef JackSocketServerNotifyChannel JackServerNotifyChannel; } + +/* __JackPlatformNotifyChannel__ */ +#include "JackSocketNotifyChannel.h" +namespace Jack { typedef JackSocketNotifyChannel JackNotifyChannel; } + +/* __JackPlatformNetSocket__ */ +#include "JackNetUnixSocket.h" +namespace Jack { typedef JackNetUnixSocket JackNetSocket; } + +#endif diff --git a/android/JackShmMem_os.h b/android/JackShmMem_os.h new file mode 100644 index 00000000..3f9027a5 --- /dev/null +++ b/android/JackShmMem_os.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2004-2008 Grame + Copyright (C) 2013 Samsung Electronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#ifndef __JackShmMem__android__ +#define __JackShmMem__android__ + +#include <sys/types.h> +#include <sys/mman.h> + +#define CHECK_MLOCK(ptr, size) (mlock((ptr), (size)) == 0) +#define CHECK_MUNLOCK(ptr, size) (munlock((ptr), (size)) == 0) +#define CHECK_MLOCKALL() (false) +#define CHECK_MUNLOCKALL() (false) + +/* fix for crash jack server issue: + * case 1) jack_destroy_shm() in JackShmReadWritePtr1::Init() causes crash + * because server lost shared memory by destroying client side ahead. + */ +#ifndef SERVER_SIDE +#define jack_destroy_shm(x) (0) +#endif + +#endif /* __JackShmMem__android__ */ diff --git a/android/JackSystemDeps_os.h b/android/JackSystemDeps_os.h new file mode 100644 index 00000000..48406f33 --- /dev/null +++ b/android/JackSystemDeps_os.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2004-2008 Grame + Copyright (C) 2013 Samsung Electronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#ifndef __JackSystemDeps_android__ +#define __JackSystemDeps_android__ + + +#include "../posix/JackSystemDeps_os.h" + +/** + * bionic c dependant functions + */ +#define pthread_setcanceltype(x,y) (0) + +#endif /* __JackSystemDeps_android__ */ diff --git a/android/NOTICE b/android/NOTICE new file mode 100644 index 00000000..b56eebe8 --- /dev/null +++ b/android/NOTICE @@ -0,0 +1,869 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. +------------------------------------------------------------------------------- + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! +------------------------------------------------------------------------------- +opensl_io.c: +Android OpenSL input/output module (header) +Copyright (c) 2012, Victor Lazzarini +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the <organization> nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/android/Shm.cpp b/android/Shm.cpp new file mode 100644 index 00000000..1149616f --- /dev/null +++ b/android/Shm.cpp @@ -0,0 +1,886 @@ +/* + Copyright (C) 2001-2003 Paul Davis + Copyright (C) 2005-2012 Grame + Copyright (C) 2013 Samsung Electronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#define LOG_TAG "JAMSHMSERVICE" + +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <binder/MemoryHeapBase.h> +#include <binder/IServiceManager.h> +#include <binder/IPCThreadState.h> +#include <utils/Log.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/un.h> +#include <sys/wait.h> +#include "BnAndroidShm.h" +#include "AndroidShm.h" + +#include "JackConstants.h" + +#include <fcntl.h> +#include <signal.h> +#include <limits.h> +#include <errno.h> +#include <dirent.h> +#include <sys/mman.h> +#include <linux/ashmem.h> +#include <cutils/ashmem.h> + +#include "JackError.h" + +// remove ALOGI log +#define jack_d +//#define jack_d ALOGI +#define jack_error ALOGE +#define MEMORY_SIZE 10*1024 + + +namespace android { + + jack_shmtype_t Shm::jack_shmtype = shm_ANDROID; + + /* The JACK SHM registry is a chunk of memory for keeping track of the + * shared memory used by each active JACK server. This allows the + * server to clean up shared memory when it exits. To avoid memory + * leakage due to kill -9, crashes or debugger-driven exits, this + * cleanup is also done when a new instance of that server starts. + */ + + /* per-process global data for the SHM interfaces */ + jack_shm_id_t Shm::registry_id; /* SHM id for the registry */ + jack_shm_fd_t Shm::registry_fd = JACK_SHM_REGISTRY_FD; + + jack_shm_info_t Shm::registry_info = { + JACK_SHM_NULL_INDEX, 0, 0, { MAP_FAILED } + }; + + /* pointers to registry header and array */ + jack_shm_header_t *Shm::jack_shm_header = NULL; + jack_shm_registry_t *Shm::jack_shm_registry = NULL; + char Shm::jack_shm_server_prefix[JACK_SERVER_NAME_SIZE] = ""; + + /* jack_shm_lock_registry() serializes updates to the shared memory + * segment JACK uses to keep track of the SHM segments allocated to + * all its processes, including multiple servers. + * + * This is not a high-contention lock, but it does need to work across + * multiple processes. High transaction rates and realtime safety are + * not required. Any solution needs to at least be portable to POSIX + * and POSIX-like systems. + * + * We must be particularly careful to ensure that the lock be released + * if the owning process terminates abnormally. Otherwise, a segfault + * or kill -9 at the wrong moment could prevent JACK from ever running + * again on that machine until after a reboot. + */ + + #define JACK_SEMAPHORE_KEY 0x282929 + #define JACK_SHM_REGISTRY_KEY JACK_SEMAPHORE_KEY + #define JACK_REGISTRY_NAME "/jack-shm-registry" + + int Shm::semid = -1; + pthread_mutex_t Shm::mutex = PTHREAD_MUTEX_INITIALIZER; + + //sp<IAndroidShm> Shm::mShmService; + sp<IMemoryHeap> Shm::mShmMemBase[JACK_SHM_HEAP_ENOUGH_COUNT] = {0,}; + + Shm* Shm::ref = NULL; + + Shm* Shm::Instantiate() { + if(Shm::ref == NULL) { + jack_d("shm::Instantiate is called"); + Shm::ref = new Shm; + //AndroidShm::instantiate(); + } + return ref; + } + + Shm::Shm() { } + + Shm::~Shm() { } + + sp<IAndroidShm> Shm::getShmService(){ + return interface_cast<IAndroidShm>(defaultServiceManager()->getService(String16("com.samsung.android.jam.IAndroidShm"))); + } + + //sp<IAndroidShm>& Shm::getShmService() { + // if (mShmService.get() == 0) { + // sp<IServiceManager> sm = defaultServiceManager(); + // sp<IBinder> binder; + // do { + // binder = sm->getService(String16("com.samsung.android.jam.IAndroidShm")); + // if (binder != 0) + // break; + // ALOGW("CameraService not published, waiting..."); + // usleep(500000); // 0.5 s + // } while(true); + // mShmService = interface_cast<IAndroidShm>(binder); + // } + // ALOGE_IF(mShmService==0, "no CameraService!?"); + // return mShmService; + //} + + void Shm::shm_copy_from_registry (jack_shm_info_t* /*si*/, jack_shm_registry_index_t ) { + // not used + } + void Shm::shm_copy_to_registry (jack_shm_info_t* /*si*/, jack_shm_registry_index_t*) { + // not used + } + + void Shm::jack_release_shm_entry (jack_shm_registry_index_t index) { + /* the registry must be locked */ + jack_shm_registry[index].size = 0; + jack_shm_registry[index].allocator = 0; + memset (&jack_shm_registry[index].id, 0, + sizeof (jack_shm_registry[index].id)); + jack_shm_registry[index].fd = 0; + } + + int Shm::release_shm_info (jack_shm_registry_index_t index) { + /* must NOT have the registry locked */ + if (jack_shm_registry[index].allocator == GetPID()) { + if (jack_shm_lock_registry () < 0) { + jack_error ("jack_shm_lock_registry fails..."); + return -1; + } + jack_release_shm_entry (index); + jack_shm_unlock_registry (); + jack_d ("release_shm_info: success!"); + } + else + jack_error ("release_shm_info: error!"); + + return 0; + } + char* Shm::shm_addr (unsigned int fd) { + if(fd >= JACK_SHM_HEAP_ENOUGH_COUNT) { + jack_error("ignore to get memory buffer : index[%d] is too big", fd); + return NULL; + } + + sp<IAndroidShm> service = Shm::getShmService(); + if(service == NULL){ + jack_error("shm service is null"); + return NULL; + } + mShmMemBase[fd] = service->getBuffer(fd); + if(mShmMemBase[fd] == NULL) { + jack_error("fail to get memory buffer"); + return NULL; + } + + return ((char *) mShmMemBase[fd]->getBase()); + } + + int Shm::shm_lock_registry (void) { + pthread_mutex_lock (&mutex); + return 0; + } + + void Shm::shm_unlock_registry (void) { + pthread_mutex_unlock (&mutex); + } + + void Shm::release_shm_entry (jack_shm_registry_index_t index) { + /* the registry must be locked */ + jack_shm_registry[index].size = 0; + jack_shm_registry[index].allocator = 0; + memset (&jack_shm_registry[index].id, 0, + sizeof (jack_shm_registry[index].id)); + } + + void Shm::remove_shm (jack_shm_id_t *id) { + int shm_fd = -1; + jack_d("remove_id [%s]",(char*)id); + if(!strcmp((const char*)id, JACK_REGISTRY_NAME)) { + shm_fd = registry_fd; + } else { + for (int i = 0; i < MAX_SHM_ID; i++) { + if(!strcmp((const char*)id, jack_shm_registry[i].id)) { + shm_fd = jack_shm_registry[i].fd; + break; + } + } + } + + if (shm_fd >= 0) { + sp<IAndroidShm> service = getShmService(); + if(service != NULL) { + service->removeShm(shm_fd); + } else { + jack_error("shm service is null"); + } + } + jack_d ("[APA] jack_remove_shm : ok "); + } + + int Shm::access_registry (jack_shm_info_t * ri) { + jack_d("access_registry\n"); + /* registry must be locked */ + sp<IAndroidShm> service = getShmService(); + if(service == NULL){ + jack_error("shm service is null"); + return EINVAL; + } + int shm_fd = service->getRegistryIndex(); + + strncpy (registry_id, JACK_REGISTRY_NAME, sizeof (registry_id) - 1); + registry_id[sizeof (registry_id) - 1] = '\0'; + + if(service->isAllocated(shm_fd) == FALSE) { + //jack_error ("Cannot mmap shm registry segment (%s)", + // strerror (errno)); + jack_error ("Cannot mmap shm registry segment"); + //close (shm_fd); + ri->ptr.attached_at = NULL; + registry_fd = JACK_SHM_REGISTRY_FD; + return EINVAL; + } + + ri->fd = shm_fd; + registry_fd = shm_fd; + ri->ptr.attached_at = shm_addr(shm_fd); + + if(ri->ptr.attached_at == NULL) { + ALOGE("attached pointer is null !"); + jack_shm_header = NULL; + jack_shm_registry = NULL; + return 0; + } + + /* set up global pointers */ + ri->index = JACK_SHM_REGISTRY_INDEX; + jack_shm_header = (jack_shm_header_t*)(ri->ptr.attached_at); + jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1); + + jack_d("jack_shm_header[%p],jack_shm_registry[%p]", jack_shm_header, jack_shm_registry); + //close (shm_fd); // steph + return 0; + } + + int Shm::GetUID() { + return getuid(); + } + + int Shm::GetPID() { + return getpid(); + } + + int Shm::jack_shm_lock_registry (void) { + // TODO: replace semaphore to mutex + pthread_mutex_lock (&mutex); + return 0; + } + + void Shm::jack_shm_unlock_registry (void) { + // TODO: replace semaphore to mutex + pthread_mutex_unlock (&mutex); + return; + } + + void Shm::shm_init_registry () { + if(jack_shm_header == NULL) + return; + + /* registry must be locked */ + + memset (jack_shm_header, 0, JACK_SHM_REGISTRY_SIZE); + + jack_shm_header->magic = JACK_SHM_MAGIC; + //jack_shm_header->protocol = JACK_PROTOCOL_VERSION; + jack_shm_header->type = jack_shmtype; + jack_shm_header->size = JACK_SHM_REGISTRY_SIZE; + jack_shm_header->hdr_len = sizeof (jack_shm_header_t); + jack_shm_header->entry_len = sizeof (jack_shm_registry_t); + + for (int i = 0; i < MAX_SHM_ID; ++i) { + jack_shm_registry[i].index = i; + } + } + + void Shm::set_server_prefix (const char *server_name) { + snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix), + "jack-%d:%s:", GetUID(), server_name); + } + + /* create a new SHM registry segment + * + * sets up global registry pointers, if successful + * + * returns: 0 if registry created successfully + * nonzero error code if unable to allocate a new registry + */ + int Shm::create_registry (jack_shm_info_t * ri) { + jack_d("create_registry\n"); + /* registry must be locked */ + int shm_fd = 0; + + strncpy (registry_id, JACK_REGISTRY_NAME, sizeof (registry_id) - 1); + registry_id[sizeof (registry_id) - 1] = '\0'; + + sp<IAndroidShm> service = getShmService(); + if(service == NULL){ + jack_error("shm service is null"); + return EINVAL; + } + + if((shm_fd = service->allocShm(JACK_SHM_REGISTRY_SIZE)) < 0) { + jack_error("Cannot create shm registry segment"); + registry_fd = JACK_SHM_REGISTRY_FD; + return EINVAL; + } + + service->setRegistryIndex(shm_fd); + + /* set up global pointers */ + ri->fd = shm_fd; + ri->index = JACK_SHM_REGISTRY_INDEX; + registry_fd = shm_fd; + ri->ptr.attached_at = shm_addr(shm_fd); + ri->size = JACK_SHM_REGISTRY_SIZE; + + jack_shm_header = (jack_shm_header_t*)(ri->ptr.attached_at); + jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1); + + jack_d("create_registry jack_shm_header[%p], jack_shm_registry[%p]", jack_shm_header, jack_shm_registry); + + /* initialize registry contents */ + shm_init_registry (); + //close (shm_fd); // steph + + return 0; + } + + int Shm::shm_validate_registry () { + /* registry must be locked */ + if(jack_shm_header == NULL) { + return -1; + } + + if ((jack_shm_header->magic == JACK_SHM_MAGIC) + //&& (jack_shm_header->protocol == JACK_PROTOCOL_VERSION) + && (jack_shm_header->type == jack_shmtype) + && (jack_shm_header->size == JACK_SHM_REGISTRY_SIZE) + && (jack_shm_header->hdr_len == sizeof (jack_shm_header_t)) + && (jack_shm_header->entry_len == sizeof (jack_shm_registry_t))) { + + return 0; /* registry OK */ + } + + return -1; + } + + int Shm::server_initialize_shm (int new_registry) { + int rc; + + jack_d("server_initialize_shm\n"); + + if (jack_shm_header) + return 0; /* already initialized */ + + if (shm_lock_registry () < 0) { + jack_error ("jack_shm_lock_registry fails..."); + return -1; + } + + rc = access_registry (®istry_info); + + if (new_registry) { + remove_shm (®istry_id); + rc = ENOENT; + } + + switch (rc) { + case ENOENT: /* registry does not exist */ + rc = create_registry (®istry_info); + break; + case 0: /* existing registry */ + if (shm_validate_registry () == 0) + break; + /* else it was invalid, so fall through */ + case EINVAL: /* bad registry */ + /* Apparently, this registry was created by an older + * JACK version. Delete it so we can try again. */ + release_shm (®istry_info); + remove_shm (®istry_id); + if ((rc = create_registry (®istry_info)) != 0) { + //jack_error ("incompatible shm registry (%s)", + // strerror (errno)); + jack_error ("incompatible shm registry"); +//#ifndef USE_POSIX_SHM +// jack_error ("to delete, use `ipcrm -M 0x%0.8x'", JACK_SHM_REGISTRY_KEY); +//#endif + } + break; + default: /* failure return code */ + break; + } + + shm_unlock_registry (); + return rc; + } + + // here begin the API + int Shm::register_server (const char *server_name, int new_registry) { + int i, res = 0; + + jack_d("register_server new_registry[%d]\n", new_registry); + + set_server_prefix (server_name); + + if (server_initialize_shm (new_registry)) + return ENOMEM; + + if (shm_lock_registry () < 0) { + jack_error ("jack_shm_lock_registry fails..."); + return -1; + } + + /* See if server_name already registered. Since server names + * are per-user, we register the unique server prefix string. + */ + for (i = 0; i < MAX_SERVERS; i++) { + + if (strncmp (jack_shm_header->server[i].name, + jack_shm_server_prefix, + JACK_SERVER_NAME_SIZE) != 0) + continue; /* no match */ + + if (jack_shm_header->server[i].pid == GetPID()) { + res = 0; /* it's me */ + goto unlock; + } + + /* see if server still exists */ + if (kill (jack_shm_header->server[i].pid, 0) == 0) { + res = EEXIST; /* other server running */ + goto unlock; + } + + /* it's gone, reclaim this entry */ + memset (&jack_shm_header->server[i], 0, + sizeof (jack_shm_server_t)); + } + + /* find a free entry */ + for (i = 0; i < MAX_SERVERS; i++) { + if (jack_shm_header->server[i].pid == 0) + break; + } + + if (i >= MAX_SERVERS) { + res = ENOSPC; /* out of space */ + goto unlock; + } + + /* claim it */ + jack_shm_header->server[i].pid = GetPID(); + strncpy (jack_shm_header->server[i].name, + jack_shm_server_prefix, + JACK_SERVER_NAME_SIZE - 1); + jack_shm_header->server[i].name[JACK_SERVER_NAME_SIZE - 1] = '\0'; + + unlock: + shm_unlock_registry (); + return res; + } + + int Shm::unregister_server (const char * /* server_name */) { + int i; + if (shm_lock_registry () < 0) { + jack_error ("jack_shm_lock_registry fails..."); + return -1; + } + + for (i = 0; i < MAX_SERVERS; i++) { + if (jack_shm_header->server[i].pid == GetPID()) { + memset (&jack_shm_header->server[i], 0, + sizeof (jack_shm_server_t)); + } + } + + shm_unlock_registry (); + return 0; + } + + int Shm::initialize_shm (const char *server_name) { + int rc; + + if (jack_shm_header) + return 0; /* already initialized */ + + set_server_prefix (server_name); + + if (shm_lock_registry () < 0) { + jack_error ("jack_shm_lock_registry fails..."); + return -1; + } + + if ((rc = access_registry (®istry_info)) == 0) { + if ((rc = shm_validate_registry ()) != 0) { + jack_error ("Incompatible shm registry, " + "are jackd and libjack in sync?"); + } + } + shm_unlock_registry (); + + return rc; + } + + int Shm::initialize_shm_server (void) { + // not used + return 0; + } + + int Shm::initialize_shm_client (void) { + // not used + return 0; + } + + int Shm::cleanup_shm (void) { + int i; + int destroy; + jack_shm_info_t copy; + + if (shm_lock_registry () < 0) { + jack_error ("jack_shm_lock_registry fails..."); + return -1; + } + + for (i = 0; i < MAX_SHM_ID; i++) { + jack_shm_registry_t* r; + + r = &jack_shm_registry[i]; + memcpy (©, r, sizeof (jack_shm_info_t)); + destroy = FALSE; + + /* ignore unused entries */ + if (r->allocator == 0) + continue; + + /* is this my shm segment? */ + if (r->allocator == GetPID()) { + + /* allocated by this process, so unattach + and destroy. */ + release_shm (©); + destroy = TRUE; + + } else { + + /* see if allocator still exists */ + if (kill (r->allocator, 0)) { + if (errno == ESRCH) { + /* allocator no longer exists, + * so destroy */ + destroy = TRUE; + } + } + } + + if (destroy) { + + int index = copy.index; + + if ((index >= 0) && (index < MAX_SHM_ID)) { + remove_shm (&jack_shm_registry[index].id); + release_shm_entry (index); + } + r->size = 0; + r->allocator = 0; + } + } + + shm_unlock_registry (); + return TRUE; + + } + + jack_shm_registry_t * Shm::get_free_shm_info () { + /* registry must be locked */ + jack_shm_registry_t* si = NULL; + int i; + + for (i = 0; i < MAX_SHM_ID; ++i) { + if (jack_shm_registry[i].size == 0) { + break; + } + } + + if (i < MAX_SHM_ID) { + si = &jack_shm_registry[i]; + } + + return si; + } + + int Shm::shmalloc (const char * /*shm_name*/, jack_shmsize_t size, jack_shm_info_t* si) { + jack_shm_registry_t* registry; + int shm_fd; + int rc = -1; + char name[SHM_NAME_MAX+1]; + + if (shm_lock_registry () < 0) { + jack_error ("jack_shm_lock_registry fails..."); + return -1; + } + + sp<IAndroidShm> service = getShmService(); + if(service == NULL){ + rc = errno; + jack_error("shm service is null"); + goto unlock; + } + + if ((registry = get_free_shm_info ()) == NULL) { + jack_error ("shm registry full"); + goto unlock; + } + + snprintf (name, sizeof (name), "/jack-%d-%d", GetUID(), registry->index); + if (strlen (name) >= sizeof (registry->id)) { + jack_error ("shm segment name too long %s", name); + goto unlock; + } + + if((shm_fd = service->allocShm(size)) < 0) { + rc = errno; + jack_error ("Cannot create shm segment %s", name); + goto unlock; + } + + //close (shm_fd); + registry->size = size; + strncpy (registry->id, name, sizeof (registry->id) - 1); + registry->id[sizeof (registry->id) - 1] = '\0'; + registry->allocator = GetPID(); + registry->fd = shm_fd; + si->fd = shm_fd; + si->index = registry->index; + si->ptr.attached_at = MAP_FAILED; /* not attached */ + rc = 0; /* success */ + + jack_d ("[APA] jack_shmalloc : ok "); + +unlock: + shm_unlock_registry (); + return rc; + } + + void Shm::release_shm (jack_shm_info_t* /*si*/) { + // do nothing + } + + void Shm::release_lib_shm (jack_shm_info_t* /*si*/) { + // do nothing + } + + void Shm::destroy_shm (jack_shm_info_t* si) { + /* must NOT have the registry locked */ + if (si->index == JACK_SHM_NULL_INDEX) + return; /* segment not allocated */ + + remove_shm (&jack_shm_registry[si->index].id); + release_shm_info (si->index); + } + + int Shm::attach_shm (jack_shm_info_t* si) { + jack_shm_registry_t *registry = &jack_shm_registry[si->index]; + + if((si->ptr.attached_at = shm_addr(registry->fd)) == NULL) { + jack_error ("Cannot mmap shm segment %s", registry->id); + close (si->fd); + return -1; + } + return 0; + } + + int Shm::attach_lib_shm (jack_shm_info_t* si) { + int res = attach_shm(si); + if (res == 0) + si->size = jack_shm_registry[si->index].size; // Keep size in si struct + return res; + } + + int Shm::attach_shm_read (jack_shm_info_t* si) { + jack_shm_registry_t *registry = &jack_shm_registry[si->index]; + + if((si->ptr.attached_at = shm_addr(registry->fd)) == NULL) { + jack_error ("Cannot mmap shm segment %s", registry->id); + close (si->fd); + return -1; + } + return 0; + } + + int Shm::attach_lib_shm_read (jack_shm_info_t* si) { + int res = attach_shm_read(si); + if (res == 0) + si->size = jack_shm_registry[si->index].size; // Keep size in si struct + return res; + } + + int Shm::resize_shm (jack_shm_info_t* si, jack_shmsize_t size) { + jack_shm_id_t id; + + /* The underlying type of `id' differs for SYSV and POSIX */ + memcpy (&id, &jack_shm_registry[si->index].id, sizeof (id)); + + release_shm (si); + destroy_shm (si); + + if (shmalloc ((char *) id, size, si)) { + return -1; + } + return attach_shm (si); + } + + void Shm::jack_shm_copy_from_registry (jack_shm_info_t* si, jack_shm_registry_index_t t) { + Shm::Instantiate()->shm_copy_from_registry(si,t); + } + void Shm::jack_shm_copy_to_registry (jack_shm_info_t* si, jack_shm_registry_index_t* t) { + Shm::Instantiate()->shm_copy_to_registry(si,t); + } + int Shm::jack_release_shm_info (jack_shm_registry_index_t t) { + return Shm::Instantiate()->release_shm_info(t); + } + char* Shm::jack_shm_addr (jack_shm_info_t* si) { + if(si != NULL) { + return (char*)si->ptr.attached_at; + } else { + jack_error ("jack_shm_addr : jack_shm_info_t is NULL!"); + return NULL; + } + } + int Shm::jack_register_server (const char *server_name, int new_registry) { + return Shm::Instantiate()->register_server(server_name, new_registry); + } + int Shm::jack_unregister_server (const char *server_name) { + return Shm::Instantiate()->unregister_server(server_name); + } + int Shm::jack_initialize_shm (const char *server_name) { + return Shm::Instantiate()->initialize_shm(server_name); + } + int Shm::jack_initialize_shm_server (void) { + return Shm::Instantiate()->initialize_shm_server(); + } + int Shm::jack_initialize_shm_client () { + return Shm::Instantiate()->initialize_shm_client(); + } + int Shm::jack_cleanup_shm (void) { + return Shm::Instantiate()->cleanup_shm(); + } + int Shm::jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* result) { + return Shm::Instantiate()->shmalloc(shm_name, size, result); + } + void Shm::jack_release_shm (jack_shm_info_t* si) { + Shm::Instantiate()->release_shm(si); + } + void Shm::jack_release_lib_shm (jack_shm_info_t* si) { + Shm::Instantiate()->release_lib_shm(si); + } + void Shm::jack_destroy_shm (jack_shm_info_t* si) { + Shm::Instantiate()->destroy_shm(si); + } + int Shm::jack_attach_shm (jack_shm_info_t* si) { + return Shm::Instantiate()->attach_shm(si); + } + int Shm::jack_attach_lib_shm (jack_shm_info_t* si) { + return Shm::Instantiate()->attach_lib_shm(si); + } + int Shm::jack_attach_shm_read (jack_shm_info_t* si) { + return Shm::Instantiate()->attach_shm_read(si); + } + int Shm::jack_attach_lib_shm_read (jack_shm_info_t* si) { + return Shm::Instantiate()->attach_lib_shm_read(si); + } + int Shm::jack_resize_shm (jack_shm_info_t* si, jack_shmsize_t size) { + return Shm::Instantiate()->resize_shm(si, size); + } +}; + +void jack_shm_copy_from_registry (jack_shm_info_t* si, jack_shm_registry_index_t t) { + android::Shm::jack_shm_copy_from_registry(si, t); +} +void jack_shm_copy_to_registry (jack_shm_info_t* si, jack_shm_registry_index_t* t) { + android::Shm::jack_shm_copy_to_registry(si, t); +} +int jack_release_shm_info (jack_shm_registry_index_t t) { + return android::Shm::jack_release_shm_info(t); +} +char* jack_shm_addr (jack_shm_info_t* si) { + return android::Shm::jack_shm_addr(si); +} +int jack_register_server (const char *server_name, int new_registry) { + return android::Shm::jack_register_server(server_name, new_registry); +} +int jack_unregister_server (const char *server_name) { + return android::Shm::jack_unregister_server(server_name); +} +int jack_initialize_shm (const char *server_name) { + return android::Shm::jack_initialize_shm(server_name); +} +int jack_initialize_shm_server (void) { + return android::Shm::jack_initialize_shm_server(); +} +int jack_initialize_shm_client (void) { + return android::Shm::jack_initialize_shm_client(); +} +int jack_cleanup_shm (void) { + return android::Shm::jack_cleanup_shm(); +} +int jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* result) { + return android::Shm::jack_shmalloc(shm_name, size, result); +} +void jack_release_shm (jack_shm_info_t* si) { + android::Shm::jack_release_shm(si); +} +void jack_release_lib_shm (jack_shm_info_t* si) { + android::Shm::jack_release_lib_shm(si); +} +void jack_destroy_shm (jack_shm_info_t* si) { + android::Shm::jack_destroy_shm(si); +} +int jack_attach_shm (jack_shm_info_t* si) { + return android::Shm::jack_attach_shm(si); +} +int jack_attach_lib_shm (jack_shm_info_t* si) { + return android::Shm::jack_attach_lib_shm(si); +} +int jack_attach_shm_read (jack_shm_info_t* si) { + return android::Shm::jack_attach_shm_read(si); +} +int jack_attach_lib_shm_read (jack_shm_info_t* si) { + return android::Shm::jack_attach_lib_shm_read(si); +} +int jack_resize_shm (jack_shm_info_t* si, jack_shmsize_t size) { + return android::Shm::jack_resize_shm(si, size); +} +void jack_instantiate() { + android::AndroidShm::instantiate(); +} + diff --git a/android/Shm.h b/android/Shm.h new file mode 100644 index 00000000..cb75396e --- /dev/null +++ b/android/Shm.h @@ -0,0 +1,144 @@ +/* + Copyright (C) 2001-2003 Paul Davis + Copyright (C) 2005-2012 Grame + Copyright (C) 2013 Samsung Electronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#ifndef __jack_shm_android_h__ +#define __jack_shm_android_h__ + +#include <limits.h> +#include <sys/types.h> +#include "types.h" +#include "JackCompilerDeps.h" +#include <binder/MemoryHeapBase.h> +#include <utils/RefBase.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define JACK_SHM_REGISTRY_FD -1 +#define JACK_SHM_HEAP_ENOUGH_COUNT 300 + +void jack_instantiate(); + +#ifdef __cplusplus +} +#endif + +namespace android { + + class IAndroidShm; + + class Shm { + public: + static Shm* Instantiate(); + virtual ~Shm(); + private: + Shm(); + Shm( const Shm&); + Shm& operator=(const Shm); + + private: + void set_server_prefix (const char *server_name); + int server_initialize_shm (int new_registry); + int shm_lock_registry (void); + void shm_unlock_registry (void); + int access_registry (jack_shm_info_t *ri); + void remove_shm (jack_shm_id_t *id); + int create_registry (jack_shm_info_t *ri); + int shm_validate_registry (); + int GetUID(); + int GetPID(); + void shm_init_registry (); + void release_shm_entry (jack_shm_registry_index_t index); + jack_shm_registry_t * get_free_shm_info (); + + public: + static void jack_shm_copy_from_registry (jack_shm_info_t*, jack_shm_registry_index_t); + static void jack_shm_copy_to_registry (jack_shm_info_t*, jack_shm_registry_index_t*); + static int jack_release_shm_info (jack_shm_registry_index_t); + static char* jack_shm_addr (jack_shm_info_t* si); + static int jack_register_server (const char *server_name, int new_registry); + static int jack_unregister_server (const char *server_name); + static int jack_initialize_shm (const char *server_name); + static int jack_initialize_shm_server (void); + static int jack_initialize_shm_client (void); + static int jack_cleanup_shm (void); + static int jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* result); + static void jack_release_shm (jack_shm_info_t*); + static void jack_release_lib_shm (jack_shm_info_t*); + static void jack_destroy_shm (jack_shm_info_t*); + static int jack_attach_shm (jack_shm_info_t*); + static int jack_attach_lib_shm (jack_shm_info_t*); + static int jack_attach_shm_read (jack_shm_info_t*); + static int jack_attach_lib_shm_read (jack_shm_info_t*); + static int jack_resize_shm (jack_shm_info_t*, jack_shmsize_t size); + + public: + void shm_copy_from_registry (jack_shm_info_t*, jack_shm_registry_index_t); + void shm_copy_to_registry (jack_shm_info_t*, jack_shm_registry_index_t*); + int release_shm_info (jack_shm_registry_index_t); + char* shm_addr (unsigned int fd); + + // here begin the API + int register_server (const char *server_name, int new_registry); + int unregister_server (const char *server_name); + + int initialize_shm (const char *server_name); + int initialize_shm_server (void); + int initialize_shm_client (void); + int cleanup_shm (void); + + int shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* result); + void release_shm (jack_shm_info_t*); + void release_lib_shm (jack_shm_info_t*); + void destroy_shm (jack_shm_info_t*); + int attach_shm (jack_shm_info_t*); + int attach_lib_shm (jack_shm_info_t*); + int attach_shm_read (jack_shm_info_t*); + int attach_lib_shm_read (jack_shm_info_t*); + int resize_shm (jack_shm_info_t*, jack_shmsize_t size); + + private: + static jack_shmtype_t jack_shmtype; + static jack_shm_id_t registry_id; + static jack_shm_fd_t registry_fd; + static jack_shm_info_t registry_info; + static jack_shm_header_t *jack_shm_header; + static jack_shm_registry_t *jack_shm_registry; + static char jack_shm_server_prefix[JACK_SERVER_NAME_SIZE]; + static int semid; + static pthread_mutex_t mutex; + static Shm* ref; + + void jack_release_shm_entry (jack_shm_registry_index_t index); + int jack_shm_lock_registry (void); + void jack_shm_unlock_registry (void); + + //static sp<IAndroidShm> mShmService; + static sp<IMemoryHeap> mShmMemBase[JACK_SHM_HEAP_ENOUGH_COUNT]; + + public: + static sp<IAndroidShm> getShmService(); + }; +}; + +#endif /* __jack_shm_android_h__ */ diff --git a/android/config.h b/android/config.h new file mode 100644 index 00000000..35ff9878 --- /dev/null +++ b/android/config.h @@ -0,0 +1,25 @@ +/* Configuration header created by Waf - do not edit */ +#ifndef _CONFIG_H_WAF +#define _CONFIG_H_WAF + +/* #define HAVE_SAMPLERATE 0 */ +/* #define HAVE_PPOLL 0 */ +/* #define HAVE_SNDFILE */ +/* #define HAVE_NCURSES 0 */ +/* #define HAVE_CELT 0 */ +/* #define HAVE_CELT_API_0_11 0 */ +/* #define HAVE_CELT_API_0_8 0 */ +/* #define HAVE_CELT_API_0_7 0 */ +/* #define HAVE_CELT_API_0_5 0 */ +/* #define HAVE_READLINE 0 */ +#define CLIENT_NUM 16 +#define PORT_NUM_FOR_CLIENT 16 +#define PORT_NUM 128 +#define PORT_NUM_MAX 256 +#define ADDON_DIR "/system/lib/jack" +#define JACK_LOCATION "/system/bin" +#define JACKMP 1 +/* #define USE_POSIX_SHM 0 */ +/* #define __CLIENTDEBUG__ 1 */ + +#endif /* _CONFIG_H_WAF */ diff --git a/android/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include/bits/ctype_base.h b/android/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include/bits/ctype_base.h new file mode 100644 index 00000000..c52689b4 --- /dev/null +++ b/android/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include/bits/ctype_base.h @@ -0,0 +1,14 @@ + +//fix build error in KitKat + +#define _U _CTYPE_U +#define _L _CTYPE_L +#define _N _CTYPE_N +#define _S _CTYPE_S +#define _P _CTYPE_P +#define _C _CTYPE_C +#define _X _CTYPE_X +#define _B _CTYPE_B + +#include <../../../../../../../../../../../prebuilts/ndk/current/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include/bits/ctype_base.h> + diff --git a/android/opensl_io.c b/android/opensl_io.c new file mode 100644 index 00000000..38b6ec0c --- /dev/null +++ b/android/opensl_io.c @@ -0,0 +1,539 @@ +/* +opensl_io.c: +Android OpenSL input/output module +Copyright (c) 2012, Victor Lazzarini +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the <organization> nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "opensl_io.h" +//#define CONV16BIT 32768 +//#define CONVMYFLT (1./32768.) +#define CONV16BIT 32640 +#define CONVMYFLT (1./32640.) + +static void* createThreadLock(void); +static int waitThreadLock(void *lock); +static void notifyThreadLock(void *lock); +static void destroyThreadLock(void *lock); +static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context); +static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context); + +// creates the OpenSL ES audio engine +static SLresult openSLCreateEngine(OPENSL_STREAM *p) +{ + SLresult result; + // create engine + result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL); + if(result != SL_RESULT_SUCCESS) goto engine_end; + + // realize the engine + result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE); + if(result != SL_RESULT_SUCCESS) goto engine_end; + + // get the engine interface, which is needed in order to create other objects + result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE, &(p->engineEngine)); + if(result != SL_RESULT_SUCCESS) goto engine_end; + + engine_end: + return result; +} + +// opens the OpenSL ES device for output +static SLresult openSLPlayOpen(OPENSL_STREAM *p) +{ + SLresult result; + SLuint32 sr = p->sr; + SLuint32 channels = p->outchannels; + + if(channels){ + // configure audio source + SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; + + switch(sr){ + + case 8000: + sr = SL_SAMPLINGRATE_8; + break; + case 11025: + sr = SL_SAMPLINGRATE_11_025; + break; + case 16000: + sr = SL_SAMPLINGRATE_16; + break; + case 22050: + sr = SL_SAMPLINGRATE_22_05; + break; + case 24000: + sr = SL_SAMPLINGRATE_24; + break; + case 32000: + sr = SL_SAMPLINGRATE_32; + break; + case 44100: + sr = SL_SAMPLINGRATE_44_1; + break; + case 48000: + sr = SL_SAMPLINGRATE_48; + break; + case 64000: + sr = SL_SAMPLINGRATE_64; + break; + case 88200: + sr = SL_SAMPLINGRATE_88_2; + break; + case 96000: + sr = SL_SAMPLINGRATE_96; + break; + case 192000: + sr = SL_SAMPLINGRATE_192; + break; + default: + return -1; + } + + const SLInterfaceID ids[] = {SL_IID_VOLUME}; + const SLboolean req[] = {SL_BOOLEAN_FALSE}; + result = (*p->engineEngine)->CreateOutputMix(p->engineEngine, &(p->outputMixObject), 1, ids, req); + if(result != SL_RESULT_SUCCESS) goto end_openaudio; + + // realize the output mix + result = (*p->outputMixObject)->Realize(p->outputMixObject, SL_BOOLEAN_FALSE); + + int speakers; + if(channels > 1) + speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; + else speakers = SL_SPEAKER_FRONT_CENTER; + SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM,channels, sr, + SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, + speakers, SL_BYTEORDER_LITTLEENDIAN}; + + SLDataSource audioSrc = {&loc_bufq, &format_pcm}; + + // configure audio sink + SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, p->outputMixObject}; + SLDataSink audioSnk = {&loc_outmix, NULL}; + + // create audio player + const SLInterfaceID ids1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; + const SLboolean req1[] = {SL_BOOLEAN_TRUE}; + result = (*p->engineEngine)->CreateAudioPlayer(p->engineEngine, &(p->bqPlayerObject), &audioSrc, &audioSnk, + 1, ids1, req1); + if(result != SL_RESULT_SUCCESS) goto end_openaudio; + + // realize the player + result = (*p->bqPlayerObject)->Realize(p->bqPlayerObject, SL_BOOLEAN_FALSE); + if(result != SL_RESULT_SUCCESS) goto end_openaudio; + + // get the play interface + result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_PLAY, &(p->bqPlayerPlay)); + if(result != SL_RESULT_SUCCESS) goto end_openaudio; + + // get the buffer queue interface + result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, + &(p->bqPlayerBufferQueue)); + if(result != SL_RESULT_SUCCESS) goto end_openaudio; + + // register callback on the buffer queue + result = (*p->bqPlayerBufferQueue)->RegisterCallback(p->bqPlayerBufferQueue, bqPlayerCallback, p); + if(result != SL_RESULT_SUCCESS) goto end_openaudio; + + // set the player's state to playing + result = (*p->bqPlayerPlay)->SetPlayState(p->bqPlayerPlay, SL_PLAYSTATE_PLAYING); + + end_openaudio: + return result; + } + return SL_RESULT_SUCCESS; +} + +// Open the OpenSL ES device for input +static SLresult openSLRecOpen(OPENSL_STREAM *p){ + + SLresult result; + SLuint32 sr = p->sr; + SLuint32 channels = p->inchannels; + + if(channels){ + + switch(sr){ + + case 8000: + sr = SL_SAMPLINGRATE_8; + break; + case 11025: + sr = SL_SAMPLINGRATE_11_025; + break; + case 16000: + sr = SL_SAMPLINGRATE_16; + break; + case 22050: + sr = SL_SAMPLINGRATE_22_05; + break; + case 24000: + sr = SL_SAMPLINGRATE_24; + break; + case 32000: + sr = SL_SAMPLINGRATE_32; + break; + case 44100: + sr = SL_SAMPLINGRATE_44_1; + break; + case 48000: + sr = SL_SAMPLINGRATE_48; + break; + case 64000: + sr = SL_SAMPLINGRATE_64; + break; + case 88200: + sr = SL_SAMPLINGRATE_88_2; + break; + case 96000: + sr = SL_SAMPLINGRATE_96; + break; + case 192000: + sr = SL_SAMPLINGRATE_192; + break; + default: + return -1; + } + + // configure audio source + SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, + SL_DEFAULTDEVICEID_AUDIOINPUT, NULL}; + SLDataSource audioSrc = {&loc_dev, NULL}; + + // configure audio sink + int speakers; + if(channels > 1) + speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; + else speakers = SL_SPEAKER_FRONT_CENTER; + SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; + SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, channels, sr, + SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, + speakers, SL_BYTEORDER_LITTLEENDIAN}; + SLDataSink audioSnk = {&loc_bq, &format_pcm}; + + // create audio recorder + // (requires the RECORD_AUDIO permission) + const SLInterfaceID id[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; + const SLboolean req[1] = {SL_BOOLEAN_TRUE}; + result = (*p->engineEngine)->CreateAudioRecorder(p->engineEngine, &(p->recorderObject), &audioSrc, + &audioSnk, 1, id, req); + if (SL_RESULT_SUCCESS != result) goto end_recopen; + + // realize the audio recorder + result = (*p->recorderObject)->Realize(p->recorderObject, SL_BOOLEAN_FALSE); + if (SL_RESULT_SUCCESS != result) goto end_recopen; + + // get the record interface + result = (*p->recorderObject)->GetInterface(p->recorderObject, SL_IID_RECORD, &(p->recorderRecord)); + if (SL_RESULT_SUCCESS != result) goto end_recopen; + + // get the buffer queue interface + result = (*p->recorderObject)->GetInterface(p->recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, + &(p->recorderBufferQueue)); + if (SL_RESULT_SUCCESS != result) goto end_recopen; + + // register callback on the buffer queue + result = (*p->recorderBufferQueue)->RegisterCallback(p->recorderBufferQueue, bqRecorderCallback, + p); + if (SL_RESULT_SUCCESS != result) goto end_recopen; + result = (*p->recorderRecord)->SetRecordState(p->recorderRecord, SL_RECORDSTATE_RECORDING); + + end_recopen: + return result; + } + else return SL_RESULT_SUCCESS; + + +} + +// close the OpenSL IO and destroy the audio engine +static void openSLDestroyEngine(OPENSL_STREAM *p){ + + // destroy buffer queue audio player object, and invalidate all associated interfaces + if (p->bqPlayerObject != NULL) { + (*p->bqPlayerObject)->Destroy(p->bqPlayerObject); + p->bqPlayerObject = NULL; + p->bqPlayerPlay = NULL; + p->bqPlayerBufferQueue = NULL; + p->bqPlayerEffectSend = NULL; + } + + // destroy audio recorder object, and invalidate all associated interfaces + if (p->recorderObject != NULL) { + (*p->recorderObject)->Destroy(p->recorderObject); + p->recorderObject = NULL; + p->recorderRecord = NULL; + p->recorderBufferQueue = NULL; + } + + // destroy output mix object, and invalidate all associated interfaces + if (p->outputMixObject != NULL) { + (*p->outputMixObject)->Destroy(p->outputMixObject); + p->outputMixObject = NULL; + } + + // destroy engine object, and invalidate all associated interfaces + if (p->engineObject != NULL) { + (*p->engineObject)->Destroy(p->engineObject); + p->engineObject = NULL; + p->engineEngine = NULL; + } + +} + + +// open the android audio device for input and/or output +OPENSL_STREAM *android_OpenAudioDevice(int sr, int inchannels, int outchannels, int bufferframes){ + + OPENSL_STREAM *p; + p = (OPENSL_STREAM *) calloc(sizeof(OPENSL_STREAM),1); + + p->inchannels = inchannels; + p->outchannels = outchannels; + p->sr = sr; + p->inlock = createThreadLock(); + p->outlock = createThreadLock(); + + if((p->outBufSamples = bufferframes*outchannels) != 0) { + if((p->outputBuffer[0] = (short *) calloc(p->outBufSamples, sizeof(short))) == NULL || + (p->outputBuffer[1] = (short *) calloc(p->outBufSamples, sizeof(short))) == NULL) { + android_CloseAudioDevice(p); + return NULL; + } + } + + if((p->inBufSamples = bufferframes*inchannels) != 0){ + if((p->inputBuffer[0] = (short *) calloc(p->inBufSamples, sizeof(short))) == NULL || + (p->inputBuffer[1] = (short *) calloc(p->inBufSamples, sizeof(short))) == NULL){ + android_CloseAudioDevice(p); + return NULL; + } + } + + p->currentInputIndex = 0; + p->currentOutputBuffer = 0; + p->currentInputIndex = p->inBufSamples; + p->currentInputBuffer = 0; + + if(openSLCreateEngine(p) != SL_RESULT_SUCCESS) { + android_CloseAudioDevice(p); + return NULL; + } + + if(openSLRecOpen(p) != SL_RESULT_SUCCESS) { + android_CloseAudioDevice(p); + return NULL; + } + + if(openSLPlayOpen(p) != SL_RESULT_SUCCESS) { + android_CloseAudioDevice(p); + return NULL; + } + + notifyThreadLock(p->outlock); + notifyThreadLock(p->inlock); + + p->time = 0.; + return p; +} + +// close the android audio device +void android_CloseAudioDevice(OPENSL_STREAM *p){ + + if (p == NULL) + return; + + openSLDestroyEngine(p); + + if (p->inlock != NULL) { + notifyThreadLock(p->inlock); + destroyThreadLock(p->inlock); + p->inlock = NULL; + } + + if (p->outlock != NULL) { + notifyThreadLock(p->outlock); + destroyThreadLock(p->outlock); + p->inlock = NULL; + } + + if (p->outputBuffer[0] != NULL) { + free(p->outputBuffer[0]); + p->outputBuffer[0] = NULL; + } + + if (p->outputBuffer[1] != NULL) { + free(p->outputBuffer[1]); + p->outputBuffer[1] = NULL; + } + + if (p->inputBuffer[0] != NULL) { + free(p->inputBuffer[0]); + p->inputBuffer[0] = NULL; + } + + if (p->inputBuffer[1] != NULL) { + free(p->inputBuffer[1]); + p->inputBuffer[1] = NULL; + } + + free(p); +} + +// returns timestamp of the processed stream +double android_GetTimestamp(OPENSL_STREAM *p){ + return p->time; +} + + +// this callback handler is called every time a buffer finishes recording +void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context) +{ + OPENSL_STREAM *p = (OPENSL_STREAM *) context; + notifyThreadLock(p->inlock); +} + +// gets a buffer of size samples from the device +int android_AudioIn(OPENSL_STREAM *p,float *buffer,int size){ + short *inBuffer; + int i, bufsamps, index; + if(p == NULL) return 0; + bufsamps = p->inBufSamples; + if(bufsamps == 0) return 0; + index = p->currentInputIndex; + + inBuffer = p->inputBuffer[p->currentInputBuffer]; + for(i=0; i < size; i++){ + if (index >= bufsamps) { + waitThreadLock(p->inlock); + (*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue, + inBuffer,bufsamps*sizeof(short)); + p->currentInputBuffer = (p->currentInputBuffer ? 0 : 1); + index = 0; + inBuffer = p->inputBuffer[p->currentInputBuffer]; + } + buffer[i] = (float) inBuffer[index++]*CONVMYFLT; + } + p->currentInputIndex = index; + if(p->outchannels == 0) p->time += (double) size/(p->sr*p->inchannels); + return i; +} + +// this callback handler is called every time a buffer finishes playing +void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) +{ + OPENSL_STREAM *p = (OPENSL_STREAM *) context; + notifyThreadLock(p->outlock); +} + +// puts a buffer of size samples to the device +int android_AudioOut(OPENSL_STREAM *p, float *buffer,int size){ + + short *outBuffer; + int i, bufsamps, index; + if(p == NULL) return 0; + bufsamps = p->outBufSamples; + if(bufsamps == 0) return 0; + index = p->currentOutputIndex; + outBuffer = p->outputBuffer[p->currentOutputBuffer]; + + for(i=0; i < size; i++){ + outBuffer[index++] = (short) (buffer[i]*CONV16BIT); + if (index >= p->outBufSamples) { + waitThreadLock(p->outlock); + (*p->bqPlayerBufferQueue)->Enqueue(p->bqPlayerBufferQueue, + outBuffer,bufsamps*sizeof(short)); + p->currentOutputBuffer = (p->currentOutputBuffer ? 0 : 1); + index = 0; + outBuffer = p->outputBuffer[p->currentOutputBuffer]; + } + } + p->currentOutputIndex = index; + p->time += (double) size/(p->sr*p->outchannels); + return i; +} + +//---------------------------------------------------------------------- +// thread Locks +// to ensure synchronisation between callbacks and processing code +void* createThreadLock(void) +{ + threadLock *p; + p = (threadLock*) malloc(sizeof(threadLock)); + if (p == NULL) + return NULL; + memset(p, 0, sizeof(threadLock)); + if (pthread_mutex_init(&(p->m), (pthread_mutexattr_t*) NULL) != 0) { + free((void*) p); + return NULL; + } + if (pthread_cond_init(&(p->c), (pthread_condattr_t*) NULL) != 0) { + pthread_mutex_destroy(&(p->m)); + free((void*) p); + return NULL; + } + p->s = (unsigned char) 1; + + return p; +} + +int waitThreadLock(void *lock) +{ + threadLock *p; + int retval = 0; + p = (threadLock*) lock; + pthread_mutex_lock(&(p->m)); + while (!p->s) { + pthread_cond_wait(&(p->c), &(p->m)); + } + p->s = (unsigned char) 0; + pthread_mutex_unlock(&(p->m)); + return NULL; +} + +void notifyThreadLock(void *lock) +{ + threadLock *p; + p = (threadLock*) lock; + pthread_mutex_lock(&(p->m)); + p->s = (unsigned char) 1; + pthread_cond_signal(&(p->c)); + pthread_mutex_unlock(&(p->m)); + return; +} + +void destroyThreadLock(void *lock) +{ + threadLock *p; + p = (threadLock*) lock; + if (p == NULL) + return; + notifyThreadLock(p); + pthread_cond_destroy(&(p->c)); + pthread_mutex_destroy(&(p->m)); + free(p); +} diff --git a/android/opensl_io.h b/android/opensl_io.h new file mode 100644 index 00000000..501f0361 --- /dev/null +++ b/android/opensl_io.h @@ -0,0 +1,121 @@ +/* +opensl_io.c: +Android OpenSL input/output module header +Copyright (c) 2012, Victor Lazzarini +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the <organization> nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef OPENSL_IO +#define OPENSL_IO + +#include <SLES/OpenSLES.h> +#include <SLES/OpenSLES_Android.h> +#include <pthread.h> +#include <stdlib.h> + +typedef struct threadLock_{ + pthread_mutex_t m; + pthread_cond_t c; + unsigned char s; +} threadLock; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct opensl_stream { + + // engine interfaces + SLObjectItf engineObject; + SLEngineItf engineEngine; + + // output mix interfaces + SLObjectItf outputMixObject; + + // buffer queue player interfaces + SLObjectItf bqPlayerObject; + SLPlayItf bqPlayerPlay; + SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; + SLEffectSendItf bqPlayerEffectSend; + + // recorder interfaces + SLObjectItf recorderObject; + SLRecordItf recorderRecord; + SLAndroidSimpleBufferQueueItf recorderBufferQueue; + + // buffer indexes + int currentInputIndex; + int currentOutputIndex; + + // current buffer half (0, 1) + int currentOutputBuffer; + int currentInputBuffer; + + // buffers + short *outputBuffer[2]; + short *inputBuffer[2]; + + // size of buffers + int outBufSamples; + int inBufSamples; + + // locks + void* inlock; + void* outlock; + + double time; + int inchannels; + int outchannels; + int sr; + +} OPENSL_STREAM; + + /* + Open the audio device with a given sampling rate (sr), input and output channels and IO buffer size + in frames. Returns a handle to the OpenSL stream + */ + OPENSL_STREAM* android_OpenAudioDevice(int sr, int inchannels, int outchannels, int bufferframes); + /* + Close the audio device + */ + void android_CloseAudioDevice(OPENSL_STREAM *p); + /* + Read a buffer from the OpenSL stream *p, of size samples. Returns the number of samples read. + */ + int android_AudioIn(OPENSL_STREAM *p, float *buffer,int size); + /* + Write a buffer to the OpenSL stream *p, of size samples. Returns the number of samples written. + */ + int android_AudioOut(OPENSL_STREAM *p, float *buffer,int size); + /* + Get the current IO block time in seconds + */ + double android_GetTimestamp(OPENSL_STREAM *p); + +#ifdef __cplusplus +}; +#endif + +#endif // #ifndef OPENSL_IO diff --git a/common/JackConstants.h b/common/JackConstants.h index c7257d08..c5ae4af4 100644 --- a/common/JackConstants.h +++ b/common/JackConstants.h @@ -45,7 +45,9 @@ #define PORT_NUM 2048 #endif +#ifndef PORT_NUM_MAX #define PORT_NUM_MAX 4096 // The "max" value for ports used in connection manager, although port number in graph manager is dynamic +#endif #define DRIVER_PORT_NUM 256 diff --git a/common/Jackdmp.cpp b/common/Jackdmp.cpp index 5b16e0de..6d8db0d0 100644 --- a/common/Jackdmp.cpp +++ b/common/Jackdmp.cpp @@ -33,6 +33,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "control.h" #include "JackConstants.h" #include "JackPlatformPlug.h" +#ifdef __ANDROID__ +#include "JackControlAPIAndroid.h" +#endif #if defined(JACK_DBUS) && defined(__linux__) #include <dbus/dbus.h> @@ -192,6 +195,25 @@ static void usage(FILE* file, jackctl_server_t *server) } } +#ifdef __ANDROID__ +static void jackctl_server_switch_master_dummy(jackctl_server_t * server_ctl, char * master_driver_name) +{ + static bool is_dummy_driver = false; + if(!strcmp(master_driver_name, "dummy")) { + return; + } + jackctl_driver_t * driver_ctr; + if(is_dummy_driver) { + is_dummy_driver = false; + driver_ctr = jackctl_server_get_driver(server_ctl, master_driver_name); + } else { + is_dummy_driver = true; + driver_ctr = jackctl_server_get_driver(server_ctl, "dummy"); + } + jackctl_server_switch_master(server_ctl, driver_ctr); +} +#endif + // Prototype to be found in libjackserver extern "C" void silent_jack_error_callback(const char *desc); @@ -556,7 +578,19 @@ int main(int argc, char** argv) return_value = 0; // Waits for signal +#ifdef __ANDROID__ + //reserve SIGUSR2 signal for switching master driver + while(1) { + int signal = jackctl_wait_signals_and_return(sigmask); + if (signal == SIGUSR2) { + jackctl_server_switch_master_dummy(server_ctl, master_driver_name); + } else { + break; + } + } +#else jackctl_wait_signals(sigmask); +#endif stop_server: if (!jackctl_server_stop(server_ctl)) { diff --git a/common/jack/types.h b/common/jack/types.h index fa059159..c1625f5f 100644 --- a/common/jack/types.h +++ b/common/jack/types.h @@ -369,7 +369,7 @@ typedef int (*JackSampleRateCallback)(jack_nframes_t nframes, void *arg); * @param register non-zero if the port is being registered, * zero if the port is being unregistered */ -typedef void (*JackPortRegistrationCallback)(jack_port_id_t port, int register, void *arg); +typedef void (*JackPortRegistrationCallback)(jack_port_id_t port, int /* register */, void *arg); /** * Prototype for the client supplied function that is called @@ -380,7 +380,7 @@ typedef void (*JackPortRegistrationCallback)(jack_port_id_t port, int register, * zero if the client is being unregistered * @param arg pointer to a client supplied structure */ -typedef void (*JackClientRegistrationCallback)(const char* name, int register, void *arg); +typedef void (*JackClientRegistrationCallback)(const char* name, int /* register */, void *arg); /** * Prototype for the client supplied function that is called diff --git a/common/shm.h b/common/shm.h index c539aa9f..ada2a9d0 100644 --- a/common/shm.h +++ b/common/shm.h @@ -79,6 +79,19 @@ extern "C" typedef char shm_name_t[SHM_NAME_MAX]; typedef shm_name_t jack_shm_id_t; +#elif __ANDROID__ + +#ifndef NAME_MAX +#define NAME_MAX 255 +#endif + +#ifndef SHM_NAME_MAX +#define SHM_NAME_MAX NAME_MAX +#endif + typedef char shm_name_t[SHM_NAME_MAX]; + typedef shm_name_t jack_shm_id_t; + typedef int jack_shm_fd_t; + #else /* System V SHM */ typedef int jack_shm_id_t; @@ -88,7 +101,8 @@ extern "C" typedef enum { shm_POSIX = 1, /* POSIX shared memory */ shm_SYSV = 2, /* System V shared memory */ - shm_WIN32 = 3 /* Windows 32 shared memory */ + shm_WIN32 = 3, /* Windows 32 shared memory */ + shm_ANDROID = 4 /* Android shared memory */ } jack_shmtype_t; typedef int16_t jack_shm_registry_index_t; @@ -135,6 +149,9 @@ extern "C" jack_shmsize_t size; /* for POSIX unattach */ jack_shm_id_t id; /* API specific, see above */ +#ifdef __ANDROID__ + jack_shm_fd_t fd; +#endif } jack_shm_registry_t; @@ -153,6 +170,9 @@ extern "C" struct _jack_shm_info { jack_shm_registry_index_t index; /* offset into the registry */ uint32_t size; +#ifdef __ANDROID__ + jack_shm_fd_t fd; +#endif union { void *attached_at; /* address where attached */ char ptr_size[8]; diff --git a/example-clients/alsa_in.c b/example-clients/alsa_in.c index 9c31a05e..1a8c0332 100644 --- a/example-clients/alsa_in.c +++ b/example-clients/alsa_in.c @@ -99,6 +99,9 @@ alsa_format_t formats[] = { { SND_PCM_FORMAT_S24_3LE, 3, sample_move_d24_sS, sample_move_dS_s24, "24bit - real" }, { SND_PCM_FORMAT_S24, 4, sample_move_d24_sS, sample_move_dS_s24, "24bit" }, { SND_PCM_FORMAT_S16, 2, sample_move_d16_sS, sample_move_dS_s16, "16bit" } +#ifdef __ANDROID__ + ,{ SND_PCM_FORMAT_S16_LE, 2, sample_move_d16_sS, sample_move_dS_s16, "16bit little-endian" } +#endif }; #define NUMFORMATS (sizeof(formats)/sizeof(formats[0])) int format=0; @@ -127,6 +130,11 @@ static int xrun_recovery(snd_pcm_t *handle, int err) { static int set_hwformat( snd_pcm_t *handle, snd_pcm_hw_params_t *params ) { +#ifdef __ANDROID__ + format = 5; + snd_pcm_hw_params_set_format(handle, params, formats[format].format_id); + return 0; +#else int i; int err; @@ -140,6 +148,7 @@ static int set_hwformat( snd_pcm_t *handle, snd_pcm_hw_params_t *params ) } return err; +#endif } static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access, int rate, int channels, int period, int nperiods ) { diff --git a/example-clients/alsa_out.c b/example-clients/alsa_out.c index ac7a149c..d5fd2680 100644 --- a/example-clients/alsa_out.c +++ b/example-clients/alsa_out.c @@ -99,6 +99,9 @@ alsa_format_t formats[] = { { SND_PCM_FORMAT_S24_3LE, 3, sample_move_d24_sS, sample_move_dS_s24, "24bit - real" }, { SND_PCM_FORMAT_S24, 4, sample_move_d24_sS, sample_move_dS_s24, "24bit" }, { SND_PCM_FORMAT_S16, 2, sample_move_d16_sS, sample_move_dS_s16, "16bit" } +#ifdef __ANDROID__ + ,{ SND_PCM_FORMAT_S16_LE, 2, sample_move_d16_sS, sample_move_dS_s16, "16bit little-endian" } +#endif }; #define NUMFORMATS (sizeof(formats)/sizeof(formats[0])) int format=0; @@ -127,6 +130,11 @@ static int xrun_recovery(snd_pcm_t *handle, int err) { static int set_hwformat( snd_pcm_t *handle, snd_pcm_hw_params_t *params ) { +#ifdef __ANDROID__ + format = 5; + snd_pcm_hw_params_set_format(handle, params, formats[format].format_id); + return 0; +#else int i; int err; @@ -140,6 +148,7 @@ static int set_hwformat( snd_pcm_t *handle, snd_pcm_hw_params_t *params ) } return err; +#endif } static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access, int rate, int channels, int period, int nperiods ) { diff --git a/example-clients/midi_latency_test.c b/example-clients/midi_latency_test.c index 39a36813..1a6988c0 100644 --- a/example-clients/midi_latency_test.c +++ b/example-clients/midi_latency_test.c @@ -635,7 +635,7 @@ main(int argc, char **argv) timeout = 5; for (;;) { - char c = getopt_long(argc, argv, option_string, long_options, + signed char c = getopt_long(argc, argv, option_string, long_options, &long_index); switch (c) { case 'h': diff --git a/example-clients/transport.c b/example-clients/transport.c index a2ff0eef..e5d22ec9 100644 --- a/example-clients/transport.c +++ b/example-clients/transport.c @@ -24,11 +24,16 @@ #include <signal.h> #include <stdlib.h> #include <string.h> +#ifdef HAVE_READLINE #include <readline/readline.h> #include <readline/history.h> +#endif #include <jack/jack.h> #include <jack/transport.h> +#ifndef HAVE_READLINE +#define whitespace(c) (((c) == ' ') || ((c) == '\t')) +#endif char *package; /* program name */ int done = 0; @@ -384,6 +389,7 @@ static char *command_generator (const char *text, int state) static void command_loop() { +#ifdef HAVE_READLINE char *line, *cmd; char prompt[32]; @@ -394,10 +400,15 @@ static void command_loop() /* Define a custom completion function. */ rl_completion_entry_function = command_generator; +#else + char line[64] = {0,}; + char *cmd = NULL; +#endif /* Read and execute commands until the user quits. */ while (!done) { +#ifdef HAVE_READLINE line = readline(prompt); if (line == NULL) { /* EOF? */ @@ -405,6 +416,11 @@ static void command_loop() done = 1; break; } +#else + printf("%s> ", package); + fgets(line, sizeof(line), stdin); + line[strlen(line)-1] = '\0'; +#endif /* Remove leading and trailing whitespace from the line. */ cmd = stripwhite(line); @@ -412,11 +428,15 @@ static void command_loop() /* If anything left, add to history and execute it. */ if (*cmd) { +#ifdef HAVE_READLINE add_history(cmd); +#endif execute_command(cmd); } +#ifdef HAVE_READLINE free(line); /* realine() called malloc() */ +#endif } } diff --git a/linux/alsa/JackAlsaDriver.cpp b/linux/alsa/JackAlsaDriver.cpp index bfed2f11..7a3dfdcd 100644 --- a/linux/alsa/JackAlsaDriver.cpp +++ b/linux/alsa/JackAlsaDriver.cpp @@ -39,7 +39,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackPort.h" #include "JackGraphManager.h" #include "JackLockedEngine.h" +#ifdef __ANDROID__ +#include "JackAndroidThread.h" +#else #include "JackPosixThread.h" +#endif #include "JackCompilerDeps.h" #include "JackServerGlobals.h" @@ -469,7 +473,11 @@ int JackAlsaDriver::is_realtime() const int JackAlsaDriver::create_thread(pthread_t *thread, int priority, int realtime, void *(*start_routine)(void*), void *arg) { +#ifdef __ANDROID__ + return JackAndroidThread::StartImp(thread, priority, realtime, start_routine, arg); +#else return JackPosixThread::StartImp(thread, priority, realtime, start_routine, arg); +#endif } jack_port_id_t JackAlsaDriver::port_register(const char *port_name, const char *port_type, unsigned long flags, unsigned long buffer_size) @@ -739,7 +747,11 @@ SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor () desc = jack_driver_descriptor_construct("alsa", JackDriverMaster, "Linux ALSA API based audio backend", &filler); strcpy(value.str, "hw:0"); - jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, enum_alsa_devices(), "ALSA device name", NULL); +#ifdef __ANDROID__ + jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "ALSA device name", NULL); +#else + jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, enum_alsa_devices, "ALSA device name", NULL); +#endif strcpy(value.str, "none"); jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set device", NULL); diff --git a/linux/alsa/alsa_driver.c b/linux/alsa/alsa_driver.c index e14458b6..9d1068c9 100644 --- a/linux/alsa/alsa_driver.c +++ b/linux/alsa/alsa_driver.c @@ -368,7 +368,7 @@ alsa_driver_configure_stream (alsa_driver_t *driver, char *device_name, snd_pcm_format_t format; int swapped; } formats[] = { - {"32bit float little-endian", SND_PCM_FORMAT_FLOAT_LE}, + {"32bit float little-endian", SND_PCM_FORMAT_FLOAT_LE, IS_LE}, {"32bit integer little-endian", SND_PCM_FORMAT_S32_LE, IS_LE}, {"32bit integer big-endian", SND_PCM_FORMAT_S32_BE, IS_BE}, {"24bit little-endian", SND_PCM_FORMAT_S24_3LE, IS_LE}, @@ -914,7 +914,7 @@ alsa_driver_get_channel_addresses (alsa_driver_t *driver, snd_pcm_uframes_t *capture_offset, snd_pcm_uframes_t *playback_offset) { - unsigned long err; + int err; channel_t chn; if (capture_avail) { @@ -1320,7 +1320,11 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float driver->poll_late++; } +#ifdef __ANDROID__ + poll_result = poll (driver->pfd, nfds, -1); //fix for sleep issue +#else poll_result = poll (driver->pfd, nfds, driver->poll_timeout); +#endif if (poll_result < 0) { if (errno == EINTR) { @@ -2034,6 +2038,13 @@ alsa_driver_new (char *name, char *playback_alsa_device, SND_PCM_NONBLOCK) < 0) { switch (errno) { case EBUSY: +#ifdef __ANDROID__ + jack_error ("\n\nATTENTION: The playback device \"%s\" is " + "already in use. Please stop the" + " application using it and " + "run JACK again", + playback_alsa_device); +#else current_apps = discover_alsa_using_apps (); if (current_apps) { jack_error ("\n\nATTENTION: The playback device \"%s\" is " @@ -2051,6 +2062,7 @@ alsa_driver_new (char *name, char *playback_alsa_device, "run JACK again", playback_alsa_device); } +#endif alsa_driver_delete (driver); return NULL; @@ -2078,6 +2090,13 @@ alsa_driver_new (char *name, char *playback_alsa_device, SND_PCM_NONBLOCK) < 0) { switch (errno) { case EBUSY: +#ifdef __ANDROID__ + jack_error ("\n\nATTENTION: The capture (recording) device \"%s\" is " + "already in use. Please stop the" + " application using it and " + "run JACK again", + capture_alsa_device); +#else current_apps = discover_alsa_using_apps (); if (current_apps) { jack_error ("\n\nATTENTION: The capture device \"%s\" is " @@ -2095,6 +2114,7 @@ alsa_driver_new (char *name, char *playback_alsa_device, "run JACK again", capture_alsa_device); } +#endif alsa_driver_delete (driver); return NULL; break; diff --git a/linux/alsa/alsa_rawmidi.c b/linux/alsa/alsa_rawmidi.c index 521ad3d4..aa69e9dd 100644 --- a/linux/alsa/alsa_rawmidi.c +++ b/linux/alsa/alsa_rawmidi.c @@ -37,6 +37,8 @@ #include "midi_unpack.h" #include "JackError.h" +extern int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *req, struct timespec *rem); + enum { NANOSLEEP_RESOLUTION = 7000 }; @@ -808,8 +810,9 @@ void jack_process(midi_stream_t *str, jack_nframes_t nframes) str->jack.ports[w] = port; ++w; } - if (str->jack.nports != w) + if (str->jack.nports != w) { debug_log("jack_%s: nports %d -> %d", str->name, str->jack.nports, w); + } str->jack.nports = w; jack_add_ports(str); // it makes no sense to add them earlier since they have no data yet @@ -910,11 +913,13 @@ void *midi_thread(void *arg) str->midi.ports[wp] = port; ++wp; } - if (str->midi.nports != wp) + if (str->midi.nports != wp) { debug_log("midi_%s: nports %d -> %d", str->name, str->midi.nports, wp); + } str->midi.nports = wp; - if (npfds != w) + if (npfds != w) { debug_log("midi_%s: npfds %d -> %d", str->name, npfds, w); + } npfds = w; /* @@ -1054,8 +1059,9 @@ int do_midi_input(process_midi_t *proc) jack_ringbuffer_get_write_vector(port->base.data_ring, vec); if (jack_ringbuffer_write_space(port->base.event_ring) < sizeof(event_head_t) || vec[0].len < 1) { port->overruns++; - if (port->base.npfds) + if (port->base.npfds) { debug_log("midi_in: internal overflow on %s", port->base.name); + } // remove from poll to prevent busy-looping port->base.npfds = 0; return 1; @@ -1106,8 +1112,9 @@ void do_jack_output(process_jack_t *proc) output_port_t *port = (output_port_t*) proc->port; int nevents = jack_midi_get_event_count(proc->buffer); int i; - if (nevents) + if (nevents) { debug_log("jack_out: %d events in %s", nevents, port->base.name); + } for (i=0; i<nevents; ++i) { jack_midi_event_t event; event_head_t hdr; @@ -1146,12 +1153,14 @@ int do_midi_output(process_midi_t *proc) port->next_event.time = 0; port->next_event.size = 0; break; - } else + } else { debug_log("midi_out: at %ld got %d bytes for %ld", (long)proc->cur_time, (int)port->next_event.size, (long)port->next_event.time); + } } - if (port->todo) + if (port->todo) { debug_log("midi_out: todo = %d at %ld", (int)port->todo, (long)proc->cur_time); + } // calc next wakeup time if (!port->todo && port->next_event.time && port->next_event.time < proc->next_time) { @@ -1193,8 +1202,9 @@ int do_midi_output(process_midi_t *proc) if (!port->todo) { int i; - if (worked) + if (worked) { debug_log("midi_out: relaxing on %s", port->base.name); + } for (i=0; i<port->base.npfds; ++i) proc->wpfds[i].events &= ~POLLOUT; } else { diff --git a/linux/alsa/alsa_seqmidi.c b/linux/alsa/alsa_seqmidi.c index 038bd8ea..f7583f39 100644 --- a/linux/alsa/alsa_seqmidi.c +++ b/linux/alsa/alsa_seqmidi.c @@ -438,8 +438,9 @@ void port_setdead(port_hash_t hash, snd_seq_addr_t addr) port_t *port = port_get(hash, addr); if (port) port->is_dead = 1; // see jack_process - else + else { debug_log("port_setdead: not found (%d:%d)", addr.client, addr.port); + } } static @@ -728,7 +729,7 @@ void do_jack_input(alsa_seqmidi_t *self, port_t *port, struct process_info *info alsa_midi_event_t ev; while (jack_ringbuffer_read(port->early_events, (char*)&ev, sizeof(ev))) { jack_midi_data_t* buf; - jack_nframes_t time = ev.time - info->period_start; + int64_t time = ev.time - info->period_start; if (time < 0) time = 0; else if (time >= info->nframes) diff --git a/linux/alsa/hammerfall.c b/linux/alsa/hammerfall.c index c2e3efea..52354070 100644 --- a/linux/alsa/hammerfall.c +++ b/linux/alsa/hammerfall.c @@ -206,10 +206,12 @@ hammerfall_release (jack_hardware_t *hw) return; } +#ifndef __ANDROID__ if (h->monitor_thread) { pthread_cancel (h->monitor_thread); pthread_join (h->monitor_thread, &status); } +#endif free (h); } |