void anp_audio_start(ANPAudioTrack* s) { if (s == NULL || s->output_unit == NULL) { return; } if (s->keepGoing) { // we are already playing. Ignore. return; } JNIEnv *jenv = GetJNIForThread(); if (!jenv) return; mozilla::AutoLocalJNIFrame autoFrame(jenv, 0); jenv->CallVoidMethod(s->output_unit, at.play); if (autoFrame.CheckForException()) { jenv->DeleteGlobalRef(s->at_class); free(s); return; } s->isStopped = false; s->keepGoing = true; // AudioRunnable now owns the ANPAudioTrack nsRefPtr<AudioRunnable> runnable = new AudioRunnable(s); nsCOMPtr<nsIThread> thread; NS_NewThread(getter_AddRefs(thread), runnable); }
void anp_audio_start(ANPAudioTrack* s) { if (s == nullptr || s->output_unit == nullptr) { return; } if (s->keepGoing) { // we are already playing. Ignore. return; } JNIEnv* const jenv = mozilla::jni::GetEnvForThread(); mozilla::AutoLocalJNIFrame autoFrame(jenv, 0); jenv->CallVoidMethod(s->output_unit, at.play); if (autoFrame.CheckForException()) { jenv->DeleteGlobalRef(s->at_class); delete s; return; } s->isStopped = false; s->keepGoing = true; // AudioRunnable now owns the ANPAudioTrack RefPtr<AudioRunnable> runnable = new AudioRunnable(s); nsCOMPtr<nsIThread> thread; NS_NewNamedThread("Android Audio", getter_AddRefs(thread), runnable); }
void anp_audio_pause(ANPAudioTrack* s) { if (s == nullptr || s->output_unit == nullptr) { return; } JNIEnv* const jenv = mozilla::jni::GetEnvForThread(); mozilla::AutoLocalJNIFrame autoFrame(jenv, 0); jenv->CallVoidMethod(s->output_unit, at.pause); }
void anp_audio_stop(ANPAudioTrack* s) { if (s == nullptr || s->output_unit == nullptr) { return; } s->isStopped = true; JNIEnv *jenv = GetJNIForThread(); mozilla::AutoLocalJNIFrame autoFrame(jenv, 0); jenv->CallVoidMethod(s->output_unit, at.stop); }
void anp_audio_pause(ANPAudioTrack* s) { if (s == NULL || s->output_unit == NULL) { return; } JNIEnv *jenv = GetJNIForThread(); if (!jenv) return; mozilla::AutoLocalJNIFrame autoFrame(jenv, 0); jenv->CallVoidMethod(s->output_unit, at.pause); }
ANPAudioTrack* anp_audio_newTrack(uint32_t sampleRate, // sampling rate in Hz ANPSampleFormat format, int channelCount, // MONO=1, STEREO=2 ANPAudioCallbackProc proc, void* user) { ANPAudioTrack *s = (ANPAudioTrack*) malloc(sizeof(ANPAudioTrack)); if (s == NULL) { return NULL; } JNIEnv *jenv = GetJNIForThread(); if (!jenv) return NULL; s->at_class = init_jni_bindings(jenv); s->rate = sampleRate; s->channels = channelCount; s->bufferSize = s->rate * s->channels; s->isStopped = true; s->keepGoing = false; s->user = user; s->proc = proc; s->format = format; int jformat; switch (format) { case kPCM16Bit_ANPSampleFormat: jformat = ENCODING_PCM_16BIT; break; case kPCM8Bit_ANPSampleFormat: jformat = ENCODING_PCM_8BIT; break; default: LOG("Unknown audio format. defaulting to 16bit."); jformat = ENCODING_PCM_16BIT; break; } int jChannels; switch (channelCount) { case 1: jChannels = CHANNEL_OUT_MONO; break; case 2: jChannels = CHANNEL_OUT_STEREO; break; default: LOG("Unknown channel count. defaulting to mono."); jChannels = CHANNEL_OUT_MONO; break; } mozilla::AutoLocalJNIFrame autoFrame(jenv); jobject obj = jenv->NewObject(s->at_class, at.constructor, STREAM_MUSIC, s->rate, jChannels, jformat, s->bufferSize, MODE_STREAM); if (autoFrame.CheckForException() || obj == NULL) { jenv->DeleteGlobalRef(s->at_class); free(s); return NULL; } jint state = jenv->CallIntMethod(obj, at.getstate); if (autoFrame.CheckForException() || state == STATE_UNINITIALIZED) { jenv->DeleteGlobalRef(s->at_class); free(s); return NULL; } s->output_unit = jenv->NewGlobalRef(obj); return s; }
NS_IMETHODIMP AudioRunnable::Run() { JNIEnv* jenv = GetJNIForThread(); if (!jenv) return NS_ERROR_FAILURE; mozilla::AutoLocalJNIFrame autoFrame(jenv, 2); jbyteArray bytearray = jenv->NewByteArray(mTrack->bufferSize); if (!bytearray) { LOG("AudioRunnable:: Run. Could not create bytearray"); return NS_ERROR_FAILURE; } jbyte *byte = jenv->GetByteArrayElements(bytearray, NULL); if (!byte) { LOG("AudioRunnable:: Run. Could not create bytearray"); return NS_ERROR_FAILURE; } ANPAudioBuffer buffer; buffer.channelCount = mTrack->channels; buffer.format = mTrack->format; buffer.bufferData = (void*) byte; while (mTrack->keepGoing) { // reset the buffer size buffer.size = mTrack->bufferSize; // Get data from the plugin mTrack->proc(kMoreData_ANPAudioEvent, mTrack->user, &buffer); if (buffer.size == 0) { LOG("%p - kMoreData_ANPAudioEvent", mTrack); continue; } size_t wroteSoFar = 0; jint retval; do { retval = jenv->CallIntMethod(mTrack->output_unit, at.write, bytearray, wroteSoFar, buffer.size - wroteSoFar); if (retval < 0) { LOG("%p - Write failed %d", mTrack, retval); break; } wroteSoFar += retval; } while(wroteSoFar < buffer.size); } jenv->CallVoidMethod(mTrack->output_unit, at.release); jenv->DeleteGlobalRef(mTrack->output_unit); jenv->DeleteGlobalRef(mTrack->at_class); free(mTrack); jenv->ReleaseByteArrayElements(bytearray, byte, 0); return NS_OK; }