예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #4
0
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);
}
예제 #5
0
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);
}
예제 #6
0
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;
}
예제 #7
0
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;
}