/* * Copyright (C) 2013 Team XBMC * http://xbmc.org * * 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, 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 XBMC; see the file COPYING. If not, see * . * */ #include "AudioTrack.h" #include "jutils/jutils-details.hpp" using namespace jni; int CJNIAudioTrack::MODE_STREAM = 0x00000001; int CJNIAudioTrack::PLAYSTATE_PLAYING = 0x00000003; void CJNIAudioTrack::PopulateStaticFields() { if (CJNIBase::GetSDKVersion() >= 3) { jhclass c = find_class("android/media/AudioTrack"); CJNIAudioTrack::PLAYSTATE_PLAYING = get_static_field(c, "PLAYSTATE_PLAYING"); if (CJNIBase::GetSDKVersion() >= 5) CJNIAudioTrack::MODE_STREAM = get_static_field(c, "MODE_STREAM"); } } CJNIAudioTrack::CJNIAudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode) throw(std::invalid_argument) : CJNIBase("android/media/AudioTrack") { m_object = new_object(GetClassName(), "", "(IIIIII)V", streamType, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes, mode); /* AudioTrack constructor may throw IllegalArgumentException, pass it to * caller instead of getting us killed */ JNIEnv* jenv = xbmc_jnienv(); jthrowable exception = jenv->ExceptionOccurred(); if (exception) { jenv->ExceptionClear(); jhclass excClass = find_class(jenv, "java/lang/Throwable"); jmethodID toStrMethod = get_method_id(jenv, excClass, "toString", "()Ljava/lang/String;"); jhstring msg = call_method(exception, toStrMethod); throw std::invalid_argument(jcast(msg)); } m_buffer = jharray(xbmc_jnienv()->NewByteArray(bufferSizeInBytes)); m_object.setGlobal(); m_buffer.setGlobal(); } void CJNIAudioTrack::play() { call_method(m_object, "play", "()V"); } void CJNIAudioTrack::stop() { call_method(m_object, "stop", "()V"); JNIEnv* jenv = xbmc_jnienv(); // might toss an exception on release so catch it. jthrowable exception = jenv->ExceptionOccurred(); if (exception) { jenv->ExceptionDescribe(); jenv->ExceptionClear(); } } void CJNIAudioTrack::flush() { call_method(m_object, "flush", "()V"); } void CJNIAudioTrack::release() { call_method(m_object, "release", "()V"); JNIEnv* jenv = xbmc_jnienv(); } int CJNIAudioTrack::write(char* audioData, int offsetInBytes, int sizeInBytes) { int written = 0; JNIEnv* jenv = xbmc_jnienv(); char* pArray; // Write a buffer of audio data to Java AudioTrack. // Warning, no other JNI function can be called after // GetPrimitiveArrayCritical until ReleasePrimitiveArrayCritical. if ((pArray = (char*)jenv->GetPrimitiveArrayCritical(m_buffer, NULL))) { memcpy(pArray + offsetInBytes, audioData, sizeInBytes); jenv->ReleasePrimitiveArrayCritical(m_buffer, pArray, 0); written = call_method(m_object, "write", "([BII)I", m_buffer, offsetInBytes, sizeInBytes); } return written; } int CJNIAudioTrack::getPlayState() { return call_method(m_object, "getPlayState", "()I"); } int CJNIAudioTrack::getPlaybackHeadPosition() { return call_method(m_object, "getPlaybackHeadPosition", "()I"); } int CJNIAudioTrack::getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) { return call_static_method( "android/media/AudioTrack", "getMinBufferSize", "(III)I", sampleRateInHz, channelConfig, audioFormat); } int CJNIAudioTrack::getNativeOutputSampleRate(int streamType) { return call_static_method( "android/media/AudioTrack", "getNativeOutputSampleRate", "(I)I", streamType); }